@praxisui/page-builder 9.0.0-beta.7 → 9.0.0-beta.71

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.
@@ -7,7 +7,7 @@ import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
7
7
  import * as i2$1 from '@angular/material/icon';
8
8
  import { MatIconModule } from '@angular/material/icon';
9
9
  import * as i2$2 from '@praxisui/core';
10
- import { PraxisIconDirective, BUILTIN_SHELL_PRESETS, providePraxisI18n, PraxisI18nService, GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, PRAXIS_GLOBAL_ACTION_CATALOG, SurfaceOpenActionEditorComponent, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, deepMerge, generateId, ComponentMetadataRegistry, PraxisRuntimeComponentObservationRegistryService, domainKnowledgeTimelineToRichContentDocument, DomainRuleService, DomainKnowledgeService, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR } from '@praxisui/core';
10
+ import { PraxisIconDirective, BUILTIN_SHELL_PRESETS, providePraxisI18n, PraxisI18nService, GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, PRAXIS_GLOBAL_ACTION_CATALOG, SurfaceOpenActionEditorComponent, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, deepMerge, generateId, ComponentMetadataRegistry, PraxisRuntimeComponentObservationRegistryService, domainKnowledgeTimelineToRichContentDocument, DomainRuleService, DomainKnowledgeService, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR } from '@praxisui/core';
11
11
  export { WidgetShellComponent } from '@praxisui/core';
12
12
  import * as i3 from '@angular/material/tooltip';
13
13
  import { MatTooltipModule } from '@angular/material/tooltip';
@@ -31,7 +31,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
31
31
  import * as i7 from '@angular/material/tabs';
32
32
  import { MatTabsModule } from '@angular/material/tabs';
33
33
  import { HttpClient, HttpHeaders } from '@angular/common/http';
34
- import { AgenticAuthoringTurnClientService, toPraxisAssistantConversationMessages, PraxisAssistantTurnOrchestratorService, PraxisAssistantSessionRegistryService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
34
+ import { AgenticAuthoringTurnClientService, withAuthoringScopePolicyContextHints, toPraxisAssistantConversationMessages, PraxisAssistantTurnOrchestratorService, PraxisAssistantSessionRegistryService, createPraxisAssistantViewportLayout, PraxisAiAssistantShellComponent } from '@praxisui/ai';
35
35
 
36
36
  const PLACEHOLDER = 1;
37
37
 
@@ -642,11 +642,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
642
642
  args: [MAT_DIALOG_DATA]
643
643
  }] }] });
644
644
 
645
- const BUILTIN_PRESET_OPTIONS = [
646
- { id: 'dark-glass', label: 'Dark Glass' },
647
- { id: 'light-neutral', label: 'Light Neutral' },
648
- { id: 'graphite', label: 'Graphite' },
649
- ];
645
+ const BUILTIN_PRESET_LABELS = {
646
+ 'dark-glass': 'Dark Glass',
647
+ 'light-neutral': 'Light Neutral',
648
+ graphite: 'Graphite',
649
+ frameless: 'Frameless',
650
+ 'data-panel': 'Data Panel',
651
+ 'chart-panel': 'Chart Panel',
652
+ 'metric-panel': 'Metric Panel',
653
+ 'executive-card': 'Executive Card',
654
+ 'filter-bar': 'Filter Bar',
655
+ };
656
+ const BUILTIN_PRESET_OPTIONS = Object.keys(BUILTIN_SHELL_PRESETS).map((id) => ({
657
+ id,
658
+ label: BUILTIN_PRESET_LABELS[id] ?? id,
659
+ }));
650
660
  const BUILTIN_PRESET_MAP = BUILTIN_SHELL_PRESETS;
651
661
  const SET_INPUT_PRESETS = {
652
662
  'praxis-dynamic-form': [
@@ -2325,9 +2335,11 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2325
2335
  'praxis.pageBuilder.editor.status.review': 'Review errors before saving',
2326
2336
  'praxis.pageBuilder.editor.status.pending': 'Pending changes',
2327
2337
  'praxis.pageBuilder.editor.status.clean': 'No changes',
2338
+ 'praxis.pageBuilder.editor.status.validationIssue': 'Review: {{issue}}',
2328
2339
  'praxis.pageBuilder.editor.summary.layout': 'Layout: {{label}}',
2329
2340
  'praxis.pageBuilder.editor.summary.theme': 'Theme: {{label}}',
2330
2341
  'praxis.pageBuilder.editor.summary.shell': 'Shell: {{label}}',
2342
+ 'praxis.pageBuilder.editor.summary.canvasColumns': 'Canvas: {{count}} columns',
2331
2343
  'praxis.pageBuilder.editor.fallback.manual': 'manual',
2332
2344
  'praxis.pageBuilder.editor.fallback.default': 'default',
2333
2345
  'praxis.pageBuilder.editor.fallback.neutral': 'neutral',
@@ -2345,6 +2357,8 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2345
2357
  'praxis.pageBuilder.editor.layout.cols': 'Columns',
2346
2358
  'praxis.pageBuilder.editor.layout.rowHeight': 'Row height (px)',
2347
2359
  'praxis.pageBuilder.editor.layout.gap': 'Gap (px)',
2360
+ 'praxis.pageBuilder.editor.layout.rowUnit': 'Row unit',
2361
+ 'praxis.pageBuilder.editor.layout.autoRows': 'Auto rows',
2348
2362
  'praxis.pageBuilder.editor.layout.presetSection': 'Layout Preset',
2349
2363
  'praxis.pageBuilder.editor.layout.presetHelp': 'Use presets to accelerate a consistent organization and refine only what is needed afterwards.',
2350
2364
  'praxis.pageBuilder.editor.layout.layoutPreset': 'Layout preset',
@@ -2427,6 +2441,14 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2427
2441
  'praxis.pageBuilder.editor.state.optionsJson': 'Options (JSON)',
2428
2442
  'praxis.pageBuilder.editor.apply': 'Apply',
2429
2443
  'praxis.pageBuilder.editor.errors.invalidJson': 'Invalid JSON',
2444
+ 'praxis.pageBuilder.editor.errors.canvasInvalid': 'Invalid canvas',
2445
+ 'praxis.pageBuilder.editor.errors.contextInvalid': 'Invalid context',
2446
+ 'praxis.pageBuilder.editor.errors.stateInvalid': 'Invalid state',
2447
+ 'praxis.pageBuilder.editor.errors.duplicateGroupIds': 'Duplicate group IDs',
2448
+ 'praxis.pageBuilder.editor.errors.invalidTabs': 'Invalid tabs',
2449
+ 'praxis.pageBuilder.editor.errors.duplicateWidgetKeys': 'Duplicate widget keys',
2450
+ 'praxis.pageBuilder.editor.errors.invalidColumns': 'Invalid columns',
2451
+ 'praxis.pageBuilder.editor.errors.invalidOverrides': 'Invalid overrides',
2430
2452
  'praxis.pageBuilder.editor.hints.contextExample': 'e.g.: {"tenantId":"acme","locale":"pt-BR"}',
2431
2453
  'praxis.pageBuilder.editor.hints.stateValuesExample': 'e.g.: {"query":{"filter":{"year":2026}},"selection":{"department":"Finance"}}',
2432
2454
  'praxis.pageBuilder.editor.hints.layoutPreset': 'Choose an initial structural arrangement for the page. Then you can refine grouping and spans without losing layout intent.',
@@ -2439,6 +2461,26 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2439
2461
  'praxis.pageBuilder.editor.hints.schemaInitial': 'Define the initial value of this state path. This helps the page start in a consistent state even before remote connections and data.',
2440
2462
  'praxis.pageBuilder.editor.hints.templateJson': 'JSON templates are useful to generate complete derived objects, such as texts, summary cards or shell settings.',
2441
2463
  'praxis.pageBuilder.editor.hints.transformerOptions': 'Pass the registered transformer options here. Prefer lean JSON with only the parameters actually used by the runtime.',
2464
+ 'praxis.pageBuilder.editor.preview.layoutEyebrow': 'Layout template',
2465
+ 'praxis.pageBuilder.editor.preview.layoutFallbackDescription': 'Page organization preset.',
2466
+ 'praxis.pageBuilder.editor.preview.layoutSummary': '{{columns}} columns · {{gap}}',
2467
+ 'praxis.pageBuilder.editor.preview.defaultGap': 'default gap',
2468
+ 'praxis.pageBuilder.editor.preview.slotsChip': 'Slots: {{value}}',
2469
+ 'praxis.pageBuilder.editor.preview.requiredSlotsChip': 'Required: {{value}}',
2470
+ 'praxis.pageBuilder.editor.preview.none': 'none',
2471
+ 'praxis.pageBuilder.editor.preview.noRequiredSlots': 'No required slots',
2472
+ 'praxis.pageBuilder.editor.preview.mobileStacking': 'mobile {{value}}',
2473
+ 'praxis.pageBuilder.editor.preview.prefersMobileTabs': 'prefers mobile tabs',
2474
+ 'praxis.pageBuilder.editor.preview.hidesSecondaryContent': 'hides secondary content',
2475
+ 'praxis.pageBuilder.editor.preview.noDevicePolicy': 'No specific mobile policy',
2476
+ 'praxis.pageBuilder.editor.preview.inheritedTheme': 'Inherited theme',
2477
+ 'praxis.pageBuilder.editor.preview.inheritedThemeHelp': '{{description}} This theme is inherited automatically while the theme field stays on layout default.',
2478
+ 'praxis.pageBuilder.editor.preview.pinTheme': 'Pin theme',
2479
+ 'praxis.pageBuilder.editor.preview.explicitTheme': 'Explicit theme',
2480
+ 'praxis.pageBuilder.editor.preview.themeFallbackDescription': 'Page visual preset.',
2481
+ 'praxis.pageBuilder.editor.preview.shellChip': 'Shell: {{value}}',
2482
+ 'praxis.pageBuilder.editor.preview.chartsChip': 'Charts: {{value}}',
2483
+ 'praxis.pageBuilder.editor.preview.deviceCanvasHint': 'Existing canvas item overrides are preserved.',
2442
2484
  'praxis.pageBuilder.toolbar.preview': 'Preview',
2443
2485
  'praxis.pageBuilder.toolbar.exitPreview': 'Back to editing',
2444
2486
  'praxis.pageBuilder.builderMode.editing': 'Editing',
@@ -2453,6 +2495,7 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2453
2495
  'praxis.pageBuilder.premiumReadiness.actions.openWidgetConfig': 'Open widget',
2454
2496
  'praxis.pageBuilder.premiumReadiness.actions.focusChart': 'Focus chart',
2455
2497
  'praxis.pageBuilder.connections.toggle': 'Edit connections',
2498
+ 'praxis.pageBuilder.connections.toggleRecommended': 'Review suggested page interactions',
2456
2499
  'praxis.pageBuilder.connections.toggleAria': 'Edit connections',
2457
2500
  'praxis.pageBuilder.connections.close': 'Close connections',
2458
2501
  'praxis.pageBuilder.connections.title': 'Connections',
@@ -2478,8 +2521,16 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2478
2521
  'praxis.pageBuilder.connections.editor.segmentKind.input': 'Input',
2479
2522
  'praxis.pageBuilder.connections.editor.segmentKind.output': 'Output',
2480
2523
  'praxis.pageBuilder.connections.editor.segmentKind.state': 'State',
2524
+ 'praxis.pageBuilder.connections.editor.nestedBadge': 'Nested',
2525
+ 'praxis.pageBuilder.connections.editor.nestedPortAria': '{{port}} is a nested component port. Canonical path: {{path}}. The top-level widget remains the owner.',
2481
2526
  'praxis.pageBuilder.connections.editor.moveSegmentUpAria': 'Move segment earlier',
2482
2527
  'praxis.pageBuilder.connections.editor.moveSegmentDownAria': 'Move segment later',
2528
+ 'praxis.pageBuilder.connections.editor.portAria': '{{role}}: {{node}}, {{port}}. {{behavior}}.',
2529
+ 'praxis.pageBuilder.connections.editor.portRole.output': 'Source',
2530
+ 'praxis.pageBuilder.connections.editor.portRole.input': 'Target',
2531
+ 'praxis.pageBuilder.connections.editor.portRole.state': 'Page state',
2532
+ 'praxis.pageBuilder.connections.editor.portBehavior.output': 'drag or choose this event as a connection source',
2533
+ 'praxis.pageBuilder.connections.editor.portBehavior.input': 'drop or choose a compatible source for this target',
2483
2534
  'praxis.pageBuilder.connections.editor.zoomInAria': 'Zoom in',
2484
2535
  'praxis.pageBuilder.connections.editor.zoomOutAria': 'Zoom out',
2485
2536
  'praxis.pageBuilder.connections.editor.resetViewAria': 'Reset view',
@@ -2510,10 +2561,34 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2510
2561
  'praxis.pageBuilder.connections.inspector.empty': 'Nothing selected',
2511
2562
  'praxis.pageBuilder.connections.inspector.sourceEndpoint': 'Source endpoint',
2512
2563
  'praxis.pageBuilder.connections.inspector.targetEndpoint': 'Target endpoint',
2564
+ 'praxis.pageBuilder.connections.inspector.selected': 'Selected connection',
2565
+ 'praxis.pageBuilder.connections.inspector.technicalDetails': 'Technical details',
2566
+ 'praxis.pageBuilder.connections.inspector.connectionId': 'Connection id',
2567
+ 'praxis.pageBuilder.connections.inspector.intent': 'Intent',
2513
2568
  'praxis.pageBuilder.connections.inspector.rotation': 'Rotation',
2514
2569
  'praxis.pageBuilder.connections.inspector.showSegments': 'Show segments',
2515
2570
  'praxis.pageBuilder.connections.inspector.hideSegments': 'Hide segments',
2516
2571
  'praxis.pageBuilder.connections.inspector.focusWidget': 'Focus widget',
2572
+ 'praxis.pageBuilder.connections.semantic.masterDetail': 'Master-detail',
2573
+ 'praxis.pageBuilder.connections.semantic.captureState': 'Capture selection',
2574
+ 'praxis.pageBuilder.connections.semantic.hydrateTarget': 'Hydrate target',
2575
+ 'praxis.pageBuilder.connections.semantic.dispatchCommand': 'Run action',
2576
+ 'praxis.pageBuilder.connections.semantic.projectData': 'Project data',
2577
+ 'praxis.pageBuilder.connections.semantic.propagateEvent': 'Propagate event',
2578
+ 'praxis.pageBuilder.connections.semantic.compatiblePorts': 'Compatible ports',
2579
+ 'praxis.pageBuilder.connections.summary.writesState': 'updates',
2580
+ 'praxis.pageBuilder.connections.summary.hydratesTarget': 'hydrates',
2581
+ 'praxis.pageBuilder.connections.summary.dispatchesCommand': 'runs',
2582
+ 'praxis.pageBuilder.connections.summary.updatesTarget': 'updates',
2583
+ 'praxis.pageBuilder.connections.preview.deliversPath': 'Delivered value',
2584
+ 'praxis.pageBuilder.connections.preview.deliversTransformed': 'Delivered value',
2585
+ 'praxis.pageBuilder.connections.preview.transformedPayload': 'transformed payload',
2586
+ 'praxis.pageBuilder.connections.preview.deliversDefault': 'Delivered value',
2587
+ 'praxis.pageBuilder.connections.preview.sourcePayload': 'source payload',
2588
+ 'praxis.pageBuilder.connections.preview.deliversSelectedRowId': 'Delivered value: selected row id (payload.row.id).',
2589
+ 'praxis.pageBuilder.connections.feedback.createdTitle': 'Connection created',
2590
+ 'praxis.pageBuilder.connections.feedback.createdMasterDetail': 'Now selecting a row sends that row id to the form.',
2591
+ 'praxis.pageBuilder.connections.feedback.createdDefault': 'This connection is now part of the page interaction flow.',
2517
2592
  'praxis.pageBuilder.connections.dock.json': 'Praxis JSON',
2518
2593
  'praxis.pageBuilder.connections.dock.links': 'Links',
2519
2594
  'praxis.pageBuilder.connections.dock.derived': 'Derived',
@@ -2535,10 +2610,21 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2535
2610
  'praxis.pageBuilder.connections.validation.nestedPathNotDeclared': 'Nested path was not found in the current widget structure.',
2536
2611
  'praxis.pageBuilder.connections.validation.statePathNotDeclared': 'State path is not declared in page state values.',
2537
2612
  'praxis.pageBuilder.connections.suggestions.title': 'Smart suggestions',
2538
- 'praxis.pageBuilder.connections.suggestions.quickConnect': 'Quick connect',
2539
- 'praxis.pageBuilder.connections.suggestions.reasons.rowSelectionToId': 'Rows expose ids consumable as target inputs.',
2540
- 'praxis.pageBuilder.connections.suggestions.reasons.stateToInput': 'Page state can hydrate this input.',
2613
+ 'praxis.pageBuilder.connections.suggestions.recommendedTitle': 'Recommended connection',
2614
+ 'praxis.pageBuilder.connections.suggestions.quickConnect': 'Create connection',
2615
+ 'praxis.pageBuilder.connections.suggestions.connectSelectionToForm': 'Connect selection to form',
2616
+ 'praxis.pageBuilder.connections.suggestions.outcome.masterDetail': 'Selecting a row in {{source}} updates {{target}}.',
2617
+ 'praxis.pageBuilder.connections.suggestions.outcome.default': '{{source}} updates {{target}}.',
2618
+ 'praxis.pageBuilder.connections.suggestions.routeTechnical': 'Technical route: {{source}} -> {{target}}',
2619
+ 'praxis.pageBuilder.connections.suggestions.diagnostics.masterDetailMissingBoth': 'To create master-detail, the table needs a row selection output and the form needs a resourceId input.',
2620
+ 'praxis.pageBuilder.connections.suggestions.diagnostics.masterDetailMissingSelection': 'To update a form from a table, expose a rowClick, rowSelection, or selectionChange output on the table.',
2621
+ 'praxis.pageBuilder.connections.suggestions.diagnostics.masterDetailMissingResourceId': 'To update a form from a table, expose a resourceId input on the form.',
2622
+ 'praxis.pageBuilder.connections.suggestions.reasons.rowSelectionToId': 'Connects the selected row id to a detail input.',
2623
+ 'praxis.pageBuilder.connections.suggestions.reasons.stateToInput': 'Uses page state to keep the target hydrated.',
2541
2624
  'praxis.pageBuilder.connections.suggestions.reasons.compatiblePort': 'Compatible source and target ports.',
2625
+ 'praxis.pageBuilder.connections.suggestions.preview.rowIdToDetail': 'Will deliver the selected row id (payload.row.id) to the form.',
2626
+ 'praxis.pageBuilder.connections.suggestions.preview.stateToInput': 'Will deliver the current page state value.',
2627
+ 'praxis.pageBuilder.connections.suggestions.preview.sourcePayload': 'Will deliver the source payload unless you add a transform.',
2542
2628
  'praxis.pageBuilder.connections.trace.simulate': 'Simulate',
2543
2629
  'praxis.pageBuilder.connections.trace.title': 'Simulation trace',
2544
2630
  'praxis.pageBuilder.connections.trace.summary': 'Derived runtime propagation preview',
@@ -2601,6 +2687,9 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
2601
2687
  'praxis.pageBuilder.connections.details.transform': 'Transform',
2602
2688
  'praxis.pageBuilder.connections.details.policy': 'Policy',
2603
2689
  'praxis.pageBuilder.connections.details.diagnostics': 'Diagnostics',
2690
+ 'praxis.pageBuilder.connections.details.nestedOwnerPreserved': 'Top-level owner is preserved',
2691
+ 'praxis.pageBuilder.connections.details.nestedSourcePath': 'Source path: {{path}}',
2692
+ 'praxis.pageBuilder.connections.details.nestedTargetPath': 'Target path: {{path}}',
2604
2693
  'praxis.pageBuilder.connections.palette.insertComponent': 'Insert component',
2605
2694
  'praxis.pageBuilder.agentic.toggle': 'Create with AI',
2606
2695
  'praxis.pageBuilder.agentic.toggle.minimize': 'Minimize Praxis copilot',
@@ -2814,9 +2903,11 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2814
2903
  'praxis.pageBuilder.editor.status.review': 'Revise erros antes de salvar',
2815
2904
  'praxis.pageBuilder.editor.status.pending': 'Alterações pendentes',
2816
2905
  'praxis.pageBuilder.editor.status.clean': 'Sem alterações',
2906
+ 'praxis.pageBuilder.editor.status.validationIssue': 'Revisar: {{issue}}',
2817
2907
  'praxis.pageBuilder.editor.summary.layout': 'Layout: {{label}}',
2818
2908
  'praxis.pageBuilder.editor.summary.theme': 'Tema: {{label}}',
2819
2909
  'praxis.pageBuilder.editor.summary.shell': 'Shell: {{label}}',
2910
+ 'praxis.pageBuilder.editor.summary.canvasColumns': 'Canvas: {{count}} colunas',
2820
2911
  'praxis.pageBuilder.editor.fallback.manual': 'manual',
2821
2912
  'praxis.pageBuilder.editor.fallback.default': 'padrão',
2822
2913
  'praxis.pageBuilder.editor.fallback.neutral': 'neutra',
@@ -2834,6 +2925,8 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2834
2925
  'praxis.pageBuilder.editor.layout.cols': 'Colunas',
2835
2926
  'praxis.pageBuilder.editor.layout.rowHeight': 'Altura da linha (px)',
2836
2927
  'praxis.pageBuilder.editor.layout.gap': 'Espaçamento (Gap - px)',
2928
+ 'praxis.pageBuilder.editor.layout.rowUnit': 'Unidade da linha',
2929
+ 'praxis.pageBuilder.editor.layout.autoRows': 'Linhas automáticas',
2837
2930
  'praxis.pageBuilder.editor.layout.presetSection': 'Predefinição de Layout (Preset)',
2838
2931
  'praxis.pageBuilder.editor.layout.presetHelp': 'Use predefinições para acelerar uma organização consistente e depois refine apenas o necessário.',
2839
2932
  'praxis.pageBuilder.editor.layout.layoutPreset': 'Predefinição de layout',
@@ -2916,6 +3009,14 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2916
3009
  'praxis.pageBuilder.editor.state.optionsJson': 'Opções (JSON)',
2917
3010
  'praxis.pageBuilder.editor.apply': 'Aplicar',
2918
3011
  'praxis.pageBuilder.editor.errors.invalidJson': 'JSON inválido',
3012
+ 'praxis.pageBuilder.editor.errors.canvasInvalid': 'Canvas inválido',
3013
+ 'praxis.pageBuilder.editor.errors.contextInvalid': 'Contexto inválido',
3014
+ 'praxis.pageBuilder.editor.errors.stateInvalid': 'Estado inválido',
3015
+ 'praxis.pageBuilder.editor.errors.duplicateGroupIds': 'IDs de grupo duplicados',
3016
+ 'praxis.pageBuilder.editor.errors.invalidTabs': 'Abas inválidas',
3017
+ 'praxis.pageBuilder.editor.errors.duplicateWidgetKeys': 'Chaves de widgets duplicadas',
3018
+ 'praxis.pageBuilder.editor.errors.invalidColumns': 'Colunas inválidas',
3019
+ 'praxis.pageBuilder.editor.errors.invalidOverrides': 'Sobrescritas inválidas',
2919
3020
  'praxis.pageBuilder.editor.hints.contextExample': 'Ex.: {"tenantId":"acme","locale":"pt-BR"}',
2920
3021
  'praxis.pageBuilder.editor.hints.stateValuesExample': 'Ex.: {"query":{"filter":{"year":2026}},"selection":{"department":"Finance"}}',
2921
3022
  'praxis.pageBuilder.editor.hints.layoutPreset': 'Escolha um arranjo estrutural inicial para a página. Depois você pode refinar agrupamentos e vãos (spans) sem perder a intenção de layout.',
@@ -2928,6 +3029,26 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2928
3029
  'praxis.pageBuilder.editor.hints.schemaInitial': 'Defina o valor inicial desse caminho de estado. Isso ajuda a página a nascer em um estado consistente mesmo antes de conexões e dados remotos.',
2929
3030
  'praxis.pageBuilder.editor.hints.templateJson': 'Modelos em JSON são úteis para gerar objetos derivados completos, como textos, cartões de resumo ou configurações de shell.',
2930
3031
  'praxis.pageBuilder.editor.hints.transformerOptions': 'Passe aqui as opções do transformador registrado. Prefira JSON enxuto com os parâmetros realmente usados pelo runtime.',
3032
+ 'praxis.pageBuilder.editor.preview.layoutEyebrow': 'Template de layout',
3033
+ 'praxis.pageBuilder.editor.preview.layoutFallbackDescription': 'Predefinição de organização da página.',
3034
+ 'praxis.pageBuilder.editor.preview.layoutSummary': '{{columns}} colunas · {{gap}}',
3035
+ 'praxis.pageBuilder.editor.preview.defaultGap': 'gap padrão',
3036
+ 'praxis.pageBuilder.editor.preview.slotsChip': 'Slots: {{value}}',
3037
+ 'praxis.pageBuilder.editor.preview.requiredSlotsChip': 'Obrigatórios: {{value}}',
3038
+ 'praxis.pageBuilder.editor.preview.none': 'nenhum',
3039
+ 'praxis.pageBuilder.editor.preview.noRequiredSlots': 'Nenhum slot obrigatório',
3040
+ 'praxis.pageBuilder.editor.preview.mobileStacking': 'mobile {{value}}',
3041
+ 'praxis.pageBuilder.editor.preview.prefersMobileTabs': 'prefere abas no mobile',
3042
+ 'praxis.pageBuilder.editor.preview.hidesSecondaryContent': 'oculta conteúdo secundário',
3043
+ 'praxis.pageBuilder.editor.preview.noDevicePolicy': 'Sem política mobile específica',
3044
+ 'praxis.pageBuilder.editor.preview.inheritedTheme': 'Tema herdado',
3045
+ 'praxis.pageBuilder.editor.preview.inheritedThemeHelp': '{{description}} Este tema é herdado automaticamente enquanto o campo de tema permanece no padrão do layout.',
3046
+ 'praxis.pageBuilder.editor.preview.pinTheme': 'Fixar tema',
3047
+ 'praxis.pageBuilder.editor.preview.explicitTheme': 'Tema explícito',
3048
+ 'praxis.pageBuilder.editor.preview.themeFallbackDescription': 'Predefinição visual da página.',
3049
+ 'praxis.pageBuilder.editor.preview.shellChip': 'Shell: {{value}}',
3050
+ 'praxis.pageBuilder.editor.preview.chartsChip': 'Gráficos: {{value}}',
3051
+ 'praxis.pageBuilder.editor.preview.deviceCanvasHint': 'Sobrescritas existentes dos itens do canvas são preservadas.',
2931
3052
  'praxis.pageBuilder.toolbar.preview': 'Pré-visualizar',
2932
3053
  'praxis.pageBuilder.toolbar.exitPreview': 'Voltar para edição',
2933
3054
  'praxis.pageBuilder.builderMode.editing': 'Edição',
@@ -2942,6 +3063,7 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2942
3063
  'praxis.pageBuilder.premiumReadiness.actions.openWidgetConfig': 'Abrir widget',
2943
3064
  'praxis.pageBuilder.premiumReadiness.actions.focusChart': 'Focar gráfico',
2944
3065
  'praxis.pageBuilder.connections.toggle': 'Editar conexões',
3066
+ 'praxis.pageBuilder.connections.toggleRecommended': 'Revisar interações sugeridas da página',
2945
3067
  'praxis.pageBuilder.connections.toggleAria': 'Editar conexões',
2946
3068
  'praxis.pageBuilder.connections.close': 'Fechar conexões',
2947
3069
  'praxis.pageBuilder.connections.title': 'Conexões',
@@ -2967,8 +3089,16 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2967
3089
  'praxis.pageBuilder.connections.editor.segmentKind.input': 'Entrada',
2968
3090
  'praxis.pageBuilder.connections.editor.segmentKind.output': 'Saída',
2969
3091
  'praxis.pageBuilder.connections.editor.segmentKind.state': 'Estado',
3092
+ 'praxis.pageBuilder.connections.editor.nestedBadge': 'Aninhado',
3093
+ 'praxis.pageBuilder.connections.editor.nestedPortAria': '{{port}} é uma porta de componente aninhado. Caminho canônico: {{path}}. O widget top-level continua como dono.',
2970
3094
  'praxis.pageBuilder.connections.editor.moveSegmentUpAria': 'Mover segmento para antes',
2971
3095
  'praxis.pageBuilder.connections.editor.moveSegmentDownAria': 'Mover segmento para depois',
3096
+ 'praxis.pageBuilder.connections.editor.portAria': '{{role}}: {{node}}, {{port}}. {{behavior}}.',
3097
+ 'praxis.pageBuilder.connections.editor.portRole.output': 'Origem',
3098
+ 'praxis.pageBuilder.connections.editor.portRole.input': 'Destino',
3099
+ 'praxis.pageBuilder.connections.editor.portRole.state': 'Estado da página',
3100
+ 'praxis.pageBuilder.connections.editor.portBehavior.output': 'arraste ou escolha este evento como origem da conexão',
3101
+ 'praxis.pageBuilder.connections.editor.portBehavior.input': 'solte ou escolha uma origem compatível para este destino',
2972
3102
  'praxis.pageBuilder.connections.editor.zoomInAria': 'Aproximar',
2973
3103
  'praxis.pageBuilder.connections.editor.zoomOutAria': 'Afastar',
2974
3104
  'praxis.pageBuilder.connections.editor.resetViewAria': 'Redefinir visualização',
@@ -2999,10 +3129,34 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
2999
3129
  'praxis.pageBuilder.connections.inspector.empty': 'Nada selecionado',
3000
3130
  'praxis.pageBuilder.connections.inspector.sourceEndpoint': 'Endpoint de origem',
3001
3131
  'praxis.pageBuilder.connections.inspector.targetEndpoint': 'Endpoint de destino',
3132
+ 'praxis.pageBuilder.connections.inspector.selected': 'Conexão selecionada',
3133
+ 'praxis.pageBuilder.connections.inspector.technicalDetails': 'Detalhes técnicos',
3134
+ 'praxis.pageBuilder.connections.inspector.connectionId': 'ID da conexão',
3135
+ 'praxis.pageBuilder.connections.inspector.intent': 'Intenção',
3002
3136
  'praxis.pageBuilder.connections.inspector.rotation': 'Rotação',
3003
3137
  'praxis.pageBuilder.connections.inspector.showSegments': 'Mostrar segmentos',
3004
3138
  'praxis.pageBuilder.connections.inspector.hideSegments': 'Ocultar segmentos',
3005
3139
  'praxis.pageBuilder.connections.inspector.focusWidget': 'Focar widget',
3140
+ 'praxis.pageBuilder.connections.semantic.masterDetail': 'Mestre-detalhe',
3141
+ 'praxis.pageBuilder.connections.semantic.captureState': 'Capturar seleção',
3142
+ 'praxis.pageBuilder.connections.semantic.hydrateTarget': 'Atualizar destino',
3143
+ 'praxis.pageBuilder.connections.semantic.dispatchCommand': 'Executar ação',
3144
+ 'praxis.pageBuilder.connections.semantic.projectData': 'Projetar dados',
3145
+ 'praxis.pageBuilder.connections.semantic.propagateEvent': 'Propagar evento',
3146
+ 'praxis.pageBuilder.connections.semantic.compatiblePorts': 'Portas compatíveis',
3147
+ 'praxis.pageBuilder.connections.summary.writesState': 'atualiza',
3148
+ 'praxis.pageBuilder.connections.summary.hydratesTarget': 'atualiza',
3149
+ 'praxis.pageBuilder.connections.summary.dispatchesCommand': 'executa',
3150
+ 'praxis.pageBuilder.connections.summary.updatesTarget': 'atualiza',
3151
+ 'praxis.pageBuilder.connections.preview.deliversPath': 'Valor entregue',
3152
+ 'praxis.pageBuilder.connections.preview.deliversTransformed': 'Valor entregue',
3153
+ 'praxis.pageBuilder.connections.preview.transformedPayload': 'payload transformado',
3154
+ 'praxis.pageBuilder.connections.preview.deliversDefault': 'Valor entregue',
3155
+ 'praxis.pageBuilder.connections.preview.sourcePayload': 'payload da origem',
3156
+ 'praxis.pageBuilder.connections.preview.deliversSelectedRowId': 'Valor entregue: ID da linha selecionada (payload.row.id).',
3157
+ 'praxis.pageBuilder.connections.feedback.createdTitle': 'Conexão criada',
3158
+ 'praxis.pageBuilder.connections.feedback.createdMasterDetail': 'Agora, ao selecionar uma linha, o formulário recebe o ID dessa linha.',
3159
+ 'praxis.pageBuilder.connections.feedback.createdDefault': 'Esta conexão agora faz parte do fluxo de interação da página.',
3006
3160
  'praxis.pageBuilder.connections.dock.json': 'Praxis JSON',
3007
3161
  'praxis.pageBuilder.connections.dock.links': 'Links',
3008
3162
  'praxis.pageBuilder.connections.dock.derived': 'Derivado',
@@ -3024,10 +3178,21 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
3024
3178
  'praxis.pageBuilder.connections.validation.nestedPathNotDeclared': 'O nestedPath não foi encontrado na estrutura atual do widget.',
3025
3179
  'praxis.pageBuilder.connections.validation.statePathNotDeclared': 'O caminho de estado não está declarado nos valores de estado da página.',
3026
3180
  'praxis.pageBuilder.connections.suggestions.title': 'Sugestões inteligentes',
3027
- 'praxis.pageBuilder.connections.suggestions.quickConnect': 'Conectar rápido',
3028
- 'praxis.pageBuilder.connections.suggestions.reasons.rowSelectionToId': 'As linhas expõem IDs consumíveis por entradas de destino.',
3029
- 'praxis.pageBuilder.connections.suggestions.reasons.stateToInput': 'O estado da página pode hidratar esta entrada.',
3181
+ 'praxis.pageBuilder.connections.suggestions.recommendedTitle': 'Conexão recomendada',
3182
+ 'praxis.pageBuilder.connections.suggestions.quickConnect': 'Criar conexão',
3183
+ 'praxis.pageBuilder.connections.suggestions.connectSelectionToForm': 'Conectar seleção ao formulário',
3184
+ 'praxis.pageBuilder.connections.suggestions.outcome.masterDetail': 'Selecionar uma linha em {{source}} atualiza {{target}}.',
3185
+ 'praxis.pageBuilder.connections.suggestions.outcome.default': '{{source}} atualiza {{target}}.',
3186
+ 'praxis.pageBuilder.connections.suggestions.routeTechnical': 'Rota técnica: {{source}} -> {{target}}',
3187
+ 'praxis.pageBuilder.connections.suggestions.diagnostics.masterDetailMissingBoth': 'Para criar mestre-detalhe, a tabela precisa expor uma saída de seleção de linha e o formulário precisa expor a entrada resourceId.',
3188
+ 'praxis.pageBuilder.connections.suggestions.diagnostics.masterDetailMissingSelection': 'Para atualizar um formulário a partir de uma tabela, exponha uma saída rowClick, rowSelection ou selectionChange na tabela.',
3189
+ 'praxis.pageBuilder.connections.suggestions.diagnostics.masterDetailMissingResourceId': 'Para atualizar um formulário a partir de uma tabela, exponha a entrada resourceId no formulário.',
3190
+ 'praxis.pageBuilder.connections.suggestions.reasons.rowSelectionToId': 'Conecta o ID da linha selecionada a uma entrada de detalhe.',
3191
+ 'praxis.pageBuilder.connections.suggestions.reasons.stateToInput': 'Usa o estado da página para manter o destino atualizado.',
3030
3192
  'praxis.pageBuilder.connections.suggestions.reasons.compatiblePort': 'Portas de origem e destino compatíveis.',
3193
+ 'praxis.pageBuilder.connections.suggestions.preview.rowIdToDetail': 'Entregará o ID da linha selecionada (payload.row.id) ao formulário.',
3194
+ 'praxis.pageBuilder.connections.suggestions.preview.stateToInput': 'Entregará o valor atual do estado da página.',
3195
+ 'praxis.pageBuilder.connections.suggestions.preview.sourcePayload': 'Entregará o payload da origem, a menos que você adicione uma transformação.',
3031
3196
  'praxis.pageBuilder.connections.trace.simulate': 'Simular',
3032
3197
  'praxis.pageBuilder.connections.trace.title': 'Trace de simulação',
3033
3198
  'praxis.pageBuilder.connections.trace.summary': 'Prévia derivada da propagação em runtime',
@@ -3090,6 +3255,9 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
3090
3255
  'praxis.pageBuilder.connections.details.transform': 'Transformação',
3091
3256
  'praxis.pageBuilder.connections.details.policy': 'Política',
3092
3257
  'praxis.pageBuilder.connections.details.diagnostics': 'Diagnósticos',
3258
+ 'praxis.pageBuilder.connections.details.nestedOwnerPreserved': 'O dono top-level é preservado',
3259
+ 'praxis.pageBuilder.connections.details.nestedSourcePath': 'Caminho da origem: {{path}}',
3260
+ 'praxis.pageBuilder.connections.details.nestedTargetPath': 'Caminho do destino: {{path}}',
3093
3261
  'praxis.pageBuilder.connections.palette.insertComponent': 'Inserir componente',
3094
3262
  'praxis.pageBuilder.agentic.toggle': 'Criar com IA',
3095
3263
  'praxis.pageBuilder.agentic.toggle.minimize': 'Minimizar copiloto Praxis',
@@ -3541,18 +3709,75 @@ function inferConnectionIntent(source, target) {
3541
3709
  return 'event-propagation';
3542
3710
  }
3543
3711
  function buildCompositionLinkFromPorts(source, target, links) {
3712
+ const transform = inferCanonicalTransform(source, target);
3544
3713
  return {
3545
3714
  id: uniqueConnectionLinkId(source, target, links),
3546
3715
  from: clone$1(source.endpoint),
3547
3716
  to: clone$1(target.endpoint),
3548
3717
  intent: inferConnectionIntent(source, target),
3718
+ ...(transform ? { transform } : {}),
3549
3719
  metadata: {
3550
3720
  source: 'native-composition-link',
3551
3721
  label: `${source.nodeId}.${source.label} -> ${target.nodeId === CONNECTION_EDITOR_STATE_NODE_ID ? 'state' : target.nodeId}.${target.label}`,
3552
3722
  },
3553
3723
  };
3554
3724
  }
3725
+ function inferCanonicalTransform(source, target) {
3726
+ if (!isTableRowSelectionToFormResourceId(source, target)) {
3727
+ return undefined;
3728
+ }
3729
+ return {
3730
+ id: `${source.nodeId}-${target.nodeId}-row-id-projection`,
3731
+ version: '2.0',
3732
+ phase: 'link-propagation',
3733
+ mode: 'single-value',
3734
+ steps: [
3735
+ {
3736
+ id: 'pick-selected-row-id',
3737
+ kind: 'pick-path',
3738
+ phase: 'link-propagation',
3739
+ config: { path: 'payload.row.id' },
3740
+ output: {
3741
+ semanticKind: 'selection',
3742
+ cardinality: 'one',
3743
+ stableShape: true,
3744
+ materializationHint: 'replace',
3745
+ description: 'Projects the selected table row id into the detail form resourceId input.',
3746
+ },
3747
+ },
3748
+ ],
3749
+ output: {
3750
+ semanticKind: 'selection',
3751
+ cardinality: 'one',
3752
+ stableShape: true,
3753
+ materializationHint: 'replace',
3754
+ },
3755
+ debugLabel: 'table row selection id -> form resourceId',
3756
+ };
3757
+ }
3758
+ function isTableRowSelectionToFormResourceId(source, target) {
3759
+ if (source.kind !== 'output' || target.kind !== 'input')
3760
+ return false;
3761
+ if (source.endpoint.kind !== 'component-port' || target.endpoint.kind !== 'component-port')
3762
+ return false;
3763
+ const sourceComponent = String(source.endpoint.ref.componentType ?? '').toLowerCase();
3764
+ const targetComponent = String(target.endpoint.ref.componentType ?? '').toLowerCase();
3765
+ const sourcePort = source.endpoint.ref.port.toLowerCase();
3766
+ const targetPort = target.endpoint.ref.port.toLowerCase();
3767
+ return sourceComponent.includes('table')
3768
+ && targetComponent.includes('dynamic-form')
3769
+ && /^(rowclick|rowselection|selectionchange)$/.test(sourcePort)
3770
+ && targetPort === 'resourceid';
3771
+ }
3555
3772
  function deriveConnectionEditorSuggestions(graph, limit = 5) {
3773
+ return buildConnectionEditorSuggestions(graph).slice(0, limit);
3774
+ }
3775
+ function deriveRecommendedMasterDetailSuggestion(graph) {
3776
+ return buildConnectionEditorSuggestions(graph)
3777
+ .find((suggestion) => isTableRowSelectionToFormResourceId(suggestion.source, suggestion.target))
3778
+ ?? null;
3779
+ }
3780
+ function buildConnectionEditorSuggestions(graph) {
3556
3781
  const connectedPairs = new Set(graph.connections.map((connection) => connection.fromPort && connection.toPort
3557
3782
  ? `${endpointKey(connection.fromPort.endpoint)}->${endpointKey(connection.toPort.endpoint)}`
3558
3783
  : ''));
@@ -3575,8 +3800,7 @@ function deriveConnectionEditorSuggestions(graph, limit = 5) {
3575
3800
  score,
3576
3801
  };
3577
3802
  }))
3578
- .sort((a, b) => b.score - a.score || a.id.localeCompare(b.id))
3579
- .slice(0, limit);
3803
+ .sort((a, b) => b.score - a.score || a.id.localeCompare(b.id));
3580
3804
  }
3581
3805
  function uniqueConnectionLinkId(source, target, links) {
3582
3806
  const base = `${source.nodeId}-${source.label}-to-${target.nodeId}-${target.label}`
@@ -4513,14 +4737,17 @@ class ConnectionEditorComponent {
4513
4737
  selectedWidgetId = signal(null, ...(ngDevMode ? [{ debugName: "selectedWidgetId" }] : /* istanbul ignore next */ []));
4514
4738
  selectedLinkId = signal(null, ...(ngDevMode ? [{ debugName: "selectedLinkId" }] : /* istanbul ignore next */ []));
4515
4739
  recentLinkId = signal(null, ...(ngDevMode ? [{ debugName: "recentLinkId" }] : /* istanbul ignore next */ []));
4740
+ lastCreatedLinkId = signal(null, ...(ngDevMode ? [{ debugName: "lastCreatedLinkId" }] : /* istanbul ignore next */ []));
4516
4741
  hoveredLinkId = signal(null, ...(ngDevMode ? [{ debugName: "hoveredLinkId" }] : /* istanbul ignore next */ []));
4517
4742
  expandedNodeId = signal(null, ...(ngDevMode ? [{ debugName: "expandedNodeId" }] : /* istanbul ignore next */ []));
4518
4743
  activeDockTab = signal('links', ...(ngDevMode ? [{ debugName: "activeDockTab" }] : /* istanbul ignore next */ []));
4519
- dockCollapsed = signal(false, ...(ngDevMode ? [{ debugName: "dockCollapsed" }] : /* istanbul ignore next */ []));
4744
+ dockCollapsed = signal(true, ...(ngDevMode ? [{ debugName: "dockCollapsed" }] : /* istanbul ignore next */ []));
4520
4745
  traceEnabled = signal(false, ...(ngDevMode ? [{ debugName: "traceEnabled" }] : /* istanbul ignore next */ []));
4521
4746
  traceStepIndex = signal(0, ...(ngDevMode ? [{ debugName: "traceStepIndex" }] : /* istanbul ignore next */ []));
4522
4747
  traceSourceNodeId = signal(null, ...(ngDevMode ? [{ debugName: "traceSourceNodeId" }] : /* istanbul ignore next */ []));
4523
4748
  selectedPort = signal(null, ...(ngDevMode ? [{ debugName: "selectedPort" }] : /* istanbul ignore next */ []));
4749
+ hoveredNodeId = signal(null, ...(ngDevMode ? [{ debugName: "hoveredNodeId" }] : /* istanbul ignore next */ []));
4750
+ visualDensity = signal('guided', ...(ngDevMode ? [{ debugName: "visualDensity" }] : /* istanbul ignore next */ []));
4524
4751
  globalActionPayloadError = signal(null, ...(ngDevMode ? [{ debugName: "globalActionPayloadError" }] : /* istanbul ignore next */ []));
4525
4752
  pendingSegmentState = signal(null, ...(ngDevMode ? [{ debugName: "pendingSegmentState" }] : /* istanbul ignore next */ []));
4526
4753
  dragState = signal(null, ...(ngDevMode ? [{ debugName: "dragState" }] : /* istanbul ignore next */ []));
@@ -4543,7 +4770,13 @@ class ConnectionEditorComponent {
4543
4770
  fitViewportOnOpen = effect(() => {
4544
4771
  if (!this.open())
4545
4772
  return;
4546
- window.setTimeout(() => this.resetViewport(), 0);
4773
+ window.setTimeout(() => {
4774
+ this.resetViewport();
4775
+ if (this.open() && this.visualDensity() === 'guided') {
4776
+ this.expandedNodeId.set(null);
4777
+ this.selectedPort.set(null);
4778
+ }
4779
+ }, 0);
4547
4780
  }, ...(ngDevMode ? [{ debugName: "fitViewportOnOpen" }] : /* istanbul ignore next */ []));
4548
4781
  filters = [
4549
4782
  { id: 'all', label: this.tx('connections.filters.all', 'All') },
@@ -4594,7 +4827,36 @@ class ConnectionEditorComponent {
4594
4827
  stateNodeTitle: this.tx('connections.editor.stateNode', 'Page state'),
4595
4828
  globalActionIds: this.availableGlobalActionIds(),
4596
4829
  }), ...(ngDevMode ? [{ debugName: "editorGraph" }] : /* istanbul ignore next */ []));
4597
- editorNodes = computed(() => autoArrangeConnectionEditorGraph(this.editorGraph()).nodes.map((node) => this.applyNodeOffset(this.applyNodeRotation(applyConnectionEditorPortOrder(node, this.portOrder())))), ...(ngDevMode ? [{ debugName: "editorNodes" }] : /* istanbul ignore next */ []));
4830
+ connectedNodeIds = computed(() => {
4831
+ const ids = new Set();
4832
+ for (const connection of this.editorGraph().connections) {
4833
+ if (connection.fromNode)
4834
+ ids.add(connection.fromNode);
4835
+ if (connection.toNode)
4836
+ ids.add(connection.toNode);
4837
+ }
4838
+ return ids;
4839
+ }, ...(ngDevMode ? [{ debugName: "connectedNodeIds" }] : /* istanbul ignore next */ []));
4840
+ connectedPortIds = computed(() => {
4841
+ const ids = new Set();
4842
+ for (const connection of this.editorGraph().connections) {
4843
+ if (connection.fromPort)
4844
+ ids.add(connection.fromPort.id);
4845
+ if (connection.toPort)
4846
+ ids.add(connection.toPort.id);
4847
+ }
4848
+ return ids;
4849
+ }, ...(ngDevMode ? [{ debugName: "connectedPortIds" }] : /* istanbul ignore next */ []));
4850
+ editorNodes = computed(() => {
4851
+ const arranged = autoArrangeConnectionEditorGraph(this.editorGraph()).nodes.map((node) => this.applyNodeOffset(this.applyNodeRotation(applyConnectionEditorPortOrder(node, this.portOrder()))));
4852
+ if (this.visualDensity() === 'full')
4853
+ return arranged;
4854
+ const connectedNodeIds = this.connectedNodeIds();
4855
+ return arranged.filter((node) => node.id !== CONNECTION_EDITOR_GLOBAL_ACTION_NODE_ID
4856
+ || connectedNodeIds.has(node.id)
4857
+ || this.selectedWidgetId() === node.id
4858
+ || this.hoveredNodeId() === node.id);
4859
+ }, ...(ngDevMode ? [{ debugName: "editorNodes" }] : /* istanbul ignore next */ []));
4598
4860
  navigationBounds = computed(() => this.connectionEditorNavigationBounds(), ...(ngDevMode ? [{ debugName: "navigationBounds" }] : /* istanbul ignore next */ []));
4599
4861
  minimapViewBox = computed(() => {
4600
4862
  const bounds = this.navigationBounds();
@@ -4633,6 +4895,26 @@ class ConnectionEditorComponent {
4633
4895
  return ids;
4634
4896
  }, ...(ngDevMode ? [{ debugName: "modeMatchedPortIds" }] : /* istanbul ignore next */ []));
4635
4897
  smartSuggestions = computed(() => deriveConnectionEditorSuggestions(this.editorGraph(), 5), ...(ngDevMode ? [{ debugName: "smartSuggestions" }] : /* istanbul ignore next */ []));
4898
+ recommendedMasterDetailSuggestion = computed(() => deriveRecommendedMasterDetailSuggestion(this.editorGraph()), ...(ngDevMode ? [{ debugName: "recommendedMasterDetailSuggestion" }] : /* istanbul ignore next */ []));
4899
+ masterDetailReadinessDiagnostic = computed(() => {
4900
+ if (this.recommendedMasterDetailSuggestion())
4901
+ return null;
4902
+ const nodes = this.editorNodes();
4903
+ const hasSelectionOutput = nodes.some((node) => node.outputs.some((port) => this.isTableSelectionOutput(port)));
4904
+ const hasResourceIdInput = nodes.some((node) => node.inputs.some((port) => this.isFormResourceIdInput(port)));
4905
+ const hasTable = nodes.some((node) => [...node.outputs, ...node.inputs, ...node.states].some((port) => this.portComponentType(port).includes('table')));
4906
+ const hasForm = nodes.some((node) => [...node.outputs, ...node.inputs, ...node.states].some((port) => this.portComponentType(port).includes('dynamic-form')));
4907
+ if (hasTable && hasForm && !hasSelectionOutput && !hasResourceIdInput) {
4908
+ return this.tx('connections.suggestions.diagnostics.masterDetailMissingBoth', 'To create master-detail, the table needs a row selection output and the form needs a resourceId input.');
4909
+ }
4910
+ if (hasTable && hasForm && !hasSelectionOutput) {
4911
+ return this.tx('connections.suggestions.diagnostics.masterDetailMissingSelection', 'To update a form from a table, expose a rowClick, rowSelection, or selectionChange output on the table.');
4912
+ }
4913
+ if (hasTable && hasForm && !hasResourceIdInput) {
4914
+ return this.tx('connections.suggestions.diagnostics.masterDetailMissingResourceId', 'To update a form from a table, expose a resourceId input on the form.');
4915
+ }
4916
+ return null;
4917
+ }, ...(ngDevMode ? [{ debugName: "masterDetailReadinessDiagnostic" }] : /* istanbul ignore next */ []));
4636
4918
  traceSteps = computed(() => {
4637
4919
  const selectedLinkId = this.selectedLinkId();
4638
4920
  if (selectedLinkId)
@@ -4811,11 +5093,11 @@ class ConnectionEditorComponent {
4811
5093
  this.selectedPort.set(null);
4812
5094
  if (nodeId === this.stateNodeId) {
4813
5095
  this.selectedWidgetId.set(null);
4814
- this.expandedNodeId.update((current) => (current === nodeId ? null : nodeId));
5096
+ this.updateAutoExpandedNode(nodeId);
4815
5097
  return;
4816
5098
  }
4817
5099
  this.selectedWidgetId.update((current) => (current === nodeId ? null : nodeId));
4818
- this.expandedNodeId.update((current) => (current === nodeId ? null : nodeId));
5100
+ this.updateAutoExpandedNode(nodeId);
4819
5101
  this.selectedLinkId.set(null);
4820
5102
  }
4821
5103
  selectSegment(port, event) {
@@ -4910,7 +5192,20 @@ class ConnectionEditorComponent {
4910
5192
  this.traceStepIndex.set(0);
4911
5193
  this.scrollActiveModeIntoView();
4912
5194
  }
5195
+ toggleVisualDensity(event) {
5196
+ event.preventDefault();
5197
+ event.stopPropagation();
5198
+ this.visualDensity.update((density) => density === 'guided' ? 'full' : 'guided');
5199
+ }
5200
+ visualDensityAriaLabel() {
5201
+ return this.visualDensity() === 'guided'
5202
+ ? this.tx('connections.mode.showFullSchemaAria', 'Show the complete connection schema')
5203
+ : this.tx('connections.mode.showGuidedViewAria', 'Show the guided connection view');
5204
+ }
4913
5205
  activeModeStatus() {
5206
+ if (this.visualDensity() === 'guided' && this.activeMode() === 'all') {
5207
+ return this.tx('connections.mode.statusGuided', 'Guided view - links and suggestions');
5208
+ }
4914
5209
  const mode = this.activeMode();
4915
5210
  if (mode === 'data') {
4916
5211
  return this.tx('connections.mode.statusData', 'Data paths only');
@@ -5147,11 +5442,11 @@ class ConnectionEditorComponent {
5147
5442
  this.selectedPort.set(null);
5148
5443
  if (current.nodeId === this.stateNodeId) {
5149
5444
  this.selectedWidgetId.set(null);
5150
- this.expandedNodeId.update((expandedNodeId) => (expandedNodeId === current.nodeId ? null : current.nodeId));
5445
+ this.updateAutoExpandedNode(current.nodeId);
5151
5446
  }
5152
5447
  else {
5153
5448
  this.selectedWidgetId.update((selectedWidgetId) => (selectedWidgetId === current.nodeId ? null : current.nodeId));
5154
- this.expandedNodeId.update((expandedNodeId) => (expandedNodeId === current.nodeId ? null : current.nodeId));
5449
+ this.updateAutoExpandedNode(current.nodeId);
5155
5450
  }
5156
5451
  this.selectedLinkId.set(null);
5157
5452
  }
@@ -5395,6 +5690,9 @@ class ConnectionEditorComponent {
5395
5690
  links: links.filter((link) => link.id !== linkId),
5396
5691
  };
5397
5692
  this.commitPageChange(next, null);
5693
+ if (this.lastCreatedLinkId() === linkId) {
5694
+ this.lastCreatedLinkId.set(null);
5695
+ }
5398
5696
  }
5399
5697
  undoHistory(event) {
5400
5698
  event.preventDefault();
@@ -5495,6 +5793,19 @@ class ConnectionEditorComponent {
5495
5793
  const trimmed = label.trim();
5496
5794
  return trimmed.length > 13 ? `${trimmed.slice(0, 10)}...` : trimmed;
5497
5795
  }
5796
+ isNestedPort(port) {
5797
+ return !!port.nestedPath?.length;
5798
+ }
5799
+ nestedPortPathText(port) {
5800
+ return this.formatNestedPath(port.nestedPath);
5801
+ }
5802
+ portDescription(port) {
5803
+ if (!this.isNestedPort(port))
5804
+ return port.label;
5805
+ return this.tx('connections.editor.nestedPortAria', '{{port}} is a nested component port. Canonical path: {{path}}. The top-level widget remains the owner.')
5806
+ .replace('{{port}}', port.label)
5807
+ .replace('{{path}}', this.nestedPortPathText(port));
5808
+ }
5498
5809
  segmentKindGlyph(kind) {
5499
5810
  if (kind === 'input')
5500
5811
  return 'v';
@@ -5532,6 +5843,25 @@ class ConnectionEditorComponent {
5532
5843
  return this.tx('connections.editor.segmentKind.state', 'State');
5533
5844
  }
5534
5845
  }
5846
+ connectionHasNestedEndpoint(connection) {
5847
+ return !!connection.fromPort?.nestedPath?.length || !!connection.toPort?.nestedPath?.length;
5848
+ }
5849
+ connectionNestedSummary(connection) {
5850
+ const parts = [];
5851
+ if (connection.fromPort?.nestedPath?.length) {
5852
+ parts.push(this.tx('connections.details.nestedSourcePath', 'Source path: {{path}}').replace('{{path}}', this.nestedPortPathText(connection.fromPort)));
5853
+ }
5854
+ if (connection.toPort?.nestedPath?.length) {
5855
+ parts.push(this.tx('connections.details.nestedTargetPath', 'Target path: {{path}}').replace('{{path}}', this.nestedPortPathText(connection.toPort)));
5856
+ }
5857
+ return parts.join(' · ');
5858
+ }
5859
+ formatNestedPath(path) {
5860
+ return (path ?? []).map((segment) => {
5861
+ const identity = segment.key ?? segment.id ?? (segment.index !== undefined ? String(segment.index) : null);
5862
+ return identity ? `${segment.kind}:${identity}` : segment.kind;
5863
+ }).join(' / ');
5864
+ }
5535
5865
  connectionHasErrors(connection) {
5536
5866
  return connection.diagnostics.some((diagnostic) => diagnostic.severity === 'error');
5537
5867
  }
@@ -5558,6 +5888,61 @@ class ConnectionEditorComponent {
5558
5888
  isModeDimmedPort(port) {
5559
5889
  return this.hasModeFocus() && !this.modeMatchedPortIds().has(port.id);
5560
5890
  }
5891
+ isGuidedQuietNode(node) {
5892
+ if (this.visualDensity() === 'full')
5893
+ return false;
5894
+ if (node.id === this.hoveredNodeId() || node.id === this.selectedWidgetId())
5895
+ return false;
5896
+ if (this.nodeHasCompatiblePreviewPort(node))
5897
+ return false;
5898
+ return !this.connectedNodeIds().has(node.id) && this.editorGraph().connections.length > 0;
5899
+ }
5900
+ areNodePortsVisible(node) {
5901
+ if (this.visualDensity() === 'full')
5902
+ return true;
5903
+ if (node.id === this.hoveredNodeId() || this.expandedNodeId() === node.id) {
5904
+ return true;
5905
+ }
5906
+ if (this.dragState() || this.pendingSegmentState() || this.nodeHasCompatiblePreviewPort(node)) {
5907
+ return true;
5908
+ }
5909
+ const connectedPortIds = this.connectedPortIds();
5910
+ return [...node.inputs, ...node.outputs, ...node.states].some((port) => connectedPortIds.has(port.id));
5911
+ }
5912
+ isGuidedPortVisible(port) {
5913
+ if (this.visualDensity() === 'full')
5914
+ return true;
5915
+ if (port.nodeId === this.hoveredNodeId() || port.nodeId === this.selectedWidgetId() || port.nodeId === this.expandedNodeId()) {
5916
+ return true;
5917
+ }
5918
+ if (this.isDragSource(port) || this.isCompatibleDrop(port) || this.isDropCandidate(port) || this.isPortFocusedByConnection(port)) {
5919
+ return true;
5920
+ }
5921
+ return this.connectedPortIds().has(port.id);
5922
+ }
5923
+ isGuidedSegmentLabelVisible(port) {
5924
+ if (this.visualDensity() === 'full')
5925
+ return true;
5926
+ if (port.nodeId === this.hoveredNodeId() || port.nodeId === this.selectedWidgetId() || port.nodeId === this.expandedNodeId()) {
5927
+ return true;
5928
+ }
5929
+ if (this.isDragSource(port) || this.isCompatibleDrop(port) || this.isDropCandidate(port) || this.isInvalidDropFeedbackTarget(port)) {
5930
+ return true;
5931
+ }
5932
+ return this.isPortFocusedByConnection(port);
5933
+ }
5934
+ clearHoveredNode(nodeId) {
5935
+ if (this.hoveredNodeId() === nodeId) {
5936
+ this.hoveredNodeId.set(null);
5937
+ }
5938
+ }
5939
+ updateAutoExpandedNode(nodeId) {
5940
+ if (this.visualDensity() === 'full') {
5941
+ this.expandedNodeId.update((current) => (current === nodeId ? null : nodeId));
5942
+ return;
5943
+ }
5944
+ this.expandedNodeId.set(null);
5945
+ }
5561
5946
  edgeMatchesMode(edge) {
5562
5947
  return this.intentMatchesMode(edge.intent, edge.hasPolicy);
5563
5948
  }
@@ -5627,13 +6012,125 @@ class ConnectionEditorComponent {
5627
6012
  suggestionReasonText(reason) {
5628
6013
  switch (reason) {
5629
6014
  case 'row-selection-to-id':
5630
- return this.tx('connections.suggestions.reasons.rowSelectionToId', 'Rows expose ids consumable as target inputs.');
6015
+ return this.tx('connections.suggestions.reasons.rowSelectionToId', 'Connects the selected row id to a detail input.');
5631
6016
  case 'state-to-input':
5632
- return this.tx('connections.suggestions.reasons.stateToInput', 'Page state can hydrate this input.');
6017
+ return this.tx('connections.suggestions.reasons.stateToInput', 'Uses page state to keep the target hydrated.');
5633
6018
  case 'compatible-port':
5634
6019
  return this.tx('connections.suggestions.reasons.compatiblePort', 'Compatible source and target ports.');
5635
6020
  }
5636
6021
  }
6022
+ connectionSemanticLabel(connection) {
6023
+ if (this.isCanonicalSelectionToDetailConnection(connection.fromPort, connection.toPort)) {
6024
+ return this.tx('connections.semantic.masterDetail', 'Master-detail');
6025
+ }
6026
+ if (connection.intent === 'state-write') {
6027
+ return this.tx('connections.semantic.captureState', 'Capture selection');
6028
+ }
6029
+ if (connection.intent === 'state-read') {
6030
+ return this.tx('connections.semantic.hydrateTarget', 'Hydrate target');
6031
+ }
6032
+ if (connection.intent === 'command-dispatch') {
6033
+ return this.tx('connections.semantic.dispatchCommand', 'Run action');
6034
+ }
6035
+ if (connection.intent === 'data-projection') {
6036
+ return this.tx('connections.semantic.projectData', 'Project data');
6037
+ }
6038
+ return this.tx('connections.semantic.propagateEvent', 'Propagate event');
6039
+ }
6040
+ connectionHumanSummary(connection) {
6041
+ const source = this.readableEndpointLabel(connection, 'from');
6042
+ const target = this.readableEndpointLabel(connection, 'to');
6043
+ if (connection.intent === 'state-write') {
6044
+ return `${source} ${this.tx('connections.summary.writesState', 'updates')} ${target}.`;
6045
+ }
6046
+ if (connection.intent === 'state-read') {
6047
+ return `${source} ${this.tx('connections.summary.hydratesTarget', 'hydrates')} ${target}.`;
6048
+ }
6049
+ if (connection.intent === 'command-dispatch') {
6050
+ return `${source} ${this.tx('connections.summary.dispatchesCommand', 'runs')} ${target}.`;
6051
+ }
6052
+ return `${source} ${this.tx('connections.summary.updatesTarget', 'updates')} ${target}.`;
6053
+ }
6054
+ connectionDeliveryPreview(connection) {
6055
+ const transform = connection.link.transform;
6056
+ const pickStep = transform?.steps?.find((step) => step.kind === 'pick-path');
6057
+ const pickedPath = typeof pickStep?.config?.['path'] === 'string' ? pickStep.config['path'] : null;
6058
+ if (pickedPath) {
6059
+ if (this.isCanonicalSelectionToDetailConnection(connection.fromPort, connection.toPort) && pickedPath === 'payload.row.id') {
6060
+ return this.tx('connections.preview.deliversSelectedRowId', 'Delivered value: selected row id (payload.row.id).');
6061
+ }
6062
+ return `${this.tx('connections.preview.deliversPath', 'Delivered value')}: ${pickedPath}.`;
6063
+ }
6064
+ if (transform?.steps?.length) {
6065
+ return `${this.tx('connections.preview.deliversTransformed', 'Delivered value')}: ${this.tx('connections.preview.transformedPayload', 'transformed payload')}.`;
6066
+ }
6067
+ return `${this.tx('connections.preview.deliversDefault', 'Delivered value')}: ${this.tx('connections.preview.sourcePayload', 'source payload')}.`;
6068
+ }
6069
+ suggestionSemanticLabel(suggestion) {
6070
+ if (this.isSuggestedMasterDetail(suggestion)) {
6071
+ return this.tx('connections.semantic.masterDetail', 'Master-detail');
6072
+ }
6073
+ switch (suggestion.reason) {
6074
+ case 'state-to-input':
6075
+ return this.tx('connections.semantic.hydrateTarget', 'Hydrate target');
6076
+ case 'row-selection-to-id':
6077
+ return this.tx('connections.semantic.projectData', 'Project data');
6078
+ case 'compatible-port':
6079
+ return this.tx('connections.semantic.compatiblePorts', 'Compatible ports');
6080
+ }
6081
+ }
6082
+ suggestionPreviewText(suggestion) {
6083
+ if (this.isSuggestedMasterDetail(suggestion)) {
6084
+ return this.tx('connections.suggestions.preview.rowIdToDetail', 'Will deliver the selected row id (payload.row.id) to the form.');
6085
+ }
6086
+ if (suggestion.source.kind === 'state') {
6087
+ return this.tx('connections.suggestions.preview.stateToInput', 'Will deliver the current page state value.');
6088
+ }
6089
+ return this.tx('connections.suggestions.preview.sourcePayload', 'Will deliver the source payload unless you add a transform.');
6090
+ }
6091
+ suggestionOutcomeText(suggestion) {
6092
+ if (this.isSuggestedMasterDetail(suggestion)) {
6093
+ return this.tx('connections.suggestions.outcome.masterDetail', 'Selecting a row in {{source}} updates {{target}}.')
6094
+ .replace('{{source}}', suggestion.sourceNodeTitle)
6095
+ .replace('{{target}}', suggestion.targetNodeTitle);
6096
+ }
6097
+ return this.tx('connections.suggestions.outcome.default', '{{source}} updates {{target}}.')
6098
+ .replace('{{source}}', suggestion.sourceNodeTitle)
6099
+ .replace('{{target}}', suggestion.targetNodeTitle);
6100
+ }
6101
+ suggestionRouteTechnicalText(suggestion) {
6102
+ return this.tx('connections.suggestions.routeTechnical', 'Technical route: {{source}} -> {{target}}')
6103
+ .replace('{{source}}', suggestion.source.label)
6104
+ .replace('{{target}}', suggestion.target.label);
6105
+ }
6106
+ suggestionActionText(suggestion) {
6107
+ if (this.isSuggestedMasterDetail(suggestion)) {
6108
+ return this.tx('connections.suggestions.connectSelectionToForm', 'Connect selection to form');
6109
+ }
6110
+ return this.tx('connections.suggestions.quickConnect', 'Quick connect');
6111
+ }
6112
+ connectionCreatedFeedback(connection) {
6113
+ if (this.isCanonicalSelectionToDetailConnection(connection.fromPort, connection.toPort)
6114
+ && connection.link.transform?.steps?.some((step) => step.kind === 'pick-path' && step.config?.['path'] === 'payload.row.id')) {
6115
+ return this.tx('connections.feedback.createdMasterDetail', 'Now selecting a row sends that row id to the form.');
6116
+ }
6117
+ return this.tx('connections.feedback.createdDefault', 'This connection is now part of the page interaction flow.');
6118
+ }
6119
+ portAriaLabel(node, port, role) {
6120
+ const roleLabel = role === 'output'
6121
+ ? this.tx('connections.editor.portRole.output', 'Source')
6122
+ : role === 'input'
6123
+ ? this.tx('connections.editor.portRole.input', 'Target')
6124
+ : this.tx('connections.editor.portRole.state', 'Page state');
6125
+ const behavior = role === 'output'
6126
+ ? this.tx('connections.editor.portBehavior.output', 'drag or choose this event as a connection source')
6127
+ : this.tx('connections.editor.portBehavior.input', 'drop or choose a compatible source for this target');
6128
+ return this.tx('connections.editor.portAria', '{{role}}: {{node}}, {{port}}. {{behavior}}.')
6129
+ .replace('{{role}}', roleLabel)
6130
+ .replace('{{node}}', node.title)
6131
+ .replace('{{port}}', port.label)
6132
+ .replace('{{behavior}}', behavior);
6133
+ }
5637
6134
  transformKindText(kind) {
5638
6135
  switch (kind) {
5639
6136
  case 'identity':
@@ -5644,6 +6141,75 @@ class ConnectionEditorComponent {
5644
6141
  return kind;
5645
6142
  }
5646
6143
  }
6144
+ readableEndpointLabel(connection, side) {
6145
+ const port = side === 'from' ? connection.fromPort : connection.toPort;
6146
+ const nodeId = side === 'from' ? connection.fromNode : connection.toNode;
6147
+ const label = side === 'from' ? connection.fromLabel : connection.toLabel;
6148
+ if (nodeId === this.stateNodeId) {
6149
+ return `${this.tx('connections.editor.stateNode', 'Page state')}.${label}`;
6150
+ }
6151
+ if (nodeId === CONNECTION_EDITOR_GLOBAL_ACTION_NODE_ID) {
6152
+ return `${this.tx('connections.editor.globalActions', 'Global actions')}.${label}`;
6153
+ }
6154
+ const nodeTitle = nodeId
6155
+ ? this.editorNodes().find((node) => node.id === nodeId)?.title ?? nodeId
6156
+ : port?.nodeId ?? '';
6157
+ return nodeTitle ? `${nodeTitle}.${label}` : label;
6158
+ }
6159
+ isSelectionToDetailConnection(source, target) {
6160
+ if (!source || !target)
6161
+ return false;
6162
+ if (source.kind !== 'output' || target.kind !== 'input')
6163
+ return false;
6164
+ const sourceLabel = source.label.toLowerCase();
6165
+ const targetLabel = target.label.toLowerCase();
6166
+ const sourceComponent = source.endpoint.kind === 'component-port'
6167
+ ? String(source.endpoint.ref.componentType ?? '').toLowerCase()
6168
+ : '';
6169
+ const targetComponent = target.endpoint.kind === 'component-port'
6170
+ ? String(target.endpoint.ref.componentType ?? '').toLowerCase()
6171
+ : '';
6172
+ return /(row|item|select|selection|click)/.test(sourceLabel)
6173
+ && /(resourceid|id|querycontext|filtercriteria)/.test(targetLabel)
6174
+ && (sourceComponent.includes('table') || sourceComponent.includes('source') || sourceLabel.includes('select'))
6175
+ && (targetComponent.includes('form') || targetComponent.includes('sink') || /(resourceid|querycontext)/.test(targetLabel));
6176
+ }
6177
+ isSuggestedMasterDetail(suggestion) {
6178
+ return suggestion.reason === 'row-selection-to-id'
6179
+ && this.isCanonicalSelectionToDetailConnection(suggestion.source, suggestion.target);
6180
+ }
6181
+ isCanonicalSelectionToDetailConnection(source, target) {
6182
+ if (!source || !target)
6183
+ return false;
6184
+ if (source.kind !== 'output' || target.kind !== 'input')
6185
+ return false;
6186
+ if (target.label !== 'resourceId')
6187
+ return false;
6188
+ if (!/^(rowClick|rowSelection|selectionChange)$/i.test(source.label))
6189
+ return false;
6190
+ const sourceComponent = source.endpoint.kind === 'component-port'
6191
+ ? String(source.endpoint.ref.componentType ?? '').toLowerCase()
6192
+ : '';
6193
+ const targetComponent = target.endpoint.kind === 'component-port'
6194
+ ? String(target.endpoint.ref.componentType ?? '').toLowerCase()
6195
+ : '';
6196
+ return sourceComponent.includes('table') && targetComponent.includes('dynamic-form');
6197
+ }
6198
+ isTableSelectionOutput(port) {
6199
+ return port.kind === 'output'
6200
+ && /^(rowClick|rowSelection|selectionChange)$/i.test(port.label)
6201
+ && this.portComponentType(port).includes('table');
6202
+ }
6203
+ isFormResourceIdInput(port) {
6204
+ return port.kind === 'input'
6205
+ && port.label === 'resourceId'
6206
+ && this.portComponentType(port).includes('dynamic-form');
6207
+ }
6208
+ portComponentType(port) {
6209
+ return port.endpoint.kind === 'component-port'
6210
+ ? String(port.endpoint.ref.componentType ?? '').toLowerCase()
6211
+ : '';
6212
+ }
5647
6213
  expandedPorts(node) {
5648
6214
  return uniqueConnectionEditorPorts(node);
5649
6215
  }
@@ -5914,7 +6480,9 @@ class ConnectionEditorComponent {
5914
6480
  links: [...links, link],
5915
6481
  };
5916
6482
  this.commitPageChange(next, link.id);
6483
+ this.lastCreatedLinkId.set(link.id);
5917
6484
  this.markRecentLink(link.id);
6485
+ this.scrollConnectionSidePanelToTop();
5918
6486
  }
5919
6487
  ensureSourceOutputDeclared(page, source) {
5920
6488
  if (source.endpoint.kind !== 'component-port')
@@ -6123,6 +6691,12 @@ class ConnectionEditorComponent {
6123
6691
  this.recentLinkFeedbackTimer = null;
6124
6692
  }, CONNECTION_EDITOR_RECENT_LINK_FEEDBACK_MS);
6125
6693
  }
6694
+ scrollConnectionSidePanelToTop() {
6695
+ const panel = this.hostElement.nativeElement.querySelector('[data-testid="page-builder-connections-side-panel"]');
6696
+ if (!panel)
6697
+ return;
6698
+ panel.scrollTop = 0;
6699
+ }
6126
6700
  clearPreviewConnectionState() {
6127
6701
  this.hoveredLinkId.set(null);
6128
6702
  this.clearInvalidDropFeedback();
@@ -6355,6 +6929,9 @@ class ConnectionEditorComponent {
6355
6929
  @if (open()) {
6356
6930
  <aside
6357
6931
  class="connection-editor"
6932
+ [class.connection-editor--guided]="visualDensity() === 'guided'"
6933
+ [class.connection-editor--full]="visualDensity() === 'full'"
6934
+ [class.connection-editor--dock-collapsed]="dockCollapsed()"
6358
6935
  data-testid="page-builder-connections-panel"
6359
6936
  [attr.aria-label]="tx('connections.editor.panelAria', 'Connection editor')"
6360
6937
  >
@@ -6363,15 +6940,6 @@ class ConnectionEditorComponent {
6363
6940
  <div class="connection-editor__eyebrow">{{ tx('connections.editor.eyebrow', 'Radial connection studio') }}</div>
6364
6941
  <div class="connection-editor__title">{{ tx('connections.title', 'Connections') }}</div>
6365
6942
  </div>
6366
- <button
6367
- type="button"
6368
- class="connection-editor__close"
6369
- data-testid="page-builder-connections-close"
6370
- [attr.aria-label]="tx('connections.closeAria', 'Close connection editor')"
6371
- (click)="close.emit()"
6372
- >
6373
- ×
6374
- </button>
6375
6943
  <div class="connection-editor__mode-frame">
6376
6944
  <div class="connection-editor__mode-shell" role="tablist" [attr.aria-label]="tx('connections.mode.aria', 'Connection flow mode')">
6377
6945
  @for (mode of flowModes; track mode.id) {
@@ -6394,11 +6962,27 @@ class ConnectionEditorComponent {
6394
6962
  </div>
6395
6963
  </div>
6396
6964
  <div class="connection-editor__subtitle">
6397
- <span class="connection-editor__status-pill">
6965
+ <button
6966
+ type="button"
6967
+ class="connection-editor__status-pill connection-editor__status-pill--button"
6968
+ data-testid="page-builder-connections-density-toggle"
6969
+ [attr.aria-pressed]="visualDensity() === 'full'"
6970
+ [attr.aria-label]="visualDensityAriaLabel()"
6971
+ (click)="toggleVisualDensity($event)"
6972
+ >
6398
6973
  <span></span>
6399
6974
  {{ activeModeStatus() }}
6400
- </span>
6975
+ </button>
6401
6976
  </div>
6977
+ <button
6978
+ type="button"
6979
+ class="connection-editor__close"
6980
+ data-testid="page-builder-connections-close"
6981
+ [attr.aria-label]="tx('connections.closeAria', 'Close connection editor')"
6982
+ (click)="close.emit()"
6983
+ >
6984
+ ×
6985
+ </button>
6402
6986
  </div>
6403
6987
 
6404
6988
  <div
@@ -6653,10 +7237,13 @@ class ConnectionEditorComponent {
6653
7237
  [class.connection-editor__node--dragging]="nodeDragState()?.nodeId === node.id"
6654
7238
  [class.connection-editor__node--compat-target]="nodeHasCompatiblePreviewPort(node)"
6655
7239
  [class.connection-editor__node--mode-dimmed]="isModeDimmedNode(node)"
7240
+ [class.connection-editor__node--quiet]="isGuidedQuietNode(node)"
6656
7241
  [style.left.px]="node.x"
6657
7242
  [style.top.px]="node.y"
6658
7243
  [attr.data-trace-label]="traceNodeLabel(node)"
6659
7244
  [attr.data-testid]="'page-builder-connections-widget-' + node.id"
7245
+ (pointerenter)="hoveredNodeId.set(node.id)"
7246
+ (pointerleave)="clearHoveredNode(node.id)"
6660
7247
  (pointerdown)="startNodeDrag(node.id, $event)"
6661
7248
  (pointerup)="finishNodePointer(node.id, $event)"
6662
7249
  (click)="selectNode(node.id)"
@@ -6711,6 +7298,7 @@ class ConnectionEditorComponent {
6711
7298
  <text
6712
7299
  class="connection-editor__segment-icon"
6713
7300
  [class.connection-editor__segment-icon--output]="segment.port.kind === 'output'"
7301
+ [class.connection-editor__segment-icon--guided-visible]="isGuidedSegmentLabelVisible(segment.port)"
6714
7302
  [attr.x]="segment.icon.x"
6715
7303
  [attr.y]="segment.icon.y"
6716
7304
  [attr.transform]="segmentLabelTransform(segment, node)"
@@ -6718,6 +7306,7 @@ class ConnectionEditorComponent {
6718
7306
  >{{ segmentKindGlyph(segment.port.kind) }}</text>
6719
7307
  <text
6720
7308
  class="connection-editor__segment-label"
7309
+ [class.connection-editor__segment-label--guided-visible]="isGuidedSegmentLabelVisible(segment.port)"
6721
7310
  [attr.x]="segment.label.x"
6722
7311
  [attr.y]="segment.label.y"
6723
7312
  [attr.transform]="segmentLabelTransform(segment, node)"
@@ -6769,12 +7358,14 @@ class ConnectionEditorComponent {
6769
7358
  [class.connection-editor__segment-row--input]="port.kind === 'input'"
6770
7359
  [class.connection-editor__segment-row--output]="port.kind === 'output'"
6771
7360
  [class.connection-editor__segment-row--state]="port.kind === 'state'"
7361
+ [class.connection-editor__segment-row--nested]="isNestedPort(port)"
6772
7362
  [class.connection-editor__segment-row--source]="isDragSource(port)"
6773
7363
  [class.connection-editor__segment-row--candidate]="isDropCandidate(port)"
6774
7364
  [class.connection-editor__segment-row--compatible]="isCompatibleDrop(port)"
6775
7365
  [class.connection-editor__segment-row--compat-preview]="isCompatibilityPreview(port)"
6776
7366
  [class.connection-editor__segment-row--invalid-drop]="isInvalidDropFeedbackTarget(port)"
6777
7367
  [attr.data-testid]="'page-builder-connections-segment-' + port.id"
7368
+ [attr.aria-label]="portDescription(port)"
6778
7369
  (click)="selectSegment(port, $event)"
6779
7370
  >
6780
7371
  <span class="connection-editor__segment-index">{{ index + 1 < 10 ? '0' + (index + 1) : index + 1 }}</span>
@@ -6784,7 +7375,13 @@ class ConnectionEditorComponent {
6784
7375
  </span>
6785
7376
  <span class="connection-editor__segment-label">
6786
7377
  {{ port.label }}
7378
+ @if (isNestedPort(port)) {
7379
+ <span class="connection-editor__segment-badge">{{ tx('connections.editor.nestedBadge', 'Nested') }}</span>
7380
+ }
6787
7381
  </span>
7382
+ @if (isNestedPort(port)) {
7383
+ <span class="connection-editor__segment-path">{{ nestedPortPathText(port) }}</span>
7384
+ }
6788
7385
  <span class="connection-editor__segment-actions">
6789
7386
  <button
6790
7387
  type="button"
@@ -6806,8 +7403,11 @@ class ConnectionEditorComponent {
6806
7403
 
6807
7404
  <div
6808
7405
  class="connection-editor__ports connection-editor__ports--outputs"
7406
+ [class.connection-editor__ports--visible]="areNodePortsVisible(node)"
6809
7407
  [style.left.px]="node.x + 132"
6810
7408
  [style.top.px]="node.y + 24"
7409
+ (pointerenter)="hoveredNodeId.set(node.id)"
7410
+ (pointerleave)="clearHoveredNode(node.id)"
6811
7411
  >
6812
7412
  @for (port of node.outputs; track port.id) {
6813
7413
  <button
@@ -6815,7 +7415,9 @@ class ConnectionEditorComponent {
6815
7415
  class="connection-editor__port connection-editor__port--output"
6816
7416
  [class.connection-editor__port--source]="isDragSource(port)"
6817
7417
  [class.connection-editor__port--connection-focus]="isPortFocusedByConnection(port)"
7418
+ [class.connection-editor__port--guided-visible]="isGuidedPortVisible(port)"
6818
7419
  [attr.data-testid]="'page-builder-connection-source-' + port.id"
7420
+ [attr.aria-label]="portAriaLabel(node, port, 'output')"
6819
7421
  (pointerdown)="startDrag(port, $event)"
6820
7422
  >
6821
7423
  {{ port.label }}
@@ -6825,8 +7427,11 @@ class ConnectionEditorComponent {
6825
7427
 
6826
7428
  <div
6827
7429
  class="connection-editor__ports connection-editor__ports--inputs"
7430
+ [class.connection-editor__ports--visible]="areNodePortsVisible(node)"
6828
7431
  [style.left.px]="node.x - 104"
6829
7432
  [style.top.px]="node.y + 24"
7433
+ (pointerenter)="hoveredNodeId.set(node.id)"
7434
+ (pointerleave)="clearHoveredNode(node.id)"
6830
7435
  >
6831
7436
  @for (port of node.inputs; track port.id) {
6832
7437
  <button
@@ -6837,7 +7442,9 @@ class ConnectionEditorComponent {
6837
7442
  [class.connection-editor__port--incompatible]="isIncompatibleDrop(port)"
6838
7443
  [class.connection-editor__port--invalid-drop]="isInvalidDropFeedbackTarget(port)"
6839
7444
  [class.connection-editor__port--connection-focus]="isPortFocusedByConnection(port)"
7445
+ [class.connection-editor__port--guided-visible]="isGuidedPortVisible(port)"
6840
7446
  [attr.data-testid]="'page-builder-connection-target-' + port.id"
7447
+ [attr.aria-label]="portAriaLabel(node, port, 'input')"
6841
7448
  (pointerenter)="previewDrop(port)"
6842
7449
  (pointerleave)="clearPreviewDrop(port)"
6843
7450
  (pointerup)="completeDrag(port, $event)"
@@ -6851,11 +7458,13 @@ class ConnectionEditorComponent {
6851
7458
  class="connection-editor__port connection-editor__port--state"
6852
7459
  [class.connection-editor__port--source]="isDragSource(port)"
6853
7460
  [class.connection-editor__port--compatible]="isCompatibleDrop(port)"
6854
- [class.connection-editor__port--candidate]="isDropCandidate(port)"
7461
+ [class.connection-editor__port--candidate]="isDropCandidate(port)"
6855
7462
  [class.connection-editor__port--incompatible]="isIncompatibleDrop(port)"
6856
7463
  [class.connection-editor__port--invalid-drop]="isInvalidDropFeedbackTarget(port)"
6857
7464
  [class.connection-editor__port--connection-focus]="isPortFocusedByConnection(port)"
7465
+ [class.connection-editor__port--guided-visible]="isGuidedPortVisible(port)"
6858
7466
  [attr.data-testid]="'page-builder-connection-target-' + port.id"
7467
+ [attr.aria-label]="portAriaLabel(node, port, 'state')"
6859
7468
  (pointerdown)="startDrag(port, $event)"
6860
7469
  (pointerenter)="previewDrop(port)"
6861
7470
  (pointerleave)="clearPreviewDrop(port)"
@@ -6873,18 +7482,21 @@ class ConnectionEditorComponent {
6873
7482
  <button
6874
7483
  type="button"
6875
7484
  class="connection-editor__tool-button"
7485
+ [attr.title]="tx('connections.editor.zoomInAria', 'Zoom in')"
6876
7486
  [attr.aria-label]="tx('connections.editor.zoomInAria', 'Zoom in')"
6877
7487
  (click)="zoomBy(0.12, $event)"
6878
7488
  >+</button>
6879
7489
  <button
6880
7490
  type="button"
6881
7491
  class="connection-editor__tool-button"
7492
+ [attr.title]="tx('connections.editor.zoomOutAria', 'Zoom out')"
6882
7493
  [attr.aria-label]="tx('connections.editor.zoomOutAria', 'Zoom out')"
6883
7494
  (click)="zoomBy(-0.12, $event)"
6884
7495
  >-</button>
6885
7496
  <button
6886
7497
  type="button"
6887
7498
  class="connection-editor__tool-button"
7499
+ [attr.title]="tx('connections.editor.resetViewAria', 'Reset view')"
6888
7500
  [attr.aria-label]="tx('connections.editor.resetViewAria', 'Reset view')"
6889
7501
  (click)="resetViewport($event)"
6890
7502
  >o</button>
@@ -6896,6 +7508,7 @@ class ConnectionEditorComponent {
6896
7508
  class="connection-editor__tool-button connection-editor__history-button"
6897
7509
  data-testid="page-builder-connections-undo"
6898
7510
  [disabled]="!canUndo()"
7511
+ [attr.title]="tx('connections.history.undoAria', 'Undo connection edit')"
6899
7512
  [attr.aria-label]="tx('connections.history.undoAria', 'Undo connection edit')"
6900
7513
  (click)="undoHistory($event)"
6901
7514
  >&lt;</button>
@@ -6904,6 +7517,7 @@ class ConnectionEditorComponent {
6904
7517
  class="connection-editor__tool-button connection-editor__history-button"
6905
7518
  data-testid="page-builder-connections-redo"
6906
7519
  [disabled]="!canRedo()"
7520
+ [attr.title]="tx('connections.history.redoAria', 'Redo connection edit')"
6907
7521
  [attr.aria-label]="tx('connections.history.redoAria', 'Redo connection edit')"
6908
7522
  (click)="redoHistory($event)"
6909
7523
  >&gt;</button>
@@ -6912,6 +7526,8 @@ class ConnectionEditorComponent {
6912
7526
  <button
6913
7527
  type="button"
6914
7528
  class="connection-editor__arrange-button"
7529
+ [attr.title]="tx('connections.editor.autoArrangeShort', 'Auto Arrange')"
7530
+ [attr.aria-label]="tx('connections.editor.autoArrangeShort', 'Auto Arrange')"
6915
7531
  (click)="autoArrange($event)"
6916
7532
  ><span>*</span>{{ tx('connections.editor.autoArrangeShort', 'Auto Arrange') }}</button>
6917
7533
  <button
@@ -6919,6 +7535,8 @@ class ConnectionEditorComponent {
6919
7535
  class="connection-editor__arrange-button"
6920
7536
  [class.connection-editor__arrange-button--active]="hasVisualPortOrder()"
6921
7537
  data-testid="page-builder-connections-reorganize-slices"
7538
+ [attr.title]="tx('connections.editor.reorganizeSlices', 'Reorganize Slices')"
7539
+ [attr.aria-label]="tx('connections.editor.reorganizeSlices', 'Reorganize Slices')"
6922
7540
  (click)="reorganizeSlices($event)"
6923
7541
  ><span>::</span>{{ tx('connections.editor.reorganizeSlices', 'Reorganize Slices') }}</button>
6924
7542
  <button
@@ -6926,6 +7544,8 @@ class ConnectionEditorComponent {
6926
7544
  class="connection-editor__arrange-button"
6927
7545
  [class.connection-editor__arrange-button--active]="traceEnabled()"
6928
7546
  data-testid="page-builder-connections-simulate"
7547
+ [attr.title]="traceEnabled() ? tx('connections.trace.pause', 'Pause') : tx('connections.trace.simulate', 'Simulate')"
7548
+ [attr.aria-label]="traceEnabled() ? tx('connections.trace.pause', 'Pause') : tx('connections.trace.simulate', 'Simulate')"
6929
7549
  (click)="toggleTrace($event)"
6930
7550
  ><span>&gt;</span>{{ traceEnabled() ? tx('connections.trace.pause', 'Pause') : tx('connections.trace.simulate', 'Simulate') }}</button>
6931
7551
 
@@ -7060,8 +7680,32 @@ class ConnectionEditorComponent {
7060
7680
  </div>
7061
7681
  </div>
7062
7682
 
7063
- <div class="connection-editor__side-panel">
7064
- <section class="connection-editor__section">
7683
+ <div
7684
+ class="connection-editor__side-panel"
7685
+ [class.connection-editor__side-panel--contextual]="!!selectedConnection() || !!selectedEditorNode()"
7686
+ data-testid="page-builder-connections-side-panel"
7687
+ >
7688
+ @if (recommendedMasterDetailSuggestion(); as suggestion) {
7689
+ <section
7690
+ class="connection-editor__section connection-editor__recommended"
7691
+ data-testid="page-builder-connections-recommended-master-detail"
7692
+ >
7693
+ <div class="connection-editor__section-title">{{ tx('connections.suggestions.recommendedTitle', 'Recommended connection') }}</div>
7694
+ <button
7695
+ type="button"
7696
+ class="connection-editor__recommended-card"
7697
+ [attr.data-testid]="'page-builder-connection-recommended-' + suggestion.id"
7698
+ (click)="quickConnectSuggestion(suggestion, $event)"
7699
+ >
7700
+ <span class="connection-editor__human-summary-label">{{ suggestionSemanticLabel(suggestion) }}</span>
7701
+ <strong>{{ suggestionOutcomeText(suggestion) }}</strong>
7702
+ <span>{{ suggestionPreviewText(suggestion) }}</span>
7703
+ <small>{{ suggestionRouteTechnicalText(suggestion) }}</small>
7704
+ <span class="connection-editor__suggestion-action">{{ suggestionActionText(suggestion) }}</span>
7705
+ </button>
7706
+ </section>
7707
+ }
7708
+ <section class="connection-editor__section connection-editor__filters-section">
7065
7709
  <div class="connection-editor__section-title">{{ tx('connections.filters.title', 'Filters') }}</div>
7066
7710
  <div class="connection-editor__filters">
7067
7711
  @for (filter of filters; track filter.id) {
@@ -7085,8 +7729,26 @@ class ConnectionEditorComponent {
7085
7729
  <div class="connection-editor__section-title">{{ tx('connections.inspector.title', 'Inspector') }}</div>
7086
7730
  @if (selectedConnection(); as connection) {
7087
7731
  <div class="connection-editor__inspector-heading">
7088
- <strong>{{ connection.id }}</strong>
7089
- <span>{{ connection.intent }}</span>
7732
+ <strong>{{ connectionHumanSummary(connection) }}</strong>
7733
+ <span>{{ tx('connections.inspector.selected', 'Selected connection') }} · {{ connectionSemanticLabel(connection) }}</span>
7734
+ </div>
7735
+ @if (lastCreatedLinkId() === connection.id) {
7736
+ <div
7737
+ class="connection-editor__success"
7738
+ role="status"
7739
+ data-testid="page-builder-connections-created-status"
7740
+ >
7741
+ <strong>{{ tx('connections.feedback.createdTitle', 'Connection created') }}</strong>
7742
+ <span>{{ connectionCreatedFeedback(connection) }}</span>
7743
+ </div>
7744
+ }
7745
+ <div
7746
+ class="connection-editor__human-summary"
7747
+ data-testid="page-builder-connections-human-summary"
7748
+ >
7749
+ <span class="connection-editor__human-summary-label">{{ connectionSemanticLabel(connection) }}</span>
7750
+ <strong>{{ connectionHumanSummary(connection) }}</strong>
7751
+ <span>{{ connectionDeliveryPreview(connection) }}</span>
7090
7752
  </div>
7091
7753
  <div class="connection-editor__details-row">
7092
7754
  <span>{{ tx('connections.details.from', 'From') }}</span>
@@ -7096,14 +7758,35 @@ class ConnectionEditorComponent {
7096
7758
  <span>{{ tx('connections.details.to', 'To') }}</span>
7097
7759
  <strong>{{ connection.toLabel }}</strong>
7098
7760
  </div>
7099
- <div class="connection-editor__details-block">
7100
- <div class="connection-editor__details-label">{{ tx('connections.inspector.sourceEndpoint', 'Source endpoint') }}</div>
7101
- <pre>{{ connection.link.from | json }}</pre>
7102
- </div>
7103
- <div class="connection-editor__details-block">
7104
- <div class="connection-editor__details-label">{{ tx('connections.inspector.targetEndpoint', 'Target endpoint') }}</div>
7105
- <pre>{{ connection.link.to | json }}</pre>
7106
- </div>
7761
+ @if (connectionHasNestedEndpoint(connection)) {
7762
+ <div
7763
+ class="connection-editor__nested-summary"
7764
+ data-testid="page-builder-connections-nested-summary"
7765
+ >
7766
+ <span class="connection-editor__human-summary-label">{{ tx('connections.editor.nestedBadge', 'Nested') }}</span>
7767
+ <strong>{{ tx('connections.details.nestedOwnerPreserved', 'Top-level owner is preserved') }}</strong>
7768
+ <span>{{ connectionNestedSummary(connection) }}</span>
7769
+ </div>
7770
+ }
7771
+ <details class="connection-editor__technical-details">
7772
+ <summary>{{ tx('connections.inspector.technicalDetails', 'Technical details') }}</summary>
7773
+ <div class="connection-editor__details-block">
7774
+ <div class="connection-editor__details-label">{{ tx('connections.inspector.connectionId', 'Connection id') }}</div>
7775
+ <pre>{{ connection.id }}</pre>
7776
+ </div>
7777
+ <div class="connection-editor__details-block">
7778
+ <div class="connection-editor__details-label">{{ tx('connections.inspector.intent', 'Intent') }}</div>
7779
+ <pre>{{ connection.intent }}</pre>
7780
+ </div>
7781
+ <div class="connection-editor__details-block">
7782
+ <div class="connection-editor__details-label">{{ tx('connections.inspector.sourceEndpoint', 'Source endpoint') }}</div>
7783
+ <pre>{{ connection.link.from | json }}</pre>
7784
+ </div>
7785
+ <div class="connection-editor__details-block">
7786
+ <div class="connection-editor__details-label">{{ tx('connections.inspector.targetEndpoint', 'Target endpoint') }}</div>
7787
+ <pre>{{ connection.link.to | json }}</pre>
7788
+ </div>
7789
+ </details>
7107
7790
  @if (connection.link.to.kind === 'global-action') {
7108
7791
  <div class="connection-editor__details-block" data-testid="page-builder-connections-global-action-payload-editor">
7109
7792
  <div class="connection-editor__details-label">{{ tx('connections.globalAction.payloadTitle', 'Action payload') }}</div>
@@ -7359,6 +8042,9 @@ class ConnectionEditorComponent {
7359
8042
  [class.connection-editor__inspector-port--state]="port.kind === 'state'"
7360
8043
  >
7361
8044
  {{ port.kind }} · {{ port.label }}
8045
+ @if (isNestedPort(port)) {
8046
+ · {{ tx('connections.editor.nestedBadge', 'Nested') }} · {{ nestedPortPathText(port) }}
8047
+ }
7362
8048
  </span>
7363
8049
  }
7364
8050
  </div>
@@ -7406,6 +8092,15 @@ class ConnectionEditorComponent {
7406
8092
  @if (smartSuggestions().length) {
7407
8093
  <div class="connection-editor__suggestions" data-testid="page-builder-connections-suggestions">
7408
8094
  <div class="connection-editor__section-title">{{ tx('connections.suggestions.title', 'Smart suggestions') }}</div>
8095
+ @if (masterDetailReadinessDiagnostic(); as diagnostic) {
8096
+ <div
8097
+ class="connection-editor__suggestion-diagnostic"
8098
+ role="note"
8099
+ data-testid="page-builder-connections-master-detail-diagnostic"
8100
+ >
8101
+ {{ diagnostic }}
8102
+ </div>
8103
+ }
7409
8104
  @for (suggestion of smartSuggestions(); track suggestion.id) {
7410
8105
  <button
7411
8106
  type="button"
@@ -7418,11 +8113,28 @@ class ConnectionEditorComponent {
7418
8113
  <span>{{ suggestion.source.label }} -> {{ suggestion.target.label }}</span>
7419
8114
  <strong>{{ suggestion.targetNodeTitle }}</strong>
7420
8115
  </span>
8116
+ <span class="connection-editor__suggestion-intent">{{ suggestionSemanticLabel(suggestion) }}</span>
8117
+ <strong class="connection-editor__suggestion-outcome">{{ suggestionOutcomeText(suggestion) }}</strong>
7421
8118
  <span class="connection-editor__suggestion-reason">{{ suggestionReasonText(suggestion.reason) }}</span>
7422
- <span class="connection-editor__suggestion-action">{{ tx('connections.suggestions.quickConnect', 'Quick connect') }}</span>
8119
+ <span class="connection-editor__suggestion-preview">{{ suggestionPreviewText(suggestion) }}</span>
8120
+ <span class="connection-editor__suggestion-action">{{ suggestionActionText(suggestion) }}</span>
7423
8121
  </button>
7424
8122
  }
7425
8123
  </div>
8124
+ } @else if (masterDetailReadinessDiagnostic(); as diagnostic) {
8125
+ <div
8126
+ class="connection-editor__suggestions"
8127
+ data-testid="page-builder-connections-suggestions"
8128
+ >
8129
+ <div class="connection-editor__section-title">{{ tx('connections.suggestions.title', 'Smart suggestions') }}</div>
8130
+ <div
8131
+ class="connection-editor__suggestion-diagnostic"
8132
+ role="note"
8133
+ data-testid="page-builder-connections-master-detail-diagnostic"
8134
+ >
8135
+ {{ diagnostic }}
8136
+ </div>
8137
+ </div>
7426
8138
  }
7427
8139
  @if (traceEnabled()) {
7428
8140
  <div class="connection-editor__trace" data-testid="page-builder-connections-trace">
@@ -7728,7 +8440,7 @@ class ConnectionEditorComponent {
7728
8440
  </section>
7729
8441
  </aside>
7730
8442
  }
7731
- `, isInline: true, styles: [":host{position:fixed;inset:0;z-index:1000;pointer-events:none}.connection-editor{--pce-fg: var(--md-sys-color-on-surface, #dce6f4);--pce-strong: var(--md-sys-color-on-surface, #f8fafc);--pce-muted: var(--md-sys-color-on-surface-variant, #94a3b8);--pce-primary: var(--md-sys-color-primary, #19c8e8);--pce-secondary: var(--md-sys-color-secondary, #b46cff);--pce-tertiary: var(--md-sys-color-tertiary, #ff9f2f);--pce-success: var(--md-sys-color-tertiary, #10b981);--pce-warning: var(--md-sys-color-error, #ff9f2f);--pce-error: var(--md-sys-color-error, #ef4444);--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #07111f) 80%, #020617);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #08101d) 78%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #0f172a) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #080d18) 64%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #899ab7) 46%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #94a3b8) 58%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #7d8fa9) 24%, transparent);--pce-glass-highlight: color-mix(in srgb, var(--md-sys-color-on-surface, #ffffff) 8%, transparent);--pce-shadow: color-mix(in srgb, #000 56%, transparent);--pce-shadow-soft: color-mix(in srgb, #000 30%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #040a13) 42%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high, #050912) 94%, transparent);position:absolute;inset:12px;height:calc(100vh - 24px);box-sizing:border-box;overflow:hidden;padding:16px;border-radius:18px;color:var(--pce-fg);background:radial-gradient(circle at 72% 20%,color-mix(in srgb,var(--pce-secondary) 16%,transparent),transparent 28%),radial-gradient(circle at 26% 74%,color-mix(in srgb,var(--pce-primary) 10%,transparent),transparent 34%),radial-gradient(circle at 48% 52%,color-mix(in srgb,var(--pce-tertiary) 5%,transparent),transparent 35%),linear-gradient(var(--pce-grid) 1px,transparent 1px),linear-gradient(90deg,var(--pce-grid) 1px,transparent 1px),var(--pce-surface-base);background-size:auto,auto,auto,38px 38px,38px 38px,auto;border:1px solid var(--pce-outline);box-shadow:0 28px 90px var(--pce-shadow);pointer-events:auto;display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);grid-template-rows:auto minmax(0,1fr) auto minmax(48px,140px);gap:14px}:host-context(.theme-light) .connection-editor{--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #ffffff) 94%, var(--md-sys-color-primary, #2563eb) 6%);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 82%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #eef2ff) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #f8fafc) 70%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 68%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #64748b) 62%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 34%, transparent);--pce-glass-highlight: color-mix(in srgb, #fff 64%, transparent);--pce-shadow: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 22%, transparent);--pce-shadow-soft: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 14%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #ffffff) 58%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 92%, transparent)}.connection-editor__header{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:42px;padding:8px 14px;border-radius:999px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__mode-frame{position:relative;min-width:0}.connection-editor__close{width:34px;height:34px;flex:0 0 auto;display:inline-grid;place-items:center;border:1px solid var(--pce-outline);border-radius:999px;color:var(--pce-text);background:var(--pce-surface-strong);box-shadow:inset 0 1px var(--pce-glass-highlight);cursor:pointer;font:inherit;font-size:1.2rem;line-height:1}.connection-editor__close:hover,.connection-editor__close:focus-visible{border-color:var(--pce-outline-strong);background:color-mix(in srgb,var(--pce-accent) 16%,var(--pce-surface-strong));outline:none}.connection-editor__mode-shell{display:inline-flex;align-items:center;gap:4px;min-width:0;padding:4px;border-radius:999px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:inset 0 1px var(--pce-glass-highlight),0 10px 26px var(--pce-shadow-soft);scrollbar-width:none}.connection-editor__mode-shell::-webkit-scrollbar{display:none}.connection-editor__mode{min-height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 12px;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.76rem;font-weight:800;white-space:nowrap;transition:background .16s ease,border-color .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__mode:hover,.connection-editor__mode--active{color:var(--pce-strong);border-color:color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-strong) 82%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 12%,transparent)}.connection-editor__mode-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__mode--active .connection-editor__mode-glyph{color:var(--pce-primary)}.connection-editor__mode-dot{width:6px;height:6px;border-radius:999px;background:var(--pce-success);box-shadow:0 0 12px color-mix(in srgb,var(--pce-success) 70%,transparent)}.connection-editor__status-pill{display:inline-flex;align-items:center;gap:8px;min-height:24px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 36%,transparent);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.72rem;font-weight:800;white-space:nowrap}.connection-editor__status-pill span{width:6px;height:6px;border-radius:999px;background:var(--pce-primary);box-shadow:0 0 12px color-mix(in srgb,var(--pce-primary) 70%,transparent)}.connection-editor__section{display:grid;gap:10px}.connection-editor__dock{grid-column:1 / -1;grid-row:4;position:relative;z-index:4;min-height:0;display:grid;border-radius:14px;border:1px solid var(--pce-outline);background:radial-gradient(circle at 16% 0%,color-mix(in srgb,var(--pce-primary) 22%,transparent),transparent 34%),radial-gradient(circle at 78% 0%,color-mix(in srgb,var(--pce-secondary) 25%,transparent),transparent 38%),linear-gradient(90deg,var(--pce-dock-bg),var(--pce-surface-strong) 46%,color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-dock-bg))),var(--pce-dock-bg);box-shadow:0 18px 58px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__dock--collapsed .connection-editor__dock-tabs{border-block-end:0}.connection-editor__dock-tabs{display:flex;align-items:center;gap:10px;min-height:52px;padding:9px 14px;border-block-end:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-glass-highlight),transparent),color-mix(in srgb,var(--pce-surface-soft) 34%,transparent)}.connection-editor__dock-tab,.connection-editor__dock-toggle{min-height:30px;border-radius:999px;border:1px solid transparent;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.72rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-tab{display:inline-flex;align-items:center;gap:8px;padding:0 13px;white-space:nowrap}.connection-editor__dock-tab-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.8rem;letter-spacing:0;text-transform:none}.connection-editor__dock-tab--active{color:var(--pce-strong);border-color:var(--pce-outline-strong);background:linear-gradient(180deg,color-mix(in srgb,var(--pce-strong) 14%,transparent),color-mix(in srgb,var(--pce-strong) 6%,transparent));box-shadow:0 0 0 1px color-mix(in srgb,var(--pce-shadow) 72%,transparent),0 0 22px color-mix(in srgb,var(--pce-strong) 8%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__dock-tab--active .connection-editor__dock-tab-glyph{color:var(--pce-strong)}.connection-editor__dock-count{margin-inline-start:auto;color:color-mix(in srgb,var(--pce-muted) 62%,transparent);font-size:.7rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-toggle{width:32px;padding:0;border-color:var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.88rem;letter-spacing:0}.connection-editor__dock-body{max-height:154px;overflow:auto;padding:12px 12px 14px;border-block-start:1px solid var(--pce-outline);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 9%,transparent),color-mix(in srgb,var(--pce-secondary) 10%,transparent) 62%,color-mix(in srgb,var(--pce-surface-strong) 18%,transparent)),color-mix(in srgb,var(--pce-surface-soft) 30%,transparent)}.connection-editor__dock-body pre{max-height:60px}.connection-editor__dock-links{display:grid;gap:8px}.connection-editor__dock-link-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;padding:7px 10px;border-radius:10px;border:1px solid var(--pce-outline);background:linear-gradient(90deg,var(--pce-surface-soft),color-mix(in srgb,var(--pce-secondary) 10%,var(--pce-surface-soft)) 72%,var(--pce-surface-soft)),var(--pce-surface-soft);color:var(--pce-fg);transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-link{display:grid;grid-template-columns:minmax(116px,.52fr) minmax(300px,1.72fr) minmax(160px,.9fr) auto;align-items:center;gap:12px;width:100%;min-height:42px;padding:0;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer;text-align:start}.connection-editor__dock-link-row:hover,.connection-editor__dock-link--active{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 13%,transparent),color-mix(in srgb,var(--pce-secondary) 16%,transparent),var(--pce-surface-strong)),var(--pce-surface-strong);box-shadow:0 12px 32px var(--pce-shadow-soft),inset 0 0 18px color-mix(in srgb,var(--pce-primary) 6%,transparent)}.connection-editor__dock-link--active{border-color:#facc1575;box-shadow:0 12px 32px var(--pce-shadow-soft),0 0 24px #facc151f}.connection-editor__dock-link--new{border-color:#fb923ca3;background:linear-gradient(90deg,#fb923c2e,#a855f729,#0ea5e91f),#0f172ac2;box-shadow:0 12px 34px #02061752,0 0 30px #fb923c2e;animation:new-dock-link-flash 1.35s ease-out forwards}.connection-editor__dock-link--error{border-color:#ef444461}.connection-editor__dock-jump{min-width:62px;min-height:30px;padding:0 10px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 54%,transparent);color:var(--pce-primary);cursor:pointer;font-size:.66rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__dock-jump:hover,.connection-editor__dock-jump:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 56%,transparent);background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 18%,transparent);outline:none}.connection-editor__dock-link-kind{display:inline-flex;align-items:center;gap:7px;min-width:0;color:var(--pce-muted);font-size:.66rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-link-kind span{width:8px;height:8px;border-radius:999px;background:#b46cff;box-shadow:0 0 14px #b46cff7a}.connection-editor__dock-link--state .connection-editor__dock-link-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2f94}.connection-editor__dock-link--state-read .connection-editor__dock-link-kind span{background:#8b7dff;box-shadow:0 0 13px #8b7dff75}.connection-editor__dock-link--projection .connection-editor__dock-link-kind span{background:#19c8e8;box-shadow:0 0 10px #19c8e857}.connection-editor__dock-link--event-propagation .connection-editor__dock-link-kind span{background:#ffb454;box-shadow:0 0 15px #ffb45485}.connection-editor__dock-link--policy .connection-editor__dock-link-kind span{outline:1px solid rgba(34,197,94,.76);outline-offset:2px;box-shadow:0 0 16px #22c55e61}.connection-editor__dock-link--policy:not(.connection-editor__dock-link--state,.connection-editor__dock-link--state-read,.connection-editor__dock-link--projection,.connection-editor__dock-link--event-propagation) .connection-editor__dock-link-kind span{background:#22c55e}.connection-editor__dock-link-route{display:inline-flex;align-items:center;gap:8px;min-width:0}.connection-editor__dock-link-chip{min-width:0;overflow:hidden;padding:4px 8px;border-radius:999px;border:1px solid var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-soft) 72%,transparent);color:var(--pce-fg);font-size:.72rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-chip--from{border-color:#ff9f2f66;color:#ffbd62}.connection-editor__dock-link-chip--to{border-color:#19c8e83d;color:#7dddeb}:host-context(.theme-light) .connection-editor__dock-link-chip--from{border-color:color-mix(in srgb,var(--pce-tertiary) 46%,transparent);color:#8a4600}:host-context(.theme-light) .connection-editor__dock-link-chip--to{border-color:color-mix(in srgb,var(--pce-primary) 34%,transparent);color:#075f73}.connection-editor__dock-link-arrow{flex:0 0 auto;color:var(--pce-muted);font-weight:900}.connection-editor__dock-link-id{min-width:0;overflow:hidden;color:var(--pce-muted);font-size:.66rem;font-weight:800;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-badges{display:inline-flex;justify-content:flex-end;gap:5px;min-width:70px}.connection-editor__dock-link-badges span{padding:3px 7px;border-radius:999px;background:#a855f724;color:#d8b4fe;font-size:.62rem;font-weight:900;text-transform:uppercase;white-space:nowrap}:host-context(.theme-light) .connection-editor__dock-link-badges span{background:color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-surface-soft));color:#6d2a9f}.connection-editor__dock-empty{padding:12px;border-radius:12px;border:1px dashed var(--pce-outline);color:var(--pce-muted);font-size:.76rem;font-weight:700}.connection-editor__inspector{border-color:color-mix(in srgb,var(--pce-primary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 10%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface)}.connection-editor__eyebrow,.connection-editor__section-title{font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;color:var(--pce-muted);font-weight:700}.connection-editor__title{font-size:1.02rem;font-weight:800}.connection-editor__subtitle,.connection-editor__item-copy,.connection-editor__item-meta,.connection-editor__details-row span,.connection-editor__details-label,.connection-editor__empty{color:var(--pce-muted);font-size:.84rem}.connection-editor__inspector-heading{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--pce-surface-soft);border:1px solid var(--pce-outline)}.connection-editor__inspector-heading strong{color:var(--pce-strong);font-size:.96rem;overflow-wrap:anywhere}.connection-editor__inspector-heading span{color:var(--pce-primary);font-size:.76rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em}.connection-editor__inspector-ports{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__inspector-port{max-width:100%;padding:4px 8px;border-radius:999px;border:1px solid rgba(148,163,184,.16);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-editor__inspector-port--input{border-color:#22d3ee57;color:#67e8f9}.connection-editor__inspector-port--output{border-color:#f59e0b57;color:#fbbf24}.connection-editor__inspector-port--state{border-color:#a855f761;color:#d8b4fe}.connection-editor__segment-kind-legend{display:grid;gap:10px;padding:12px;border-radius:16px;border:1px solid rgba(148,163,184,.14);background:linear-gradient(135deg,#0f172aa8,#080d1885),#02061757}.connection-editor__segment-kind-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.connection-editor__segment-kind-pill{min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:900;overflow:hidden;white-space:nowrap}.connection-editor__segment-kind-pill span{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:currentColor;box-shadow:0 0 12px currentColor}.connection-editor__segment-kind-pill--input{border-color:#19c8e83d;color:#7dddeb}.connection-editor__segment-kind-pill--output{border-color:#ff9f2f61;color:#ffbd62}.connection-editor__segment-kind-pill--state{border-color:#b46cff61;color:#d9b8ff}:host-context(.theme-light) .connection-editor__segment-kind-pill{border-color:var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-strong) 88%,transparent)}:host-context(.theme-light) .connection-editor__segment-kind-pill--input{color:#075f73}:host-context(.theme-light) .connection-editor__segment-kind-pill--output{color:#8a4600}:host-context(.theme-light) .connection-editor__segment-kind-pill--state{color:#6d2a9f}.connection-editor__stage{grid-column:1;grid-row:2;position:relative;min-height:0;height:100%;overflow:visible;border-radius:16px;border:1px solid var(--pce-outline);background:radial-gradient(circle at center,color-mix(in srgb,var(--pce-secondary) 7%,transparent),transparent 38%),radial-gradient(circle,var(--pce-grid) 1px,transparent 1.5px),var(--pce-stage-bg);background-size:auto,31px 31px,auto;box-shadow:inset 0 0 0 1px var(--pce-glass-highlight);cursor:grab;touch-action:none}.connection-editor__stage--panning,.connection-editor__stage:active{cursor:grabbing}.connection-editor__stage--dragging{cursor:crosshair}.connection-editor__stage--rotating{cursor:grabbing}.connection-editor__viewport{position:absolute;inset-block-start:0;inset-inline-start:0;width:900px;height:540px;overflow:visible;transform-origin:0 0;transition:transform .14s ease}.connection-editor__wires{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.connection-editor__wire,.connection-editor__wire-hit{fill:none;stroke-linecap:round}.connection-editor__wire{stroke:#b46cff;stroke-width:1.45;stroke-opacity:.48;pointer-events:none;filter:url(#connection-glow);stroke-dasharray:10 8;animation:connection-flow 1.65s linear infinite}.connection-editor__wire-hit{stroke:transparent;stroke-width:18;cursor:pointer;pointer-events:stroke}.connection-editor__wire-hit--active{stroke-width:28}.connection-editor__wire--halo{stroke:#b46cff1f;stroke-width:7;stroke-dasharray:none;animation:none}.connection-editor__wire--state{stroke:#ff9f2f;stroke-width:2.25;stroke-dasharray:8 7;animation:connection-flow .92s linear infinite}.connection-editor__wire--state.connection-editor__wire--halo{stroke:#ff9f2f29;stroke-width:11}.connection-editor__wire--projection{stroke:#15b8d8;stroke-width:1.75;stroke-dasharray:20 8;animation:connection-flow 1.9s linear infinite}.connection-editor__wire--projection.connection-editor__wire--halo{stroke:#15b8d81a;stroke-width:7}.connection-editor__wire--state-read{stroke:#8b7dff;stroke-width:1.65;stroke-dasharray:3 11;animation:connection-flow 2.25s linear infinite reverse}.connection-editor__wire--state-read.connection-editor__wire--halo{stroke:#8b7dff21;stroke-width:8}.connection-editor__wire--event-propagation{stroke:#ffb454;stroke-width:2.05;stroke-dasharray:5 7;animation:connection-flow .78s linear infinite}.connection-editor__wire--event-propagation.connection-editor__wire--halo{stroke:#ffb4542e;stroke-width:10}.connection-editor__wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.2)) url(#connection-glow)}.connection-editor__wire--policy.connection-editor__wire--halo{stroke:#22c55e1f;stroke-width:13}.connection-editor__wire--warning{stroke:#ff9f2f}.connection-editor__wire--warning.connection-editor__wire--halo{stroke:#ff9f2f2e}.connection-editor__wire--error{stroke:#ef4444}.connection-editor__wire--error.connection-editor__wire--halo{stroke:#ef44442e}.connection-editor__wire--active{stroke:#d9b8ff;stroke-width:3;stroke-opacity:1;stroke-dasharray:5 7;animation-duration:.58s}.connection-editor__wire--halo.connection-editor__wire--active{stroke-width:16;stroke-opacity:.8;animation:selected-wire-aura 1.35s ease-in-out infinite}.connection-editor__wire--new{stroke-width:3.4;stroke-opacity:1;stroke-dasharray:640;stroke-dashoffset:640;animation:wire-draw-in .62s cubic-bezier(.16,1,.3,1) forwards,connection-flow 1.05s linear .62s infinite}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:22;stroke-opacity:0;animation:new-wire-halo 1.45s ease-out forwards}.connection-editor__wire--trace{stroke:#9b5cff;stroke-width:3.2;stroke-opacity:1;stroke-dasharray:7 6;animation:connection-flow .72s linear infinite,trace-wire-pulse 1.18s ease-in-out infinite}.connection-editor__wire--halo.connection-editor__wire--trace{stroke:#9b5cff57;stroke-width:18;stroke-opacity:.86;animation:trace-halo-pulse 1.18s ease-in-out infinite}.connection-editor__wire--mode-dimmed{stroke-opacity:.14;stroke-width:1.05;filter:none;animation-duration:2.6s}.connection-editor__wire--halo.connection-editor__wire--mode-dimmed{stroke-opacity:.05;stroke-width:5;animation:none}.connection-editor__wire-hit--mode-dimmed{stroke-width:12}.connection-editor__wire-endpoint{fill:#f8fafc;stroke:#0f172ae6;stroke-width:1.5;filter:drop-shadow(0 0 8px rgba(216,180,254,.8));pointer-events:none;animation:endpoint-pulse 1.2s ease-in-out infinite}.connection-editor__wire-endpoint--source{fill:#ff9f2f}.connection-editor__wire-endpoint--target{fill:#19c8e8}.connection-editor__connection-tooltip{position:absolute;z-index:6;width:min(312px,calc(100% - 24px));display:grid;gap:8px;padding:12px 14px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(135deg,var(--pce-surface-strong),var(--pce-surface)),var(--pce-surface-strong);box-shadow:0 18px 44px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);color:var(--pce-fg);pointer-events:none;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .14s ease-out}.connection-editor__connection-tooltip-callout{position:absolute;inset-block-start:100%;inset-inline-start:var(--connection-tooltip-callout-x, 42px);width:2px;height:28px;border-radius:999px;background:linear-gradient(180deg,#e2e8f0bd,#19c8e800);box-shadow:0 0 12px #19c8e852;transform:translate(-1px);pointer-events:none}.connection-editor__connection-tooltip-callout:before,.connection-editor__connection-tooltip-callout:after{content:\"\";position:absolute;border-radius:999px;pointer-events:none}.connection-editor__connection-tooltip-callout:before{inset-block-start:-5px;inset-inline-start:-5px;width:12px;height:12px;border:1px solid rgba(148,163,184,.24);background:#080d18f5;box-shadow:inset 0 1px #ffffff14}.connection-editor__connection-tooltip-callout:after{inset-block-end:-3px;inset-inline-start:-4px;width:10px;height:10px;background:#19c8e8;box-shadow:0 0 16px #19c8e88f}.connection-editor__connection-tooltip--projection{border-color:#19c8e833;background:linear-gradient(135deg,#15b8d81f,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state{border-color:#ff9f2f66;background:linear-gradient(135deg,#ff9f2f3d,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout{background:linear-gradient(180deg,#ffbd62d1,#ff9f2f00);box-shadow:0 0 14px #ff9f2f61}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout:after{background:#ff9f2f;box-shadow:0 0 18px #ff9f2fad}.connection-editor__connection-tooltip--error{border-color:#f871716b}.connection-editor__connection-tooltip--error .connection-editor__connection-tooltip-callout:after{background:#fb7185;box-shadow:0 0 18px #fb7185ad}.connection-editor__connection-tooltip-kind{display:inline-flex;align-items:center;gap:8px;color:#94a3b8;font-size:.62rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__connection-tooltip-kind span{width:8px;height:8px;border-radius:999px;background:#19c8e8;box-shadow:0 0 12px #19c8e880}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2fc7}.connection-editor__connection-tooltip-row{min-width:0;display:grid;grid-template-columns:54px minmax(0,1fr);align-items:center;gap:8px;min-height:28px;padding:0 10px;border-radius:999px;background:#0f172a94}.connection-editor__connection-tooltip-row span{color:#8d9bb0;font-size:.62rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.connection-editor__connection-tooltip-row strong{min-width:0;overflow:hidden;color:#e2e8f0;font-size:.75rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__connection-tooltip-badges{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__connection-tooltip-badges span{padding:3px 8px;border-radius:999px;background:#02061799;color:#fbbf24;font-size:.66rem;font-weight:900}.connection-editor__trace-overlay{position:absolute;z-index:6;inset-block-start:16px;inset-inline-start:50%;width:min(560px,calc(100% - 360px));min-width:320px;padding:12px 14px;border-radius:16px;border:1px solid rgba(34,197,94,.26);background:linear-gradient(135deg,#22c55e1f,#0ea5e91a),#080d18f0;box-shadow:0 22px 56px #02061775,0 0 42px #22c55e1f;transform:translate(-50%);pointer-events:auto;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .16s ease-out}.connection-editor__trace-overlay-head,.connection-editor__trace-overlay-route{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}.connection-editor__trace-overlay-head span,.connection-editor__trace-overlay-route span{color:#86efac;font-size:.66rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase;white-space:nowrap}.connection-editor__trace-overlay-head strong{color:#cbd5e1;font-size:.7rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace}.connection-editor__trace-overlay-route{margin-top:6px}.connection-editor__trace-overlay-controls{display:grid;grid-template-columns:28px minmax(0,1fr) 28px;align-items:center;gap:8px;margin-top:10px}.connection-editor__trace-overlay-button{width:28px;height:24px;display:inline-grid;place-items:center;border:1px solid rgba(148,163,184,.18);border-radius:999px;background:#0206176b;color:#e2e8f0;cursor:pointer;font-size:1rem;font-weight:900;line-height:1;transition:border-color .15s ease,background .15s ease,color .15s ease,opacity .15s ease}.connection-editor__trace-overlay-button:hover:not(:disabled){border-color:#22d3ee6b;background:#0ea5e929;color:#f8fafc}.connection-editor__trace-overlay-button:disabled{cursor:default;opacity:.36}.connection-editor__trace-overlay-steps{min-width:0;display:flex;align-items:center;gap:6px;overflow-x:auto;padding:2px;scrollbar-width:none}.connection-editor__trace-overlay-steps::-webkit-scrollbar{display:none}.connection-editor__trace-overlay-step{position:relative;flex:1 0 28px;min-width:28px;height:22px;border:1px solid rgba(148,163,184,.16);border-radius:999px;background:#0f172a9e;color:#94a3b8;cursor:pointer;font-size:.62rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__trace-overlay-step--active{border-color:#22d3eea3;background:linear-gradient(90deg,#22d3ee3d,#9b5cff33);color:#f8fafc;box-shadow:0 0 18px #22d3ee33}.connection-editor__trace-overlay-step--blocked{border-color:#fb71855c;color:#fecdd3}.connection-editor__trace-overlay-route strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.82rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__trace-overlay-bar{position:relative;height:5px;margin-top:10px;overflow:hidden;border-radius:999px;background:#94a3b829}.connection-editor__trace-overlay-bar span{position:absolute;inset-block:0;inset-inline-start:0;border-radius:inherit;background:linear-gradient(90deg,#22c55e,#22d3ee);box-shadow:0 0 18px #22c55e61;min-width:8%}.connection-editor__drag-wire{fill:none;stroke:#94a3b8;stroke-width:2.4;stroke-linecap:round;stroke-dasharray:6 7;pointer-events:none;filter:url(#connection-glow);animation:connection-flow 1.05s linear infinite,drag-wire-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--halo{stroke:#94a3b829;stroke-width:14;stroke-dasharray:none;animation:drag-halo-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--valid{stroke:#22c55e}.connection-editor__drag-wire--halo.connection-editor__drag-wire--valid{stroke:#22c55e47}.connection-editor__drag-endpoint{fill:#94a3b8;stroke:#020617eb;stroke-width:2;pointer-events:none;filter:url(#connection-glow);transform-box:fill-box;transform-origin:center;animation:endpoint-pulse 1s ease-in-out infinite}.connection-editor__drag-endpoint--source{fill:#ff9f2f}.connection-editor__drag-endpoint--target{fill:#7dddeb}.connection-editor__drag-endpoint--valid{fill:#22c55e;stroke:#bbf7d0e0}.connection-editor__wire-handle-line{stroke-width:2;stroke-linecap:round;stroke-dasharray:4 5;pointer-events:none;opacity:.88;filter:url(#connection-glow)}.connection-editor__wire-handle-line--source{stroke:#ff9f2ff0}.connection-editor__wire-handle-line--target{stroke:#19c8e8c2}.connection-editor__wire-control{fill:#0f172af5;stroke:#cbd5e1c7;stroke-width:1.8;pointer-events:none;filter:url(#connection-glow)}.connection-editor__wire-label{pointer-events:none;filter:drop-shadow(0 0 10px rgba(2,6,23,.44));animation:tooltip-rise .14s ease-out}.connection-editor__wire-label rect{fill:#080d18eb;stroke-width:1}.connection-editor__wire-label text{fill:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:8px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__wire-label--source rect{stroke:#ff9f2fad}.connection-editor__wire-label--target rect{stroke:#19c8e86b}.connection-editor__zoom-controls{position:absolute;inset-inline-start:14px;inset-block-start:14px;z-index:4;display:grid;gap:8px;width:210px;pointer-events:auto}.connection-editor__tool-group,.connection-editor__trace-source{display:grid;gap:8px;padding:10px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:0 16px 36px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__tool-group{grid-template-columns:repeat(3,30px);width:max-content}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:repeat(2,30px)}.connection-editor__arrange-button{width:100%;min-height:32px;display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:999px;border:1px solid rgba(168,85,247,.34);background:linear-gradient(90deg,#a855f72e,#22d3ee1f);color:#e9d5ff;font-size:.74rem;font-weight:800;letter-spacing:.02em;cursor:pointer}.connection-editor__arrange-button span{color:#c084fc;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:900}.connection-editor__tool-button{width:30px;height:30px;border-radius:999px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.9rem;font-weight:800;letter-spacing:.02em;cursor:pointer;line-height:1}.connection-editor__tool-button:hover:not(:disabled){border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);color:var(--pce-primary);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 16%,transparent)}.connection-editor__history-button:disabled{cursor:not-allowed;opacity:.42}.connection-editor__arrange-button--active{border-color:#22d3ee94;background:linear-gradient(90deg,#0ea5e93d,#22d3ee2e);color:#cffafe}.connection-editor__trace-source{gap:4px;max-height:230px;overflow:auto}.connection-editor__trace-source-title{padding:2px 4px 6px;color:var(--pce-muted);font-size:.64rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase}.connection-editor__trace-source-item{min-width:0;min-height:30px;display:flex;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:8px;background:transparent;color:var(--pce-fg);cursor:pointer;font-size:.74rem;font-weight:800;text-align:start}.connection-editor__trace-source-item span{color:#f59e0b;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__trace-source-item:hover,.connection-editor__trace-source-item--active{background:var(--pce-surface-strong);color:var(--pce-strong);box-shadow:inset 3px 0 #f59e0bd1}.connection-editor__minimap{position:absolute;inset-inline-end:14px;inset-block-end:14px;z-index:4;width:184px;height:124px;padding:18px 10px 10px;overflow:hidden;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-primary) 30%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),var(--pce-surface-strong)),var(--pce-surface);box-shadow:0 20px 48px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);cursor:pointer;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__minimap:hover,.connection-editor__minimap--panning{border-color:#22d3ee75;box-shadow:0 20px 48px var(--pce-shadow-soft),0 0 24px color-mix(in srgb,var(--pce-primary) 14%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__minimap--panning{cursor:grabbing}.connection-editor__minimap:before{content:\"\";position:absolute;inset:22px 10px 10px;border-radius:10px;background-image:radial-gradient(circle,rgba(125,211,252,.18) 1px,transparent 1px);background-size:22px 22px;opacity:.58;pointer-events:none}.connection-editor__minimap-title{position:absolute;inset-block-start:7px;inset-inline-start:12px;color:var(--pce-muted);font-size:.6rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__minimap svg{position:relative;width:100%;height:100%;display:block;overflow:visible}.connection-editor__minimap-wire{fill:none;stroke:#b46cff8f;stroke-width:4;stroke-linecap:round;opacity:.86}.connection-editor__minimap-wire--state{stroke:#ff9f2fdb}.connection-editor__minimap-wire--state-read{stroke:#8b7dffb8;stroke-dasharray:4 9}.connection-editor__minimap-wire--projection{stroke:#19c8e88a;stroke-dasharray:18 8}.connection-editor__minimap-wire--event-propagation{stroke:#ffb454cc;stroke-dasharray:6 7}.connection-editor__minimap-wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.28))}.connection-editor__minimap-wire--trace{stroke:#9b5cffe0;stroke-width:5;stroke-dasharray:12 9;animation:connection-flow 1s linear infinite}.connection-editor__minimap-wire--active{stroke:#facc15eb;stroke-width:6;filter:drop-shadow(0 0 8px rgba(250,204,21,.38))}.connection-editor__minimap-wire--mode-dimmed{opacity:.2;stroke-width:2.6;filter:none}.connection-editor__minimap-node{fill:#f59e0be0;stroke:#020617db;stroke-width:4;filter:drop-shadow(0 0 7px rgba(245,158,11,.24))}.connection-editor__minimap-node--state{fill:#a855f7e6;filter:drop-shadow(0 0 8px rgba(168,85,247,.34))}.connection-editor__minimap-node--selected{fill:#facc15f5;stroke:#fef08aeb;filter:drop-shadow(0 0 10px rgba(250,204,21,.42))}.connection-editor__minimap-node--trace-source{fill:#facc15f5;filter:drop-shadow(0 0 10px rgba(250,204,21,.44))}.connection-editor__minimap-node--trace-reacting{fill:#22c55eeb;filter:drop-shadow(0 0 10px rgba(34,197,94,.42))}.connection-editor__minimap-node--mode-dimmed{opacity:.28;filter:none}.connection-editor__minimap-viewport{fill:#7dd3fc1f;stroke:#7dd3fce6;stroke-width:5;stroke-dasharray:18 10;filter:drop-shadow(0 0 10px rgba(125,211,252,.3));transition:x .12s ease,y .12s ease,width .12s ease,height .12s ease}.connection-editor__minimap--panning .connection-editor__minimap-viewport{fill:#22d3ee2e;stroke:#22d3eef5;stroke-dasharray:none}.connection-editor__node{position:absolute;width:168px;height:168px;transform:translate(-84px,-84px);border:0;padding:0;background:transparent;color:inherit;cursor:pointer;transition:filter .16s ease}.connection-editor__node--dragging{cursor:grabbing;filter:drop-shadow(0 0 22px rgba(34,211,238,.26));z-index:12}.connection-editor__node--connection-focus{filter:drop-shadow(0 0 16px rgba(34,211,238,.2))}.connection-editor__node--compat-target .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e66,0 0 0 18px #22c55e0b,0 0 32px #22c55e29}.connection-editor__node--mode-dimmed{opacity:.42;filter:grayscale(.22) saturate(.56)}.connection-editor__node--mode-dimmed .connection-editor__node-ring{animation:none;box-shadow:0 0 0 1px #2dd4bf14,0 0 14px #0ea5e90f}.connection-editor__node--mode-dimmed .connection-editor__node-halo{stroke-opacity:.28}.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-svg{position:absolute;inset:0}.connection-editor__node-ring,.connection-editor__node-core{display:grid;place-items:center;clip-path:polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%)}.connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from -28deg,#06b6d4b3 0 28%,#f59e0b9e 28% 48%,#a855f780 48% 68%,#06b6d4a3 68% 100%);box-shadow:0 0 0 1px #2dd4bf2e,0 0 26px #0ea5e929;animation:node-breathe 2.8s ease-in-out infinite}.connection-editor__node-svg{overflow:visible;filter:drop-shadow(0 0 16px rgba(14,165,233,.16))}.connection-editor__node-halo{fill:transparent;stroke:#38bdf838;stroke-width:1;stroke-dasharray:0;pointer-events:none}.connection-editor__node-halo:nth-child(2){stroke:#38bdf824}.connection-editor__node-halo:nth-child(3){stroke:#94a3b81a}.connection-editor__node-segment{fill-opacity:.28;stroke-opacity:.72;stroke-width:1.15;transition:fill-opacity .16s ease,stroke-opacity .16s ease,stroke-width .16s ease;cursor:grab}.connection-editor__node:hover .connection-editor__node-segment,.connection-editor__node--selected .connection-editor__node-segment,.connection-editor__node--connection-focus .connection-editor__node-segment{fill-opacity:.54;stroke-opacity:.95;stroke-width:1.55}.connection-editor__node-segment--connection-focus{fill-opacity:.76;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 8px rgba(34,211,238,.76));animation:segment-focus-sweep 1.45s ease-in-out infinite}.connection-editor__node-segment--source{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 12px rgba(251,146,60,.82))}.connection-editor__node-segment--compatible{fill-opacity:.74;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 10px rgba(34,197,94,.72));animation:snap-pulse 1s ease-in-out infinite}.connection-editor__node-segment--compat-preview{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 13px rgba(245,158,11,.78))}.connection-editor__node-segment--candidate{fill-opacity:.92;stroke-opacity:1;stroke-width:2.8;filter:drop-shadow(0 0 16px rgba(34,197,94,.86))}.connection-editor__node-segment--incompatible{fill-opacity:.12;stroke-opacity:.28;cursor:not-allowed}.connection-editor__node-segment--invalid-drop{fill-opacity:.72;stroke:#fb7185;stroke-opacity:1;stroke-width:3;filter:drop-shadow(0 0 16px rgba(244,63,94,.84));animation:invalid-drop-jolt .36s ease-out}.connection-editor__node-segment--state{fill-opacity:.44;filter:drop-shadow(0 0 8px rgba(180,108,255,.2))}.connection-editor__node-segment--mode-dimmed{fill-opacity:.08;stroke-opacity:.2;stroke-width:.9;filter:none}.connection-editor__node-anchor{opacity:.95;filter:drop-shadow(0 0 6px currentColor)}.connection-editor__node-rotate-handle{cursor:grab;opacity:0;pointer-events:none;transition:opacity .16s ease,filter .16s ease;filter:drop-shadow(0 0 8px rgba(34,211,238,.28))}.connection-editor__node:hover .connection-editor__node-rotate-handle,.connection-editor__node--selected .connection-editor__node-rotate-handle,.connection-editor__node--rotating .connection-editor__node-rotate-handle{opacity:1;pointer-events:auto}.connection-editor__node--rotating .connection-editor__node-rotate-handle{cursor:grabbing;filter:drop-shadow(0 0 12px rgba(34,211,238,.54))}.connection-editor__node-rotate-hit{fill:transparent}.connection-editor__node-rotate-dot{fill:var(--pce-surface-strong);stroke:var(--pce-primary);stroke-opacity:.88;stroke-width:1.4}.connection-editor__node-rotate-arc,.connection-editor__node-rotate-arrow{fill:none;stroke:var(--pce-primary);stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.96;stroke-width:1.2;pointer-events:none}.connection-editor__segment-icon,.connection-editor__segment-label{pointer-events:none;fill:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:800;paint-order:stroke;stroke:#020617c2;stroke-width:3px;stroke-linejoin:round}.connection-editor__segment-icon{font-size:12px;fill:#19c8e8}.connection-editor__segment-icon--output{fill:#ff9f2f}.connection-editor__segment-label{font-size:9.5px;letter-spacing:0;fill:#e2e8f0e0}.connection-editor__node-core{inset:43px;padding:12px;border-radius:999px;clip-path:none;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(circle at center,#111827 0 58%,#060b14);border:1px solid rgba(226,232,240,.1);box-shadow:0 12px 28px #00000073,inset 0 1px #ffffff0d;color:#f8fafc;text-shadow:0 1px 2px rgba(0,0,0,.62)}.connection-editor__node-icon{display:block;max-width:44px;overflow:hidden;color:#f8fafc;font-family:Material Symbols Outlined,Material Icons,sans-serif;font-size:1.22rem;font-weight:400;line-height:1;text-align:center;text-transform:none;letter-spacing:0;white-space:nowrap;filter:drop-shadow(0 0 10px rgba(226,232,240,.18))}.connection-editor__node--state .connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from 14deg,#a855f7c7 0 42%,#7e3af26b 42% 78%,#f59e0b47 78% 100%);box-shadow:0 0 0 1px #a855f738,0 0 30px #a855f733}.connection-editor__node--selected .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15bd,0 0 34px #facc153d}.connection-editor__node--connection-focus .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eead,0 0 38px #22d3ee42;animation:node-focus-breathe 1.7s ease-in-out infinite}.connection-editor__node--trace-source .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 0 18px #facc150f,0 0 54px #facc154d;animation:trace-source-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:before{content:\"\";position:absolute;z-index:0;inset:-44px;border-radius:999px;border:2px solid rgba(250,204,21,.36);background:radial-gradient(circle at center,transparent 0 64%,rgba(250,204,21,.05) 65% 66%,transparent 67%),conic-gradient(from -20deg,#facc1500,#facc1552,#facc1500);box-shadow:0 0 36px #facc151f;opacity:.92;pointer-events:none;animation:trace-source-orbit 2.8s linear infinite}.connection-editor__node--trace-reacting .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e94,0 0 46px #22c55e38;animation:trace-reacting-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:after,.connection-editor__node--trace-reacting:after{position:absolute;z-index:3;inset-inline-start:50%;inset-block-start:-42px;padding:0;border:0;background:transparent;color:#facc15;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.68rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase;transform:translate(-50%);text-shadow:0 0 12px rgba(250,204,21,.52);pointer-events:none}.connection-editor__node--trace-source:after{content:attr(data-trace-label)}.connection-editor__node--trace-reacting:after{content:attr(data-trace-label);color:#86efac;text-shadow:0 0 12px rgba(34,197,94,.44)}.connection-editor__node--trace-source .connection-editor__node-segment--output{fill-opacity:.66;stroke-width:2.2;filter:drop-shadow(0 0 14px rgba(255,159,47,.42))}.connection-editor__node--expanded .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eebd,0 0 34px #22d3ee3d}.connection-editor__node--rotating .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 42px #facc1547;animation:node-focus-breathe 1.1s ease-in-out infinite}.connection-editor__node--rotating .connection-editor__node-segment{fill-opacity:.68;stroke-opacity:1;stroke-width:1.9;cursor:grabbing}.connection-editor__node-title,.connection-editor__node-subtitle{display:block;max-width:92px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.connection-editor__node-title{color:#f8fafc;font-size:.82rem;font-weight:800}.connection-editor__node-subtitle{margin-top:4px;color:#a7b4c8;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__ports{position:absolute;display:grid;gap:6px;width:104px;opacity:0;pointer-events:none;transition:opacity .16s ease}.connection-editor__segment-popover{position:absolute;z-index:80;width:292px;max-height:320px;overflow:auto;display:grid;gap:10px;padding:14px;border-radius:16px;border:1px solid rgba(148,163,184,.18);background:linear-gradient(135deg,#0f172af5,#110c20f0),#090c16eb;box-shadow:0 28px 72px #0000007a,0 0 48px #a855f71a,inset 0 1px #ffffff0d;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__segment-popover-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:2px}.connection-editor__segment-popover-title{color:#94a3b8;font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}.connection-editor__segment-popover-hint{margin-top:5px;color:#64748b;font-size:.66rem;font-weight:700}.connection-editor__segment-rotation{flex:0 0 auto;min-width:54px;padding:5px 8px;border-radius:999px;border:1px solid rgba(34,211,238,.28);background:#082f4957;color:#7dd3fc;font-size:.66rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-align:center;box-shadow:inset 0 0 16px #0ea5e914}.connection-editor__segment-row{display:grid;grid-template-columns:28px 72px minmax(0,1fr) auto;align-items:center;gap:8px;min-height:40px;padding:7px;border-radius:12px;border:1px solid rgba(148,163,184,.12);background:linear-gradient(90deg,#0f172ac7,#0f172a75),#0f172a99;transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__segment-row--input{border-color:#22d3ee42}.connection-editor__segment-row--output{border-color:#f59e0b47}.connection-editor__segment-row--state{border-color:#a855f74d}.connection-editor__segment-row--source,.connection-editor__segment-row--candidate{transform:translate(2px);box-shadow:0 0 22px #f59e0b24,inset 0 0 20px #f59e0b14}.connection-editor__segment-row--compatible{border-color:#22d3ee6b;box-shadow:inset 0 0 18px #22d3ee14}.connection-editor__segment-row--compat-preview{border-color:#f59e0b94;background:linear-gradient(90deg,#f59e0b1f,#0f172a8a),#0f172ab3;box-shadow:0 0 22px #f59e0b1f,inset 0 0 18px #f59e0b14}.connection-editor__segment-row--invalid-drop{border-color:#fb7185b3;background:linear-gradient(90deg,#f43f5e24,#0f172a94),#0f172ab3;box-shadow:0 0 24px #f43f5e2e,inset 0 0 18px #f43f5e1a;animation:invalid-drop-jolt .36s ease-out}.connection-editor__segment-index{color:#64748b;font-size:.64rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;letter-spacing:.08em}.connection-editor__segment-kind{display:inline-flex;align-items:center;gap:6px;color:#94a3b8;font-size:.62rem;font-weight:800;text-transform:uppercase;min-width:0;white-space:nowrap}.connection-editor__segment-kind-dot{width:7px;height:7px;border-radius:999px;background:#94a3b8;box-shadow:0 0 12px #94a3b847}.connection-editor__segment-row--input .connection-editor__segment-kind-dot{background:#22d3ee;box-shadow:0 0 12px #22d3ee61}.connection-editor__segment-row--output .connection-editor__segment-kind-dot{background:#fb923c;box-shadow:0 0 12px #fb923c66}.connection-editor__segment-row--state .connection-editor__segment-kind-dot{background:#a855f7;box-shadow:0 0 12px #a855f76b}.connection-editor__segment-label{display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden;color:#e2e8f0;font-size:.74rem;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-actions{display:inline-flex;gap:4px}.connection-editor__segment-action{width:24px;height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.18);background:#060c16b8;color:#dbeafe;cursor:pointer;font-weight:900;line-height:1}.connection-editor__segment-action:hover{border-color:#22d3ee75;box-shadow:0 0 14px #22d3ee29}.connection-editor__port{min-height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#080d18c2;color:#cbd5e1;font-size:.64rem;font-weight:700;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:crosshair;box-shadow:0 8px 20px #00000038}.connection-editor__port--output{border-color:#f59e0b75;color:#fbbf24}.connection-editor__port--input{border-color:#06b6d475;color:#22d3ee}.connection-editor__port--state{border-color:#a855f785;color:#c084fc}.connection-editor__port--compatible{background:#22c55e29;box-shadow:0 0 0 1px #22c55e61,0 0 18px #22c55e2e;animation:snap-pulse 1s ease-in-out infinite}.connection-editor__port--source{border-color:#fb923cb8;background:#fb923c29;color:#fed7aa;box-shadow:0 0 0 1px #fb923c73,0 0 20px #fb923c2e}.connection-editor__port--candidate{background:#22c55e3d;box-shadow:0 0 0 2px #22c55e94,0 0 24px #22c55e3d}.connection-editor__port--incompatible{opacity:.42;cursor:not-allowed;filter:grayscale(.45)}.connection-editor__port--invalid-drop{opacity:1;border-color:#fb7185c7;color:#fecdd3;background:#f43f5e2e;box-shadow:0 0 0 2px #f43f5e75,0 0 24px #f43f5e38;filter:none;animation:invalid-drop-jolt .36s ease-out}.connection-editor__port--connection-focus{border-color:#facc15ad;color:#fde68a;background:#facc151f;box-shadow:0 0 0 1px #facc156b,0 0 20px #facc152e;animation:port-focus-pulse 1.25s ease-in-out infinite}.connection-editor__drag-tip{position:absolute;z-index:6;display:grid;gap:4px;width:min(330px,calc(100% - 28px));padding:10px 12px;border-radius:14px;border:1px solid rgba(125,211,252,.26);background:linear-gradient(135deg,#0ea5e91f,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 28px #0ea5e91a;font-size:.76rem;pointer-events:none;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);animation:tooltip-rise .14s ease-out}.connection-editor__drag-tip--valid{border-color:#22c55e66;background:linear-gradient(135deg,#22c55e29,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 30px #22c55e24}.connection-editor__drag-tip--invalid{z-index:7;border-color:#fb71858a;background:linear-gradient(135deg,#f43f5e2e,#0f172af0),#080d18f5;box-shadow:0 18px 44px #0206176b,0 0 34px #f43f5e29;animation:tooltip-rise .14s ease-out,invalid-drop-jolt .36s ease-out}.connection-editor__invalid-drop-pulse{position:absolute;z-index:6;width:16px;height:16px;border-radius:999px;border:2px solid rgba(251,113,133,.88);background:#f43f5e38;box-shadow:0 0 0 8px #f43f5e1a,0 0 28px #f43f5e3d;pointer-events:none;transform:translate(-50%,-50%);animation:invalid-drop-ping 1.2s ease-out both}.connection-editor__drag-tip span{color:#7dd3fc;text-transform:uppercase;letter-spacing:.12em;font-size:.62rem;font-weight:800}.connection-editor__drag-tip strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.78rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__drag-tip small{color:#94a3b8;font-size:.68rem;font-weight:700}.connection-editor__drag-tip--valid small{color:#86efac}.connection-editor__drag-tip--invalid span,.connection-editor__drag-tip--invalid small{color:#fda4af}.connection-editor__summary{grid-column:1;grid-row:3;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.connection-editor__side-panel{grid-column:2;grid-row:2 / 4;position:relative;z-index:8;min-width:0;min-height:0;display:grid;align-content:start;gap:14px;overflow:auto;padding-inline-end:4px;scrollbar-color:var(--pce-outline-strong) var(--pce-surface-soft)}.connection-editor__metric,.connection-editor__item{border-radius:16px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__metric{padding:10px;display:grid;gap:4px}.connection-editor__metric span{color:var(--pce-muted);font-size:.72rem}.connection-editor__metric strong,.connection-editor__details-row strong{color:var(--pce-strong);font-size:.9rem}.connection-editor__filters,.connection-editor__actions,.connection-editor__badges{display:flex;gap:8px;flex-wrap:wrap}.connection-editor__filter,.connection-editor__action{border:1px solid var(--pce-outline-strong);background:var(--pce-surface-soft);color:var(--pce-fg);border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connection-editor__filter--active,.connection-editor__action:hover{border-color:color-mix(in srgb,var(--pce-secondary) 62%,transparent);background:color-mix(in srgb,var(--pce-secondary) 16%,var(--pce-surface-soft));color:var(--pce-strong)}.connection-editor__action--danger{border-color:#f8717161;color:#fecaca}.connection-editor__item{width:100%;text-align:start;padding:12px;display:grid;gap:6px;cursor:pointer;color:inherit}.connection-editor__item--active{border-color:#a855f7b8;background:linear-gradient(90deg,#0ea5e91a,#a855f721)}.connection-editor__item-title{font-weight:800;color:#f8fafc;word-break:break-word}.connection-editor__badge{padding:3px 8px;border-radius:999px;background:#0ea5e92e;color:#bae6fd;font-size:.72rem;font-weight:800}.connection-editor__section{min-width:0;padding:14px;border-radius:18px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight),0 18px 50px var(--pce-shadow-soft);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__badge--warning{background:#facc1524;color:#fde68a}.connection-editor__badge--error{background:#ef444424;color:#fecaca}.connection-editor__diagnostics{display:grid;gap:8px}.connection-editor__diagnostic{display:grid;gap:4px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.78rem;line-height:1.35}.connection-editor__diagnostic--warning{border-color:#f59e0b47;background:#f59e0b1a}.connection-editor__diagnostic--error{border-color:#ef44445c;background:#ef44441f}.connection-editor__diagnostic-severity{font-size:.68rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#f8fafc}.connection-editor__suggestions{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__suggestion{display:grid;gap:8px;width:100%;padding:12px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 12%,transparent),color-mix(in srgb,var(--pce-primary) 8%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__suggestion:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 46%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 18%,transparent),color-mix(in srgb,var(--pce-primary) 12%,transparent)),var(--pce-surface-strong)}.connection-editor__suggestion-route{display:grid;gap:4px;font-size:.78rem}.connection-editor__suggestion-route strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__suggestion-reason{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__suggestion-action{justify-self:start;padding:3px 8px;border-radius:999px;background:#22d3ee24;color:#67e8f9;font-size:.68rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase}:host-context(.theme-light) .connection-editor__suggestion-action{background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:#075f73}.connection-editor__trace{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__trace-summary{color:var(--pce-muted);font-size:.78rem;line-height:1.35}.connection-editor__trace-step{display:grid;grid-template-columns:24px minmax(76px,auto) 1fr;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(34,211,238,.18);background:var(--pce-surface-soft);font-size:.76rem}.connection-editor__trace-step--blocked{border-color:#ef444457;background:#ef44441a}.connection-editor__trace-order{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:999px;background:#22d3ee29;color:#67e8f9;font-weight:900}.connection-editor__trace-phase{color:var(--pce-strong);font-weight:900;text-transform:uppercase;letter-spacing:.06em;font-size:.66rem}.connection-editor__trace-copy{min-width:0;color:var(--pce-fg);word-break:break-word}.connection-editor__transform-steps{display:grid;gap:8px}.connection-editor__transform-step{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(168,85,247,.22);background:var(--pce-surface-soft)}.connection-editor__transform-kind{min-width:0;color:var(--pce-strong);font-weight:900;word-break:break-word}.connection-editor__transform-phase{color:var(--pce-muted);font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.connection-editor__details-row,.connection-editor__details-block{display:grid;gap:6px}.connection-editor__payload-input{width:100%;min-height:128px;box-sizing:border-box;resize:vertical;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 92%,black);color:var(--pce-fg);padding:10px;font:.76rem/1.45 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.connection-editor__surface-action-editor{display:block;max-height:min(58vh,620px);overflow:auto;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 96%,black);padding:10px;margin-bottom:10px}.connection-editor__rule-grid{display:grid;gap:10px}.connection-editor__rule-card{display:grid;gap:8px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__rule-heading{color:var(--pce-fg);font-size:.72rem;font-weight:900;text-transform:uppercase;letter-spacing:.06em}pre{margin:0;padding:12px;border-radius:12px;background:color-mix(in srgb,var(--pce-surface-strong) 82%,#020617);color:var(--pce-fg);overflow:auto;font-size:.75rem}@keyframes connection-flow{to{stroke-dashoffset:-38}}@keyframes drag-wire-pulse{0%,to{stroke-opacity:.76}50%{stroke-opacity:1}}@keyframes drag-halo-pulse{0%,to{stroke-opacity:.48}50%{stroke-opacity:.82}}@keyframes endpoint-pulse{0%,to{opacity:.78;transform:scale(1)}50%{opacity:1;transform:scale(1.25)}}@keyframes selected-wire-aura{0%,to{stroke-opacity:.46}50%{stroke-opacity:.92}}@keyframes wire-draw-in{0%{stroke-dashoffset:640;opacity:.32}70%{opacity:1}to{stroke-dashoffset:0;opacity:1}}@keyframes new-wire-halo{0%{stroke-opacity:0;stroke-width:30}28%{stroke-opacity:.78}to{stroke-opacity:0;stroke-width:12}}@keyframes new-dock-link-flash{0%{transform:translateY(-2px);box-shadow:0 16px 40px #0206175c,0 0 42px #fb923c47}to{transform:translateY(0)}}@keyframes trace-wire-pulse{0%,to{stroke-opacity:.78}50%{stroke-opacity:1}}@keyframes trace-halo-pulse{0%,to{stroke-opacity:.34}50%{stroke-opacity:.86}}@keyframes tooltip-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes invalid-drop-jolt{0%,to{transform:translate(0)}28%{transform:translate(-3px)}56%{transform:translate(3px)}}@keyframes invalid-drop-ping{0%{opacity:1;transform:translate(-50%,-50%) scale(.72)}72%{opacity:.74;transform:translate(-50%,-50%) scale(1.35)}to{opacity:0;transform:translate(-50%,-50%) scale(1.8)}}@keyframes node-breathe{50%{transform:scale(1.035)}}@keyframes node-focus-breathe{0%,to{transform:scale(1)}50%{transform:scale(1.055)}}@keyframes trace-source-pulse{50%{transform:scale(1.04);box-shadow:0 0 0 3px #facc15db,0 0 0 22px #facc1514,0 0 64px #facc1557}}@keyframes trace-source-orbit{to{transform:rotate(360deg)}}@keyframes trace-reacting-pulse{50%{transform:scale(1.045);box-shadow:0 0 0 3px #22c55ead,0 0 62px #22c55e4d}}@keyframes segment-focus-sweep{0%,to{stroke-opacity:.82}50%{stroke-opacity:1}}@keyframes snap-pulse{50%{transform:scale(1.04)}}@keyframes port-focus-pulse{50%{transform:translateY(-1px);box-shadow:0 0 0 2px #facc158f,0 0 26px #facc153d}}@media(prefers-reduced-motion:reduce){.connection-editor__viewport,.connection-editor__node,.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-segment,.connection-editor__dock-link,.connection-editor__port{transition-duration:1ms}.connection-editor__wire,.connection-editor__wire--state,.connection-editor__wire--projection,.connection-editor__wire--state-read,.connection-editor__wire--event-propagation,.connection-editor__wire--halo.connection-editor__wire--active,.connection-editor__wire--trace,.connection-editor__wire--halo.connection-editor__wire--trace,.connection-editor__wire-endpoint,.connection-editor__connection-tooltip,.connection-editor__dock-link--new,.connection-editor__trace-overlay,.connection-editor__trace-overlay-step,.connection-editor__drag-wire,.connection-editor__drag-wire--halo,.connection-editor__drag-endpoint,.connection-editor__drag-tip,.connection-editor__node-ring,.connection-editor__node--connection-focus .connection-editor__node-ring,.connection-editor__node--trace-source .connection-editor__node-ring,.connection-editor__node--trace-source:before,.connection-editor__node--trace-reacting .connection-editor__node-ring,.connection-editor__node--rotating .connection-editor__node-ring,.connection-editor__node-segment--connection-focus,.connection-editor__node-segment--compatible,.connection-editor__node-segment--invalid-drop,.connection-editor__segment-popover,.connection-editor__port--compatible,.connection-editor__port--invalid-drop,.connection-editor__port--connection-focus,.connection-editor__invalid-drop,.connection-editor__invalid-drop-pulse{animation:none}.connection-editor__wire{stroke-dashoffset:0}.connection-editor__wire--new{stroke-dasharray:10 8;stroke-dashoffset:0;opacity:1}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:12;stroke-opacity:.16}.connection-editor__wire-endpoint,.connection-editor__drag-endpoint,.connection-editor__node-ring,.connection-editor__node--trace-source:before{transform:none}.connection-editor__invalid-drop-pulse{opacity:0}}@media(max-width:900px){:host{inset:0}.connection-editor{inset:8px;height:calc(100vh - 16px);padding:12px;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(260px,1fr) auto minmax(150px,30vh) minmax(86px,126px)}.connection-editor__header,.connection-editor__stage,.connection-editor__summary,.connection-editor__side-panel,.connection-editor__dock{grid-column:1}.connection-editor__header{align-items:stretch;flex-wrap:wrap;border-radius:18px}.connection-editor__mode-frame{order:3;width:100%;max-width:100%}.connection-editor__mode-frame:before,.connection-editor__mode-frame:after{content:\"\";position:absolute;z-index:2;inset-block:4px;width:24px;border-radius:999px;pointer-events:none}.connection-editor__mode-frame:before{inset-inline-start:1px;background:linear-gradient(90deg,#080d18f0,#080d1800)}.connection-editor__mode-frame:after{inset-inline-end:1px;background:linear-gradient(270deg,#080d18f0,#080d1800)}.connection-editor__mode-shell{width:100%;max-width:100%;overflow-x:auto;scroll-padding-inline:28px;-webkit-overflow-scrolling:touch}.connection-editor__subtitle{margin-inline-start:auto}.connection-editor__stage{grid-row:2;min-height:260px}.connection-editor__summary{grid-row:3;grid-template-columns:1fr 1fr}.connection-editor__side-panel{grid-row:4;max-height:30vh}.connection-editor__dock{grid-row:5;min-height:0}.connection-editor__connection-tooltip{width:min(620px,calc(100% - 24px));max-height:min(260px,calc(100% - 24px));overflow:auto}.connection-editor__dock-tabs{width:100%;min-width:0;min-height:0;flex-wrap:wrap;align-items:flex-start}.connection-editor__dock-count{flex:1 1 100%;margin-inline-start:0}.connection-editor__dock-body{width:100%;min-width:0;max-height:76px;box-sizing:border-box}.connection-editor__dock-body pre{white-space:pre-wrap;overflow-wrap:anywhere}.connection-editor__dock-link{grid-template-columns:1fr;align-items:start}.connection-editor__dock-link-route{flex-wrap:wrap}.connection-editor__dock-link-badges{justify-content:flex-start}.connection-editor__trace-overlay{inset-inline-start:14px;width:min(420px,calc(100% - 28px));min-width:0;transform:none}.connection-editor__drag-tip{width:min(300px,calc(100% - 28px))}.connection-editor__segment-popover{width:min(280px,calc(100% - 28px));max-height:min(280px,calc(100% - 28px))}.connection-editor__minimap{inset-inline-end:10px;inset-block-end:10px;width:132px;height:94px;padding:16px 8px 8px;border-radius:14px}.connection-editor__minimap:before{inset:20px 8px 8px;background-size:18px 18px}.connection-editor__minimap-title{inset-block-start:6px;inset-inline-start:10px;font-size:.54rem}}@media(max-width:640px){.connection-editor{inset:4px;height:calc(100vh - 8px);padding:8px;gap:8px;grid-template-rows:auto minmax(240px,1fr) auto minmax(140px,28vh) minmax(82px,116px)}.connection-editor__header{gap:8px;padding:10px}.connection-editor__mode-shell{padding:4px;gap:2px}.connection-editor__mode{min-height:28px;gap:4px;padding:0 7px;font-size:.68rem}.connection-editor__mode-glyph{font-size:.64rem}.connection-editor__stage{min-height:240px}.connection-editor__zoom-controls{inset-inline-start:8px;inset-block-start:8px;gap:6px;width:126px}.connection-editor__tool-group,.connection-editor__trace-source{gap:6px;padding:8px;border-radius:12px}.connection-editor__tool-group{grid-template-columns:repeat(3,28px)}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:repeat(2,28px)}.connection-editor__tool-button{width:28px;height:28px}.connection-editor__arrange-button,.connection-editor__simulate-button{min-height:30px;gap:6px;padding-inline:8px;font-size:.68rem}.connection-editor__summary{gap:6px}.connection-editor__side-panel{max-height:28vh}.connection-editor__dock{border-radius:16px}.connection-editor__dock-tabs{gap:4px}.connection-editor__dock-tab{padding:0 9px}.connection-editor__dock-count{font-size:.62rem}.connection-editor__dock-body{max-height:66px;padding:8px}.connection-editor__minimap{width:116px;height:84px}.connection-editor__segment-row{grid-template-columns:24px minmax(54px,.55fr) minmax(0,1fr) auto}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SurfaceOpenActionEditorComponent, selector: "praxis-surface-open-action-editor", inputs: ["value", "hostKind"], outputs: ["valueChange"] }, { kind: "pipe", type: i2$3.JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8443
+ `, isInline: true, styles: [":host{position:fixed;inset:0;z-index:1000;pointer-events:none}.connection-editor{--pce-fg: var(--md-sys-color-on-surface, #dce6f4);--pce-strong: var(--md-sys-color-on-surface, #f8fafc);--pce-muted: var(--md-sys-color-on-surface-variant, #94a3b8);--pce-primary: var(--md-sys-color-primary, #19c8e8);--pce-secondary: var(--md-sys-color-secondary, #b46cff);--pce-tertiary: var(--md-sys-color-tertiary, #ff9f2f);--pce-success: var(--md-sys-color-tertiary, #10b981);--pce-warning: var(--md-sys-color-error, #ff9f2f);--pce-error: var(--md-sys-color-error, #ef4444);--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #07111f) 80%, #020617);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #08101d) 78%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #0f172a) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #080d18) 64%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #899ab7) 46%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #94a3b8) 58%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #7d8fa9) 24%, transparent);--pce-glass-highlight: color-mix(in srgb, var(--md-sys-color-on-surface, #ffffff) 8%, transparent);--pce-shadow: color-mix(in srgb, #000 56%, transparent);--pce-shadow-soft: color-mix(in srgb, #000 30%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #040a13) 42%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high, #050912) 94%, transparent);position:absolute;inset:12px;height:calc(100vh - 24px);box-sizing:border-box;overflow:hidden;padding:16px;border-radius:18px;color:var(--pce-fg);background:radial-gradient(circle at 72% 20%,color-mix(in srgb,var(--pce-secondary) 16%,transparent),transparent 28%),radial-gradient(circle at 26% 74%,color-mix(in srgb,var(--pce-primary) 10%,transparent),transparent 34%),radial-gradient(circle at 48% 52%,color-mix(in srgb,var(--pce-tertiary) 5%,transparent),transparent 35%),linear-gradient(var(--pce-grid) 1px,transparent 1px),linear-gradient(90deg,var(--pce-grid) 1px,transparent 1px),var(--pce-surface-base);background-size:auto,auto,auto,38px 38px,38px 38px,auto;border:1px solid var(--pce-outline);box-shadow:0 28px 90px var(--pce-shadow);pointer-events:auto;display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);grid-template-rows:auto minmax(0,1fr) minmax(44px,118px);gap:14px}:host-context(.theme-light) .connection-editor{--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #ffffff) 94%, var(--md-sys-color-primary, #2563eb) 6%);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 82%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #eef2ff) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #f8fafc) 70%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 68%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #64748b) 62%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 34%, transparent);--pce-glass-highlight: color-mix(in srgb, #fff 64%, transparent);--pce-shadow: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 22%, transparent);--pce-shadow-soft: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 14%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #ffffff) 58%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 92%, transparent)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(0,1fr) 48px}.connection-editor__header{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:42px;padding:8px 14px;border-radius:999px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__mode-frame{position:relative;min-width:0;flex:1 1 auto;display:flex;justify-content:center}.connection-editor__close{width:32px;height:32px;flex:0 0 auto;display:inline-grid;place-items:center;border:1px solid var(--pce-outline);border-radius:999px;color:var(--pce-text);background:var(--pce-surface-strong);box-shadow:inset 0 1px var(--pce-glass-highlight);cursor:pointer;font:inherit;font-size:1.2rem;line-height:1}.connection-editor__close:hover,.connection-editor__close:focus-visible{border-color:var(--pce-outline-strong);background:color-mix(in srgb,var(--pce-accent) 16%,var(--pce-surface-strong));outline:none}.connection-editor__mode-shell{display:inline-flex;align-items:center;gap:4px;min-width:0;padding:4px;border-radius:999px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:inset 0 1px var(--pce-glass-highlight),0 10px 26px var(--pce-shadow-soft);scrollbar-width:none}.connection-editor__mode-shell::-webkit-scrollbar{display:none}.connection-editor__mode{min-height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 12px;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.76rem;font-weight:800;white-space:nowrap;transition:background .16s ease,border-color .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__mode:hover,.connection-editor__mode--active{color:var(--pce-strong);border-color:color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-strong) 82%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 12%,transparent)}.connection-editor__mode-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__mode--active .connection-editor__mode-glyph{color:var(--pce-primary)}.connection-editor__mode-dot{width:6px;height:6px;border-radius:999px;background:var(--pce-success);box-shadow:0 0 12px color-mix(in srgb,var(--pce-success) 70%,transparent)}.connection-editor__status-pill{display:inline-flex;align-items:center;gap:8px;min-height:24px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 36%,transparent);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.72rem;font-weight:800;white-space:nowrap}.connection-editor__status-pill--button{cursor:pointer;transition:border-color .16s ease,background .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__status-pill--button:hover,.connection-editor__status-pill--button:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 62%,transparent);background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 14%,transparent);outline:none}.connection-editor__status-pill span{width:6px;height:6px;border-radius:999px;background:var(--pce-primary);box-shadow:0 0 12px color-mix(in srgb,var(--pce-primary) 70%,transparent)}.connection-editor__section{display:grid;gap:10px}.connection-editor__dock{grid-column:1 / -1;grid-row:3;position:relative;z-index:4;min-height:0;display:grid;border-radius:14px;border:1px solid var(--pce-outline);background:radial-gradient(circle at 16% 0%,color-mix(in srgb,var(--pce-primary) 22%,transparent),transparent 34%),radial-gradient(circle at 78% 0%,color-mix(in srgb,var(--pce-secondary) 25%,transparent),transparent 38%),linear-gradient(90deg,var(--pce-dock-bg),var(--pce-surface-strong) 46%,color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-dock-bg))),var(--pce-dock-bg);box-shadow:0 18px 58px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__dock--collapsed .connection-editor__dock-tabs{border-block-end:0}.connection-editor__dock-tabs{display:flex;align-items:center;gap:10px;min-height:52px;padding:9px 14px;border-block-end:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-glass-highlight),transparent),color-mix(in srgb,var(--pce-surface-soft) 34%,transparent)}.connection-editor__dock-tab,.connection-editor__dock-toggle{min-height:30px;border-radius:999px;border:1px solid transparent;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.72rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-tab{display:inline-flex;align-items:center;gap:8px;padding:0 13px;white-space:nowrap}.connection-editor__dock-tab-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.8rem;letter-spacing:0;text-transform:none}.connection-editor__dock-tab--active{color:var(--pce-strong);border-color:var(--pce-outline-strong);background:linear-gradient(180deg,color-mix(in srgb,var(--pce-strong) 14%,transparent),color-mix(in srgb,var(--pce-strong) 6%,transparent));box-shadow:0 0 0 1px color-mix(in srgb,var(--pce-shadow) 72%,transparent),0 0 22px color-mix(in srgb,var(--pce-strong) 8%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__dock-tab--active .connection-editor__dock-tab-glyph{color:var(--pce-strong)}.connection-editor__dock-count{margin-inline-start:auto;color:color-mix(in srgb,var(--pce-muted) 62%,transparent);font-size:.7rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-toggle{width:32px;padding:0;border-color:var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.88rem;letter-spacing:0}.connection-editor__dock-body{max-height:154px;overflow:auto;padding:12px 12px 14px;border-block-start:1px solid var(--pce-outline);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 9%,transparent),color-mix(in srgb,var(--pce-secondary) 10%,transparent) 62%,color-mix(in srgb,var(--pce-surface-strong) 18%,transparent)),color-mix(in srgb,var(--pce-surface-soft) 30%,transparent)}.connection-editor__dock-body pre{max-height:60px}.connection-editor__dock-links{display:grid;gap:8px}.connection-editor__dock-link-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;padding:7px 10px;border-radius:10px;border:1px solid var(--pce-outline);background:linear-gradient(90deg,var(--pce-surface-soft),color-mix(in srgb,var(--pce-secondary) 10%,var(--pce-surface-soft)) 72%,var(--pce-surface-soft)),var(--pce-surface-soft);color:var(--pce-fg);transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-link{display:grid;grid-template-columns:minmax(116px,.52fr) minmax(300px,1.72fr) minmax(160px,.9fr) auto;align-items:center;gap:12px;width:100%;min-height:42px;padding:0;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer;text-align:start}.connection-editor__dock-link-row:hover,.connection-editor__dock-link--active{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 13%,transparent),color-mix(in srgb,var(--pce-secondary) 16%,transparent),var(--pce-surface-strong)),var(--pce-surface-strong);box-shadow:0 12px 32px var(--pce-shadow-soft),inset 0 0 18px color-mix(in srgb,var(--pce-primary) 6%,transparent)}.connection-editor__dock-link--active{border-color:#facc1575;box-shadow:0 12px 32px var(--pce-shadow-soft),0 0 24px #facc151f}.connection-editor__dock-link--new{border-color:#fb923ca3;background:linear-gradient(90deg,#fb923c2e,#a855f729,#0ea5e91f),#0f172ac2;box-shadow:0 12px 34px #02061752,0 0 30px #fb923c2e;animation:new-dock-link-flash 1.35s ease-out forwards}.connection-editor__dock-link--error{border-color:#ef444461}.connection-editor__dock-jump{min-width:62px;min-height:30px;padding:0 10px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 54%,transparent);color:var(--pce-primary);cursor:pointer;font-size:.66rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__dock-jump:hover,.connection-editor__dock-jump:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 56%,transparent);background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 18%,transparent);outline:none}.connection-editor__dock-link-kind{display:inline-flex;align-items:center;gap:7px;min-width:0;color:var(--pce-muted);font-size:.66rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-link-kind span{width:8px;height:8px;border-radius:999px;background:#b46cff;box-shadow:0 0 14px #b46cff7a}.connection-editor__dock-link--state .connection-editor__dock-link-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2f94}.connection-editor__dock-link--state-read .connection-editor__dock-link-kind span{background:#8b7dff;box-shadow:0 0 13px #8b7dff75}.connection-editor__dock-link--projection .connection-editor__dock-link-kind span{background:#19c8e8;box-shadow:0 0 10px #19c8e857}.connection-editor__dock-link--event-propagation .connection-editor__dock-link-kind span{background:#ffb454;box-shadow:0 0 15px #ffb45485}.connection-editor__dock-link--policy .connection-editor__dock-link-kind span{outline:1px solid rgba(34,197,94,.76);outline-offset:2px;box-shadow:0 0 16px #22c55e61}.connection-editor__dock-link--policy:not(.connection-editor__dock-link--state,.connection-editor__dock-link--state-read,.connection-editor__dock-link--projection,.connection-editor__dock-link--event-propagation) .connection-editor__dock-link-kind span{background:#22c55e}.connection-editor__dock-link-route{display:inline-flex;align-items:center;gap:8px;min-width:0}.connection-editor__dock-link-chip{min-width:0;overflow:hidden;padding:4px 8px;border-radius:999px;border:1px solid var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-soft) 72%,transparent);color:var(--pce-fg);font-size:.72rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-chip--from{border-color:#ff9f2f66;color:#ffbd62}.connection-editor__dock-link-chip--to{border-color:#19c8e83d;color:#7dddeb}:host-context(.theme-light) .connection-editor__dock-link-chip--from{border-color:color-mix(in srgb,var(--pce-tertiary) 46%,transparent);color:#8a4600}:host-context(.theme-light) .connection-editor__dock-link-chip--to{border-color:color-mix(in srgb,var(--pce-primary) 34%,transparent);color:#075f73}.connection-editor__dock-link-arrow{flex:0 0 auto;color:var(--pce-muted);font-weight:900}.connection-editor__dock-link-id{min-width:0;overflow:hidden;color:var(--pce-muted);font-size:.66rem;font-weight:800;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-badges{display:inline-flex;justify-content:flex-end;gap:5px;min-width:70px}.connection-editor__dock-link-badges span{padding:3px 7px;border-radius:999px;background:#a855f724;color:#d8b4fe;font-size:.62rem;font-weight:900;text-transform:uppercase;white-space:nowrap}:host-context(.theme-light) .connection-editor__dock-link-badges span{background:color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-surface-soft));color:#6d2a9f}.connection-editor__dock-empty{padding:12px;border-radius:12px;border:1px dashed var(--pce-outline);color:var(--pce-muted);font-size:.76rem;font-weight:700}.connection-editor__inspector{border-color:color-mix(in srgb,var(--pce-primary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 10%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface)}.connection-editor__eyebrow,.connection-editor__section-title{font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;color:var(--pce-muted);font-weight:700}.connection-editor__title{font-size:1.02rem;font-weight:800}.connection-editor__subtitle,.connection-editor__item-copy,.connection-editor__item-meta,.connection-editor__details-row span,.connection-editor__details-label,.connection-editor__empty{color:var(--pce-muted);font-size:.84rem}.connection-editor__inspector-heading{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--pce-surface-soft);border:1px solid var(--pce-outline)}.connection-editor__inspector-heading strong{color:var(--pce-strong);font-size:.96rem;overflow-wrap:anywhere}.connection-editor__inspector-heading span{color:var(--pce-primary);font-size:.76rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em}.connection-editor__human-summary{display:grid;gap:6px;padding:12px;border-radius:14px;border:1px solid color-mix(in srgb,var(--pce-primary) 24%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface-soft);color:var(--pce-fg);line-height:1.35}.connection-editor__nested-summary{display:grid;gap:6px;padding:10px;border-radius:12px;border:1px solid color-mix(in srgb,var(--pce-primary) 22%,transparent);background:color-mix(in srgb,var(--pce-primary) 8%,var(--pce-surface-soft))}.connection-editor__nested-summary strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__nested-summary span:last-child{color:var(--pce-primary);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.72rem;overflow-wrap:anywhere}.connection-editor__recommended{border-color:color-mix(in srgb,var(--pce-secondary) 32%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 14%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface)}.connection-editor__recommended-card{display:grid;gap:8px;width:100%;padding:13px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 36%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 16%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__recommended-card:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 52%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 22%,transparent),color-mix(in srgb,var(--pce-primary) 14%,transparent)),var(--pce-surface-strong)}.connection-editor__recommended-card strong{color:var(--pce-strong);font-size:.92rem;line-height:1.28}.connection-editor__recommended-card span:not(.connection-editor__human-summary-label):not(.connection-editor__suggestion-action),.connection-editor__recommended-card small{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__success{display:grid;gap:4px;padding:10px 12px;border-radius:14px;border:1px solid rgba(34,197,94,.34);background:#22c55e1f;color:var(--pce-fg);line-height:1.35}.connection-editor__success strong{color:#bbf7d0;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__success span{color:var(--pce-strong);font-size:.82rem}.connection-editor__human-summary-label,.connection-editor__suggestion-intent{justify-self:start;padding:3px 8px;border-radius:999px;background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:#bae6fd;font-size:.66rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__human-summary strong{color:var(--pce-strong);font-size:.88rem}.connection-editor__human-summary span:last-child,.connection-editor__suggestion-preview{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__technical-details{display:grid;gap:10px;padding:10px 12px;border-radius:14px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__technical-details summary{cursor:pointer;color:var(--pce-muted);font-size:.78rem;font-weight:800}.connection-editor__technical-details[open] summary{margin-bottom:10px;color:var(--pce-strong)}.connection-editor__inspector-ports{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__inspector-port{max-width:100%;padding:4px 8px;border-radius:999px;border:1px solid rgba(148,163,184,.16);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-editor__inspector-port--input{border-color:#22d3ee57;color:#67e8f9}.connection-editor__inspector-port--output{border-color:#f59e0b57;color:#fbbf24}.connection-editor__inspector-port--state{border-color:#a855f761;color:#d8b4fe}.connection-editor__segment-kind-legend{display:grid;gap:10px;padding:12px;border-radius:16px;border:1px solid rgba(148,163,184,.14);background:linear-gradient(135deg,#0f172aa8,#080d1885),#02061757}.connection-editor__segment-kind-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.connection-editor__segment-kind-pill{min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:900;overflow:hidden;white-space:nowrap}.connection-editor__segment-kind-pill span{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:currentColor;box-shadow:0 0 12px currentColor}.connection-editor__segment-kind-pill--input{border-color:#19c8e83d;color:#7dddeb}.connection-editor__segment-kind-pill--output{border-color:#ff9f2f61;color:#ffbd62}.connection-editor__segment-kind-pill--state{border-color:#b46cff61;color:#d9b8ff}:host-context(.theme-light) .connection-editor__segment-kind-pill{border-color:var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-strong) 88%,transparent)}:host-context(.theme-light) .connection-editor__segment-kind-pill--input{color:#075f73}:host-context(.theme-light) .connection-editor__segment-kind-pill--output{color:#8a4600}:host-context(.theme-light) .connection-editor__segment-kind-pill--state{color:#6d2a9f}.connection-editor__stage{grid-column:1;grid-row:2;position:relative;min-height:0;height:100%;overflow:visible;border-radius:16px;border:1px solid var(--pce-outline);background:radial-gradient(circle at center,color-mix(in srgb,var(--pce-secondary) 7%,transparent),transparent 38%),radial-gradient(circle,var(--pce-grid) 1px,transparent 1.5px),var(--pce-stage-bg);background-size:auto,31px 31px,auto;box-shadow:inset 0 0 0 1px var(--pce-glass-highlight);cursor:grab;touch-action:none}.connection-editor__stage--panning,.connection-editor__stage:active{cursor:grabbing}.connection-editor__stage--dragging{cursor:crosshair}.connection-editor__stage--rotating{cursor:grabbing}.connection-editor__viewport{position:absolute;inset-block-start:0;inset-inline-start:0;width:900px;height:540px;overflow:visible;transform-origin:0 0;transition:transform .14s ease}.connection-editor__wires{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.connection-editor__wire,.connection-editor__wire-hit{fill:none;stroke-linecap:round}.connection-editor__wire{stroke:#b46cff;stroke-width:1.45;stroke-opacity:.48;pointer-events:none;filter:url(#connection-glow);stroke-dasharray:10 8;animation:connection-flow 1.65s linear infinite}.connection-editor__wire-hit{stroke:transparent;stroke-width:18;cursor:pointer;pointer-events:stroke}.connection-editor__wire-hit--active{stroke-width:28}.connection-editor__wire--halo{stroke:#b46cff1f;stroke-width:7;stroke-dasharray:none;animation:none}.connection-editor__wire--state{stroke:#ff9f2f;stroke-width:2.25;stroke-dasharray:8 7;animation:connection-flow .92s linear infinite}.connection-editor__wire--state.connection-editor__wire--halo{stroke:#ff9f2f29;stroke-width:11}.connection-editor__wire--projection{stroke:#15b8d8;stroke-width:1.75;stroke-dasharray:20 8;animation:connection-flow 1.9s linear infinite}.connection-editor__wire--projection.connection-editor__wire--halo{stroke:#15b8d81a;stroke-width:7}.connection-editor__wire--state-read{stroke:#8b7dff;stroke-width:1.65;stroke-dasharray:3 11;animation:connection-flow 2.25s linear infinite reverse}.connection-editor__wire--state-read.connection-editor__wire--halo{stroke:#8b7dff21;stroke-width:8}.connection-editor__wire--event-propagation{stroke:#ffb454;stroke-width:2.05;stroke-dasharray:5 7;animation:connection-flow .78s linear infinite}.connection-editor__wire--event-propagation.connection-editor__wire--halo{stroke:#ffb4542e;stroke-width:10}.connection-editor__wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.2)) url(#connection-glow)}.connection-editor__wire--policy.connection-editor__wire--halo{stroke:#22c55e1f;stroke-width:13}.connection-editor__wire--warning{stroke:#ff9f2f}.connection-editor__wire--warning.connection-editor__wire--halo{stroke:#ff9f2f2e}.connection-editor__wire--error{stroke:#ef4444}.connection-editor__wire--error.connection-editor__wire--halo{stroke:#ef44442e}.connection-editor__wire--active{stroke:#d9b8ff;stroke-width:3;stroke-opacity:1;stroke-dasharray:5 7;animation-duration:.58s}.connection-editor__wire--halo.connection-editor__wire--active{stroke-width:16;stroke-opacity:.8;animation:selected-wire-aura 1.35s ease-in-out infinite}.connection-editor__wire--new{stroke-width:3.4;stroke-opacity:1;stroke-dasharray:640;stroke-dashoffset:640;animation:wire-draw-in .62s cubic-bezier(.16,1,.3,1) forwards,connection-flow 1.05s linear .62s infinite}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:22;stroke-opacity:0;animation:new-wire-halo 1.45s ease-out forwards}.connection-editor__wire--trace{stroke:#9b5cff;stroke-width:3.2;stroke-opacity:1;stroke-dasharray:7 6;animation:connection-flow .72s linear infinite,trace-wire-pulse 1.18s ease-in-out infinite}.connection-editor__wire--halo.connection-editor__wire--trace{stroke:#9b5cff57;stroke-width:18;stroke-opacity:.86;animation:trace-halo-pulse 1.18s ease-in-out infinite}.connection-editor__wire--mode-dimmed{stroke-opacity:.14;stroke-width:1.05;filter:none;animation-duration:2.6s}.connection-editor--guided .connection-editor__wire:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.34;filter:none;animation:none}.connection-editor--guided .connection-editor__wire--halo:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.08;animation:none}.connection-editor__wire--halo.connection-editor__wire--mode-dimmed{stroke-opacity:.05;stroke-width:5;animation:none}.connection-editor__wire-hit--mode-dimmed{stroke-width:12}.connection-editor__wire-endpoint{fill:#f8fafc;stroke:#0f172ae6;stroke-width:1.5;filter:drop-shadow(0 0 8px rgba(216,180,254,.8));pointer-events:none;animation:endpoint-pulse 1.2s ease-in-out infinite}.connection-editor__wire-endpoint--source{fill:#ff9f2f}.connection-editor__wire-endpoint--target{fill:#19c8e8}.connection-editor__connection-tooltip{position:absolute;z-index:6;width:min(312px,calc(100% - 24px));display:grid;gap:8px;padding:12px 14px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(135deg,var(--pce-surface-strong),var(--pce-surface)),var(--pce-surface-strong);box-shadow:0 18px 44px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);color:var(--pce-fg);pointer-events:none;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .14s ease-out}.connection-editor__connection-tooltip-callout{position:absolute;inset-block-start:100%;inset-inline-start:var(--connection-tooltip-callout-x, 42px);width:2px;height:28px;border-radius:999px;background:linear-gradient(180deg,#e2e8f0bd,#19c8e800);box-shadow:0 0 12px #19c8e852;transform:translate(-1px);pointer-events:none}.connection-editor__connection-tooltip-callout:before,.connection-editor__connection-tooltip-callout:after{content:\"\";position:absolute;border-radius:999px;pointer-events:none}.connection-editor__connection-tooltip-callout:before{inset-block-start:-5px;inset-inline-start:-5px;width:12px;height:12px;border:1px solid rgba(148,163,184,.24);background:#080d18f5;box-shadow:inset 0 1px #ffffff14}.connection-editor__connection-tooltip-callout:after{inset-block-end:-3px;inset-inline-start:-4px;width:10px;height:10px;background:#19c8e8;box-shadow:0 0 16px #19c8e88f}.connection-editor__connection-tooltip--projection{border-color:#19c8e833;background:linear-gradient(135deg,#15b8d81f,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state{border-color:#ff9f2f66;background:linear-gradient(135deg,#ff9f2f3d,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout{background:linear-gradient(180deg,#ffbd62d1,#ff9f2f00);box-shadow:0 0 14px #ff9f2f61}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout:after{background:#ff9f2f;box-shadow:0 0 18px #ff9f2fad}.connection-editor__connection-tooltip--error{border-color:#f871716b}.connection-editor__connection-tooltip--error .connection-editor__connection-tooltip-callout:after{background:#fb7185;box-shadow:0 0 18px #fb7185ad}.connection-editor__connection-tooltip-kind{display:inline-flex;align-items:center;gap:8px;color:#94a3b8;font-size:.62rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__connection-tooltip-kind span{width:8px;height:8px;border-radius:999px;background:#19c8e8;box-shadow:0 0 12px #19c8e880}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2fc7}.connection-editor__connection-tooltip-row{min-width:0;display:grid;grid-template-columns:54px minmax(0,1fr);align-items:center;gap:8px;min-height:28px;padding:0 10px;border-radius:999px;background:#0f172a94}.connection-editor__connection-tooltip-row span{color:#8d9bb0;font-size:.62rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.connection-editor__connection-tooltip-row strong{min-width:0;overflow:hidden;color:#e2e8f0;font-size:.75rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__connection-tooltip-badges{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__connection-tooltip-badges span{padding:3px 8px;border-radius:999px;background:#02061799;color:#fbbf24;font-size:.66rem;font-weight:900}.connection-editor__trace-overlay{position:absolute;z-index:6;inset-block-start:16px;inset-inline-start:50%;width:min(560px,calc(100% - 360px));min-width:320px;padding:12px 14px;border-radius:16px;border:1px solid rgba(34,197,94,.26);background:linear-gradient(135deg,#22c55e1f,#0ea5e91a),#080d18f0;box-shadow:0 22px 56px #02061775,0 0 42px #22c55e1f;transform:translate(-50%);pointer-events:auto;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .16s ease-out}.connection-editor__trace-overlay-head,.connection-editor__trace-overlay-route{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}.connection-editor__trace-overlay-head span,.connection-editor__trace-overlay-route span{color:#86efac;font-size:.66rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase;white-space:nowrap}.connection-editor__trace-overlay-head strong{color:#cbd5e1;font-size:.7rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace}.connection-editor__trace-overlay-route{margin-top:6px}.connection-editor__trace-overlay-controls{display:grid;grid-template-columns:28px minmax(0,1fr) 28px;align-items:center;gap:8px;margin-top:10px}.connection-editor__trace-overlay-button{width:28px;height:24px;display:inline-grid;place-items:center;border:1px solid rgba(148,163,184,.18);border-radius:999px;background:#0206176b;color:#e2e8f0;cursor:pointer;font-size:1rem;font-weight:900;line-height:1;transition:border-color .15s ease,background .15s ease,color .15s ease,opacity .15s ease}.connection-editor__trace-overlay-button:hover:not(:disabled){border-color:#22d3ee6b;background:#0ea5e929;color:#f8fafc}.connection-editor__trace-overlay-button:disabled{cursor:default;opacity:.36}.connection-editor__trace-overlay-steps{min-width:0;display:flex;align-items:center;gap:6px;overflow-x:auto;padding:2px;scrollbar-width:none}.connection-editor__trace-overlay-steps::-webkit-scrollbar{display:none}.connection-editor__trace-overlay-step{position:relative;flex:1 0 28px;min-width:28px;height:22px;border:1px solid rgba(148,163,184,.16);border-radius:999px;background:#0f172a9e;color:#94a3b8;cursor:pointer;font-size:.62rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__trace-overlay-step--active{border-color:#22d3eea3;background:linear-gradient(90deg,#22d3ee3d,#9b5cff33);color:#f8fafc;box-shadow:0 0 18px #22d3ee33}.connection-editor__trace-overlay-step--blocked{border-color:#fb71855c;color:#fecdd3}.connection-editor__trace-overlay-route strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.82rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__trace-overlay-bar{position:relative;height:5px;margin-top:10px;overflow:hidden;border-radius:999px;background:#94a3b829}.connection-editor__trace-overlay-bar span{position:absolute;inset-block:0;inset-inline-start:0;border-radius:inherit;background:linear-gradient(90deg,#22c55e,#22d3ee);box-shadow:0 0 18px #22c55e61;min-width:8%}.connection-editor__drag-wire{fill:none;stroke:#94a3b8;stroke-width:2.4;stroke-linecap:round;stroke-dasharray:6 7;pointer-events:none;filter:url(#connection-glow);animation:connection-flow 1.05s linear infinite,drag-wire-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--halo{stroke:#94a3b829;stroke-width:14;stroke-dasharray:none;animation:drag-halo-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--valid{stroke:#22c55e}.connection-editor__drag-wire--halo.connection-editor__drag-wire--valid{stroke:#22c55e47}.connection-editor__drag-endpoint{fill:#94a3b8;stroke:#020617eb;stroke-width:2;pointer-events:none;filter:url(#connection-glow);transform-box:fill-box;transform-origin:center;animation:endpoint-pulse 1s ease-in-out infinite}.connection-editor__drag-endpoint--source{fill:#ff9f2f}.connection-editor__drag-endpoint--target{fill:#7dddeb}.connection-editor__drag-endpoint--valid{fill:#22c55e;stroke:#bbf7d0e0}.connection-editor__wire-handle-line{stroke-width:2;stroke-linecap:round;stroke-dasharray:4 5;pointer-events:none;opacity:.88;filter:url(#connection-glow)}.connection-editor__wire-handle-line--source{stroke:#ff9f2ff0}.connection-editor__wire-handle-line--target{stroke:#19c8e8c2}.connection-editor__wire-control{fill:#0f172af5;stroke:#cbd5e1c7;stroke-width:1.8;pointer-events:none;filter:url(#connection-glow)}.connection-editor__wire-label{pointer-events:none;filter:drop-shadow(0 0 10px rgba(2,6,23,.44));animation:tooltip-rise .14s ease-out}.connection-editor__wire-label rect{fill:#080d18eb;stroke-width:1}.connection-editor__wire-label text{fill:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:8px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__wire-label--source rect{stroke:#ff9f2fad}.connection-editor__wire-label--target rect{stroke:#19c8e86b}.connection-editor__zoom-controls{position:absolute;inset-inline-start:14px;inset-block-start:14px;z-index:4;display:grid;grid-template-columns:max-content;gap:6px;width:46px;pointer-events:auto}.connection-editor__tool-group,.connection-editor__trace-source{display:grid;gap:6px;padding:6px;border-radius:12px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:0 16px 36px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__tool-group{grid-template-columns:30px;width:max-content}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:30px}.connection-editor__arrange-button{width:34px;min-height:34px;display:inline-flex;align-items:center;justify-content:center;gap:0;padding:0;border-radius:999px;border:1px solid rgba(168,85,247,.34);background:linear-gradient(90deg,#a855f72e,#22d3ee1f);color:#e9d5ff;font-size:0;font-weight:800;letter-spacing:0;cursor:pointer;opacity:1;transform:scale(1);transition:opacity .14s ease,transform .14s ease,border-color .14s ease,background .14s ease}.connection-editor--guided .connection-editor__arrange-button{opacity:.34;transform:scale(.9);border-color:color-mix(in srgb,var(--pce-outline) 82%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 84%,transparent)}.connection-editor--guided .connection-editor__zoom-controls:hover .connection-editor__arrange-button,.connection-editor--guided .connection-editor__zoom-controls:focus-within .connection-editor__arrange-button,.connection-editor--guided .connection-editor__arrange-button:hover,.connection-editor--guided .connection-editor__arrange-button:focus-visible,.connection-editor--guided .connection-editor__arrange-button--active{opacity:1;transform:scale(1);border-color:#a855f757;background:linear-gradient(90deg,#a855f72e,#22d3ee1f)}.connection-editor__arrange-button span{color:#c084fc;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.78rem;font-weight:900}.connection-editor__tool-button{width:30px;height:30px;border-radius:999px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.9rem;font-weight:800;letter-spacing:.02em;cursor:pointer;line-height:1}.connection-editor__tool-button:hover:not(:disabled){border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);color:var(--pce-primary);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 16%,transparent)}.connection-editor__history-button:disabled{cursor:not-allowed;opacity:.42}.connection-editor__arrange-button--active{border-color:#22d3ee94;background:linear-gradient(90deg,#0ea5e93d,#22d3ee2e);color:#cffafe}.connection-editor__trace-source{gap:4px;max-height:230px;overflow:auto}.connection-editor__trace-source-title{padding:2px 4px 6px;color:var(--pce-muted);font-size:.64rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase}.connection-editor__trace-source-item{min-width:0;min-height:30px;display:flex;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:8px;background:transparent;color:var(--pce-fg);cursor:pointer;font-size:.74rem;font-weight:800;text-align:start}.connection-editor__trace-source-item span{color:#f59e0b;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__trace-source-item:hover,.connection-editor__trace-source-item--active{background:var(--pce-surface-strong);color:var(--pce-strong);box-shadow:inset 3px 0 #f59e0bd1}.connection-editor__minimap{position:absolute;inset-inline-end:14px;inset-block-end:14px;z-index:4;width:184px;height:124px;padding:18px 10px 10px;overflow:hidden;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-primary) 30%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),var(--pce-surface-strong)),var(--pce-surface);box-shadow:0 20px 48px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);cursor:pointer;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);opacity:1;transform:scale(1);transform-origin:100% 100%;transition:opacity .16s ease,transform .16s ease,border-color .16s ease,box-shadow .16s ease}.connection-editor--guided .connection-editor__minimap{opacity:.54;transform:scale(.88);border-color:color-mix(in srgb,var(--pce-outline) 64%,transparent);box-shadow:0 14px 34px color-mix(in srgb,var(--pce-shadow-soft) 70%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor--guided .connection-editor__minimap:hover,.connection-editor--guided .connection-editor__minimap:focus-visible,.connection-editor--guided .connection-editor__minimap--panning{opacity:1;transform:scale(1)}.connection-editor__minimap:hover,.connection-editor__minimap--panning{border-color:#22d3ee75;box-shadow:0 20px 48px var(--pce-shadow-soft),0 0 24px color-mix(in srgb,var(--pce-primary) 14%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__minimap--panning{cursor:grabbing}.connection-editor__minimap:before{content:\"\";position:absolute;inset:22px 10px 10px;border-radius:10px;background-image:radial-gradient(circle,rgba(125,211,252,.18) 1px,transparent 1px);background-size:22px 22px;opacity:.58;pointer-events:none}.connection-editor__minimap-title{position:absolute;inset-block-start:7px;inset-inline-start:12px;color:var(--pce-muted);font-size:.6rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__minimap svg{position:relative;width:100%;height:100%;display:block;overflow:visible}.connection-editor__minimap-wire{fill:none;stroke:#b46cff8f;stroke-width:4;stroke-linecap:round;opacity:.86}.connection-editor__minimap-wire--state{stroke:#ff9f2fdb}.connection-editor__minimap-wire--state-read{stroke:#8b7dffb8;stroke-dasharray:4 9}.connection-editor__minimap-wire--projection{stroke:#19c8e88a;stroke-dasharray:18 8}.connection-editor__minimap-wire--event-propagation{stroke:#ffb454cc;stroke-dasharray:6 7}.connection-editor__minimap-wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.28))}.connection-editor__minimap-wire--trace{stroke:#9b5cffe0;stroke-width:5;stroke-dasharray:12 9;animation:connection-flow 1s linear infinite}.connection-editor__minimap-wire--active{stroke:#facc15eb;stroke-width:6;filter:drop-shadow(0 0 8px rgba(250,204,21,.38))}.connection-editor__minimap-wire--mode-dimmed{opacity:.2;stroke-width:2.6;filter:none}.connection-editor__minimap-node{fill:#f59e0be0;stroke:#020617db;stroke-width:4;filter:drop-shadow(0 0 7px rgba(245,158,11,.24))}.connection-editor__minimap-node--state{fill:#a855f7e6;filter:drop-shadow(0 0 8px rgba(168,85,247,.34))}.connection-editor__minimap-node--selected{fill:#facc15f5;stroke:#fef08aeb;filter:drop-shadow(0 0 10px rgba(250,204,21,.42))}.connection-editor__minimap-node--trace-source{fill:#facc15f5;filter:drop-shadow(0 0 10px rgba(250,204,21,.44))}.connection-editor__minimap-node--trace-reacting{fill:#22c55eeb;filter:drop-shadow(0 0 10px rgba(34,197,94,.42))}.connection-editor__minimap-node--mode-dimmed{opacity:.28;filter:none}.connection-editor__minimap-viewport{fill:#7dd3fc1f;stroke:#7dd3fce6;stroke-width:5;stroke-dasharray:18 10;filter:drop-shadow(0 0 10px rgba(125,211,252,.3));transition:x .12s ease,y .12s ease,width .12s ease,height .12s ease}.connection-editor__minimap--panning .connection-editor__minimap-viewport{fill:#22d3ee2e;stroke:#22d3eef5;stroke-dasharray:none}.connection-editor__node{position:absolute;z-index:10;width:168px;height:168px;transform:translate(-84px,-84px);border:0;padding:0;background:transparent;color:inherit;cursor:pointer;transition:filter .16s ease}.connection-editor__node--dragging{cursor:grabbing;filter:drop-shadow(0 0 22px rgba(34,211,238,.26));z-index:12}.connection-editor__node--connection-focus{filter:drop-shadow(0 0 16px rgba(34,211,238,.2))}.connection-editor__node--compat-target .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e66,0 0 0 18px #22c55e0b,0 0 32px #22c55e29}.connection-editor__node--mode-dimmed{opacity:.42;filter:grayscale(.22) saturate(.56)}.connection-editor__node--quiet{opacity:.58;filter:saturate(.68) brightness(.86)}.connection-editor__node--mode-dimmed .connection-editor__node-ring{animation:none;box-shadow:0 0 0 1px #2dd4bf14,0 0 14px #0ea5e90f}.connection-editor__node--mode-dimmed .connection-editor__node-halo{stroke-opacity:.28}.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-svg{position:absolute;inset:0}.connection-editor__node-ring,.connection-editor__node-core{display:grid;place-items:center;clip-path:polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%)}.connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from -28deg,#06b6d4b3 0 28%,#f59e0b9e 28% 48%,#a855f780 48% 68%,#06b6d4a3 68% 100%);box-shadow:0 0 0 1px #2dd4bf2e,0 0 26px #0ea5e929;animation:node-breathe 2.8s ease-in-out infinite}.connection-editor__node-svg{overflow:visible;filter:drop-shadow(0 0 16px rgba(14,165,233,.16))}.connection-editor__node-halo{fill:transparent;stroke:#38bdf838;stroke-width:1;stroke-dasharray:0;pointer-events:none}.connection-editor__node-halo:nth-child(2){stroke:#38bdf824}.connection-editor__node-halo:nth-child(3){stroke:#94a3b81a}.connection-editor__node-segment{fill-opacity:.28;stroke-opacity:.72;stroke-width:1.15;transition:fill-opacity .16s ease,stroke-opacity .16s ease,stroke-width .16s ease;cursor:grab}.connection-editor__node:hover .connection-editor__node-segment,.connection-editor__node--selected .connection-editor__node-segment,.connection-editor__node--connection-focus .connection-editor__node-segment{fill-opacity:.54;stroke-opacity:.95;stroke-width:1.55}.connection-editor__node-segment--connection-focus{fill-opacity:.76;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 8px rgba(34,211,238,.76));animation:segment-focus-sweep 1.45s ease-in-out infinite}.connection-editor__node-segment--source{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 12px rgba(251,146,60,.82))}.connection-editor__node-segment--compatible{fill-opacity:.74;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 10px rgba(34,197,94,.72));animation:snap-pulse 1s ease-in-out infinite}.connection-editor__node-segment--compat-preview{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 13px rgba(245,158,11,.78))}.connection-editor__node-segment--candidate{fill-opacity:.92;stroke-opacity:1;stroke-width:2.8;filter:drop-shadow(0 0 16px rgba(34,197,94,.86))}.connection-editor__node-segment--incompatible{fill-opacity:.12;stroke-opacity:.28;cursor:not-allowed}.connection-editor__node-segment--invalid-drop{fill-opacity:.72;stroke:#fb7185;stroke-opacity:1;stroke-width:3;filter:drop-shadow(0 0 16px rgba(244,63,94,.84));animation:invalid-drop-jolt .36s ease-out}.connection-editor__node-segment--state{fill-opacity:.44;filter:drop-shadow(0 0 8px rgba(180,108,255,.2))}.connection-editor__node-segment--mode-dimmed{fill-opacity:.08;stroke-opacity:.2;stroke-width:.9;filter:none}.connection-editor__node-anchor{opacity:.95;filter:drop-shadow(0 0 6px currentColor)}.connection-editor__node-rotate-handle{cursor:grab;opacity:0;pointer-events:none;transition:opacity .16s ease,filter .16s ease;filter:drop-shadow(0 0 8px rgba(34,211,238,.28))}.connection-editor__node:hover .connection-editor__node-rotate-handle,.connection-editor__node--selected .connection-editor__node-rotate-handle,.connection-editor__node--rotating .connection-editor__node-rotate-handle{opacity:1;pointer-events:auto}.connection-editor__node--rotating .connection-editor__node-rotate-handle{cursor:grabbing;filter:drop-shadow(0 0 12px rgba(34,211,238,.54))}.connection-editor__node-rotate-hit{fill:transparent}.connection-editor__node-rotate-dot{fill:var(--pce-surface-strong);stroke:var(--pce-primary);stroke-opacity:.88;stroke-width:1.4}.connection-editor__node-rotate-arc,.connection-editor__node-rotate-arrow{fill:none;stroke:var(--pce-primary);stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.96;stroke-width:1.2;pointer-events:none}.connection-editor__segment-icon,.connection-editor__segment-label{pointer-events:none;fill:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:800;paint-order:stroke;stroke:#020617c2;stroke-width:3px;stroke-linejoin:round}.connection-editor__segment-icon{font-size:12px;fill:#19c8e8;opacity:1;transition:opacity .14s ease}.connection-editor__segment-icon--output{fill:#ff9f2f}.connection-editor--guided .connection-editor__segment-icon:not(.connection-editor__segment-icon--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-icon{opacity:0}.connection-editor__segment-label{font-size:9.5px;letter-spacing:0;fill:#e2e8f0e0;opacity:1;transition:opacity .14s ease}.connection-editor--guided .connection-editor__segment-label:not(.connection-editor__segment-label--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-label{opacity:0}.connection-editor__node-core{inset:43px;padding:12px;border-radius:999px;clip-path:none;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(circle at center,#111827 0 58%,#060b14);border:1px solid rgba(226,232,240,.1);box-shadow:0 12px 28px #00000073,inset 0 1px #ffffff0d;color:#f8fafc;text-shadow:0 1px 2px rgba(0,0,0,.62)}.connection-editor__node-icon{display:block;max-width:44px;overflow:hidden;color:#f8fafc;font-family:Material Symbols Outlined,Material Icons,sans-serif;font-size:1.22rem;font-weight:400;line-height:1;text-align:center;text-transform:none;letter-spacing:0;white-space:nowrap;filter:drop-shadow(0 0 10px rgba(226,232,240,.18))}.connection-editor__node--state .connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from 14deg,#a855f7c7 0 42%,#7e3af26b 42% 78%,#f59e0b47 78% 100%);box-shadow:0 0 0 1px #a855f738,0 0 30px #a855f733}.connection-editor__node--selected .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15bd,0 0 34px #facc153d}.connection-editor__node--connection-focus .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eead,0 0 38px #22d3ee42;animation:node-focus-breathe 1.7s ease-in-out infinite}.connection-editor__node--trace-source .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 0 18px #facc150f,0 0 54px #facc154d;animation:trace-source-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:before{content:\"\";position:absolute;z-index:0;inset:-44px;border-radius:999px;border:2px solid rgba(250,204,21,.36);background:radial-gradient(circle at center,transparent 0 64%,rgba(250,204,21,.05) 65% 66%,transparent 67%),conic-gradient(from -20deg,#facc1500,#facc1552,#facc1500);box-shadow:0 0 36px #facc151f;opacity:.92;pointer-events:none;animation:trace-source-orbit 2.8s linear infinite}.connection-editor__node--trace-reacting .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e94,0 0 46px #22c55e38;animation:trace-reacting-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:after,.connection-editor__node--trace-reacting:after{position:absolute;z-index:3;inset-inline-start:50%;inset-block-start:-42px;padding:0;border:0;background:transparent;color:#facc15;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.68rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase;transform:translate(-50%);text-shadow:0 0 12px rgba(250,204,21,.52);pointer-events:none}.connection-editor__node--trace-source:after{content:attr(data-trace-label)}.connection-editor__node--trace-reacting:after{content:attr(data-trace-label);color:#86efac;text-shadow:0 0 12px rgba(34,197,94,.44)}.connection-editor__node--trace-source .connection-editor__node-segment--output{fill-opacity:.66;stroke-width:2.2;filter:drop-shadow(0 0 14px rgba(255,159,47,.42))}.connection-editor__node--expanded .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eebd,0 0 34px #22d3ee3d}.connection-editor__node--rotating .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 42px #facc1547;animation:node-focus-breathe 1.1s ease-in-out infinite}.connection-editor__node--rotating .connection-editor__node-segment{fill-opacity:.68;stroke-opacity:1;stroke-width:1.9;cursor:grabbing}.connection-editor__node-title,.connection-editor__node-subtitle{display:block;max-width:92px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.connection-editor__node-title{color:#f8fafc;font-size:.82rem;font-weight:800}.connection-editor__node-subtitle{margin-top:4px;color:#a7b4c8;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__ports{position:absolute;z-index:30;display:grid;gap:6px;width:104px;opacity:0;pointer-events:none;transform:translateY(3px);transition:opacity .16s ease,transform .16s ease}.connection-editor__ports--visible{opacity:1;pointer-events:auto;transform:translateY(0)}.connection-editor__ports--outputs{z-index:42}.connection-editor__ports--inputs{z-index:36}.connection-editor__segment-popover{position:absolute;z-index:80;width:292px;max-height:320px;overflow:auto;display:grid;gap:10px;padding:14px;border-radius:16px;border:1px solid rgba(148,163,184,.18);background:linear-gradient(135deg,#0f172af5,#110c20f0),#090c16eb;box-shadow:0 28px 72px #0000007a,0 0 48px #a855f71a,inset 0 1px #ffffff0d;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__segment-popover-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:2px}.connection-editor__segment-popover-title{color:#94a3b8;font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}.connection-editor__segment-popover-hint{margin-top:5px;color:#64748b;font-size:.66rem;font-weight:700}.connection-editor__segment-rotation{flex:0 0 auto;min-width:54px;padding:5px 8px;border-radius:999px;border:1px solid rgba(34,211,238,.28);background:#082f4957;color:#7dd3fc;font-size:.66rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-align:center;box-shadow:inset 0 0 16px #0ea5e914}.connection-editor__segment-row{display:grid;grid-template-columns:28px 72px minmax(0,1fr) auto;align-items:center;gap:8px;min-height:40px;padding:7px;border-radius:12px;border:1px solid rgba(148,163,184,.12);background:linear-gradient(90deg,#0f172ac7,#0f172a75),#0f172a99;transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__segment-row--input{border-color:#22d3ee42}.connection-editor__segment-row--output{border-color:#f59e0b47}.connection-editor__segment-row--state{border-color:#a855f74d}.connection-editor__segment-row--source,.connection-editor__segment-row--candidate{transform:translate(2px);box-shadow:0 0 22px #f59e0b24,inset 0 0 20px #f59e0b14}.connection-editor__segment-row--compatible{border-color:#22d3ee6b;box-shadow:inset 0 0 18px #22d3ee14}.connection-editor__segment-row--compat-preview{border-color:#f59e0b94;background:linear-gradient(90deg,#f59e0b1f,#0f172a8a),#0f172ab3;box-shadow:0 0 22px #f59e0b1f,inset 0 0 18px #f59e0b14}.connection-editor__segment-row--invalid-drop{border-color:#fb7185b3;background:linear-gradient(90deg,#f43f5e24,#0f172a94),#0f172ab3;box-shadow:0 0 24px #f43f5e2e,inset 0 0 18px #f43f5e1a;animation:invalid-drop-jolt .36s ease-out}.connection-editor__segment-index{color:#64748b;font-size:.64rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;letter-spacing:.08em}.connection-editor__segment-kind{display:inline-flex;align-items:center;gap:6px;color:#94a3b8;font-size:.62rem;font-weight:800;text-transform:uppercase;min-width:0;white-space:nowrap}.connection-editor__segment-kind-dot{width:7px;height:7px;border-radius:999px;background:#94a3b8;box-shadow:0 0 12px #94a3b847}.connection-editor__segment-row--input .connection-editor__segment-kind-dot{background:#22d3ee;box-shadow:0 0 12px #22d3ee61}.connection-editor__segment-row--output .connection-editor__segment-kind-dot{background:#fb923c;box-shadow:0 0 12px #fb923c66}.connection-editor__segment-row--state .connection-editor__segment-kind-dot{background:#a855f7;box-shadow:0 0 12px #a855f76b}.connection-editor__segment-label{display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden;color:#e2e8f0;font-size:.74rem;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-badge{flex:0 0 auto;padding:2px 5px;border-radius:999px;border:1px solid rgba(56,189,248,.28);background:#0ea5e91a;color:#bae6fd;font-size:.55rem;font-weight:900;text-transform:uppercase}.connection-editor__segment-path{grid-column:3 / 4;min-width:0;margin-top:-5px;overflow:hidden;color:#93c5fd;font-size:.62rem;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-row--nested{min-height:56px;border-color:#38bdf84d;background:linear-gradient(90deg,#0ea5e91a,#0f172a80),#0f172aa3}.connection-editor__segment-actions{display:inline-flex;gap:4px}.connection-editor__segment-action{width:24px;height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.18);background:#060c16b8;color:#dbeafe;cursor:pointer;font-weight:900;line-height:1}.connection-editor__segment-action:hover{border-color:#22d3ee75;box-shadow:0 0 14px #22d3ee29}.connection-editor__port{min-height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#080d18c2;color:#cbd5e1;font-size:.64rem;font-weight:700;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:crosshair;box-shadow:0 8px 20px #00000038}.connection-editor--guided .connection-editor__ports--visible .connection-editor__port:not(.connection-editor__port--guided-visible){display:none}.connection-editor__port--output{border-color:#f59e0b75;color:#fbbf24}.connection-editor__port--input{border-color:#06b6d475;color:#22d3ee}.connection-editor__port--state{border-color:#a855f785;color:#c084fc}.connection-editor__port--compatible{background:#22c55e29;box-shadow:0 0 0 1px #22c55e61,0 0 18px #22c55e2e;animation:snap-pulse 1s ease-in-out infinite}.connection-editor__port--source{border-color:#fb923cb8;background:#fb923c29;color:#fed7aa;box-shadow:0 0 0 1px #fb923c73,0 0 20px #fb923c2e}.connection-editor__port--candidate{background:#22c55e3d;box-shadow:0 0 0 2px #22c55e94,0 0 24px #22c55e3d}.connection-editor__port--incompatible{opacity:.42;cursor:not-allowed;filter:grayscale(.45)}.connection-editor__port--invalid-drop{opacity:1;border-color:#fb7185c7;color:#fecdd3;background:#f43f5e2e;box-shadow:0 0 0 2px #f43f5e75,0 0 24px #f43f5e38;filter:none;animation:invalid-drop-jolt .36s ease-out}.connection-editor__port--connection-focus{border-color:#facc15ad;color:#fde68a;background:#facc151f;box-shadow:0 0 0 1px #facc156b,0 0 20px #facc152e;animation:port-focus-pulse 1.25s ease-in-out infinite}.connection-editor__drag-tip{position:absolute;z-index:6;display:grid;gap:4px;width:min(330px,calc(100% - 28px));padding:10px 12px;border-radius:14px;border:1px solid rgba(125,211,252,.26);background:linear-gradient(135deg,#0ea5e91f,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 28px #0ea5e91a;font-size:.76rem;pointer-events:none;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);animation:tooltip-rise .14s ease-out}.connection-editor__drag-tip--valid{border-color:#22c55e66;background:linear-gradient(135deg,#22c55e29,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 30px #22c55e24}.connection-editor__drag-tip--invalid{z-index:7;border-color:#fb71858a;background:linear-gradient(135deg,#f43f5e2e,#0f172af0),#080d18f5;box-shadow:0 18px 44px #0206176b,0 0 34px #f43f5e29;animation:tooltip-rise .14s ease-out,invalid-drop-jolt .36s ease-out}.connection-editor__invalid-drop-pulse{position:absolute;z-index:6;width:16px;height:16px;border-radius:999px;border:2px solid rgba(251,113,133,.88);background:#f43f5e38;box-shadow:0 0 0 8px #f43f5e1a,0 0 28px #f43f5e3d;pointer-events:none;transform:translate(-50%,-50%);animation:invalid-drop-ping 1.2s ease-out both}.connection-editor__drag-tip span{color:#7dd3fc;text-transform:uppercase;letter-spacing:.12em;font-size:.62rem;font-weight:800}.connection-editor__drag-tip strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.78rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__drag-tip small{color:#94a3b8;font-size:.68rem;font-weight:700}.connection-editor__drag-tip--valid small{color:#86efac}.connection-editor__drag-tip--invalid span,.connection-editor__drag-tip--invalid small{color:#fda4af}.connection-editor__summary{grid-column:1;grid-row:2;align-self:end;justify-self:start;z-index:6;display:flex;flex-wrap:wrap;gap:6px;padding:0 0 12px 12px;pointer-events:none}.connection-editor__side-panel{grid-column:2;grid-row:2 / 3;position:relative;z-index:8;min-width:0;min-height:0;display:grid;align-content:start;gap:14px;overflow:auto;padding-inline-end:4px;scrollbar-color:var(--pce-outline-strong) var(--pce-surface-soft)}.connection-editor__side-panel--contextual .connection-editor__inspector{order:-3}.connection-editor__side-panel--contextual .connection-editor__recommended{order:2}.connection-editor__side-panel--contextual .connection-editor__filters-section{order:3}.connection-editor__side-panel--contextual .connection-editor__recommended,.connection-editor__side-panel--contextual .connection-editor__filters-section{opacity:.82}.connection-editor__metric,.connection-editor__item{border-radius:16px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__metric{min-width:auto;display:inline-flex;align-items:baseline;gap:7px;padding:6px 9px;border-radius:999px;background:color-mix(in srgb,var(--pce-surface-strong) 86%,transparent);box-shadow:0 10px 26px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight)}.connection-editor__metric span{color:var(--pce-muted);font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__metric strong,.connection-editor__details-row strong{color:var(--pce-strong);font-size:.78rem}.connection-editor__filters,.connection-editor__actions,.connection-editor__badges{display:flex;gap:8px;flex-wrap:wrap}.connection-editor__filter,.connection-editor__action{border:1px solid var(--pce-outline-strong);background:var(--pce-surface-soft);color:var(--pce-fg);border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connection-editor__filter--active,.connection-editor__action:hover{border-color:color-mix(in srgb,var(--pce-secondary) 62%,transparent);background:color-mix(in srgb,var(--pce-secondary) 16%,var(--pce-surface-soft));color:var(--pce-strong)}.connection-editor__action--danger{border-color:#f8717161;color:#fecaca}.connection-editor__item{width:100%;text-align:start;padding:12px;display:grid;gap:6px;cursor:pointer;color:inherit}.connection-editor__item--active{border-color:#a855f7b8;background:linear-gradient(90deg,#0ea5e91a,#a855f721)}.connection-editor__item-title{font-weight:800;color:#f8fafc;word-break:break-word}.connection-editor__badge{padding:3px 8px;border-radius:999px;background:#0ea5e92e;color:#bae6fd;font-size:.72rem;font-weight:800}.connection-editor__section{min-width:0;padding:14px;border-radius:18px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight),0 18px 50px var(--pce-shadow-soft);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__badge--warning{background:#facc1524;color:#fde68a}.connection-editor__badge--error{background:#ef444424;color:#fecaca}.connection-editor__diagnostics{display:grid;gap:8px}.connection-editor__diagnostic{display:grid;gap:4px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.78rem;line-height:1.35}.connection-editor__diagnostic--warning{border-color:#f59e0b47;background:#f59e0b1a}.connection-editor__diagnostic--error{border-color:#ef44445c;background:#ef44441f}.connection-editor__diagnostic-severity{font-size:.68rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#f8fafc}.connection-editor__suggestions{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__suggestion{display:grid;gap:8px;width:100%;padding:12px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 12%,transparent),color-mix(in srgb,var(--pce-primary) 8%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__suggestion:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 46%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 18%,transparent),color-mix(in srgb,var(--pce-primary) 12%,transparent)),var(--pce-surface-strong)}.connection-editor__suggestion-route{display:grid;gap:4px;font-size:.78rem}.connection-editor__suggestion-route strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__suggestion-reason{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__suggestion-diagnostic{padding:10px 12px;border-radius:14px;border:1px solid rgba(245,158,11,.28);background:#f59e0b1a;color:var(--pce-strong);font-size:.78rem;line-height:1.35}.connection-editor__suggestion-outcome{color:var(--pce-strong);font-size:.84rem;line-height:1.3}.connection-editor__suggestion-action{justify-self:start;padding:3px 8px;border-radius:999px;background:#22d3ee24;color:#67e8f9;font-size:.68rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase}:host-context(.theme-light) .connection-editor__suggestion-action{background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:#075f73}.connection-editor__trace{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__trace-summary{color:var(--pce-muted);font-size:.78rem;line-height:1.35}.connection-editor__trace-step{display:grid;grid-template-columns:24px minmax(76px,auto) 1fr;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(34,211,238,.18);background:var(--pce-surface-soft);font-size:.76rem}.connection-editor__trace-step--blocked{border-color:#ef444457;background:#ef44441a}.connection-editor__trace-order{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:999px;background:#22d3ee29;color:#67e8f9;font-weight:900}.connection-editor__trace-phase{color:var(--pce-strong);font-weight:900;text-transform:uppercase;letter-spacing:.06em;font-size:.66rem}.connection-editor__trace-copy{min-width:0;color:var(--pce-fg);word-break:break-word}.connection-editor__transform-steps{display:grid;gap:8px}.connection-editor__transform-step{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(168,85,247,.22);background:var(--pce-surface-soft)}.connection-editor__transform-kind{min-width:0;color:var(--pce-strong);font-weight:900;word-break:break-word}.connection-editor__transform-phase{color:var(--pce-muted);font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.connection-editor__details-row,.connection-editor__details-block{display:grid;gap:6px}.connection-editor__payload-input{width:100%;min-height:128px;box-sizing:border-box;resize:vertical;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 92%,black);color:var(--pce-fg);padding:10px;font:.76rem/1.45 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.connection-editor__surface-action-editor{display:block;max-height:min(58vh,620px);overflow:auto;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 96%,black);padding:10px;margin-bottom:10px}.connection-editor__rule-grid{display:grid;gap:10px}.connection-editor__rule-card{display:grid;gap:8px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__rule-heading{color:var(--pce-fg);font-size:.72rem;font-weight:900;text-transform:uppercase;letter-spacing:.06em}pre{margin:0;padding:12px;border-radius:12px;background:color-mix(in srgb,var(--pce-surface-strong) 82%,#020617);color:var(--pce-fg);overflow:auto;font-size:.75rem}@keyframes connection-flow{to{stroke-dashoffset:-38}}@keyframes drag-wire-pulse{0%,to{stroke-opacity:.76}50%{stroke-opacity:1}}@keyframes drag-halo-pulse{0%,to{stroke-opacity:.48}50%{stroke-opacity:.82}}@keyframes endpoint-pulse{0%,to{opacity:.78;transform:scale(1)}50%{opacity:1;transform:scale(1.25)}}@keyframes selected-wire-aura{0%,to{stroke-opacity:.46}50%{stroke-opacity:.92}}@keyframes wire-draw-in{0%{stroke-dashoffset:640;opacity:.32}70%{opacity:1}to{stroke-dashoffset:0;opacity:1}}@keyframes new-wire-halo{0%{stroke-opacity:0;stroke-width:30}28%{stroke-opacity:.78}to{stroke-opacity:0;stroke-width:12}}@keyframes new-dock-link-flash{0%{transform:translateY(-2px);box-shadow:0 16px 40px #0206175c,0 0 42px #fb923c47}to{transform:translateY(0)}}@keyframes trace-wire-pulse{0%,to{stroke-opacity:.78}50%{stroke-opacity:1}}@keyframes trace-halo-pulse{0%,to{stroke-opacity:.34}50%{stroke-opacity:.86}}@keyframes tooltip-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes invalid-drop-jolt{0%,to{transform:translate(0)}28%{transform:translate(-3px)}56%{transform:translate(3px)}}@keyframes invalid-drop-ping{0%{opacity:1;transform:translate(-50%,-50%) scale(.72)}72%{opacity:.74;transform:translate(-50%,-50%) scale(1.35)}to{opacity:0;transform:translate(-50%,-50%) scale(1.8)}}@keyframes node-breathe{50%{transform:scale(1.035)}}@keyframes node-focus-breathe{0%,to{transform:scale(1)}50%{transform:scale(1.055)}}@keyframes trace-source-pulse{50%{transform:scale(1.04);box-shadow:0 0 0 3px #facc15db,0 0 0 22px #facc1514,0 0 64px #facc1557}}@keyframes trace-source-orbit{to{transform:rotate(360deg)}}@keyframes trace-reacting-pulse{50%{transform:scale(1.045);box-shadow:0 0 0 3px #22c55ead,0 0 62px #22c55e4d}}@keyframes segment-focus-sweep{0%,to{stroke-opacity:.82}50%{stroke-opacity:1}}@keyframes snap-pulse{50%{filter:brightness(1.16)}}@keyframes port-focus-pulse{50%{transform:translateY(-1px);box-shadow:0 0 0 2px #facc158f,0 0 26px #facc153d}}@media(prefers-reduced-motion:reduce){.connection-editor__viewport,.connection-editor__node,.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-segment,.connection-editor__dock-link,.connection-editor__port{transition-duration:1ms}.connection-editor__wire,.connection-editor__wire--state,.connection-editor__wire--projection,.connection-editor__wire--state-read,.connection-editor__wire--event-propagation,.connection-editor__wire--halo.connection-editor__wire--active,.connection-editor__wire--trace,.connection-editor__wire--halo.connection-editor__wire--trace,.connection-editor__wire-endpoint,.connection-editor__connection-tooltip,.connection-editor__dock-link--new,.connection-editor__trace-overlay,.connection-editor__trace-overlay-step,.connection-editor__drag-wire,.connection-editor__drag-wire--halo,.connection-editor__drag-endpoint,.connection-editor__drag-tip,.connection-editor__node-ring,.connection-editor__node--connection-focus .connection-editor__node-ring,.connection-editor__node--trace-source .connection-editor__node-ring,.connection-editor__node--trace-source:before,.connection-editor__node--trace-reacting .connection-editor__node-ring,.connection-editor__node--rotating .connection-editor__node-ring,.connection-editor__node-segment--connection-focus,.connection-editor__node-segment--compatible,.connection-editor__node-segment--invalid-drop,.connection-editor__segment-popover,.connection-editor__port--compatible,.connection-editor__port--invalid-drop,.connection-editor__port--connection-focus,.connection-editor__invalid-drop,.connection-editor__invalid-drop-pulse{animation:none}.connection-editor__wire{stroke-dashoffset:0}.connection-editor__wire--new{stroke-dasharray:10 8;stroke-dashoffset:0;opacity:1}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:12;stroke-opacity:.16}.connection-editor__wire-endpoint,.connection-editor__drag-endpoint,.connection-editor__node-ring,.connection-editor__node--trace-source:before{transform:none}.connection-editor__invalid-drop-pulse{opacity:0}}@media(max-width:900px){:host{inset:0}.connection-editor{inset:8px;height:calc(100vh - 16px);padding:12px;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) minmax(76px,112px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) 48px}.connection-editor__header,.connection-editor__stage,.connection-editor__summary,.connection-editor__side-panel,.connection-editor__dock{grid-column:1}.connection-editor__header{align-items:stretch;flex-wrap:wrap;border-radius:18px}.connection-editor__mode-frame{order:3;width:100%;max-width:100%}.connection-editor__close{margin-inline-start:auto}.connection-editor__mode-frame:before,.connection-editor__mode-frame:after{content:\"\";position:absolute;z-index:2;inset-block:4px;width:24px;border-radius:999px;pointer-events:none}.connection-editor__mode-frame:before{inset-inline-start:1px;background:linear-gradient(90deg,#080d18f0,#080d1800)}.connection-editor__mode-frame:after{inset-inline-end:1px;background:linear-gradient(270deg,#080d18f0,#080d1800)}.connection-editor__mode-shell{width:100%;max-width:100%;overflow-x:auto;scroll-padding-inline:28px;-webkit-overflow-scrolling:touch}.connection-editor__subtitle{margin-inline-start:auto}.connection-editor__stage{grid-row:2;min-height:260px}.connection-editor__summary{grid-row:2;max-width:calc(100% - 24px)}.connection-editor__side-panel{grid-row:3;max-height:30vh}.connection-editor__dock{grid-row:4;min-height:0}.connection-editor__connection-tooltip{width:min(620px,calc(100% - 24px));max-height:min(260px,calc(100% - 24px));overflow:auto}.connection-editor__dock-tabs{width:100%;min-width:0;min-height:0;flex-wrap:wrap;align-items:flex-start}.connection-editor__dock-count{flex:1 1 100%;margin-inline-start:0}.connection-editor__dock-body{width:100%;min-width:0;max-height:76px;box-sizing:border-box}.connection-editor__dock-body pre{white-space:pre-wrap;overflow-wrap:anywhere}.connection-editor__dock-link{grid-template-columns:1fr;align-items:start}.connection-editor__dock-link-route{flex-wrap:wrap}.connection-editor__dock-link-badges{justify-content:flex-start}.connection-editor__trace-overlay{inset-inline-start:14px;width:min(420px,calc(100% - 28px));min-width:0;transform:none}.connection-editor__drag-tip{width:min(300px,calc(100% - 28px))}.connection-editor__segment-popover{width:min(280px,calc(100% - 28px));max-height:min(280px,calc(100% - 28px))}.connection-editor__minimap{inset-inline-end:10px;inset-block-end:10px;width:132px;height:94px;padding:16px 8px 8px;border-radius:14px}.connection-editor__minimap:before{inset:20px 8px 8px;background-size:18px 18px}.connection-editor__minimap-title{inset-block-start:6px;inset-inline-start:10px;font-size:.54rem}}@media(max-width:640px){.connection-editor{inset:4px;height:calc(100vh - 8px);padding:8px;gap:8px;grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) minmax(72px,104px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) 46px}.connection-editor__header{gap:8px;padding:10px}.connection-editor__mode-shell{padding:4px;gap:2px}.connection-editor__mode{min-height:28px;gap:4px;padding:0 7px;font-size:.68rem}.connection-editor__mode-glyph{font-size:.64rem}.connection-editor__stage{min-height:240px}.connection-editor__zoom-controls{inset-inline-start:8px;inset-block-start:8px;gap:6px;width:42px}.connection-editor__tool-group,.connection-editor__trace-source{gap:6px;padding:8px;border-radius:12px}.connection-editor__tool-group{grid-template-columns:28px}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:28px}.connection-editor__tool-button{width:28px;height:28px}.connection-editor__arrange-button,.connection-editor__simulate-button{width:30px;min-height:30px}.connection-editor__summary{gap:6px;padding-inline-end:8px}.connection-editor__side-panel{max-height:28vh}.connection-editor__dock{border-radius:16px}.connection-editor__dock-tabs{gap:4px}.connection-editor__dock-tab{padding:0 9px}.connection-editor__dock-count{font-size:.62rem}.connection-editor__dock-body{max-height:66px;padding:8px}.connection-editor__minimap{width:116px;height:84px}.connection-editor__segment-row{grid-template-columns:24px minmax(54px,.55fr) minmax(0,1fr) auto}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SurfaceOpenActionEditorComponent, selector: "praxis-surface-open-action-editor", inputs: ["value", "hostKind"], outputs: ["valueChange"] }, { kind: "pipe", type: i2$3.JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7732
8444
  }
7733
8445
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ConnectionEditorComponent, decorators: [{
7734
8446
  type: Component,
@@ -7741,6 +8453,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
7741
8453
  @if (open()) {
7742
8454
  <aside
7743
8455
  class="connection-editor"
8456
+ [class.connection-editor--guided]="visualDensity() === 'guided'"
8457
+ [class.connection-editor--full]="visualDensity() === 'full'"
8458
+ [class.connection-editor--dock-collapsed]="dockCollapsed()"
7744
8459
  data-testid="page-builder-connections-panel"
7745
8460
  [attr.aria-label]="tx('connections.editor.panelAria', 'Connection editor')"
7746
8461
  >
@@ -7749,15 +8464,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
7749
8464
  <div class="connection-editor__eyebrow">{{ tx('connections.editor.eyebrow', 'Radial connection studio') }}</div>
7750
8465
  <div class="connection-editor__title">{{ tx('connections.title', 'Connections') }}</div>
7751
8466
  </div>
7752
- <button
7753
- type="button"
7754
- class="connection-editor__close"
7755
- data-testid="page-builder-connections-close"
7756
- [attr.aria-label]="tx('connections.closeAria', 'Close connection editor')"
7757
- (click)="close.emit()"
7758
- >
7759
- ×
7760
- </button>
7761
8467
  <div class="connection-editor__mode-frame">
7762
8468
  <div class="connection-editor__mode-shell" role="tablist" [attr.aria-label]="tx('connections.mode.aria', 'Connection flow mode')">
7763
8469
  @for (mode of flowModes; track mode.id) {
@@ -7780,11 +8486,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
7780
8486
  </div>
7781
8487
  </div>
7782
8488
  <div class="connection-editor__subtitle">
7783
- <span class="connection-editor__status-pill">
8489
+ <button
8490
+ type="button"
8491
+ class="connection-editor__status-pill connection-editor__status-pill--button"
8492
+ data-testid="page-builder-connections-density-toggle"
8493
+ [attr.aria-pressed]="visualDensity() === 'full'"
8494
+ [attr.aria-label]="visualDensityAriaLabel()"
8495
+ (click)="toggleVisualDensity($event)"
8496
+ >
7784
8497
  <span></span>
7785
8498
  {{ activeModeStatus() }}
7786
- </span>
8499
+ </button>
7787
8500
  </div>
8501
+ <button
8502
+ type="button"
8503
+ class="connection-editor__close"
8504
+ data-testid="page-builder-connections-close"
8505
+ [attr.aria-label]="tx('connections.closeAria', 'Close connection editor')"
8506
+ (click)="close.emit()"
8507
+ >
8508
+ ×
8509
+ </button>
7788
8510
  </div>
7789
8511
 
7790
8512
  <div
@@ -8039,10 +8761,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8039
8761
  [class.connection-editor__node--dragging]="nodeDragState()?.nodeId === node.id"
8040
8762
  [class.connection-editor__node--compat-target]="nodeHasCompatiblePreviewPort(node)"
8041
8763
  [class.connection-editor__node--mode-dimmed]="isModeDimmedNode(node)"
8764
+ [class.connection-editor__node--quiet]="isGuidedQuietNode(node)"
8042
8765
  [style.left.px]="node.x"
8043
8766
  [style.top.px]="node.y"
8044
8767
  [attr.data-trace-label]="traceNodeLabel(node)"
8045
8768
  [attr.data-testid]="'page-builder-connections-widget-' + node.id"
8769
+ (pointerenter)="hoveredNodeId.set(node.id)"
8770
+ (pointerleave)="clearHoveredNode(node.id)"
8046
8771
  (pointerdown)="startNodeDrag(node.id, $event)"
8047
8772
  (pointerup)="finishNodePointer(node.id, $event)"
8048
8773
  (click)="selectNode(node.id)"
@@ -8097,6 +8822,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8097
8822
  <text
8098
8823
  class="connection-editor__segment-icon"
8099
8824
  [class.connection-editor__segment-icon--output]="segment.port.kind === 'output'"
8825
+ [class.connection-editor__segment-icon--guided-visible]="isGuidedSegmentLabelVisible(segment.port)"
8100
8826
  [attr.x]="segment.icon.x"
8101
8827
  [attr.y]="segment.icon.y"
8102
8828
  [attr.transform]="segmentLabelTransform(segment, node)"
@@ -8104,6 +8830,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8104
8830
  >{{ segmentKindGlyph(segment.port.kind) }}</text>
8105
8831
  <text
8106
8832
  class="connection-editor__segment-label"
8833
+ [class.connection-editor__segment-label--guided-visible]="isGuidedSegmentLabelVisible(segment.port)"
8107
8834
  [attr.x]="segment.label.x"
8108
8835
  [attr.y]="segment.label.y"
8109
8836
  [attr.transform]="segmentLabelTransform(segment, node)"
@@ -8155,12 +8882,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8155
8882
  [class.connection-editor__segment-row--input]="port.kind === 'input'"
8156
8883
  [class.connection-editor__segment-row--output]="port.kind === 'output'"
8157
8884
  [class.connection-editor__segment-row--state]="port.kind === 'state'"
8885
+ [class.connection-editor__segment-row--nested]="isNestedPort(port)"
8158
8886
  [class.connection-editor__segment-row--source]="isDragSource(port)"
8159
8887
  [class.connection-editor__segment-row--candidate]="isDropCandidate(port)"
8160
8888
  [class.connection-editor__segment-row--compatible]="isCompatibleDrop(port)"
8161
8889
  [class.connection-editor__segment-row--compat-preview]="isCompatibilityPreview(port)"
8162
8890
  [class.connection-editor__segment-row--invalid-drop]="isInvalidDropFeedbackTarget(port)"
8163
8891
  [attr.data-testid]="'page-builder-connections-segment-' + port.id"
8892
+ [attr.aria-label]="portDescription(port)"
8164
8893
  (click)="selectSegment(port, $event)"
8165
8894
  >
8166
8895
  <span class="connection-editor__segment-index">{{ index + 1 < 10 ? '0' + (index + 1) : index + 1 }}</span>
@@ -8170,7 +8899,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8170
8899
  </span>
8171
8900
  <span class="connection-editor__segment-label">
8172
8901
  {{ port.label }}
8902
+ @if (isNestedPort(port)) {
8903
+ <span class="connection-editor__segment-badge">{{ tx('connections.editor.nestedBadge', 'Nested') }}</span>
8904
+ }
8173
8905
  </span>
8906
+ @if (isNestedPort(port)) {
8907
+ <span class="connection-editor__segment-path">{{ nestedPortPathText(port) }}</span>
8908
+ }
8174
8909
  <span class="connection-editor__segment-actions">
8175
8910
  <button
8176
8911
  type="button"
@@ -8192,8 +8927,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8192
8927
 
8193
8928
  <div
8194
8929
  class="connection-editor__ports connection-editor__ports--outputs"
8930
+ [class.connection-editor__ports--visible]="areNodePortsVisible(node)"
8195
8931
  [style.left.px]="node.x + 132"
8196
8932
  [style.top.px]="node.y + 24"
8933
+ (pointerenter)="hoveredNodeId.set(node.id)"
8934
+ (pointerleave)="clearHoveredNode(node.id)"
8197
8935
  >
8198
8936
  @for (port of node.outputs; track port.id) {
8199
8937
  <button
@@ -8201,7 +8939,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8201
8939
  class="connection-editor__port connection-editor__port--output"
8202
8940
  [class.connection-editor__port--source]="isDragSource(port)"
8203
8941
  [class.connection-editor__port--connection-focus]="isPortFocusedByConnection(port)"
8942
+ [class.connection-editor__port--guided-visible]="isGuidedPortVisible(port)"
8204
8943
  [attr.data-testid]="'page-builder-connection-source-' + port.id"
8944
+ [attr.aria-label]="portAriaLabel(node, port, 'output')"
8205
8945
  (pointerdown)="startDrag(port, $event)"
8206
8946
  >
8207
8947
  {{ port.label }}
@@ -8211,8 +8951,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8211
8951
 
8212
8952
  <div
8213
8953
  class="connection-editor__ports connection-editor__ports--inputs"
8954
+ [class.connection-editor__ports--visible]="areNodePortsVisible(node)"
8214
8955
  [style.left.px]="node.x - 104"
8215
8956
  [style.top.px]="node.y + 24"
8957
+ (pointerenter)="hoveredNodeId.set(node.id)"
8958
+ (pointerleave)="clearHoveredNode(node.id)"
8216
8959
  >
8217
8960
  @for (port of node.inputs; track port.id) {
8218
8961
  <button
@@ -8223,7 +8966,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8223
8966
  [class.connection-editor__port--incompatible]="isIncompatibleDrop(port)"
8224
8967
  [class.connection-editor__port--invalid-drop]="isInvalidDropFeedbackTarget(port)"
8225
8968
  [class.connection-editor__port--connection-focus]="isPortFocusedByConnection(port)"
8969
+ [class.connection-editor__port--guided-visible]="isGuidedPortVisible(port)"
8226
8970
  [attr.data-testid]="'page-builder-connection-target-' + port.id"
8971
+ [attr.aria-label]="portAriaLabel(node, port, 'input')"
8227
8972
  (pointerenter)="previewDrop(port)"
8228
8973
  (pointerleave)="clearPreviewDrop(port)"
8229
8974
  (pointerup)="completeDrag(port, $event)"
@@ -8237,11 +8982,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8237
8982
  class="connection-editor__port connection-editor__port--state"
8238
8983
  [class.connection-editor__port--source]="isDragSource(port)"
8239
8984
  [class.connection-editor__port--compatible]="isCompatibleDrop(port)"
8240
- [class.connection-editor__port--candidate]="isDropCandidate(port)"
8985
+ [class.connection-editor__port--candidate]="isDropCandidate(port)"
8241
8986
  [class.connection-editor__port--incompatible]="isIncompatibleDrop(port)"
8242
8987
  [class.connection-editor__port--invalid-drop]="isInvalidDropFeedbackTarget(port)"
8243
8988
  [class.connection-editor__port--connection-focus]="isPortFocusedByConnection(port)"
8989
+ [class.connection-editor__port--guided-visible]="isGuidedPortVisible(port)"
8244
8990
  [attr.data-testid]="'page-builder-connection-target-' + port.id"
8991
+ [attr.aria-label]="portAriaLabel(node, port, 'state')"
8245
8992
  (pointerdown)="startDrag(port, $event)"
8246
8993
  (pointerenter)="previewDrop(port)"
8247
8994
  (pointerleave)="clearPreviewDrop(port)"
@@ -8259,18 +9006,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8259
9006
  <button
8260
9007
  type="button"
8261
9008
  class="connection-editor__tool-button"
9009
+ [attr.title]="tx('connections.editor.zoomInAria', 'Zoom in')"
8262
9010
  [attr.aria-label]="tx('connections.editor.zoomInAria', 'Zoom in')"
8263
9011
  (click)="zoomBy(0.12, $event)"
8264
9012
  >+</button>
8265
9013
  <button
8266
9014
  type="button"
8267
9015
  class="connection-editor__tool-button"
9016
+ [attr.title]="tx('connections.editor.zoomOutAria', 'Zoom out')"
8268
9017
  [attr.aria-label]="tx('connections.editor.zoomOutAria', 'Zoom out')"
8269
9018
  (click)="zoomBy(-0.12, $event)"
8270
9019
  >-</button>
8271
9020
  <button
8272
9021
  type="button"
8273
9022
  class="connection-editor__tool-button"
9023
+ [attr.title]="tx('connections.editor.resetViewAria', 'Reset view')"
8274
9024
  [attr.aria-label]="tx('connections.editor.resetViewAria', 'Reset view')"
8275
9025
  (click)="resetViewport($event)"
8276
9026
  >o</button>
@@ -8282,6 +9032,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8282
9032
  class="connection-editor__tool-button connection-editor__history-button"
8283
9033
  data-testid="page-builder-connections-undo"
8284
9034
  [disabled]="!canUndo()"
9035
+ [attr.title]="tx('connections.history.undoAria', 'Undo connection edit')"
8285
9036
  [attr.aria-label]="tx('connections.history.undoAria', 'Undo connection edit')"
8286
9037
  (click)="undoHistory($event)"
8287
9038
  >&lt;</button>
@@ -8290,6 +9041,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8290
9041
  class="connection-editor__tool-button connection-editor__history-button"
8291
9042
  data-testid="page-builder-connections-redo"
8292
9043
  [disabled]="!canRedo()"
9044
+ [attr.title]="tx('connections.history.redoAria', 'Redo connection edit')"
8293
9045
  [attr.aria-label]="tx('connections.history.redoAria', 'Redo connection edit')"
8294
9046
  (click)="redoHistory($event)"
8295
9047
  >&gt;</button>
@@ -8298,6 +9050,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8298
9050
  <button
8299
9051
  type="button"
8300
9052
  class="connection-editor__arrange-button"
9053
+ [attr.title]="tx('connections.editor.autoArrangeShort', 'Auto Arrange')"
9054
+ [attr.aria-label]="tx('connections.editor.autoArrangeShort', 'Auto Arrange')"
8301
9055
  (click)="autoArrange($event)"
8302
9056
  ><span>*</span>{{ tx('connections.editor.autoArrangeShort', 'Auto Arrange') }}</button>
8303
9057
  <button
@@ -8305,6 +9059,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8305
9059
  class="connection-editor__arrange-button"
8306
9060
  [class.connection-editor__arrange-button--active]="hasVisualPortOrder()"
8307
9061
  data-testid="page-builder-connections-reorganize-slices"
9062
+ [attr.title]="tx('connections.editor.reorganizeSlices', 'Reorganize Slices')"
9063
+ [attr.aria-label]="tx('connections.editor.reorganizeSlices', 'Reorganize Slices')"
8308
9064
  (click)="reorganizeSlices($event)"
8309
9065
  ><span>::</span>{{ tx('connections.editor.reorganizeSlices', 'Reorganize Slices') }}</button>
8310
9066
  <button
@@ -8312,6 +9068,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8312
9068
  class="connection-editor__arrange-button"
8313
9069
  [class.connection-editor__arrange-button--active]="traceEnabled()"
8314
9070
  data-testid="page-builder-connections-simulate"
9071
+ [attr.title]="traceEnabled() ? tx('connections.trace.pause', 'Pause') : tx('connections.trace.simulate', 'Simulate')"
9072
+ [attr.aria-label]="traceEnabled() ? tx('connections.trace.pause', 'Pause') : tx('connections.trace.simulate', 'Simulate')"
8315
9073
  (click)="toggleTrace($event)"
8316
9074
  ><span>&gt;</span>{{ traceEnabled() ? tx('connections.trace.pause', 'Pause') : tx('connections.trace.simulate', 'Simulate') }}</button>
8317
9075
 
@@ -8446,8 +9204,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8446
9204
  </div>
8447
9205
  </div>
8448
9206
 
8449
- <div class="connection-editor__side-panel">
8450
- <section class="connection-editor__section">
9207
+ <div
9208
+ class="connection-editor__side-panel"
9209
+ [class.connection-editor__side-panel--contextual]="!!selectedConnection() || !!selectedEditorNode()"
9210
+ data-testid="page-builder-connections-side-panel"
9211
+ >
9212
+ @if (recommendedMasterDetailSuggestion(); as suggestion) {
9213
+ <section
9214
+ class="connection-editor__section connection-editor__recommended"
9215
+ data-testid="page-builder-connections-recommended-master-detail"
9216
+ >
9217
+ <div class="connection-editor__section-title">{{ tx('connections.suggestions.recommendedTitle', 'Recommended connection') }}</div>
9218
+ <button
9219
+ type="button"
9220
+ class="connection-editor__recommended-card"
9221
+ [attr.data-testid]="'page-builder-connection-recommended-' + suggestion.id"
9222
+ (click)="quickConnectSuggestion(suggestion, $event)"
9223
+ >
9224
+ <span class="connection-editor__human-summary-label">{{ suggestionSemanticLabel(suggestion) }}</span>
9225
+ <strong>{{ suggestionOutcomeText(suggestion) }}</strong>
9226
+ <span>{{ suggestionPreviewText(suggestion) }}</span>
9227
+ <small>{{ suggestionRouteTechnicalText(suggestion) }}</small>
9228
+ <span class="connection-editor__suggestion-action">{{ suggestionActionText(suggestion) }}</span>
9229
+ </button>
9230
+ </section>
9231
+ }
9232
+ <section class="connection-editor__section connection-editor__filters-section">
8451
9233
  <div class="connection-editor__section-title">{{ tx('connections.filters.title', 'Filters') }}</div>
8452
9234
  <div class="connection-editor__filters">
8453
9235
  @for (filter of filters; track filter.id) {
@@ -8471,8 +9253,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8471
9253
  <div class="connection-editor__section-title">{{ tx('connections.inspector.title', 'Inspector') }}</div>
8472
9254
  @if (selectedConnection(); as connection) {
8473
9255
  <div class="connection-editor__inspector-heading">
8474
- <strong>{{ connection.id }}</strong>
8475
- <span>{{ connection.intent }}</span>
9256
+ <strong>{{ connectionHumanSummary(connection) }}</strong>
9257
+ <span>{{ tx('connections.inspector.selected', 'Selected connection') }} · {{ connectionSemanticLabel(connection) }}</span>
9258
+ </div>
9259
+ @if (lastCreatedLinkId() === connection.id) {
9260
+ <div
9261
+ class="connection-editor__success"
9262
+ role="status"
9263
+ data-testid="page-builder-connections-created-status"
9264
+ >
9265
+ <strong>{{ tx('connections.feedback.createdTitle', 'Connection created') }}</strong>
9266
+ <span>{{ connectionCreatedFeedback(connection) }}</span>
9267
+ </div>
9268
+ }
9269
+ <div
9270
+ class="connection-editor__human-summary"
9271
+ data-testid="page-builder-connections-human-summary"
9272
+ >
9273
+ <span class="connection-editor__human-summary-label">{{ connectionSemanticLabel(connection) }}</span>
9274
+ <strong>{{ connectionHumanSummary(connection) }}</strong>
9275
+ <span>{{ connectionDeliveryPreview(connection) }}</span>
8476
9276
  </div>
8477
9277
  <div class="connection-editor__details-row">
8478
9278
  <span>{{ tx('connections.details.from', 'From') }}</span>
@@ -8482,14 +9282,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8482
9282
  <span>{{ tx('connections.details.to', 'To') }}</span>
8483
9283
  <strong>{{ connection.toLabel }}</strong>
8484
9284
  </div>
8485
- <div class="connection-editor__details-block">
8486
- <div class="connection-editor__details-label">{{ tx('connections.inspector.sourceEndpoint', 'Source endpoint') }}</div>
8487
- <pre>{{ connection.link.from | json }}</pre>
8488
- </div>
8489
- <div class="connection-editor__details-block">
8490
- <div class="connection-editor__details-label">{{ tx('connections.inspector.targetEndpoint', 'Target endpoint') }}</div>
8491
- <pre>{{ connection.link.to | json }}</pre>
8492
- </div>
9285
+ @if (connectionHasNestedEndpoint(connection)) {
9286
+ <div
9287
+ class="connection-editor__nested-summary"
9288
+ data-testid="page-builder-connections-nested-summary"
9289
+ >
9290
+ <span class="connection-editor__human-summary-label">{{ tx('connections.editor.nestedBadge', 'Nested') }}</span>
9291
+ <strong>{{ tx('connections.details.nestedOwnerPreserved', 'Top-level owner is preserved') }}</strong>
9292
+ <span>{{ connectionNestedSummary(connection) }}</span>
9293
+ </div>
9294
+ }
9295
+ <details class="connection-editor__technical-details">
9296
+ <summary>{{ tx('connections.inspector.technicalDetails', 'Technical details') }}</summary>
9297
+ <div class="connection-editor__details-block">
9298
+ <div class="connection-editor__details-label">{{ tx('connections.inspector.connectionId', 'Connection id') }}</div>
9299
+ <pre>{{ connection.id }}</pre>
9300
+ </div>
9301
+ <div class="connection-editor__details-block">
9302
+ <div class="connection-editor__details-label">{{ tx('connections.inspector.intent', 'Intent') }}</div>
9303
+ <pre>{{ connection.intent }}</pre>
9304
+ </div>
9305
+ <div class="connection-editor__details-block">
9306
+ <div class="connection-editor__details-label">{{ tx('connections.inspector.sourceEndpoint', 'Source endpoint') }}</div>
9307
+ <pre>{{ connection.link.from | json }}</pre>
9308
+ </div>
9309
+ <div class="connection-editor__details-block">
9310
+ <div class="connection-editor__details-label">{{ tx('connections.inspector.targetEndpoint', 'Target endpoint') }}</div>
9311
+ <pre>{{ connection.link.to | json }}</pre>
9312
+ </div>
9313
+ </details>
8493
9314
  @if (connection.link.to.kind === 'global-action') {
8494
9315
  <div class="connection-editor__details-block" data-testid="page-builder-connections-global-action-payload-editor">
8495
9316
  <div class="connection-editor__details-label">{{ tx('connections.globalAction.payloadTitle', 'Action payload') }}</div>
@@ -8745,6 +9566,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8745
9566
  [class.connection-editor__inspector-port--state]="port.kind === 'state'"
8746
9567
  >
8747
9568
  {{ port.kind }} · {{ port.label }}
9569
+ @if (isNestedPort(port)) {
9570
+ · {{ tx('connections.editor.nestedBadge', 'Nested') }} · {{ nestedPortPathText(port) }}
9571
+ }
8748
9572
  </span>
8749
9573
  }
8750
9574
  </div>
@@ -8792,6 +9616,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8792
9616
  @if (smartSuggestions().length) {
8793
9617
  <div class="connection-editor__suggestions" data-testid="page-builder-connections-suggestions">
8794
9618
  <div class="connection-editor__section-title">{{ tx('connections.suggestions.title', 'Smart suggestions') }}</div>
9619
+ @if (masterDetailReadinessDiagnostic(); as diagnostic) {
9620
+ <div
9621
+ class="connection-editor__suggestion-diagnostic"
9622
+ role="note"
9623
+ data-testid="page-builder-connections-master-detail-diagnostic"
9624
+ >
9625
+ {{ diagnostic }}
9626
+ </div>
9627
+ }
8795
9628
  @for (suggestion of smartSuggestions(); track suggestion.id) {
8796
9629
  <button
8797
9630
  type="button"
@@ -8804,11 +9637,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
8804
9637
  <span>{{ suggestion.source.label }} -> {{ suggestion.target.label }}</span>
8805
9638
  <strong>{{ suggestion.targetNodeTitle }}</strong>
8806
9639
  </span>
9640
+ <span class="connection-editor__suggestion-intent">{{ suggestionSemanticLabel(suggestion) }}</span>
9641
+ <strong class="connection-editor__suggestion-outcome">{{ suggestionOutcomeText(suggestion) }}</strong>
8807
9642
  <span class="connection-editor__suggestion-reason">{{ suggestionReasonText(suggestion.reason) }}</span>
8808
- <span class="connection-editor__suggestion-action">{{ tx('connections.suggestions.quickConnect', 'Quick connect') }}</span>
9643
+ <span class="connection-editor__suggestion-preview">{{ suggestionPreviewText(suggestion) }}</span>
9644
+ <span class="connection-editor__suggestion-action">{{ suggestionActionText(suggestion) }}</span>
8809
9645
  </button>
8810
9646
  }
8811
9647
  </div>
9648
+ } @else if (masterDetailReadinessDiagnostic(); as diagnostic) {
9649
+ <div
9650
+ class="connection-editor__suggestions"
9651
+ data-testid="page-builder-connections-suggestions"
9652
+ >
9653
+ <div class="connection-editor__section-title">{{ tx('connections.suggestions.title', 'Smart suggestions') }}</div>
9654
+ <div
9655
+ class="connection-editor__suggestion-diagnostic"
9656
+ role="note"
9657
+ data-testid="page-builder-connections-master-detail-diagnostic"
9658
+ >
9659
+ {{ diagnostic }}
9660
+ </div>
9661
+ </div>
8812
9662
  }
8813
9663
  @if (traceEnabled()) {
8814
9664
  <div class="connection-editor__trace" data-testid="page-builder-connections-trace">
@@ -9114,11 +9964,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
9114
9964
  </section>
9115
9965
  </aside>
9116
9966
  }
9117
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{position:fixed;inset:0;z-index:1000;pointer-events:none}.connection-editor{--pce-fg: var(--md-sys-color-on-surface, #dce6f4);--pce-strong: var(--md-sys-color-on-surface, #f8fafc);--pce-muted: var(--md-sys-color-on-surface-variant, #94a3b8);--pce-primary: var(--md-sys-color-primary, #19c8e8);--pce-secondary: var(--md-sys-color-secondary, #b46cff);--pce-tertiary: var(--md-sys-color-tertiary, #ff9f2f);--pce-success: var(--md-sys-color-tertiary, #10b981);--pce-warning: var(--md-sys-color-error, #ff9f2f);--pce-error: var(--md-sys-color-error, #ef4444);--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #07111f) 80%, #020617);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #08101d) 78%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #0f172a) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #080d18) 64%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #899ab7) 46%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #94a3b8) 58%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #7d8fa9) 24%, transparent);--pce-glass-highlight: color-mix(in srgb, var(--md-sys-color-on-surface, #ffffff) 8%, transparent);--pce-shadow: color-mix(in srgb, #000 56%, transparent);--pce-shadow-soft: color-mix(in srgb, #000 30%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #040a13) 42%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high, #050912) 94%, transparent);position:absolute;inset:12px;height:calc(100vh - 24px);box-sizing:border-box;overflow:hidden;padding:16px;border-radius:18px;color:var(--pce-fg);background:radial-gradient(circle at 72% 20%,color-mix(in srgb,var(--pce-secondary) 16%,transparent),transparent 28%),radial-gradient(circle at 26% 74%,color-mix(in srgb,var(--pce-primary) 10%,transparent),transparent 34%),radial-gradient(circle at 48% 52%,color-mix(in srgb,var(--pce-tertiary) 5%,transparent),transparent 35%),linear-gradient(var(--pce-grid) 1px,transparent 1px),linear-gradient(90deg,var(--pce-grid) 1px,transparent 1px),var(--pce-surface-base);background-size:auto,auto,auto,38px 38px,38px 38px,auto;border:1px solid var(--pce-outline);box-shadow:0 28px 90px var(--pce-shadow);pointer-events:auto;display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);grid-template-rows:auto minmax(0,1fr) auto minmax(48px,140px);gap:14px}:host-context(.theme-light) .connection-editor{--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #ffffff) 94%, var(--md-sys-color-primary, #2563eb) 6%);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 82%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #eef2ff) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #f8fafc) 70%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 68%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #64748b) 62%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 34%, transparent);--pce-glass-highlight: color-mix(in srgb, #fff 64%, transparent);--pce-shadow: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 22%, transparent);--pce-shadow-soft: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 14%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #ffffff) 58%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 92%, transparent)}.connection-editor__header{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:42px;padding:8px 14px;border-radius:999px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__mode-frame{position:relative;min-width:0}.connection-editor__close{width:34px;height:34px;flex:0 0 auto;display:inline-grid;place-items:center;border:1px solid var(--pce-outline);border-radius:999px;color:var(--pce-text);background:var(--pce-surface-strong);box-shadow:inset 0 1px var(--pce-glass-highlight);cursor:pointer;font:inherit;font-size:1.2rem;line-height:1}.connection-editor__close:hover,.connection-editor__close:focus-visible{border-color:var(--pce-outline-strong);background:color-mix(in srgb,var(--pce-accent) 16%,var(--pce-surface-strong));outline:none}.connection-editor__mode-shell{display:inline-flex;align-items:center;gap:4px;min-width:0;padding:4px;border-radius:999px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:inset 0 1px var(--pce-glass-highlight),0 10px 26px var(--pce-shadow-soft);scrollbar-width:none}.connection-editor__mode-shell::-webkit-scrollbar{display:none}.connection-editor__mode{min-height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 12px;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.76rem;font-weight:800;white-space:nowrap;transition:background .16s ease,border-color .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__mode:hover,.connection-editor__mode--active{color:var(--pce-strong);border-color:color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-strong) 82%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 12%,transparent)}.connection-editor__mode-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__mode--active .connection-editor__mode-glyph{color:var(--pce-primary)}.connection-editor__mode-dot{width:6px;height:6px;border-radius:999px;background:var(--pce-success);box-shadow:0 0 12px color-mix(in srgb,var(--pce-success) 70%,transparent)}.connection-editor__status-pill{display:inline-flex;align-items:center;gap:8px;min-height:24px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 36%,transparent);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.72rem;font-weight:800;white-space:nowrap}.connection-editor__status-pill span{width:6px;height:6px;border-radius:999px;background:var(--pce-primary);box-shadow:0 0 12px color-mix(in srgb,var(--pce-primary) 70%,transparent)}.connection-editor__section{display:grid;gap:10px}.connection-editor__dock{grid-column:1 / -1;grid-row:4;position:relative;z-index:4;min-height:0;display:grid;border-radius:14px;border:1px solid var(--pce-outline);background:radial-gradient(circle at 16% 0%,color-mix(in srgb,var(--pce-primary) 22%,transparent),transparent 34%),radial-gradient(circle at 78% 0%,color-mix(in srgb,var(--pce-secondary) 25%,transparent),transparent 38%),linear-gradient(90deg,var(--pce-dock-bg),var(--pce-surface-strong) 46%,color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-dock-bg))),var(--pce-dock-bg);box-shadow:0 18px 58px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__dock--collapsed .connection-editor__dock-tabs{border-block-end:0}.connection-editor__dock-tabs{display:flex;align-items:center;gap:10px;min-height:52px;padding:9px 14px;border-block-end:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-glass-highlight),transparent),color-mix(in srgb,var(--pce-surface-soft) 34%,transparent)}.connection-editor__dock-tab,.connection-editor__dock-toggle{min-height:30px;border-radius:999px;border:1px solid transparent;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.72rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-tab{display:inline-flex;align-items:center;gap:8px;padding:0 13px;white-space:nowrap}.connection-editor__dock-tab-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.8rem;letter-spacing:0;text-transform:none}.connection-editor__dock-tab--active{color:var(--pce-strong);border-color:var(--pce-outline-strong);background:linear-gradient(180deg,color-mix(in srgb,var(--pce-strong) 14%,transparent),color-mix(in srgb,var(--pce-strong) 6%,transparent));box-shadow:0 0 0 1px color-mix(in srgb,var(--pce-shadow) 72%,transparent),0 0 22px color-mix(in srgb,var(--pce-strong) 8%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__dock-tab--active .connection-editor__dock-tab-glyph{color:var(--pce-strong)}.connection-editor__dock-count{margin-inline-start:auto;color:color-mix(in srgb,var(--pce-muted) 62%,transparent);font-size:.7rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-toggle{width:32px;padding:0;border-color:var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.88rem;letter-spacing:0}.connection-editor__dock-body{max-height:154px;overflow:auto;padding:12px 12px 14px;border-block-start:1px solid var(--pce-outline);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 9%,transparent),color-mix(in srgb,var(--pce-secondary) 10%,transparent) 62%,color-mix(in srgb,var(--pce-surface-strong) 18%,transparent)),color-mix(in srgb,var(--pce-surface-soft) 30%,transparent)}.connection-editor__dock-body pre{max-height:60px}.connection-editor__dock-links{display:grid;gap:8px}.connection-editor__dock-link-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;padding:7px 10px;border-radius:10px;border:1px solid var(--pce-outline);background:linear-gradient(90deg,var(--pce-surface-soft),color-mix(in srgb,var(--pce-secondary) 10%,var(--pce-surface-soft)) 72%,var(--pce-surface-soft)),var(--pce-surface-soft);color:var(--pce-fg);transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-link{display:grid;grid-template-columns:minmax(116px,.52fr) minmax(300px,1.72fr) minmax(160px,.9fr) auto;align-items:center;gap:12px;width:100%;min-height:42px;padding:0;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer;text-align:start}.connection-editor__dock-link-row:hover,.connection-editor__dock-link--active{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 13%,transparent),color-mix(in srgb,var(--pce-secondary) 16%,transparent),var(--pce-surface-strong)),var(--pce-surface-strong);box-shadow:0 12px 32px var(--pce-shadow-soft),inset 0 0 18px color-mix(in srgb,var(--pce-primary) 6%,transparent)}.connection-editor__dock-link--active{border-color:#facc1575;box-shadow:0 12px 32px var(--pce-shadow-soft),0 0 24px #facc151f}.connection-editor__dock-link--new{border-color:#fb923ca3;background:linear-gradient(90deg,#fb923c2e,#a855f729,#0ea5e91f),#0f172ac2;box-shadow:0 12px 34px #02061752,0 0 30px #fb923c2e;animation:new-dock-link-flash 1.35s ease-out forwards}.connection-editor__dock-link--error{border-color:#ef444461}.connection-editor__dock-jump{min-width:62px;min-height:30px;padding:0 10px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 54%,transparent);color:var(--pce-primary);cursor:pointer;font-size:.66rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__dock-jump:hover,.connection-editor__dock-jump:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 56%,transparent);background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 18%,transparent);outline:none}.connection-editor__dock-link-kind{display:inline-flex;align-items:center;gap:7px;min-width:0;color:var(--pce-muted);font-size:.66rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-link-kind span{width:8px;height:8px;border-radius:999px;background:#b46cff;box-shadow:0 0 14px #b46cff7a}.connection-editor__dock-link--state .connection-editor__dock-link-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2f94}.connection-editor__dock-link--state-read .connection-editor__dock-link-kind span{background:#8b7dff;box-shadow:0 0 13px #8b7dff75}.connection-editor__dock-link--projection .connection-editor__dock-link-kind span{background:#19c8e8;box-shadow:0 0 10px #19c8e857}.connection-editor__dock-link--event-propagation .connection-editor__dock-link-kind span{background:#ffb454;box-shadow:0 0 15px #ffb45485}.connection-editor__dock-link--policy .connection-editor__dock-link-kind span{outline:1px solid rgba(34,197,94,.76);outline-offset:2px;box-shadow:0 0 16px #22c55e61}.connection-editor__dock-link--policy:not(.connection-editor__dock-link--state,.connection-editor__dock-link--state-read,.connection-editor__dock-link--projection,.connection-editor__dock-link--event-propagation) .connection-editor__dock-link-kind span{background:#22c55e}.connection-editor__dock-link-route{display:inline-flex;align-items:center;gap:8px;min-width:0}.connection-editor__dock-link-chip{min-width:0;overflow:hidden;padding:4px 8px;border-radius:999px;border:1px solid var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-soft) 72%,transparent);color:var(--pce-fg);font-size:.72rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-chip--from{border-color:#ff9f2f66;color:#ffbd62}.connection-editor__dock-link-chip--to{border-color:#19c8e83d;color:#7dddeb}:host-context(.theme-light) .connection-editor__dock-link-chip--from{border-color:color-mix(in srgb,var(--pce-tertiary) 46%,transparent);color:#8a4600}:host-context(.theme-light) .connection-editor__dock-link-chip--to{border-color:color-mix(in srgb,var(--pce-primary) 34%,transparent);color:#075f73}.connection-editor__dock-link-arrow{flex:0 0 auto;color:var(--pce-muted);font-weight:900}.connection-editor__dock-link-id{min-width:0;overflow:hidden;color:var(--pce-muted);font-size:.66rem;font-weight:800;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-badges{display:inline-flex;justify-content:flex-end;gap:5px;min-width:70px}.connection-editor__dock-link-badges span{padding:3px 7px;border-radius:999px;background:#a855f724;color:#d8b4fe;font-size:.62rem;font-weight:900;text-transform:uppercase;white-space:nowrap}:host-context(.theme-light) .connection-editor__dock-link-badges span{background:color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-surface-soft));color:#6d2a9f}.connection-editor__dock-empty{padding:12px;border-radius:12px;border:1px dashed var(--pce-outline);color:var(--pce-muted);font-size:.76rem;font-weight:700}.connection-editor__inspector{border-color:color-mix(in srgb,var(--pce-primary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 10%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface)}.connection-editor__eyebrow,.connection-editor__section-title{font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;color:var(--pce-muted);font-weight:700}.connection-editor__title{font-size:1.02rem;font-weight:800}.connection-editor__subtitle,.connection-editor__item-copy,.connection-editor__item-meta,.connection-editor__details-row span,.connection-editor__details-label,.connection-editor__empty{color:var(--pce-muted);font-size:.84rem}.connection-editor__inspector-heading{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--pce-surface-soft);border:1px solid var(--pce-outline)}.connection-editor__inspector-heading strong{color:var(--pce-strong);font-size:.96rem;overflow-wrap:anywhere}.connection-editor__inspector-heading span{color:var(--pce-primary);font-size:.76rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em}.connection-editor__inspector-ports{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__inspector-port{max-width:100%;padding:4px 8px;border-radius:999px;border:1px solid rgba(148,163,184,.16);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-editor__inspector-port--input{border-color:#22d3ee57;color:#67e8f9}.connection-editor__inspector-port--output{border-color:#f59e0b57;color:#fbbf24}.connection-editor__inspector-port--state{border-color:#a855f761;color:#d8b4fe}.connection-editor__segment-kind-legend{display:grid;gap:10px;padding:12px;border-radius:16px;border:1px solid rgba(148,163,184,.14);background:linear-gradient(135deg,#0f172aa8,#080d1885),#02061757}.connection-editor__segment-kind-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.connection-editor__segment-kind-pill{min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:900;overflow:hidden;white-space:nowrap}.connection-editor__segment-kind-pill span{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:currentColor;box-shadow:0 0 12px currentColor}.connection-editor__segment-kind-pill--input{border-color:#19c8e83d;color:#7dddeb}.connection-editor__segment-kind-pill--output{border-color:#ff9f2f61;color:#ffbd62}.connection-editor__segment-kind-pill--state{border-color:#b46cff61;color:#d9b8ff}:host-context(.theme-light) .connection-editor__segment-kind-pill{border-color:var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-strong) 88%,transparent)}:host-context(.theme-light) .connection-editor__segment-kind-pill--input{color:#075f73}:host-context(.theme-light) .connection-editor__segment-kind-pill--output{color:#8a4600}:host-context(.theme-light) .connection-editor__segment-kind-pill--state{color:#6d2a9f}.connection-editor__stage{grid-column:1;grid-row:2;position:relative;min-height:0;height:100%;overflow:visible;border-radius:16px;border:1px solid var(--pce-outline);background:radial-gradient(circle at center,color-mix(in srgb,var(--pce-secondary) 7%,transparent),transparent 38%),radial-gradient(circle,var(--pce-grid) 1px,transparent 1.5px),var(--pce-stage-bg);background-size:auto,31px 31px,auto;box-shadow:inset 0 0 0 1px var(--pce-glass-highlight);cursor:grab;touch-action:none}.connection-editor__stage--panning,.connection-editor__stage:active{cursor:grabbing}.connection-editor__stage--dragging{cursor:crosshair}.connection-editor__stage--rotating{cursor:grabbing}.connection-editor__viewport{position:absolute;inset-block-start:0;inset-inline-start:0;width:900px;height:540px;overflow:visible;transform-origin:0 0;transition:transform .14s ease}.connection-editor__wires{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.connection-editor__wire,.connection-editor__wire-hit{fill:none;stroke-linecap:round}.connection-editor__wire{stroke:#b46cff;stroke-width:1.45;stroke-opacity:.48;pointer-events:none;filter:url(#connection-glow);stroke-dasharray:10 8;animation:connection-flow 1.65s linear infinite}.connection-editor__wire-hit{stroke:transparent;stroke-width:18;cursor:pointer;pointer-events:stroke}.connection-editor__wire-hit--active{stroke-width:28}.connection-editor__wire--halo{stroke:#b46cff1f;stroke-width:7;stroke-dasharray:none;animation:none}.connection-editor__wire--state{stroke:#ff9f2f;stroke-width:2.25;stroke-dasharray:8 7;animation:connection-flow .92s linear infinite}.connection-editor__wire--state.connection-editor__wire--halo{stroke:#ff9f2f29;stroke-width:11}.connection-editor__wire--projection{stroke:#15b8d8;stroke-width:1.75;stroke-dasharray:20 8;animation:connection-flow 1.9s linear infinite}.connection-editor__wire--projection.connection-editor__wire--halo{stroke:#15b8d81a;stroke-width:7}.connection-editor__wire--state-read{stroke:#8b7dff;stroke-width:1.65;stroke-dasharray:3 11;animation:connection-flow 2.25s linear infinite reverse}.connection-editor__wire--state-read.connection-editor__wire--halo{stroke:#8b7dff21;stroke-width:8}.connection-editor__wire--event-propagation{stroke:#ffb454;stroke-width:2.05;stroke-dasharray:5 7;animation:connection-flow .78s linear infinite}.connection-editor__wire--event-propagation.connection-editor__wire--halo{stroke:#ffb4542e;stroke-width:10}.connection-editor__wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.2)) url(#connection-glow)}.connection-editor__wire--policy.connection-editor__wire--halo{stroke:#22c55e1f;stroke-width:13}.connection-editor__wire--warning{stroke:#ff9f2f}.connection-editor__wire--warning.connection-editor__wire--halo{stroke:#ff9f2f2e}.connection-editor__wire--error{stroke:#ef4444}.connection-editor__wire--error.connection-editor__wire--halo{stroke:#ef44442e}.connection-editor__wire--active{stroke:#d9b8ff;stroke-width:3;stroke-opacity:1;stroke-dasharray:5 7;animation-duration:.58s}.connection-editor__wire--halo.connection-editor__wire--active{stroke-width:16;stroke-opacity:.8;animation:selected-wire-aura 1.35s ease-in-out infinite}.connection-editor__wire--new{stroke-width:3.4;stroke-opacity:1;stroke-dasharray:640;stroke-dashoffset:640;animation:wire-draw-in .62s cubic-bezier(.16,1,.3,1) forwards,connection-flow 1.05s linear .62s infinite}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:22;stroke-opacity:0;animation:new-wire-halo 1.45s ease-out forwards}.connection-editor__wire--trace{stroke:#9b5cff;stroke-width:3.2;stroke-opacity:1;stroke-dasharray:7 6;animation:connection-flow .72s linear infinite,trace-wire-pulse 1.18s ease-in-out infinite}.connection-editor__wire--halo.connection-editor__wire--trace{stroke:#9b5cff57;stroke-width:18;stroke-opacity:.86;animation:trace-halo-pulse 1.18s ease-in-out infinite}.connection-editor__wire--mode-dimmed{stroke-opacity:.14;stroke-width:1.05;filter:none;animation-duration:2.6s}.connection-editor__wire--halo.connection-editor__wire--mode-dimmed{stroke-opacity:.05;stroke-width:5;animation:none}.connection-editor__wire-hit--mode-dimmed{stroke-width:12}.connection-editor__wire-endpoint{fill:#f8fafc;stroke:#0f172ae6;stroke-width:1.5;filter:drop-shadow(0 0 8px rgba(216,180,254,.8));pointer-events:none;animation:endpoint-pulse 1.2s ease-in-out infinite}.connection-editor__wire-endpoint--source{fill:#ff9f2f}.connection-editor__wire-endpoint--target{fill:#19c8e8}.connection-editor__connection-tooltip{position:absolute;z-index:6;width:min(312px,calc(100% - 24px));display:grid;gap:8px;padding:12px 14px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(135deg,var(--pce-surface-strong),var(--pce-surface)),var(--pce-surface-strong);box-shadow:0 18px 44px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);color:var(--pce-fg);pointer-events:none;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .14s ease-out}.connection-editor__connection-tooltip-callout{position:absolute;inset-block-start:100%;inset-inline-start:var(--connection-tooltip-callout-x, 42px);width:2px;height:28px;border-radius:999px;background:linear-gradient(180deg,#e2e8f0bd,#19c8e800);box-shadow:0 0 12px #19c8e852;transform:translate(-1px);pointer-events:none}.connection-editor__connection-tooltip-callout:before,.connection-editor__connection-tooltip-callout:after{content:\"\";position:absolute;border-radius:999px;pointer-events:none}.connection-editor__connection-tooltip-callout:before{inset-block-start:-5px;inset-inline-start:-5px;width:12px;height:12px;border:1px solid rgba(148,163,184,.24);background:#080d18f5;box-shadow:inset 0 1px #ffffff14}.connection-editor__connection-tooltip-callout:after{inset-block-end:-3px;inset-inline-start:-4px;width:10px;height:10px;background:#19c8e8;box-shadow:0 0 16px #19c8e88f}.connection-editor__connection-tooltip--projection{border-color:#19c8e833;background:linear-gradient(135deg,#15b8d81f,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state{border-color:#ff9f2f66;background:linear-gradient(135deg,#ff9f2f3d,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout{background:linear-gradient(180deg,#ffbd62d1,#ff9f2f00);box-shadow:0 0 14px #ff9f2f61}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout:after{background:#ff9f2f;box-shadow:0 0 18px #ff9f2fad}.connection-editor__connection-tooltip--error{border-color:#f871716b}.connection-editor__connection-tooltip--error .connection-editor__connection-tooltip-callout:after{background:#fb7185;box-shadow:0 0 18px #fb7185ad}.connection-editor__connection-tooltip-kind{display:inline-flex;align-items:center;gap:8px;color:#94a3b8;font-size:.62rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__connection-tooltip-kind span{width:8px;height:8px;border-radius:999px;background:#19c8e8;box-shadow:0 0 12px #19c8e880}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2fc7}.connection-editor__connection-tooltip-row{min-width:0;display:grid;grid-template-columns:54px minmax(0,1fr);align-items:center;gap:8px;min-height:28px;padding:0 10px;border-radius:999px;background:#0f172a94}.connection-editor__connection-tooltip-row span{color:#8d9bb0;font-size:.62rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.connection-editor__connection-tooltip-row strong{min-width:0;overflow:hidden;color:#e2e8f0;font-size:.75rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__connection-tooltip-badges{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__connection-tooltip-badges span{padding:3px 8px;border-radius:999px;background:#02061799;color:#fbbf24;font-size:.66rem;font-weight:900}.connection-editor__trace-overlay{position:absolute;z-index:6;inset-block-start:16px;inset-inline-start:50%;width:min(560px,calc(100% - 360px));min-width:320px;padding:12px 14px;border-radius:16px;border:1px solid rgba(34,197,94,.26);background:linear-gradient(135deg,#22c55e1f,#0ea5e91a),#080d18f0;box-shadow:0 22px 56px #02061775,0 0 42px #22c55e1f;transform:translate(-50%);pointer-events:auto;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .16s ease-out}.connection-editor__trace-overlay-head,.connection-editor__trace-overlay-route{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}.connection-editor__trace-overlay-head span,.connection-editor__trace-overlay-route span{color:#86efac;font-size:.66rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase;white-space:nowrap}.connection-editor__trace-overlay-head strong{color:#cbd5e1;font-size:.7rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace}.connection-editor__trace-overlay-route{margin-top:6px}.connection-editor__trace-overlay-controls{display:grid;grid-template-columns:28px minmax(0,1fr) 28px;align-items:center;gap:8px;margin-top:10px}.connection-editor__trace-overlay-button{width:28px;height:24px;display:inline-grid;place-items:center;border:1px solid rgba(148,163,184,.18);border-radius:999px;background:#0206176b;color:#e2e8f0;cursor:pointer;font-size:1rem;font-weight:900;line-height:1;transition:border-color .15s ease,background .15s ease,color .15s ease,opacity .15s ease}.connection-editor__trace-overlay-button:hover:not(:disabled){border-color:#22d3ee6b;background:#0ea5e929;color:#f8fafc}.connection-editor__trace-overlay-button:disabled{cursor:default;opacity:.36}.connection-editor__trace-overlay-steps{min-width:0;display:flex;align-items:center;gap:6px;overflow-x:auto;padding:2px;scrollbar-width:none}.connection-editor__trace-overlay-steps::-webkit-scrollbar{display:none}.connection-editor__trace-overlay-step{position:relative;flex:1 0 28px;min-width:28px;height:22px;border:1px solid rgba(148,163,184,.16);border-radius:999px;background:#0f172a9e;color:#94a3b8;cursor:pointer;font-size:.62rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__trace-overlay-step--active{border-color:#22d3eea3;background:linear-gradient(90deg,#22d3ee3d,#9b5cff33);color:#f8fafc;box-shadow:0 0 18px #22d3ee33}.connection-editor__trace-overlay-step--blocked{border-color:#fb71855c;color:#fecdd3}.connection-editor__trace-overlay-route strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.82rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__trace-overlay-bar{position:relative;height:5px;margin-top:10px;overflow:hidden;border-radius:999px;background:#94a3b829}.connection-editor__trace-overlay-bar span{position:absolute;inset-block:0;inset-inline-start:0;border-radius:inherit;background:linear-gradient(90deg,#22c55e,#22d3ee);box-shadow:0 0 18px #22c55e61;min-width:8%}.connection-editor__drag-wire{fill:none;stroke:#94a3b8;stroke-width:2.4;stroke-linecap:round;stroke-dasharray:6 7;pointer-events:none;filter:url(#connection-glow);animation:connection-flow 1.05s linear infinite,drag-wire-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--halo{stroke:#94a3b829;stroke-width:14;stroke-dasharray:none;animation:drag-halo-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--valid{stroke:#22c55e}.connection-editor__drag-wire--halo.connection-editor__drag-wire--valid{stroke:#22c55e47}.connection-editor__drag-endpoint{fill:#94a3b8;stroke:#020617eb;stroke-width:2;pointer-events:none;filter:url(#connection-glow);transform-box:fill-box;transform-origin:center;animation:endpoint-pulse 1s ease-in-out infinite}.connection-editor__drag-endpoint--source{fill:#ff9f2f}.connection-editor__drag-endpoint--target{fill:#7dddeb}.connection-editor__drag-endpoint--valid{fill:#22c55e;stroke:#bbf7d0e0}.connection-editor__wire-handle-line{stroke-width:2;stroke-linecap:round;stroke-dasharray:4 5;pointer-events:none;opacity:.88;filter:url(#connection-glow)}.connection-editor__wire-handle-line--source{stroke:#ff9f2ff0}.connection-editor__wire-handle-line--target{stroke:#19c8e8c2}.connection-editor__wire-control{fill:#0f172af5;stroke:#cbd5e1c7;stroke-width:1.8;pointer-events:none;filter:url(#connection-glow)}.connection-editor__wire-label{pointer-events:none;filter:drop-shadow(0 0 10px rgba(2,6,23,.44));animation:tooltip-rise .14s ease-out}.connection-editor__wire-label rect{fill:#080d18eb;stroke-width:1}.connection-editor__wire-label text{fill:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:8px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__wire-label--source rect{stroke:#ff9f2fad}.connection-editor__wire-label--target rect{stroke:#19c8e86b}.connection-editor__zoom-controls{position:absolute;inset-inline-start:14px;inset-block-start:14px;z-index:4;display:grid;gap:8px;width:210px;pointer-events:auto}.connection-editor__tool-group,.connection-editor__trace-source{display:grid;gap:8px;padding:10px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:0 16px 36px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__tool-group{grid-template-columns:repeat(3,30px);width:max-content}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:repeat(2,30px)}.connection-editor__arrange-button{width:100%;min-height:32px;display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:999px;border:1px solid rgba(168,85,247,.34);background:linear-gradient(90deg,#a855f72e,#22d3ee1f);color:#e9d5ff;font-size:.74rem;font-weight:800;letter-spacing:.02em;cursor:pointer}.connection-editor__arrange-button span{color:#c084fc;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:900}.connection-editor__tool-button{width:30px;height:30px;border-radius:999px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.9rem;font-weight:800;letter-spacing:.02em;cursor:pointer;line-height:1}.connection-editor__tool-button:hover:not(:disabled){border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);color:var(--pce-primary);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 16%,transparent)}.connection-editor__history-button:disabled{cursor:not-allowed;opacity:.42}.connection-editor__arrange-button--active{border-color:#22d3ee94;background:linear-gradient(90deg,#0ea5e93d,#22d3ee2e);color:#cffafe}.connection-editor__trace-source{gap:4px;max-height:230px;overflow:auto}.connection-editor__trace-source-title{padding:2px 4px 6px;color:var(--pce-muted);font-size:.64rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase}.connection-editor__trace-source-item{min-width:0;min-height:30px;display:flex;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:8px;background:transparent;color:var(--pce-fg);cursor:pointer;font-size:.74rem;font-weight:800;text-align:start}.connection-editor__trace-source-item span{color:#f59e0b;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__trace-source-item:hover,.connection-editor__trace-source-item--active{background:var(--pce-surface-strong);color:var(--pce-strong);box-shadow:inset 3px 0 #f59e0bd1}.connection-editor__minimap{position:absolute;inset-inline-end:14px;inset-block-end:14px;z-index:4;width:184px;height:124px;padding:18px 10px 10px;overflow:hidden;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-primary) 30%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),var(--pce-surface-strong)),var(--pce-surface);box-shadow:0 20px 48px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);cursor:pointer;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__minimap:hover,.connection-editor__minimap--panning{border-color:#22d3ee75;box-shadow:0 20px 48px var(--pce-shadow-soft),0 0 24px color-mix(in srgb,var(--pce-primary) 14%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__minimap--panning{cursor:grabbing}.connection-editor__minimap:before{content:\"\";position:absolute;inset:22px 10px 10px;border-radius:10px;background-image:radial-gradient(circle,rgba(125,211,252,.18) 1px,transparent 1px);background-size:22px 22px;opacity:.58;pointer-events:none}.connection-editor__minimap-title{position:absolute;inset-block-start:7px;inset-inline-start:12px;color:var(--pce-muted);font-size:.6rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__minimap svg{position:relative;width:100%;height:100%;display:block;overflow:visible}.connection-editor__minimap-wire{fill:none;stroke:#b46cff8f;stroke-width:4;stroke-linecap:round;opacity:.86}.connection-editor__minimap-wire--state{stroke:#ff9f2fdb}.connection-editor__minimap-wire--state-read{stroke:#8b7dffb8;stroke-dasharray:4 9}.connection-editor__minimap-wire--projection{stroke:#19c8e88a;stroke-dasharray:18 8}.connection-editor__minimap-wire--event-propagation{stroke:#ffb454cc;stroke-dasharray:6 7}.connection-editor__minimap-wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.28))}.connection-editor__minimap-wire--trace{stroke:#9b5cffe0;stroke-width:5;stroke-dasharray:12 9;animation:connection-flow 1s linear infinite}.connection-editor__minimap-wire--active{stroke:#facc15eb;stroke-width:6;filter:drop-shadow(0 0 8px rgba(250,204,21,.38))}.connection-editor__minimap-wire--mode-dimmed{opacity:.2;stroke-width:2.6;filter:none}.connection-editor__minimap-node{fill:#f59e0be0;stroke:#020617db;stroke-width:4;filter:drop-shadow(0 0 7px rgba(245,158,11,.24))}.connection-editor__minimap-node--state{fill:#a855f7e6;filter:drop-shadow(0 0 8px rgba(168,85,247,.34))}.connection-editor__minimap-node--selected{fill:#facc15f5;stroke:#fef08aeb;filter:drop-shadow(0 0 10px rgba(250,204,21,.42))}.connection-editor__minimap-node--trace-source{fill:#facc15f5;filter:drop-shadow(0 0 10px rgba(250,204,21,.44))}.connection-editor__minimap-node--trace-reacting{fill:#22c55eeb;filter:drop-shadow(0 0 10px rgba(34,197,94,.42))}.connection-editor__minimap-node--mode-dimmed{opacity:.28;filter:none}.connection-editor__minimap-viewport{fill:#7dd3fc1f;stroke:#7dd3fce6;stroke-width:5;stroke-dasharray:18 10;filter:drop-shadow(0 0 10px rgba(125,211,252,.3));transition:x .12s ease,y .12s ease,width .12s ease,height .12s ease}.connection-editor__minimap--panning .connection-editor__minimap-viewport{fill:#22d3ee2e;stroke:#22d3eef5;stroke-dasharray:none}.connection-editor__node{position:absolute;width:168px;height:168px;transform:translate(-84px,-84px);border:0;padding:0;background:transparent;color:inherit;cursor:pointer;transition:filter .16s ease}.connection-editor__node--dragging{cursor:grabbing;filter:drop-shadow(0 0 22px rgba(34,211,238,.26));z-index:12}.connection-editor__node--connection-focus{filter:drop-shadow(0 0 16px rgba(34,211,238,.2))}.connection-editor__node--compat-target .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e66,0 0 0 18px #22c55e0b,0 0 32px #22c55e29}.connection-editor__node--mode-dimmed{opacity:.42;filter:grayscale(.22) saturate(.56)}.connection-editor__node--mode-dimmed .connection-editor__node-ring{animation:none;box-shadow:0 0 0 1px #2dd4bf14,0 0 14px #0ea5e90f}.connection-editor__node--mode-dimmed .connection-editor__node-halo{stroke-opacity:.28}.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-svg{position:absolute;inset:0}.connection-editor__node-ring,.connection-editor__node-core{display:grid;place-items:center;clip-path:polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%)}.connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from -28deg,#06b6d4b3 0 28%,#f59e0b9e 28% 48%,#a855f780 48% 68%,#06b6d4a3 68% 100%);box-shadow:0 0 0 1px #2dd4bf2e,0 0 26px #0ea5e929;animation:node-breathe 2.8s ease-in-out infinite}.connection-editor__node-svg{overflow:visible;filter:drop-shadow(0 0 16px rgba(14,165,233,.16))}.connection-editor__node-halo{fill:transparent;stroke:#38bdf838;stroke-width:1;stroke-dasharray:0;pointer-events:none}.connection-editor__node-halo:nth-child(2){stroke:#38bdf824}.connection-editor__node-halo:nth-child(3){stroke:#94a3b81a}.connection-editor__node-segment{fill-opacity:.28;stroke-opacity:.72;stroke-width:1.15;transition:fill-opacity .16s ease,stroke-opacity .16s ease,stroke-width .16s ease;cursor:grab}.connection-editor__node:hover .connection-editor__node-segment,.connection-editor__node--selected .connection-editor__node-segment,.connection-editor__node--connection-focus .connection-editor__node-segment{fill-opacity:.54;stroke-opacity:.95;stroke-width:1.55}.connection-editor__node-segment--connection-focus{fill-opacity:.76;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 8px rgba(34,211,238,.76));animation:segment-focus-sweep 1.45s ease-in-out infinite}.connection-editor__node-segment--source{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 12px rgba(251,146,60,.82))}.connection-editor__node-segment--compatible{fill-opacity:.74;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 10px rgba(34,197,94,.72));animation:snap-pulse 1s ease-in-out infinite}.connection-editor__node-segment--compat-preview{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 13px rgba(245,158,11,.78))}.connection-editor__node-segment--candidate{fill-opacity:.92;stroke-opacity:1;stroke-width:2.8;filter:drop-shadow(0 0 16px rgba(34,197,94,.86))}.connection-editor__node-segment--incompatible{fill-opacity:.12;stroke-opacity:.28;cursor:not-allowed}.connection-editor__node-segment--invalid-drop{fill-opacity:.72;stroke:#fb7185;stroke-opacity:1;stroke-width:3;filter:drop-shadow(0 0 16px rgba(244,63,94,.84));animation:invalid-drop-jolt .36s ease-out}.connection-editor__node-segment--state{fill-opacity:.44;filter:drop-shadow(0 0 8px rgba(180,108,255,.2))}.connection-editor__node-segment--mode-dimmed{fill-opacity:.08;stroke-opacity:.2;stroke-width:.9;filter:none}.connection-editor__node-anchor{opacity:.95;filter:drop-shadow(0 0 6px currentColor)}.connection-editor__node-rotate-handle{cursor:grab;opacity:0;pointer-events:none;transition:opacity .16s ease,filter .16s ease;filter:drop-shadow(0 0 8px rgba(34,211,238,.28))}.connection-editor__node:hover .connection-editor__node-rotate-handle,.connection-editor__node--selected .connection-editor__node-rotate-handle,.connection-editor__node--rotating .connection-editor__node-rotate-handle{opacity:1;pointer-events:auto}.connection-editor__node--rotating .connection-editor__node-rotate-handle{cursor:grabbing;filter:drop-shadow(0 0 12px rgba(34,211,238,.54))}.connection-editor__node-rotate-hit{fill:transparent}.connection-editor__node-rotate-dot{fill:var(--pce-surface-strong);stroke:var(--pce-primary);stroke-opacity:.88;stroke-width:1.4}.connection-editor__node-rotate-arc,.connection-editor__node-rotate-arrow{fill:none;stroke:var(--pce-primary);stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.96;stroke-width:1.2;pointer-events:none}.connection-editor__segment-icon,.connection-editor__segment-label{pointer-events:none;fill:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:800;paint-order:stroke;stroke:#020617c2;stroke-width:3px;stroke-linejoin:round}.connection-editor__segment-icon{font-size:12px;fill:#19c8e8}.connection-editor__segment-icon--output{fill:#ff9f2f}.connection-editor__segment-label{font-size:9.5px;letter-spacing:0;fill:#e2e8f0e0}.connection-editor__node-core{inset:43px;padding:12px;border-radius:999px;clip-path:none;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(circle at center,#111827 0 58%,#060b14);border:1px solid rgba(226,232,240,.1);box-shadow:0 12px 28px #00000073,inset 0 1px #ffffff0d;color:#f8fafc;text-shadow:0 1px 2px rgba(0,0,0,.62)}.connection-editor__node-icon{display:block;max-width:44px;overflow:hidden;color:#f8fafc;font-family:Material Symbols Outlined,Material Icons,sans-serif;font-size:1.22rem;font-weight:400;line-height:1;text-align:center;text-transform:none;letter-spacing:0;white-space:nowrap;filter:drop-shadow(0 0 10px rgba(226,232,240,.18))}.connection-editor__node--state .connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from 14deg,#a855f7c7 0 42%,#7e3af26b 42% 78%,#f59e0b47 78% 100%);box-shadow:0 0 0 1px #a855f738,0 0 30px #a855f733}.connection-editor__node--selected .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15bd,0 0 34px #facc153d}.connection-editor__node--connection-focus .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eead,0 0 38px #22d3ee42;animation:node-focus-breathe 1.7s ease-in-out infinite}.connection-editor__node--trace-source .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 0 18px #facc150f,0 0 54px #facc154d;animation:trace-source-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:before{content:\"\";position:absolute;z-index:0;inset:-44px;border-radius:999px;border:2px solid rgba(250,204,21,.36);background:radial-gradient(circle at center,transparent 0 64%,rgba(250,204,21,.05) 65% 66%,transparent 67%),conic-gradient(from -20deg,#facc1500,#facc1552,#facc1500);box-shadow:0 0 36px #facc151f;opacity:.92;pointer-events:none;animation:trace-source-orbit 2.8s linear infinite}.connection-editor__node--trace-reacting .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e94,0 0 46px #22c55e38;animation:trace-reacting-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:after,.connection-editor__node--trace-reacting:after{position:absolute;z-index:3;inset-inline-start:50%;inset-block-start:-42px;padding:0;border:0;background:transparent;color:#facc15;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.68rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase;transform:translate(-50%);text-shadow:0 0 12px rgba(250,204,21,.52);pointer-events:none}.connection-editor__node--trace-source:after{content:attr(data-trace-label)}.connection-editor__node--trace-reacting:after{content:attr(data-trace-label);color:#86efac;text-shadow:0 0 12px rgba(34,197,94,.44)}.connection-editor__node--trace-source .connection-editor__node-segment--output{fill-opacity:.66;stroke-width:2.2;filter:drop-shadow(0 0 14px rgba(255,159,47,.42))}.connection-editor__node--expanded .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eebd,0 0 34px #22d3ee3d}.connection-editor__node--rotating .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 42px #facc1547;animation:node-focus-breathe 1.1s ease-in-out infinite}.connection-editor__node--rotating .connection-editor__node-segment{fill-opacity:.68;stroke-opacity:1;stroke-width:1.9;cursor:grabbing}.connection-editor__node-title,.connection-editor__node-subtitle{display:block;max-width:92px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.connection-editor__node-title{color:#f8fafc;font-size:.82rem;font-weight:800}.connection-editor__node-subtitle{margin-top:4px;color:#a7b4c8;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__ports{position:absolute;display:grid;gap:6px;width:104px;opacity:0;pointer-events:none;transition:opacity .16s ease}.connection-editor__segment-popover{position:absolute;z-index:80;width:292px;max-height:320px;overflow:auto;display:grid;gap:10px;padding:14px;border-radius:16px;border:1px solid rgba(148,163,184,.18);background:linear-gradient(135deg,#0f172af5,#110c20f0),#090c16eb;box-shadow:0 28px 72px #0000007a,0 0 48px #a855f71a,inset 0 1px #ffffff0d;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__segment-popover-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:2px}.connection-editor__segment-popover-title{color:#94a3b8;font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}.connection-editor__segment-popover-hint{margin-top:5px;color:#64748b;font-size:.66rem;font-weight:700}.connection-editor__segment-rotation{flex:0 0 auto;min-width:54px;padding:5px 8px;border-radius:999px;border:1px solid rgba(34,211,238,.28);background:#082f4957;color:#7dd3fc;font-size:.66rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-align:center;box-shadow:inset 0 0 16px #0ea5e914}.connection-editor__segment-row{display:grid;grid-template-columns:28px 72px minmax(0,1fr) auto;align-items:center;gap:8px;min-height:40px;padding:7px;border-radius:12px;border:1px solid rgba(148,163,184,.12);background:linear-gradient(90deg,#0f172ac7,#0f172a75),#0f172a99;transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__segment-row--input{border-color:#22d3ee42}.connection-editor__segment-row--output{border-color:#f59e0b47}.connection-editor__segment-row--state{border-color:#a855f74d}.connection-editor__segment-row--source,.connection-editor__segment-row--candidate{transform:translate(2px);box-shadow:0 0 22px #f59e0b24,inset 0 0 20px #f59e0b14}.connection-editor__segment-row--compatible{border-color:#22d3ee6b;box-shadow:inset 0 0 18px #22d3ee14}.connection-editor__segment-row--compat-preview{border-color:#f59e0b94;background:linear-gradient(90deg,#f59e0b1f,#0f172a8a),#0f172ab3;box-shadow:0 0 22px #f59e0b1f,inset 0 0 18px #f59e0b14}.connection-editor__segment-row--invalid-drop{border-color:#fb7185b3;background:linear-gradient(90deg,#f43f5e24,#0f172a94),#0f172ab3;box-shadow:0 0 24px #f43f5e2e,inset 0 0 18px #f43f5e1a;animation:invalid-drop-jolt .36s ease-out}.connection-editor__segment-index{color:#64748b;font-size:.64rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;letter-spacing:.08em}.connection-editor__segment-kind{display:inline-flex;align-items:center;gap:6px;color:#94a3b8;font-size:.62rem;font-weight:800;text-transform:uppercase;min-width:0;white-space:nowrap}.connection-editor__segment-kind-dot{width:7px;height:7px;border-radius:999px;background:#94a3b8;box-shadow:0 0 12px #94a3b847}.connection-editor__segment-row--input .connection-editor__segment-kind-dot{background:#22d3ee;box-shadow:0 0 12px #22d3ee61}.connection-editor__segment-row--output .connection-editor__segment-kind-dot{background:#fb923c;box-shadow:0 0 12px #fb923c66}.connection-editor__segment-row--state .connection-editor__segment-kind-dot{background:#a855f7;box-shadow:0 0 12px #a855f76b}.connection-editor__segment-label{display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden;color:#e2e8f0;font-size:.74rem;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-actions{display:inline-flex;gap:4px}.connection-editor__segment-action{width:24px;height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.18);background:#060c16b8;color:#dbeafe;cursor:pointer;font-weight:900;line-height:1}.connection-editor__segment-action:hover{border-color:#22d3ee75;box-shadow:0 0 14px #22d3ee29}.connection-editor__port{min-height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#080d18c2;color:#cbd5e1;font-size:.64rem;font-weight:700;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:crosshair;box-shadow:0 8px 20px #00000038}.connection-editor__port--output{border-color:#f59e0b75;color:#fbbf24}.connection-editor__port--input{border-color:#06b6d475;color:#22d3ee}.connection-editor__port--state{border-color:#a855f785;color:#c084fc}.connection-editor__port--compatible{background:#22c55e29;box-shadow:0 0 0 1px #22c55e61,0 0 18px #22c55e2e;animation:snap-pulse 1s ease-in-out infinite}.connection-editor__port--source{border-color:#fb923cb8;background:#fb923c29;color:#fed7aa;box-shadow:0 0 0 1px #fb923c73,0 0 20px #fb923c2e}.connection-editor__port--candidate{background:#22c55e3d;box-shadow:0 0 0 2px #22c55e94,0 0 24px #22c55e3d}.connection-editor__port--incompatible{opacity:.42;cursor:not-allowed;filter:grayscale(.45)}.connection-editor__port--invalid-drop{opacity:1;border-color:#fb7185c7;color:#fecdd3;background:#f43f5e2e;box-shadow:0 0 0 2px #f43f5e75,0 0 24px #f43f5e38;filter:none;animation:invalid-drop-jolt .36s ease-out}.connection-editor__port--connection-focus{border-color:#facc15ad;color:#fde68a;background:#facc151f;box-shadow:0 0 0 1px #facc156b,0 0 20px #facc152e;animation:port-focus-pulse 1.25s ease-in-out infinite}.connection-editor__drag-tip{position:absolute;z-index:6;display:grid;gap:4px;width:min(330px,calc(100% - 28px));padding:10px 12px;border-radius:14px;border:1px solid rgba(125,211,252,.26);background:linear-gradient(135deg,#0ea5e91f,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 28px #0ea5e91a;font-size:.76rem;pointer-events:none;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);animation:tooltip-rise .14s ease-out}.connection-editor__drag-tip--valid{border-color:#22c55e66;background:linear-gradient(135deg,#22c55e29,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 30px #22c55e24}.connection-editor__drag-tip--invalid{z-index:7;border-color:#fb71858a;background:linear-gradient(135deg,#f43f5e2e,#0f172af0),#080d18f5;box-shadow:0 18px 44px #0206176b,0 0 34px #f43f5e29;animation:tooltip-rise .14s ease-out,invalid-drop-jolt .36s ease-out}.connection-editor__invalid-drop-pulse{position:absolute;z-index:6;width:16px;height:16px;border-radius:999px;border:2px solid rgba(251,113,133,.88);background:#f43f5e38;box-shadow:0 0 0 8px #f43f5e1a,0 0 28px #f43f5e3d;pointer-events:none;transform:translate(-50%,-50%);animation:invalid-drop-ping 1.2s ease-out both}.connection-editor__drag-tip span{color:#7dd3fc;text-transform:uppercase;letter-spacing:.12em;font-size:.62rem;font-weight:800}.connection-editor__drag-tip strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.78rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__drag-tip small{color:#94a3b8;font-size:.68rem;font-weight:700}.connection-editor__drag-tip--valid small{color:#86efac}.connection-editor__drag-tip--invalid span,.connection-editor__drag-tip--invalid small{color:#fda4af}.connection-editor__summary{grid-column:1;grid-row:3;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.connection-editor__side-panel{grid-column:2;grid-row:2 / 4;position:relative;z-index:8;min-width:0;min-height:0;display:grid;align-content:start;gap:14px;overflow:auto;padding-inline-end:4px;scrollbar-color:var(--pce-outline-strong) var(--pce-surface-soft)}.connection-editor__metric,.connection-editor__item{border-radius:16px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__metric{padding:10px;display:grid;gap:4px}.connection-editor__metric span{color:var(--pce-muted);font-size:.72rem}.connection-editor__metric strong,.connection-editor__details-row strong{color:var(--pce-strong);font-size:.9rem}.connection-editor__filters,.connection-editor__actions,.connection-editor__badges{display:flex;gap:8px;flex-wrap:wrap}.connection-editor__filter,.connection-editor__action{border:1px solid var(--pce-outline-strong);background:var(--pce-surface-soft);color:var(--pce-fg);border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connection-editor__filter--active,.connection-editor__action:hover{border-color:color-mix(in srgb,var(--pce-secondary) 62%,transparent);background:color-mix(in srgb,var(--pce-secondary) 16%,var(--pce-surface-soft));color:var(--pce-strong)}.connection-editor__action--danger{border-color:#f8717161;color:#fecaca}.connection-editor__item{width:100%;text-align:start;padding:12px;display:grid;gap:6px;cursor:pointer;color:inherit}.connection-editor__item--active{border-color:#a855f7b8;background:linear-gradient(90deg,#0ea5e91a,#a855f721)}.connection-editor__item-title{font-weight:800;color:#f8fafc;word-break:break-word}.connection-editor__badge{padding:3px 8px;border-radius:999px;background:#0ea5e92e;color:#bae6fd;font-size:.72rem;font-weight:800}.connection-editor__section{min-width:0;padding:14px;border-radius:18px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight),0 18px 50px var(--pce-shadow-soft);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__badge--warning{background:#facc1524;color:#fde68a}.connection-editor__badge--error{background:#ef444424;color:#fecaca}.connection-editor__diagnostics{display:grid;gap:8px}.connection-editor__diagnostic{display:grid;gap:4px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.78rem;line-height:1.35}.connection-editor__diagnostic--warning{border-color:#f59e0b47;background:#f59e0b1a}.connection-editor__diagnostic--error{border-color:#ef44445c;background:#ef44441f}.connection-editor__diagnostic-severity{font-size:.68rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#f8fafc}.connection-editor__suggestions{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__suggestion{display:grid;gap:8px;width:100%;padding:12px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 12%,transparent),color-mix(in srgb,var(--pce-primary) 8%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__suggestion:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 46%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 18%,transparent),color-mix(in srgb,var(--pce-primary) 12%,transparent)),var(--pce-surface-strong)}.connection-editor__suggestion-route{display:grid;gap:4px;font-size:.78rem}.connection-editor__suggestion-route strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__suggestion-reason{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__suggestion-action{justify-self:start;padding:3px 8px;border-radius:999px;background:#22d3ee24;color:#67e8f9;font-size:.68rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase}:host-context(.theme-light) .connection-editor__suggestion-action{background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:#075f73}.connection-editor__trace{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__trace-summary{color:var(--pce-muted);font-size:.78rem;line-height:1.35}.connection-editor__trace-step{display:grid;grid-template-columns:24px minmax(76px,auto) 1fr;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(34,211,238,.18);background:var(--pce-surface-soft);font-size:.76rem}.connection-editor__trace-step--blocked{border-color:#ef444457;background:#ef44441a}.connection-editor__trace-order{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:999px;background:#22d3ee29;color:#67e8f9;font-weight:900}.connection-editor__trace-phase{color:var(--pce-strong);font-weight:900;text-transform:uppercase;letter-spacing:.06em;font-size:.66rem}.connection-editor__trace-copy{min-width:0;color:var(--pce-fg);word-break:break-word}.connection-editor__transform-steps{display:grid;gap:8px}.connection-editor__transform-step{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(168,85,247,.22);background:var(--pce-surface-soft)}.connection-editor__transform-kind{min-width:0;color:var(--pce-strong);font-weight:900;word-break:break-word}.connection-editor__transform-phase{color:var(--pce-muted);font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.connection-editor__details-row,.connection-editor__details-block{display:grid;gap:6px}.connection-editor__payload-input{width:100%;min-height:128px;box-sizing:border-box;resize:vertical;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 92%,black);color:var(--pce-fg);padding:10px;font:.76rem/1.45 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.connection-editor__surface-action-editor{display:block;max-height:min(58vh,620px);overflow:auto;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 96%,black);padding:10px;margin-bottom:10px}.connection-editor__rule-grid{display:grid;gap:10px}.connection-editor__rule-card{display:grid;gap:8px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__rule-heading{color:var(--pce-fg);font-size:.72rem;font-weight:900;text-transform:uppercase;letter-spacing:.06em}pre{margin:0;padding:12px;border-radius:12px;background:color-mix(in srgb,var(--pce-surface-strong) 82%,#020617);color:var(--pce-fg);overflow:auto;font-size:.75rem}@keyframes connection-flow{to{stroke-dashoffset:-38}}@keyframes drag-wire-pulse{0%,to{stroke-opacity:.76}50%{stroke-opacity:1}}@keyframes drag-halo-pulse{0%,to{stroke-opacity:.48}50%{stroke-opacity:.82}}@keyframes endpoint-pulse{0%,to{opacity:.78;transform:scale(1)}50%{opacity:1;transform:scale(1.25)}}@keyframes selected-wire-aura{0%,to{stroke-opacity:.46}50%{stroke-opacity:.92}}@keyframes wire-draw-in{0%{stroke-dashoffset:640;opacity:.32}70%{opacity:1}to{stroke-dashoffset:0;opacity:1}}@keyframes new-wire-halo{0%{stroke-opacity:0;stroke-width:30}28%{stroke-opacity:.78}to{stroke-opacity:0;stroke-width:12}}@keyframes new-dock-link-flash{0%{transform:translateY(-2px);box-shadow:0 16px 40px #0206175c,0 0 42px #fb923c47}to{transform:translateY(0)}}@keyframes trace-wire-pulse{0%,to{stroke-opacity:.78}50%{stroke-opacity:1}}@keyframes trace-halo-pulse{0%,to{stroke-opacity:.34}50%{stroke-opacity:.86}}@keyframes tooltip-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes invalid-drop-jolt{0%,to{transform:translate(0)}28%{transform:translate(-3px)}56%{transform:translate(3px)}}@keyframes invalid-drop-ping{0%{opacity:1;transform:translate(-50%,-50%) scale(.72)}72%{opacity:.74;transform:translate(-50%,-50%) scale(1.35)}to{opacity:0;transform:translate(-50%,-50%) scale(1.8)}}@keyframes node-breathe{50%{transform:scale(1.035)}}@keyframes node-focus-breathe{0%,to{transform:scale(1)}50%{transform:scale(1.055)}}@keyframes trace-source-pulse{50%{transform:scale(1.04);box-shadow:0 0 0 3px #facc15db,0 0 0 22px #facc1514,0 0 64px #facc1557}}@keyframes trace-source-orbit{to{transform:rotate(360deg)}}@keyframes trace-reacting-pulse{50%{transform:scale(1.045);box-shadow:0 0 0 3px #22c55ead,0 0 62px #22c55e4d}}@keyframes segment-focus-sweep{0%,to{stroke-opacity:.82}50%{stroke-opacity:1}}@keyframes snap-pulse{50%{transform:scale(1.04)}}@keyframes port-focus-pulse{50%{transform:translateY(-1px);box-shadow:0 0 0 2px #facc158f,0 0 26px #facc153d}}@media(prefers-reduced-motion:reduce){.connection-editor__viewport,.connection-editor__node,.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-segment,.connection-editor__dock-link,.connection-editor__port{transition-duration:1ms}.connection-editor__wire,.connection-editor__wire--state,.connection-editor__wire--projection,.connection-editor__wire--state-read,.connection-editor__wire--event-propagation,.connection-editor__wire--halo.connection-editor__wire--active,.connection-editor__wire--trace,.connection-editor__wire--halo.connection-editor__wire--trace,.connection-editor__wire-endpoint,.connection-editor__connection-tooltip,.connection-editor__dock-link--new,.connection-editor__trace-overlay,.connection-editor__trace-overlay-step,.connection-editor__drag-wire,.connection-editor__drag-wire--halo,.connection-editor__drag-endpoint,.connection-editor__drag-tip,.connection-editor__node-ring,.connection-editor__node--connection-focus .connection-editor__node-ring,.connection-editor__node--trace-source .connection-editor__node-ring,.connection-editor__node--trace-source:before,.connection-editor__node--trace-reacting .connection-editor__node-ring,.connection-editor__node--rotating .connection-editor__node-ring,.connection-editor__node-segment--connection-focus,.connection-editor__node-segment--compatible,.connection-editor__node-segment--invalid-drop,.connection-editor__segment-popover,.connection-editor__port--compatible,.connection-editor__port--invalid-drop,.connection-editor__port--connection-focus,.connection-editor__invalid-drop,.connection-editor__invalid-drop-pulse{animation:none}.connection-editor__wire{stroke-dashoffset:0}.connection-editor__wire--new{stroke-dasharray:10 8;stroke-dashoffset:0;opacity:1}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:12;stroke-opacity:.16}.connection-editor__wire-endpoint,.connection-editor__drag-endpoint,.connection-editor__node-ring,.connection-editor__node--trace-source:before{transform:none}.connection-editor__invalid-drop-pulse{opacity:0}}@media(max-width:900px){:host{inset:0}.connection-editor{inset:8px;height:calc(100vh - 16px);padding:12px;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(260px,1fr) auto minmax(150px,30vh) minmax(86px,126px)}.connection-editor__header,.connection-editor__stage,.connection-editor__summary,.connection-editor__side-panel,.connection-editor__dock{grid-column:1}.connection-editor__header{align-items:stretch;flex-wrap:wrap;border-radius:18px}.connection-editor__mode-frame{order:3;width:100%;max-width:100%}.connection-editor__mode-frame:before,.connection-editor__mode-frame:after{content:\"\";position:absolute;z-index:2;inset-block:4px;width:24px;border-radius:999px;pointer-events:none}.connection-editor__mode-frame:before{inset-inline-start:1px;background:linear-gradient(90deg,#080d18f0,#080d1800)}.connection-editor__mode-frame:after{inset-inline-end:1px;background:linear-gradient(270deg,#080d18f0,#080d1800)}.connection-editor__mode-shell{width:100%;max-width:100%;overflow-x:auto;scroll-padding-inline:28px;-webkit-overflow-scrolling:touch}.connection-editor__subtitle{margin-inline-start:auto}.connection-editor__stage{grid-row:2;min-height:260px}.connection-editor__summary{grid-row:3;grid-template-columns:1fr 1fr}.connection-editor__side-panel{grid-row:4;max-height:30vh}.connection-editor__dock{grid-row:5;min-height:0}.connection-editor__connection-tooltip{width:min(620px,calc(100% - 24px));max-height:min(260px,calc(100% - 24px));overflow:auto}.connection-editor__dock-tabs{width:100%;min-width:0;min-height:0;flex-wrap:wrap;align-items:flex-start}.connection-editor__dock-count{flex:1 1 100%;margin-inline-start:0}.connection-editor__dock-body{width:100%;min-width:0;max-height:76px;box-sizing:border-box}.connection-editor__dock-body pre{white-space:pre-wrap;overflow-wrap:anywhere}.connection-editor__dock-link{grid-template-columns:1fr;align-items:start}.connection-editor__dock-link-route{flex-wrap:wrap}.connection-editor__dock-link-badges{justify-content:flex-start}.connection-editor__trace-overlay{inset-inline-start:14px;width:min(420px,calc(100% - 28px));min-width:0;transform:none}.connection-editor__drag-tip{width:min(300px,calc(100% - 28px))}.connection-editor__segment-popover{width:min(280px,calc(100% - 28px));max-height:min(280px,calc(100% - 28px))}.connection-editor__minimap{inset-inline-end:10px;inset-block-end:10px;width:132px;height:94px;padding:16px 8px 8px;border-radius:14px}.connection-editor__minimap:before{inset:20px 8px 8px;background-size:18px 18px}.connection-editor__minimap-title{inset-block-start:6px;inset-inline-start:10px;font-size:.54rem}}@media(max-width:640px){.connection-editor{inset:4px;height:calc(100vh - 8px);padding:8px;gap:8px;grid-template-rows:auto minmax(240px,1fr) auto minmax(140px,28vh) minmax(82px,116px)}.connection-editor__header{gap:8px;padding:10px}.connection-editor__mode-shell{padding:4px;gap:2px}.connection-editor__mode{min-height:28px;gap:4px;padding:0 7px;font-size:.68rem}.connection-editor__mode-glyph{font-size:.64rem}.connection-editor__stage{min-height:240px}.connection-editor__zoom-controls{inset-inline-start:8px;inset-block-start:8px;gap:6px;width:126px}.connection-editor__tool-group,.connection-editor__trace-source{gap:6px;padding:8px;border-radius:12px}.connection-editor__tool-group{grid-template-columns:repeat(3,28px)}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:repeat(2,28px)}.connection-editor__tool-button{width:28px;height:28px}.connection-editor__arrange-button,.connection-editor__simulate-button{min-height:30px;gap:6px;padding-inline:8px;font-size:.68rem}.connection-editor__summary{gap:6px}.connection-editor__side-panel{max-height:28vh}.connection-editor__dock{border-radius:16px}.connection-editor__dock-tabs{gap:4px}.connection-editor__dock-tab{padding:0 9px}.connection-editor__dock-count{font-size:.62rem}.connection-editor__dock-body{max-height:66px;padding:8px}.connection-editor__minimap{width:116px;height:84px}.connection-editor__segment-row{grid-template-columns:24px minmax(54px,.55fr) minmax(0,1fr) auto}}\n"] }]
9967
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{position:fixed;inset:0;z-index:1000;pointer-events:none}.connection-editor{--pce-fg: var(--md-sys-color-on-surface, #dce6f4);--pce-strong: var(--md-sys-color-on-surface, #f8fafc);--pce-muted: var(--md-sys-color-on-surface-variant, #94a3b8);--pce-primary: var(--md-sys-color-primary, #19c8e8);--pce-secondary: var(--md-sys-color-secondary, #b46cff);--pce-tertiary: var(--md-sys-color-tertiary, #ff9f2f);--pce-success: var(--md-sys-color-tertiary, #10b981);--pce-warning: var(--md-sys-color-error, #ff9f2f);--pce-error: var(--md-sys-color-error, #ef4444);--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #07111f) 80%, #020617);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #08101d) 78%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #0f172a) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #080d18) 64%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #899ab7) 46%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #94a3b8) 58%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #7d8fa9) 24%, transparent);--pce-glass-highlight: color-mix(in srgb, var(--md-sys-color-on-surface, #ffffff) 8%, transparent);--pce-shadow: color-mix(in srgb, #000 56%, transparent);--pce-shadow-soft: color-mix(in srgb, #000 30%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #040a13) 42%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container-high, #050912) 94%, transparent);position:absolute;inset:12px;height:calc(100vh - 24px);box-sizing:border-box;overflow:hidden;padding:16px;border-radius:18px;color:var(--pce-fg);background:radial-gradient(circle at 72% 20%,color-mix(in srgb,var(--pce-secondary) 16%,transparent),transparent 28%),radial-gradient(circle at 26% 74%,color-mix(in srgb,var(--pce-primary) 10%,transparent),transparent 34%),radial-gradient(circle at 48% 52%,color-mix(in srgb,var(--pce-tertiary) 5%,transparent),transparent 35%),linear-gradient(var(--pce-grid) 1px,transparent 1px),linear-gradient(90deg,var(--pce-grid) 1px,transparent 1px),var(--pce-surface-base);background-size:auto,auto,auto,38px 38px,38px 38px,auto;border:1px solid var(--pce-outline);box-shadow:0 28px 90px var(--pce-shadow);pointer-events:auto;display:grid;grid-template-columns:minmax(0,1fr) minmax(300px,380px);grid-template-rows:auto minmax(0,1fr) minmax(44px,118px);gap:14px}:host-context(.theme-light) .connection-editor{--pce-surface-base: color-mix(in srgb, var(--md-sys-color-surface, #ffffff) 94%, var(--md-sys-color-primary, #2563eb) 6%);--pce-surface: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 82%, transparent);--pce-surface-strong: color-mix(in srgb, var(--md-sys-color-surface-container-high, #eef2ff) 88%, transparent);--pce-surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container-low, #f8fafc) 70%, transparent);--pce-outline: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 68%, transparent);--pce-outline-strong: color-mix(in srgb, var(--md-sys-color-outline, #64748b) 62%, transparent);--pce-grid: color-mix(in srgb, var(--md-sys-color-outline-variant, #cbd5e1) 34%, transparent);--pce-glass-highlight: color-mix(in srgb, #fff 64%, transparent);--pce-shadow: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 22%, transparent);--pce-shadow-soft: color-mix(in srgb, var(--md-sys-color-shadow, #64748b) 14%, transparent);--pce-stage-bg: color-mix(in srgb, var(--md-sys-color-surface-container-lowest, #ffffff) 58%, transparent);--pce-dock-bg: color-mix(in srgb, var(--md-sys-color-surface-container, #f8fafc) 92%, transparent)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(0,1fr) 48px}.connection-editor__header{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:42px;padding:8px 14px;border-radius:999px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__mode-frame{position:relative;min-width:0;flex:1 1 auto;display:flex;justify-content:center}.connection-editor__close{width:32px;height:32px;flex:0 0 auto;display:inline-grid;place-items:center;border:1px solid var(--pce-outline);border-radius:999px;color:var(--pce-text);background:var(--pce-surface-strong);box-shadow:inset 0 1px var(--pce-glass-highlight);cursor:pointer;font:inherit;font-size:1.2rem;line-height:1}.connection-editor__close:hover,.connection-editor__close:focus-visible{border-color:var(--pce-outline-strong);background:color-mix(in srgb,var(--pce-accent) 16%,var(--pce-surface-strong));outline:none}.connection-editor__mode-shell{display:inline-flex;align-items:center;gap:4px;min-width:0;padding:4px;border-radius:999px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:inset 0 1px var(--pce-glass-highlight),0 10px 26px var(--pce-shadow-soft);scrollbar-width:none}.connection-editor__mode-shell::-webkit-scrollbar{display:none}.connection-editor__mode{min-height:30px;display:inline-flex;align-items:center;gap:7px;padding:0 12px;border:1px solid transparent;border-radius:999px;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.76rem;font-weight:800;white-space:nowrap;transition:background .16s ease,border-color .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__mode:hover,.connection-editor__mode--active{color:var(--pce-strong);border-color:color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-strong) 82%,transparent);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 12%,transparent)}.connection-editor__mode-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__mode--active .connection-editor__mode-glyph{color:var(--pce-primary)}.connection-editor__mode-dot{width:6px;height:6px;border-radius:999px;background:var(--pce-success);box-shadow:0 0 12px color-mix(in srgb,var(--pce-success) 70%,transparent)}.connection-editor__status-pill{display:inline-flex;align-items:center;gap:8px;min-height:24px;padding:0 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 36%,transparent);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.72rem;font-weight:800;white-space:nowrap}.connection-editor__status-pill--button{cursor:pointer;transition:border-color .16s ease,background .16s ease,color .16s ease,box-shadow .16s ease}.connection-editor__status-pill--button:hover,.connection-editor__status-pill--button:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 62%,transparent);background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 14%,transparent);outline:none}.connection-editor__status-pill span{width:6px;height:6px;border-radius:999px;background:var(--pce-primary);box-shadow:0 0 12px color-mix(in srgb,var(--pce-primary) 70%,transparent)}.connection-editor__section{display:grid;gap:10px}.connection-editor__dock{grid-column:1 / -1;grid-row:3;position:relative;z-index:4;min-height:0;display:grid;border-radius:14px;border:1px solid var(--pce-outline);background:radial-gradient(circle at 16% 0%,color-mix(in srgb,var(--pce-primary) 22%,transparent),transparent 34%),radial-gradient(circle at 78% 0%,color-mix(in srgb,var(--pce-secondary) 25%,transparent),transparent 38%),linear-gradient(90deg,var(--pce-dock-bg),var(--pce-surface-strong) 46%,color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-dock-bg))),var(--pce-dock-bg);box-shadow:0 18px 58px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);overflow:hidden;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__dock--collapsed .connection-editor__dock-tabs{border-block-end:0}.connection-editor__dock-tabs{display:flex;align-items:center;gap:10px;min-height:52px;padding:9px 14px;border-block-end:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-glass-highlight),transparent),color-mix(in srgb,var(--pce-surface-soft) 34%,transparent)}.connection-editor__dock-tab,.connection-editor__dock-toggle{min-height:30px;border-radius:999px;border:1px solid transparent;background:transparent;color:var(--pce-muted);cursor:pointer;font-size:.72rem;font-weight:900;letter-spacing:.14em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-tab{display:inline-flex;align-items:center;gap:8px;padding:0 13px;white-space:nowrap}.connection-editor__dock-tab-glyph{color:var(--pce-muted);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.8rem;letter-spacing:0;text-transform:none}.connection-editor__dock-tab--active{color:var(--pce-strong);border-color:var(--pce-outline-strong);background:linear-gradient(180deg,color-mix(in srgb,var(--pce-strong) 14%,transparent),color-mix(in srgb,var(--pce-strong) 6%,transparent));box-shadow:0 0 0 1px color-mix(in srgb,var(--pce-shadow) 72%,transparent),0 0 22px color-mix(in srgb,var(--pce-strong) 8%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__dock-tab--active .connection-editor__dock-tab-glyph{color:var(--pce-strong)}.connection-editor__dock-count{margin-inline-start:auto;color:color-mix(in srgb,var(--pce-muted) 62%,transparent);font-size:.7rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-toggle{width:32px;padding:0;border-color:var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-muted);font-size:.88rem;letter-spacing:0}.connection-editor__dock-body{max-height:154px;overflow:auto;padding:12px 12px 14px;border-block-start:1px solid var(--pce-outline);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 9%,transparent),color-mix(in srgb,var(--pce-secondary) 10%,transparent) 62%,color-mix(in srgb,var(--pce-surface-strong) 18%,transparent)),color-mix(in srgb,var(--pce-surface-soft) 30%,transparent)}.connection-editor__dock-body pre{max-height:60px}.connection-editor__dock-links{display:grid;gap:8px}.connection-editor__dock-link-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:10px;width:100%;padding:7px 10px;border-radius:10px;border:1px solid var(--pce-outline);background:linear-gradient(90deg,var(--pce-surface-soft),color-mix(in srgb,var(--pce-secondary) 10%,var(--pce-surface-soft)) 72%,var(--pce-surface-soft)),var(--pce-surface-soft);color:var(--pce-fg);transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__dock-link{display:grid;grid-template-columns:minmax(116px,.52fr) minmax(300px,1.72fr) minmax(160px,.9fr) auto;align-items:center;gap:12px;width:100%;min-height:42px;padding:0;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer;text-align:start}.connection-editor__dock-link-row:hover,.connection-editor__dock-link--active{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);background:linear-gradient(90deg,color-mix(in srgb,var(--pce-primary) 13%,transparent),color-mix(in srgb,var(--pce-secondary) 16%,transparent),var(--pce-surface-strong)),var(--pce-surface-strong);box-shadow:0 12px 32px var(--pce-shadow-soft),inset 0 0 18px color-mix(in srgb,var(--pce-primary) 6%,transparent)}.connection-editor__dock-link--active{border-color:#facc1575;box-shadow:0 12px 32px var(--pce-shadow-soft),0 0 24px #facc151f}.connection-editor__dock-link--new{border-color:#fb923ca3;background:linear-gradient(90deg,#fb923c2e,#a855f729,#0ea5e91f),#0f172ac2;box-shadow:0 12px 34px #02061752,0 0 30px #fb923c2e;animation:new-dock-link-flash 1.35s ease-out forwards}.connection-editor__dock-link--error{border-color:#ef444461}.connection-editor__dock-jump{min-width:62px;min-height:30px;padding:0 10px;border-radius:999px;border:1px solid color-mix(in srgb,var(--pce-primary) 28%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 54%,transparent);color:var(--pce-primary);cursor:pointer;font-size:.66rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__dock-jump:hover,.connection-editor__dock-jump:focus-visible{border-color:color-mix(in srgb,var(--pce-primary) 56%,transparent);background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:var(--pce-strong);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 18%,transparent);outline:none}.connection-editor__dock-link-kind{display:inline-flex;align-items:center;gap:7px;min-width:0;color:var(--pce-muted);font-size:.66rem;font-weight:900;letter-spacing:.1em;text-transform:uppercase;white-space:nowrap}.connection-editor__dock-link-kind span{width:8px;height:8px;border-radius:999px;background:#b46cff;box-shadow:0 0 14px #b46cff7a}.connection-editor__dock-link--state .connection-editor__dock-link-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2f94}.connection-editor__dock-link--state-read .connection-editor__dock-link-kind span{background:#8b7dff;box-shadow:0 0 13px #8b7dff75}.connection-editor__dock-link--projection .connection-editor__dock-link-kind span{background:#19c8e8;box-shadow:0 0 10px #19c8e857}.connection-editor__dock-link--event-propagation .connection-editor__dock-link-kind span{background:#ffb454;box-shadow:0 0 15px #ffb45485}.connection-editor__dock-link--policy .connection-editor__dock-link-kind span{outline:1px solid rgba(34,197,94,.76);outline-offset:2px;box-shadow:0 0 16px #22c55e61}.connection-editor__dock-link--policy:not(.connection-editor__dock-link--state,.connection-editor__dock-link--state-read,.connection-editor__dock-link--projection,.connection-editor__dock-link--event-propagation) .connection-editor__dock-link-kind span{background:#22c55e}.connection-editor__dock-link-route{display:inline-flex;align-items:center;gap:8px;min-width:0}.connection-editor__dock-link-chip{min-width:0;overflow:hidden;padding:4px 8px;border-radius:999px;border:1px solid var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-soft) 72%,transparent);color:var(--pce-fg);font-size:.72rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-chip--from{border-color:#ff9f2f66;color:#ffbd62}.connection-editor__dock-link-chip--to{border-color:#19c8e83d;color:#7dddeb}:host-context(.theme-light) .connection-editor__dock-link-chip--from{border-color:color-mix(in srgb,var(--pce-tertiary) 46%,transparent);color:#8a4600}:host-context(.theme-light) .connection-editor__dock-link-chip--to{border-color:color-mix(in srgb,var(--pce-primary) 34%,transparent);color:#075f73}.connection-editor__dock-link-arrow{flex:0 0 auto;color:var(--pce-muted);font-weight:900}.connection-editor__dock-link-id{min-width:0;overflow:hidden;color:var(--pce-muted);font-size:.66rem;font-weight:800;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__dock-link-badges{display:inline-flex;justify-content:flex-end;gap:5px;min-width:70px}.connection-editor__dock-link-badges span{padding:3px 7px;border-radius:999px;background:#a855f724;color:#d8b4fe;font-size:.62rem;font-weight:900;text-transform:uppercase;white-space:nowrap}:host-context(.theme-light) .connection-editor__dock-link-badges span{background:color-mix(in srgb,var(--pce-secondary) 14%,var(--pce-surface-soft));color:#6d2a9f}.connection-editor__dock-empty{padding:12px;border-radius:12px;border:1px dashed var(--pce-outline);color:var(--pce-muted);font-size:.76rem;font-weight:700}.connection-editor__inspector{border-color:color-mix(in srgb,var(--pce-primary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 10%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface)}.connection-editor__eyebrow,.connection-editor__section-title{font-size:.72rem;text-transform:uppercase;letter-spacing:.16em;color:var(--pce-muted);font-weight:700}.connection-editor__title{font-size:1.02rem;font-weight:800}.connection-editor__subtitle,.connection-editor__item-copy,.connection-editor__item-meta,.connection-editor__details-row span,.connection-editor__details-label,.connection-editor__empty{color:var(--pce-muted);font-size:.84rem}.connection-editor__inspector-heading{display:grid;gap:4px;padding:10px 12px;border-radius:14px;background:var(--pce-surface-soft);border:1px solid var(--pce-outline)}.connection-editor__inspector-heading strong{color:var(--pce-strong);font-size:.96rem;overflow-wrap:anywhere}.connection-editor__inspector-heading span{color:var(--pce-primary);font-size:.76rem;font-weight:800;text-transform:uppercase;letter-spacing:.1em}.connection-editor__human-summary{display:grid;gap:6px;padding:12px;border-radius:14px;border:1px solid color-mix(in srgb,var(--pce-primary) 24%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),color-mix(in srgb,var(--pce-secondary) 8%,transparent)),var(--pce-surface-soft);color:var(--pce-fg);line-height:1.35}.connection-editor__nested-summary{display:grid;gap:6px;padding:10px;border-radius:12px;border:1px solid color-mix(in srgb,var(--pce-primary) 22%,transparent);background:color-mix(in srgb,var(--pce-primary) 8%,var(--pce-surface-soft))}.connection-editor__nested-summary strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__nested-summary span:last-child{color:var(--pce-primary);font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:.72rem;overflow-wrap:anywhere}.connection-editor__recommended{border-color:color-mix(in srgb,var(--pce-secondary) 32%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 14%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface)}.connection-editor__recommended-card{display:grid;gap:8px;width:100%;padding:13px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 36%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 16%,transparent),color-mix(in srgb,var(--pce-primary) 10%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__recommended-card:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 52%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 22%,transparent),color-mix(in srgb,var(--pce-primary) 14%,transparent)),var(--pce-surface-strong)}.connection-editor__recommended-card strong{color:var(--pce-strong);font-size:.92rem;line-height:1.28}.connection-editor__recommended-card span:not(.connection-editor__human-summary-label):not(.connection-editor__suggestion-action),.connection-editor__recommended-card small{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__success{display:grid;gap:4px;padding:10px 12px;border-radius:14px;border:1px solid rgba(34,197,94,.34);background:#22c55e1f;color:var(--pce-fg);line-height:1.35}.connection-editor__success strong{color:#bbf7d0;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__success span{color:var(--pce-strong);font-size:.82rem}.connection-editor__human-summary-label,.connection-editor__suggestion-intent{justify-self:start;padding:3px 8px;border-radius:999px;background:color-mix(in srgb,var(--pce-primary) 16%,transparent);color:#bae6fd;font-size:.66rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__human-summary strong{color:var(--pce-strong);font-size:.88rem}.connection-editor__human-summary span:last-child,.connection-editor__suggestion-preview{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__technical-details{display:grid;gap:10px;padding:10px 12px;border-radius:14px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__technical-details summary{cursor:pointer;color:var(--pce-muted);font-size:.78rem;font-weight:800}.connection-editor__technical-details[open] summary{margin-bottom:10px;color:var(--pce-strong)}.connection-editor__inspector-ports{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__inspector-port{max-width:100%;padding:4px 8px;border-radius:999px;border:1px solid rgba(148,163,184,.16);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:800;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.connection-editor__inspector-port--input{border-color:#22d3ee57;color:#67e8f9}.connection-editor__inspector-port--output{border-color:#f59e0b57;color:#fbbf24}.connection-editor__inspector-port--state{border-color:#a855f761;color:#d8b4fe}.connection-editor__segment-kind-legend{display:grid;gap:10px;padding:12px;border-radius:16px;border:1px solid rgba(148,163,184,.14);background:linear-gradient(135deg,#0f172aa8,#080d1885),#02061757}.connection-editor__segment-kind-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.connection-editor__segment-kind-pill{min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:28px;padding:0 8px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#0f172a94;color:#cbd5e1;font-size:.68rem;font-weight:900;overflow:hidden;white-space:nowrap}.connection-editor__segment-kind-pill span{width:8px;height:8px;flex:0 0 auto;border-radius:999px;background:currentColor;box-shadow:0 0 12px currentColor}.connection-editor__segment-kind-pill--input{border-color:#19c8e83d;color:#7dddeb}.connection-editor__segment-kind-pill--output{border-color:#ff9f2f61;color:#ffbd62}.connection-editor__segment-kind-pill--state{border-color:#b46cff61;color:#d9b8ff}:host-context(.theme-light) .connection-editor__segment-kind-pill{border-color:var(--pce-outline);background:color-mix(in srgb,var(--pce-surface-strong) 88%,transparent)}:host-context(.theme-light) .connection-editor__segment-kind-pill--input{color:#075f73}:host-context(.theme-light) .connection-editor__segment-kind-pill--output{color:#8a4600}:host-context(.theme-light) .connection-editor__segment-kind-pill--state{color:#6d2a9f}.connection-editor__stage{grid-column:1;grid-row:2;position:relative;min-height:0;height:100%;overflow:visible;border-radius:16px;border:1px solid var(--pce-outline);background:radial-gradient(circle at center,color-mix(in srgb,var(--pce-secondary) 7%,transparent),transparent 38%),radial-gradient(circle,var(--pce-grid) 1px,transparent 1.5px),var(--pce-stage-bg);background-size:auto,31px 31px,auto;box-shadow:inset 0 0 0 1px var(--pce-glass-highlight);cursor:grab;touch-action:none}.connection-editor__stage--panning,.connection-editor__stage:active{cursor:grabbing}.connection-editor__stage--dragging{cursor:crosshair}.connection-editor__stage--rotating{cursor:grabbing}.connection-editor__viewport{position:absolute;inset-block-start:0;inset-inline-start:0;width:900px;height:540px;overflow:visible;transform-origin:0 0;transition:transform .14s ease}.connection-editor__wires{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.connection-editor__wire,.connection-editor__wire-hit{fill:none;stroke-linecap:round}.connection-editor__wire{stroke:#b46cff;stroke-width:1.45;stroke-opacity:.48;pointer-events:none;filter:url(#connection-glow);stroke-dasharray:10 8;animation:connection-flow 1.65s linear infinite}.connection-editor__wire-hit{stroke:transparent;stroke-width:18;cursor:pointer;pointer-events:stroke}.connection-editor__wire-hit--active{stroke-width:28}.connection-editor__wire--halo{stroke:#b46cff1f;stroke-width:7;stroke-dasharray:none;animation:none}.connection-editor__wire--state{stroke:#ff9f2f;stroke-width:2.25;stroke-dasharray:8 7;animation:connection-flow .92s linear infinite}.connection-editor__wire--state.connection-editor__wire--halo{stroke:#ff9f2f29;stroke-width:11}.connection-editor__wire--projection{stroke:#15b8d8;stroke-width:1.75;stroke-dasharray:20 8;animation:connection-flow 1.9s linear infinite}.connection-editor__wire--projection.connection-editor__wire--halo{stroke:#15b8d81a;stroke-width:7}.connection-editor__wire--state-read{stroke:#8b7dff;stroke-width:1.65;stroke-dasharray:3 11;animation:connection-flow 2.25s linear infinite reverse}.connection-editor__wire--state-read.connection-editor__wire--halo{stroke:#8b7dff21;stroke-width:8}.connection-editor__wire--event-propagation{stroke:#ffb454;stroke-width:2.05;stroke-dasharray:5 7;animation:connection-flow .78s linear infinite}.connection-editor__wire--event-propagation.connection-editor__wire--halo{stroke:#ffb4542e;stroke-width:10}.connection-editor__wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.2)) url(#connection-glow)}.connection-editor__wire--policy.connection-editor__wire--halo{stroke:#22c55e1f;stroke-width:13}.connection-editor__wire--warning{stroke:#ff9f2f}.connection-editor__wire--warning.connection-editor__wire--halo{stroke:#ff9f2f2e}.connection-editor__wire--error{stroke:#ef4444}.connection-editor__wire--error.connection-editor__wire--halo{stroke:#ef44442e}.connection-editor__wire--active{stroke:#d9b8ff;stroke-width:3;stroke-opacity:1;stroke-dasharray:5 7;animation-duration:.58s}.connection-editor__wire--halo.connection-editor__wire--active{stroke-width:16;stroke-opacity:.8;animation:selected-wire-aura 1.35s ease-in-out infinite}.connection-editor__wire--new{stroke-width:3.4;stroke-opacity:1;stroke-dasharray:640;stroke-dashoffset:640;animation:wire-draw-in .62s cubic-bezier(.16,1,.3,1) forwards,connection-flow 1.05s linear .62s infinite}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:22;stroke-opacity:0;animation:new-wire-halo 1.45s ease-out forwards}.connection-editor__wire--trace{stroke:#9b5cff;stroke-width:3.2;stroke-opacity:1;stroke-dasharray:7 6;animation:connection-flow .72s linear infinite,trace-wire-pulse 1.18s ease-in-out infinite}.connection-editor__wire--halo.connection-editor__wire--trace{stroke:#9b5cff57;stroke-width:18;stroke-opacity:.86;animation:trace-halo-pulse 1.18s ease-in-out infinite}.connection-editor__wire--mode-dimmed{stroke-opacity:.14;stroke-width:1.05;filter:none;animation-duration:2.6s}.connection-editor--guided .connection-editor__wire:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.34;filter:none;animation:none}.connection-editor--guided .connection-editor__wire--halo:not(.connection-editor__wire--active,.connection-editor__wire--new,.connection-editor__wire--trace){stroke-opacity:.08;animation:none}.connection-editor__wire--halo.connection-editor__wire--mode-dimmed{stroke-opacity:.05;stroke-width:5;animation:none}.connection-editor__wire-hit--mode-dimmed{stroke-width:12}.connection-editor__wire-endpoint{fill:#f8fafc;stroke:#0f172ae6;stroke-width:1.5;filter:drop-shadow(0 0 8px rgba(216,180,254,.8));pointer-events:none;animation:endpoint-pulse 1.2s ease-in-out infinite}.connection-editor__wire-endpoint--source{fill:#ff9f2f}.connection-editor__wire-endpoint--target{fill:#19c8e8}.connection-editor__connection-tooltip{position:absolute;z-index:6;width:min(312px,calc(100% - 24px));display:grid;gap:8px;padding:12px 14px;border-radius:14px;border:1px solid var(--pce-outline);background:linear-gradient(135deg,var(--pce-surface-strong),var(--pce-surface)),var(--pce-surface-strong);box-shadow:0 18px 44px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);color:var(--pce-fg);pointer-events:none;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .14s ease-out}.connection-editor__connection-tooltip-callout{position:absolute;inset-block-start:100%;inset-inline-start:var(--connection-tooltip-callout-x, 42px);width:2px;height:28px;border-radius:999px;background:linear-gradient(180deg,#e2e8f0bd,#19c8e800);box-shadow:0 0 12px #19c8e852;transform:translate(-1px);pointer-events:none}.connection-editor__connection-tooltip-callout:before,.connection-editor__connection-tooltip-callout:after{content:\"\";position:absolute;border-radius:999px;pointer-events:none}.connection-editor__connection-tooltip-callout:before{inset-block-start:-5px;inset-inline-start:-5px;width:12px;height:12px;border:1px solid rgba(148,163,184,.24);background:#080d18f5;box-shadow:inset 0 1px #ffffff14}.connection-editor__connection-tooltip-callout:after{inset-block-end:-3px;inset-inline-start:-4px;width:10px;height:10px;background:#19c8e8;box-shadow:0 0 16px #19c8e88f}.connection-editor__connection-tooltip--projection{border-color:#19c8e833;background:linear-gradient(135deg,#15b8d81f,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state{border-color:#ff9f2f66;background:linear-gradient(135deg,#ff9f2f3d,#0f172ae0),#070c16eb}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout{background:linear-gradient(180deg,#ffbd62d1,#ff9f2f00);box-shadow:0 0 14px #ff9f2f61}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-callout:after{background:#ff9f2f;box-shadow:0 0 18px #ff9f2fad}.connection-editor__connection-tooltip--error{border-color:#f871716b}.connection-editor__connection-tooltip--error .connection-editor__connection-tooltip-callout:after{background:#fb7185;box-shadow:0 0 18px #fb7185ad}.connection-editor__connection-tooltip-kind{display:inline-flex;align-items:center;gap:8px;color:#94a3b8;font-size:.62rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__connection-tooltip-kind span{width:8px;height:8px;border-radius:999px;background:#19c8e8;box-shadow:0 0 12px #19c8e880}.connection-editor__connection-tooltip--state .connection-editor__connection-tooltip-kind span{background:#ff9f2f;box-shadow:0 0 16px #ff9f2fc7}.connection-editor__connection-tooltip-row{min-width:0;display:grid;grid-template-columns:54px minmax(0,1fr);align-items:center;gap:8px;min-height:28px;padding:0 10px;border-radius:999px;background:#0f172a94}.connection-editor__connection-tooltip-row span{color:#8d9bb0;font-size:.62rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase}.connection-editor__connection-tooltip-row strong{min-width:0;overflow:hidden;color:#e2e8f0;font-size:.75rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__connection-tooltip-badges{display:flex;flex-wrap:wrap;gap:6px}.connection-editor__connection-tooltip-badges span{padding:3px 8px;border-radius:999px;background:#02061799;color:#fbbf24;font-size:.66rem;font-weight:900}.connection-editor__trace-overlay{position:absolute;z-index:6;inset-block-start:16px;inset-inline-start:50%;width:min(560px,calc(100% - 360px));min-width:320px;padding:12px 14px;border-radius:16px;border:1px solid rgba(34,197,94,.26);background:linear-gradient(135deg,#22c55e1f,#0ea5e91a),#080d18f0;box-shadow:0 22px 56px #02061775,0 0 42px #22c55e1f;transform:translate(-50%);pointer-events:auto;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);animation:tooltip-rise .16s ease-out}.connection-editor__trace-overlay-head,.connection-editor__trace-overlay-route{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}.connection-editor__trace-overlay-head span,.connection-editor__trace-overlay-route span{color:#86efac;font-size:.66rem;font-weight:900;letter-spacing:.12em;text-transform:uppercase;white-space:nowrap}.connection-editor__trace-overlay-head strong{color:#cbd5e1;font-size:.7rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace}.connection-editor__trace-overlay-route{margin-top:6px}.connection-editor__trace-overlay-controls{display:grid;grid-template-columns:28px minmax(0,1fr) 28px;align-items:center;gap:8px;margin-top:10px}.connection-editor__trace-overlay-button{width:28px;height:24px;display:inline-grid;place-items:center;border:1px solid rgba(148,163,184,.18);border-radius:999px;background:#0206176b;color:#e2e8f0;cursor:pointer;font-size:1rem;font-weight:900;line-height:1;transition:border-color .15s ease,background .15s ease,color .15s ease,opacity .15s ease}.connection-editor__trace-overlay-button:hover:not(:disabled){border-color:#22d3ee6b;background:#0ea5e929;color:#f8fafc}.connection-editor__trace-overlay-button:disabled{cursor:default;opacity:.36}.connection-editor__trace-overlay-steps{min-width:0;display:flex;align-items:center;gap:6px;overflow-x:auto;padding:2px;scrollbar-width:none}.connection-editor__trace-overlay-steps::-webkit-scrollbar{display:none}.connection-editor__trace-overlay-step{position:relative;flex:1 0 28px;min-width:28px;height:22px;border:1px solid rgba(148,163,184,.16);border-radius:999px;background:#0f172a9e;color:#94a3b8;cursor:pointer;font-size:.62rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;transition:border-color .15s ease,background .15s ease,color .15s ease,box-shadow .15s ease}.connection-editor__trace-overlay-step--active{border-color:#22d3eea3;background:linear-gradient(90deg,#22d3ee3d,#9b5cff33);color:#f8fafc;box-shadow:0 0 18px #22d3ee33}.connection-editor__trace-overlay-step--blocked{border-color:#fb71855c;color:#fecdd3}.connection-editor__trace-overlay-route strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.82rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__trace-overlay-bar{position:relative;height:5px;margin-top:10px;overflow:hidden;border-radius:999px;background:#94a3b829}.connection-editor__trace-overlay-bar span{position:absolute;inset-block:0;inset-inline-start:0;border-radius:inherit;background:linear-gradient(90deg,#22c55e,#22d3ee);box-shadow:0 0 18px #22c55e61;min-width:8%}.connection-editor__drag-wire{fill:none;stroke:#94a3b8;stroke-width:2.4;stroke-linecap:round;stroke-dasharray:6 7;pointer-events:none;filter:url(#connection-glow);animation:connection-flow 1.05s linear infinite,drag-wire-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--halo{stroke:#94a3b829;stroke-width:14;stroke-dasharray:none;animation:drag-halo-pulse 1.2s ease-in-out infinite}.connection-editor__drag-wire--valid{stroke:#22c55e}.connection-editor__drag-wire--halo.connection-editor__drag-wire--valid{stroke:#22c55e47}.connection-editor__drag-endpoint{fill:#94a3b8;stroke:#020617eb;stroke-width:2;pointer-events:none;filter:url(#connection-glow);transform-box:fill-box;transform-origin:center;animation:endpoint-pulse 1s ease-in-out infinite}.connection-editor__drag-endpoint--source{fill:#ff9f2f}.connection-editor__drag-endpoint--target{fill:#7dddeb}.connection-editor__drag-endpoint--valid{fill:#22c55e;stroke:#bbf7d0e0}.connection-editor__wire-handle-line{stroke-width:2;stroke-linecap:round;stroke-dasharray:4 5;pointer-events:none;opacity:.88;filter:url(#connection-glow)}.connection-editor__wire-handle-line--source{stroke:#ff9f2ff0}.connection-editor__wire-handle-line--target{stroke:#19c8e8c2}.connection-editor__wire-control{fill:#0f172af5;stroke:#cbd5e1c7;stroke-width:1.8;pointer-events:none;filter:url(#connection-glow)}.connection-editor__wire-label{pointer-events:none;filter:drop-shadow(0 0 10px rgba(2,6,23,.44));animation:tooltip-rise .14s ease-out}.connection-editor__wire-label rect{fill:#080d18eb;stroke-width:1}.connection-editor__wire-label text{fill:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;font-size:8px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.connection-editor__wire-label--source rect{stroke:#ff9f2fad}.connection-editor__wire-label--target rect{stroke:#19c8e86b}.connection-editor__zoom-controls{position:absolute;inset-inline-start:14px;inset-block-start:14px;z-index:4;display:grid;grid-template-columns:max-content;gap:6px;width:46px;pointer-events:auto}.connection-editor__tool-group,.connection-editor__trace-source{display:grid;gap:6px;padding:6px;border-radius:12px;border:1px solid var(--pce-outline);background:linear-gradient(180deg,var(--pce-surface-strong),var(--pce-surface));box-shadow:0 16px 36px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__tool-group{grid-template-columns:30px;width:max-content}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:30px}.connection-editor__arrange-button{width:34px;min-height:34px;display:inline-flex;align-items:center;justify-content:center;gap:0;padding:0;border-radius:999px;border:1px solid rgba(168,85,247,.34);background:linear-gradient(90deg,#a855f72e,#22d3ee1f);color:#e9d5ff;font-size:0;font-weight:800;letter-spacing:0;cursor:pointer;opacity:1;transform:scale(1);transition:opacity .14s ease,transform .14s ease,border-color .14s ease,background .14s ease}.connection-editor--guided .connection-editor__arrange-button{opacity:.34;transform:scale(.9);border-color:color-mix(in srgb,var(--pce-outline) 82%,transparent);background:color-mix(in srgb,var(--pce-surface-soft) 84%,transparent)}.connection-editor--guided .connection-editor__zoom-controls:hover .connection-editor__arrange-button,.connection-editor--guided .connection-editor__zoom-controls:focus-within .connection-editor__arrange-button,.connection-editor--guided .connection-editor__arrange-button:hover,.connection-editor--guided .connection-editor__arrange-button:focus-visible,.connection-editor--guided .connection-editor__arrange-button--active{opacity:1;transform:scale(1);border-color:#a855f757;background:linear-gradient(90deg,#a855f72e,#22d3ee1f)}.connection-editor__arrange-button span{color:#c084fc;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.78rem;font-weight:900}.connection-editor__tool-button{width:30px;height:30px;border-radius:999px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.9rem;font-weight:800;letter-spacing:.02em;cursor:pointer;line-height:1}.connection-editor__tool-button:hover:not(:disabled){border-color:color-mix(in srgb,var(--pce-primary) 42%,transparent);color:var(--pce-primary);box-shadow:0 0 18px color-mix(in srgb,var(--pce-primary) 16%,transparent)}.connection-editor__history-button:disabled{cursor:not-allowed;opacity:.42}.connection-editor__arrange-button--active{border-color:#22d3ee94;background:linear-gradient(90deg,#0ea5e93d,#22d3ee2e);color:#cffafe}.connection-editor__trace-source{gap:4px;max-height:230px;overflow:auto}.connection-editor__trace-source-title{padding:2px 4px 6px;color:var(--pce-muted);font-size:.64rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase}.connection-editor__trace-source-item{min-width:0;min-height:30px;display:flex;align-items:center;gap:8px;padding:0 8px;border:0;border-radius:8px;background:transparent;color:var(--pce-fg);cursor:pointer;font-size:.74rem;font-weight:800;text-align:start}.connection-editor__trace-source-item span{color:#f59e0b;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.72rem;font-weight:900}.connection-editor__trace-source-item:hover,.connection-editor__trace-source-item--active{background:var(--pce-surface-strong);color:var(--pce-strong);box-shadow:inset 3px 0 #f59e0bd1}.connection-editor__minimap{position:absolute;inset-inline-end:14px;inset-block-end:14px;z-index:4;width:184px;height:124px;padding:18px 10px 10px;overflow:hidden;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-primary) 30%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-primary) 12%,transparent),var(--pce-surface-strong)),var(--pce-surface);box-shadow:0 20px 48px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight);cursor:pointer;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);opacity:1;transform:scale(1);transform-origin:100% 100%;transition:opacity .16s ease,transform .16s ease,border-color .16s ease,box-shadow .16s ease}.connection-editor--guided .connection-editor__minimap{opacity:.54;transform:scale(.88);border-color:color-mix(in srgb,var(--pce-outline) 64%,transparent);box-shadow:0 14px 34px color-mix(in srgb,var(--pce-shadow-soft) 70%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor--guided .connection-editor__minimap:hover,.connection-editor--guided .connection-editor__minimap:focus-visible,.connection-editor--guided .connection-editor__minimap--panning{opacity:1;transform:scale(1)}.connection-editor__minimap:hover,.connection-editor__minimap--panning{border-color:#22d3ee75;box-shadow:0 20px 48px var(--pce-shadow-soft),0 0 24px color-mix(in srgb,var(--pce-primary) 14%,transparent),inset 0 1px var(--pce-glass-highlight)}.connection-editor__minimap--panning{cursor:grabbing}.connection-editor__minimap:before{content:\"\";position:absolute;inset:22px 10px 10px;border-radius:10px;background-image:radial-gradient(circle,rgba(125,211,252,.18) 1px,transparent 1px);background-size:22px 22px;opacity:.58;pointer-events:none}.connection-editor__minimap-title{position:absolute;inset-block-start:7px;inset-inline-start:12px;color:var(--pce-muted);font-size:.6rem;font-weight:900;letter-spacing:.16em;text-transform:uppercase}.connection-editor__minimap svg{position:relative;width:100%;height:100%;display:block;overflow:visible}.connection-editor__minimap-wire{fill:none;stroke:#b46cff8f;stroke-width:4;stroke-linecap:round;opacity:.86}.connection-editor__minimap-wire--state{stroke:#ff9f2fdb}.connection-editor__minimap-wire--state-read{stroke:#8b7dffb8;stroke-dasharray:4 9}.connection-editor__minimap-wire--projection{stroke:#19c8e88a;stroke-dasharray:18 8}.connection-editor__minimap-wire--event-propagation{stroke:#ffb454cc;stroke-dasharray:6 7}.connection-editor__minimap-wire--policy{filter:drop-shadow(0 0 6px rgba(34,197,94,.28))}.connection-editor__minimap-wire--trace{stroke:#9b5cffe0;stroke-width:5;stroke-dasharray:12 9;animation:connection-flow 1s linear infinite}.connection-editor__minimap-wire--active{stroke:#facc15eb;stroke-width:6;filter:drop-shadow(0 0 8px rgba(250,204,21,.38))}.connection-editor__minimap-wire--mode-dimmed{opacity:.2;stroke-width:2.6;filter:none}.connection-editor__minimap-node{fill:#f59e0be0;stroke:#020617db;stroke-width:4;filter:drop-shadow(0 0 7px rgba(245,158,11,.24))}.connection-editor__minimap-node--state{fill:#a855f7e6;filter:drop-shadow(0 0 8px rgba(168,85,247,.34))}.connection-editor__minimap-node--selected{fill:#facc15f5;stroke:#fef08aeb;filter:drop-shadow(0 0 10px rgba(250,204,21,.42))}.connection-editor__minimap-node--trace-source{fill:#facc15f5;filter:drop-shadow(0 0 10px rgba(250,204,21,.44))}.connection-editor__minimap-node--trace-reacting{fill:#22c55eeb;filter:drop-shadow(0 0 10px rgba(34,197,94,.42))}.connection-editor__minimap-node--mode-dimmed{opacity:.28;filter:none}.connection-editor__minimap-viewport{fill:#7dd3fc1f;stroke:#7dd3fce6;stroke-width:5;stroke-dasharray:18 10;filter:drop-shadow(0 0 10px rgba(125,211,252,.3));transition:x .12s ease,y .12s ease,width .12s ease,height .12s ease}.connection-editor__minimap--panning .connection-editor__minimap-viewport{fill:#22d3ee2e;stroke:#22d3eef5;stroke-dasharray:none}.connection-editor__node{position:absolute;z-index:10;width:168px;height:168px;transform:translate(-84px,-84px);border:0;padding:0;background:transparent;color:inherit;cursor:pointer;transition:filter .16s ease}.connection-editor__node--dragging{cursor:grabbing;filter:drop-shadow(0 0 22px rgba(34,211,238,.26));z-index:12}.connection-editor__node--connection-focus{filter:drop-shadow(0 0 16px rgba(34,211,238,.2))}.connection-editor__node--compat-target .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e66,0 0 0 18px #22c55e0b,0 0 32px #22c55e29}.connection-editor__node--mode-dimmed{opacity:.42;filter:grayscale(.22) saturate(.56)}.connection-editor__node--quiet{opacity:.58;filter:saturate(.68) brightness(.86)}.connection-editor__node--mode-dimmed .connection-editor__node-ring{animation:none;box-shadow:0 0 0 1px #2dd4bf14,0 0 14px #0ea5e90f}.connection-editor__node--mode-dimmed .connection-editor__node-halo{stroke-opacity:.28}.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-svg{position:absolute;inset:0}.connection-editor__node-ring,.connection-editor__node-core{display:grid;place-items:center;clip-path:polygon(30% 0,70% 0,100% 30%,100% 70%,70% 100%,30% 100%,0 70%,0 30%)}.connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from -28deg,#06b6d4b3 0 28%,#f59e0b9e 28% 48%,#a855f780 48% 68%,#06b6d4a3 68% 100%);box-shadow:0 0 0 1px #2dd4bf2e,0 0 26px #0ea5e929;animation:node-breathe 2.8s ease-in-out infinite}.connection-editor__node-svg{overflow:visible;filter:drop-shadow(0 0 16px rgba(14,165,233,.16))}.connection-editor__node-halo{fill:transparent;stroke:#38bdf838;stroke-width:1;stroke-dasharray:0;pointer-events:none}.connection-editor__node-halo:nth-child(2){stroke:#38bdf824}.connection-editor__node-halo:nth-child(3){stroke:#94a3b81a}.connection-editor__node-segment{fill-opacity:.28;stroke-opacity:.72;stroke-width:1.15;transition:fill-opacity .16s ease,stroke-opacity .16s ease,stroke-width .16s ease;cursor:grab}.connection-editor__node:hover .connection-editor__node-segment,.connection-editor__node--selected .connection-editor__node-segment,.connection-editor__node--connection-focus .connection-editor__node-segment{fill-opacity:.54;stroke-opacity:.95;stroke-width:1.55}.connection-editor__node-segment--connection-focus{fill-opacity:.76;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 8px rgba(34,211,238,.76));animation:segment-focus-sweep 1.45s ease-in-out infinite}.connection-editor__node-segment--source{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 12px rgba(251,146,60,.82))}.connection-editor__node-segment--compatible{fill-opacity:.74;stroke-opacity:1;stroke-width:2;filter:drop-shadow(0 0 10px rgba(34,197,94,.72));animation:snap-pulse 1s ease-in-out infinite}.connection-editor__node-segment--compat-preview{fill-opacity:.86;stroke-opacity:1;stroke-width:2.45;filter:drop-shadow(0 0 13px rgba(245,158,11,.78))}.connection-editor__node-segment--candidate{fill-opacity:.92;stroke-opacity:1;stroke-width:2.8;filter:drop-shadow(0 0 16px rgba(34,197,94,.86))}.connection-editor__node-segment--incompatible{fill-opacity:.12;stroke-opacity:.28;cursor:not-allowed}.connection-editor__node-segment--invalid-drop{fill-opacity:.72;stroke:#fb7185;stroke-opacity:1;stroke-width:3;filter:drop-shadow(0 0 16px rgba(244,63,94,.84));animation:invalid-drop-jolt .36s ease-out}.connection-editor__node-segment--state{fill-opacity:.44;filter:drop-shadow(0 0 8px rgba(180,108,255,.2))}.connection-editor__node-segment--mode-dimmed{fill-opacity:.08;stroke-opacity:.2;stroke-width:.9;filter:none}.connection-editor__node-anchor{opacity:.95;filter:drop-shadow(0 0 6px currentColor)}.connection-editor__node-rotate-handle{cursor:grab;opacity:0;pointer-events:none;transition:opacity .16s ease,filter .16s ease;filter:drop-shadow(0 0 8px rgba(34,211,238,.28))}.connection-editor__node:hover .connection-editor__node-rotate-handle,.connection-editor__node--selected .connection-editor__node-rotate-handle,.connection-editor__node--rotating .connection-editor__node-rotate-handle{opacity:1;pointer-events:auto}.connection-editor__node--rotating .connection-editor__node-rotate-handle{cursor:grabbing;filter:drop-shadow(0 0 12px rgba(34,211,238,.54))}.connection-editor__node-rotate-hit{fill:transparent}.connection-editor__node-rotate-dot{fill:var(--pce-surface-strong);stroke:var(--pce-primary);stroke-opacity:.88;stroke-width:1.4}.connection-editor__node-rotate-arc,.connection-editor__node-rotate-arrow{fill:none;stroke:var(--pce-primary);stroke-linecap:round;stroke-linejoin:round;stroke-opacity:.96;stroke-width:1.2;pointer-events:none}.connection-editor__segment-icon,.connection-editor__segment-label{pointer-events:none;fill:#cbd5e1;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-weight:800;paint-order:stroke;stroke:#020617c2;stroke-width:3px;stroke-linejoin:round}.connection-editor__segment-icon{font-size:12px;fill:#19c8e8;opacity:1;transition:opacity .14s ease}.connection-editor__segment-icon--output{fill:#ff9f2f}.connection-editor--guided .connection-editor__segment-icon:not(.connection-editor__segment-icon--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-icon{opacity:0}.connection-editor__segment-label{font-size:9.5px;letter-spacing:0;fill:#e2e8f0e0;opacity:1;transition:opacity .14s ease}.connection-editor--guided .connection-editor__segment-label:not(.connection-editor__segment-label--guided-visible){opacity:0}.connection-editor--guided .connection-editor__node--rotating .connection-editor__segment-label{opacity:0}.connection-editor__node-core{inset:43px;padding:12px;border-radius:999px;clip-path:none;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(circle at center,#111827 0 58%,#060b14);border:1px solid rgba(226,232,240,.1);box-shadow:0 12px 28px #00000073,inset 0 1px #ffffff0d;color:#f8fafc;text-shadow:0 1px 2px rgba(0,0,0,.62)}.connection-editor__node-icon{display:block;max-width:44px;overflow:hidden;color:#f8fafc;font-family:Material Symbols Outlined,Material Icons,sans-serif;font-size:1.22rem;font-weight:400;line-height:1;text-align:center;text-transform:none;letter-spacing:0;white-space:nowrap;filter:drop-shadow(0 0 10px rgba(226,232,240,.18))}.connection-editor__node--state .connection-editor__node-ring{background:radial-gradient(circle at center,transparent 0 44%,rgba(7,17,31,.96) 45% 57%,transparent 58%),conic-gradient(from 14deg,#a855f7c7 0 42%,#7e3af26b 42% 78%,#f59e0b47 78% 100%);box-shadow:0 0 0 1px #a855f738,0 0 30px #a855f733}.connection-editor__node--selected .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15bd,0 0 34px #facc153d}.connection-editor__node--connection-focus .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eead,0 0 38px #22d3ee42;animation:node-focus-breathe 1.7s ease-in-out infinite}.connection-editor__node--trace-source .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 0 18px #facc150f,0 0 54px #facc154d;animation:trace-source-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:before{content:\"\";position:absolute;z-index:0;inset:-44px;border-radius:999px;border:2px solid rgba(250,204,21,.36);background:radial-gradient(circle at center,transparent 0 64%,rgba(250,204,21,.05) 65% 66%,transparent 67%),conic-gradient(from -20deg,#facc1500,#facc1552,#facc1500);box-shadow:0 0 36px #facc151f;opacity:.92;pointer-events:none;animation:trace-source-orbit 2.8s linear infinite}.connection-editor__node--trace-reacting .connection-editor__node-ring{box-shadow:0 0 0 2px #22c55e94,0 0 46px #22c55e38;animation:trace-reacting-pulse 1.38s ease-in-out infinite}.connection-editor__node--trace-source:after,.connection-editor__node--trace-reacting:after{position:absolute;z-index:3;inset-inline-start:50%;inset-block-start:-42px;padding:0;border:0;background:transparent;color:#facc15;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace;font-size:.68rem;font-weight:900;letter-spacing:.18em;text-transform:uppercase;transform:translate(-50%);text-shadow:0 0 12px rgba(250,204,21,.52);pointer-events:none}.connection-editor__node--trace-source:after{content:attr(data-trace-label)}.connection-editor__node--trace-reacting:after{content:attr(data-trace-label);color:#86efac;text-shadow:0 0 12px rgba(34,197,94,.44)}.connection-editor__node--trace-source .connection-editor__node-segment--output{fill-opacity:.66;stroke-width:2.2;filter:drop-shadow(0 0 14px rgba(255,159,47,.42))}.connection-editor__node--expanded .connection-editor__node-ring{box-shadow:0 0 0 2px #22d3eebd,0 0 34px #22d3ee3d}.connection-editor__node--rotating .connection-editor__node-ring{box-shadow:0 0 0 2px #facc15c7,0 0 42px #facc1547;animation:node-focus-breathe 1.1s ease-in-out infinite}.connection-editor__node--rotating .connection-editor__node-segment{fill-opacity:.68;stroke-opacity:1;stroke-width:1.9;cursor:grabbing}.connection-editor__node-title,.connection-editor__node-subtitle{display:block;max-width:92px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.connection-editor__node-title{color:#f8fafc;font-size:.82rem;font-weight:800}.connection-editor__node-subtitle{margin-top:4px;color:#a7b4c8;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__ports{position:absolute;z-index:30;display:grid;gap:6px;width:104px;opacity:0;pointer-events:none;transform:translateY(3px);transition:opacity .16s ease,transform .16s ease}.connection-editor__ports--visible{opacity:1;pointer-events:auto;transform:translateY(0)}.connection-editor__ports--outputs{z-index:42}.connection-editor__ports--inputs{z-index:36}.connection-editor__segment-popover{position:absolute;z-index:80;width:292px;max-height:320px;overflow:auto;display:grid;gap:10px;padding:14px;border-radius:16px;border:1px solid rgba(148,163,184,.18);background:linear-gradient(135deg,#0f172af5,#110c20f0),#090c16eb;box-shadow:0 28px 72px #0000007a,0 0 48px #a855f71a,inset 0 1px #ffffff0d;-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__segment-popover-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding-bottom:2px}.connection-editor__segment-popover-title{color:#94a3b8;font-size:.68rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase}.connection-editor__segment-popover-hint{margin-top:5px;color:#64748b;font-size:.66rem;font-weight:700}.connection-editor__segment-rotation{flex:0 0 auto;min-width:54px;padding:5px 8px;border-radius:999px;border:1px solid rgba(34,211,238,.28);background:#082f4957;color:#7dd3fc;font-size:.66rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-align:center;box-shadow:inset 0 0 16px #0ea5e914}.connection-editor__segment-row{display:grid;grid-template-columns:28px 72px minmax(0,1fr) auto;align-items:center;gap:8px;min-height:40px;padding:7px;border-radius:12px;border:1px solid rgba(148,163,184,.12);background:linear-gradient(90deg,#0f172ac7,#0f172a75),#0f172a99;transition:border-color .15s ease,background .15s ease,box-shadow .15s ease,transform .15s ease}.connection-editor__segment-row--input{border-color:#22d3ee42}.connection-editor__segment-row--output{border-color:#f59e0b47}.connection-editor__segment-row--state{border-color:#a855f74d}.connection-editor__segment-row--source,.connection-editor__segment-row--candidate{transform:translate(2px);box-shadow:0 0 22px #f59e0b24,inset 0 0 20px #f59e0b14}.connection-editor__segment-row--compatible{border-color:#22d3ee6b;box-shadow:inset 0 0 18px #22d3ee14}.connection-editor__segment-row--compat-preview{border-color:#f59e0b94;background:linear-gradient(90deg,#f59e0b1f,#0f172a8a),#0f172ab3;box-shadow:0 0 22px #f59e0b1f,inset 0 0 18px #f59e0b14}.connection-editor__segment-row--invalid-drop{border-color:#fb7185b3;background:linear-gradient(90deg,#f43f5e24,#0f172a94),#0f172ab3;box-shadow:0 0 24px #f43f5e2e,inset 0 0 18px #f43f5e1a;animation:invalid-drop-jolt .36s ease-out}.connection-editor__segment-index{color:#64748b;font-size:.64rem;font-weight:900;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;letter-spacing:.08em}.connection-editor__segment-kind{display:inline-flex;align-items:center;gap:6px;color:#94a3b8;font-size:.62rem;font-weight:800;text-transform:uppercase;min-width:0;white-space:nowrap}.connection-editor__segment-kind-dot{width:7px;height:7px;border-radius:999px;background:#94a3b8;box-shadow:0 0 12px #94a3b847}.connection-editor__segment-row--input .connection-editor__segment-kind-dot{background:#22d3ee;box-shadow:0 0 12px #22d3ee61}.connection-editor__segment-row--output .connection-editor__segment-kind-dot{background:#fb923c;box-shadow:0 0 12px #fb923c66}.connection-editor__segment-row--state .connection-editor__segment-kind-dot{background:#a855f7;box-shadow:0 0 12px #a855f76b}.connection-editor__segment-label{display:inline-flex;align-items:center;gap:5px;min-width:0;overflow:hidden;color:#e2e8f0;font-size:.74rem;font-weight:700;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-badge{flex:0 0 auto;padding:2px 5px;border-radius:999px;border:1px solid rgba(56,189,248,.28);background:#0ea5e91a;color:#bae6fd;font-size:.55rem;font-weight:900;text-transform:uppercase}.connection-editor__segment-path{grid-column:3 / 4;min-width:0;margin-top:-5px;overflow:hidden;color:#93c5fd;font-size:.62rem;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;text-overflow:ellipsis;white-space:nowrap}.connection-editor__segment-row--nested{min-height:56px;border-color:#38bdf84d;background:linear-gradient(90deg,#0ea5e91a,#0f172a80),#0f172aa3}.connection-editor__segment-actions{display:inline-flex;gap:4px}.connection-editor__segment-action{width:24px;height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.18);background:#060c16b8;color:#dbeafe;cursor:pointer;font-weight:900;line-height:1}.connection-editor__segment-action:hover{border-color:#22d3ee75;box-shadow:0 0 14px #22d3ee29}.connection-editor__port{min-height:24px;border-radius:999px;border:1px solid rgba(148,163,184,.14);background:#080d18c2;color:#cbd5e1;font-size:.64rem;font-weight:700;font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:crosshair;box-shadow:0 8px 20px #00000038}.connection-editor--guided .connection-editor__ports--visible .connection-editor__port:not(.connection-editor__port--guided-visible){display:none}.connection-editor__port--output{border-color:#f59e0b75;color:#fbbf24}.connection-editor__port--input{border-color:#06b6d475;color:#22d3ee}.connection-editor__port--state{border-color:#a855f785;color:#c084fc}.connection-editor__port--compatible{background:#22c55e29;box-shadow:0 0 0 1px #22c55e61,0 0 18px #22c55e2e;animation:snap-pulse 1s ease-in-out infinite}.connection-editor__port--source{border-color:#fb923cb8;background:#fb923c29;color:#fed7aa;box-shadow:0 0 0 1px #fb923c73,0 0 20px #fb923c2e}.connection-editor__port--candidate{background:#22c55e3d;box-shadow:0 0 0 2px #22c55e94,0 0 24px #22c55e3d}.connection-editor__port--incompatible{opacity:.42;cursor:not-allowed;filter:grayscale(.45)}.connection-editor__port--invalid-drop{opacity:1;border-color:#fb7185c7;color:#fecdd3;background:#f43f5e2e;box-shadow:0 0 0 2px #f43f5e75,0 0 24px #f43f5e38;filter:none;animation:invalid-drop-jolt .36s ease-out}.connection-editor__port--connection-focus{border-color:#facc15ad;color:#fde68a;background:#facc151f;box-shadow:0 0 0 1px #facc156b,0 0 20px #facc152e;animation:port-focus-pulse 1.25s ease-in-out infinite}.connection-editor__drag-tip{position:absolute;z-index:6;display:grid;gap:4px;width:min(330px,calc(100% - 28px));padding:10px 12px;border-radius:14px;border:1px solid rgba(125,211,252,.26);background:linear-gradient(135deg,#0ea5e91f,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 28px #0ea5e91a;font-size:.76rem;pointer-events:none;-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);animation:tooltip-rise .14s ease-out}.connection-editor__drag-tip--valid{border-color:#22c55e66;background:linear-gradient(135deg,#22c55e29,#0f172aeb),#080d18f0;box-shadow:0 18px 44px #0206176b,0 0 30px #22c55e24}.connection-editor__drag-tip--invalid{z-index:7;border-color:#fb71858a;background:linear-gradient(135deg,#f43f5e2e,#0f172af0),#080d18f5;box-shadow:0 18px 44px #0206176b,0 0 34px #f43f5e29;animation:tooltip-rise .14s ease-out,invalid-drop-jolt .36s ease-out}.connection-editor__invalid-drop-pulse{position:absolute;z-index:6;width:16px;height:16px;border-radius:999px;border:2px solid rgba(251,113,133,.88);background:#f43f5e38;box-shadow:0 0 0 8px #f43f5e1a,0 0 28px #f43f5e3d;pointer-events:none;transform:translate(-50%,-50%);animation:invalid-drop-ping 1.2s ease-out both}.connection-editor__drag-tip span{color:#7dd3fc;text-transform:uppercase;letter-spacing:.12em;font-size:.62rem;font-weight:800}.connection-editor__drag-tip strong{min-width:0;overflow:hidden;color:#f8fafc;font-size:.78rem;font-weight:900;text-overflow:ellipsis;white-space:nowrap}.connection-editor__drag-tip small{color:#94a3b8;font-size:.68rem;font-weight:700}.connection-editor__drag-tip--valid small{color:#86efac}.connection-editor__drag-tip--invalid span,.connection-editor__drag-tip--invalid small{color:#fda4af}.connection-editor__summary{grid-column:1;grid-row:2;align-self:end;justify-self:start;z-index:6;display:flex;flex-wrap:wrap;gap:6px;padding:0 0 12px 12px;pointer-events:none}.connection-editor__side-panel{grid-column:2;grid-row:2 / 3;position:relative;z-index:8;min-width:0;min-height:0;display:grid;align-content:start;gap:14px;overflow:auto;padding-inline-end:4px;scrollbar-color:var(--pce-outline-strong) var(--pce-surface-soft)}.connection-editor__side-panel--contextual .connection-editor__inspector{order:-3}.connection-editor__side-panel--contextual .connection-editor__recommended{order:2}.connection-editor__side-panel--contextual .connection-editor__filters-section{order:3}.connection-editor__side-panel--contextual .connection-editor__recommended,.connection-editor__side-panel--contextual .connection-editor__filters-section{opacity:.82}.connection-editor__metric,.connection-editor__item{border-radius:16px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight);-webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px)}.connection-editor__metric{min-width:auto;display:inline-flex;align-items:baseline;gap:7px;padding:6px 9px;border-radius:999px;background:color-mix(in srgb,var(--pce-surface-strong) 86%,transparent);box-shadow:0 10px 26px var(--pce-shadow-soft),inset 0 1px var(--pce-glass-highlight)}.connection-editor__metric span{color:var(--pce-muted);font-size:.62rem;text-transform:uppercase;letter-spacing:.08em}.connection-editor__metric strong,.connection-editor__details-row strong{color:var(--pce-strong);font-size:.78rem}.connection-editor__filters,.connection-editor__actions,.connection-editor__badges{display:flex;gap:8px;flex-wrap:wrap}.connection-editor__filter,.connection-editor__action{border:1px solid var(--pce-outline-strong);background:var(--pce-surface-soft);color:var(--pce-fg);border-radius:999px;padding:6px 10px;font-size:.75rem;font-weight:700;cursor:pointer}.connection-editor__filter--active,.connection-editor__action:hover{border-color:color-mix(in srgb,var(--pce-secondary) 62%,transparent);background:color-mix(in srgb,var(--pce-secondary) 16%,var(--pce-surface-soft));color:var(--pce-strong)}.connection-editor__action--danger{border-color:#f8717161;color:#fecaca}.connection-editor__item{width:100%;text-align:start;padding:12px;display:grid;gap:6px;cursor:pointer;color:inherit}.connection-editor__item--active{border-color:#a855f7b8;background:linear-gradient(90deg,#0ea5e91a,#a855f721)}.connection-editor__item-title{font-weight:800;color:#f8fafc;word-break:break-word}.connection-editor__badge{padding:3px 8px;border-radius:999px;background:#0ea5e92e;color:#bae6fd;font-size:.72rem;font-weight:800}.connection-editor__section{min-width:0;padding:14px;border-radius:18px;background:var(--pce-surface);border:1px solid var(--pce-outline);box-shadow:inset 0 1px var(--pce-glass-highlight),0 18px 50px var(--pce-shadow-soft);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px)}.connection-editor__badge--warning{background:#facc1524;color:#fde68a}.connection-editor__badge--error{background:#ef444424;color:#fecaca}.connection-editor__diagnostics{display:grid;gap:8px}.connection-editor__diagnostic{display:grid;gap:4px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft);color:var(--pce-fg);font-size:.78rem;line-height:1.35}.connection-editor__diagnostic--warning{border-color:#f59e0b47;background:#f59e0b1a}.connection-editor__diagnostic--error{border-color:#ef44445c;background:#ef44441f}.connection-editor__diagnostic-severity{font-size:.68rem;font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:#f8fafc}.connection-editor__suggestions{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__suggestion{display:grid;gap:8px;width:100%;padding:12px;border-radius:16px;border:1px solid color-mix(in srgb,var(--pce-secondary) 26%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 12%,transparent),color-mix(in srgb,var(--pce-primary) 8%,transparent)),var(--pce-surface-strong);color:var(--pce-fg);text-align:start;cursor:pointer;transition:transform .16s ease,border-color .16s ease,background .16s ease}.connection-editor__suggestion:hover{transform:translateY(-1px);border-color:color-mix(in srgb,var(--pce-primary) 46%,transparent);background:linear-gradient(135deg,color-mix(in srgb,var(--pce-secondary) 18%,transparent),color-mix(in srgb,var(--pce-primary) 12%,transparent)),var(--pce-surface-strong)}.connection-editor__suggestion-route{display:grid;gap:4px;font-size:.78rem}.connection-editor__suggestion-route strong{color:var(--pce-strong);font-size:.82rem}.connection-editor__suggestion-reason{color:var(--pce-muted);font-size:.76rem;line-height:1.35}.connection-editor__suggestion-diagnostic{padding:10px 12px;border-radius:14px;border:1px solid rgba(245,158,11,.28);background:#f59e0b1a;color:var(--pce-strong);font-size:.78rem;line-height:1.35}.connection-editor__suggestion-outcome{color:var(--pce-strong);font-size:.84rem;line-height:1.3}.connection-editor__suggestion-action{justify-self:start;padding:3px 8px;border-radius:999px;background:#22d3ee24;color:#67e8f9;font-size:.68rem;font-weight:900;letter-spacing:.06em;text-transform:uppercase}:host-context(.theme-light) .connection-editor__suggestion-action{background:color-mix(in srgb,var(--pce-primary) 12%,var(--pce-surface-soft));color:#075f73}.connection-editor__trace{display:grid;gap:10px;margin-top:14px;padding-top:14px;border-top:1px solid var(--pce-outline)}.connection-editor__trace-summary{color:var(--pce-muted);font-size:.78rem;line-height:1.35}.connection-editor__trace-step{display:grid;grid-template-columns:24px minmax(76px,auto) 1fr;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(34,211,238,.18);background:var(--pce-surface-soft);font-size:.76rem}.connection-editor__trace-step--blocked{border-color:#ef444457;background:#ef44441a}.connection-editor__trace-order{display:inline-grid;place-items:center;width:22px;height:22px;border-radius:999px;background:#22d3ee29;color:#67e8f9;font-weight:900}.connection-editor__trace-phase{color:var(--pce-strong);font-weight:900;text-transform:uppercase;letter-spacing:.06em;font-size:.66rem}.connection-editor__trace-copy{min-width:0;color:var(--pce-fg);word-break:break-word}.connection-editor__transform-steps{display:grid;gap:8px}.connection-editor__transform-step{display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center;padding:9px;border-radius:12px;border:1px solid rgba(168,85,247,.22);background:var(--pce-surface-soft)}.connection-editor__transform-kind{min-width:0;color:var(--pce-strong);font-weight:900;word-break:break-word}.connection-editor__transform-phase{color:var(--pce-muted);font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em}.connection-editor__details-row,.connection-editor__details-block{display:grid;gap:6px}.connection-editor__payload-input{width:100%;min-height:128px;box-sizing:border-box;resize:vertical;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 92%,black);color:var(--pce-fg);padding:10px;font:.76rem/1.45 ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace}.connection-editor__surface-action-editor{display:block;max-height:min(58vh,620px);overflow:auto;border:1px solid var(--pce-outline);border-radius:8px;background:color-mix(in srgb,var(--pce-surface) 96%,black);padding:10px;margin-bottom:10px}.connection-editor__rule-grid{display:grid;gap:10px}.connection-editor__rule-card{display:grid;gap:8px;padding:10px;border-radius:12px;border:1px solid var(--pce-outline);background:var(--pce-surface-soft)}.connection-editor__rule-heading{color:var(--pce-fg);font-size:.72rem;font-weight:900;text-transform:uppercase;letter-spacing:.06em}pre{margin:0;padding:12px;border-radius:12px;background:color-mix(in srgb,var(--pce-surface-strong) 82%,#020617);color:var(--pce-fg);overflow:auto;font-size:.75rem}@keyframes connection-flow{to{stroke-dashoffset:-38}}@keyframes drag-wire-pulse{0%,to{stroke-opacity:.76}50%{stroke-opacity:1}}@keyframes drag-halo-pulse{0%,to{stroke-opacity:.48}50%{stroke-opacity:.82}}@keyframes endpoint-pulse{0%,to{opacity:.78;transform:scale(1)}50%{opacity:1;transform:scale(1.25)}}@keyframes selected-wire-aura{0%,to{stroke-opacity:.46}50%{stroke-opacity:.92}}@keyframes wire-draw-in{0%{stroke-dashoffset:640;opacity:.32}70%{opacity:1}to{stroke-dashoffset:0;opacity:1}}@keyframes new-wire-halo{0%{stroke-opacity:0;stroke-width:30}28%{stroke-opacity:.78}to{stroke-opacity:0;stroke-width:12}}@keyframes new-dock-link-flash{0%{transform:translateY(-2px);box-shadow:0 16px 40px #0206175c,0 0 42px #fb923c47}to{transform:translateY(0)}}@keyframes trace-wire-pulse{0%,to{stroke-opacity:.78}50%{stroke-opacity:1}}@keyframes trace-halo-pulse{0%,to{stroke-opacity:.34}50%{stroke-opacity:.86}}@keyframes tooltip-rise{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@keyframes invalid-drop-jolt{0%,to{transform:translate(0)}28%{transform:translate(-3px)}56%{transform:translate(3px)}}@keyframes invalid-drop-ping{0%{opacity:1;transform:translate(-50%,-50%) scale(.72)}72%{opacity:.74;transform:translate(-50%,-50%) scale(1.35)}to{opacity:0;transform:translate(-50%,-50%) scale(1.8)}}@keyframes node-breathe{50%{transform:scale(1.035)}}@keyframes node-focus-breathe{0%,to{transform:scale(1)}50%{transform:scale(1.055)}}@keyframes trace-source-pulse{50%{transform:scale(1.04);box-shadow:0 0 0 3px #facc15db,0 0 0 22px #facc1514,0 0 64px #facc1557}}@keyframes trace-source-orbit{to{transform:rotate(360deg)}}@keyframes trace-reacting-pulse{50%{transform:scale(1.045);box-shadow:0 0 0 3px #22c55ead,0 0 62px #22c55e4d}}@keyframes segment-focus-sweep{0%,to{stroke-opacity:.82}50%{stroke-opacity:1}}@keyframes snap-pulse{50%{filter:brightness(1.16)}}@keyframes port-focus-pulse{50%{transform:translateY(-1px);box-shadow:0 0 0 2px #facc158f,0 0 26px #facc153d}}@media(prefers-reduced-motion:reduce){.connection-editor__viewport,.connection-editor__node,.connection-editor__node-ring,.connection-editor__node-core,.connection-editor__node-segment,.connection-editor__dock-link,.connection-editor__port{transition-duration:1ms}.connection-editor__wire,.connection-editor__wire--state,.connection-editor__wire--projection,.connection-editor__wire--state-read,.connection-editor__wire--event-propagation,.connection-editor__wire--halo.connection-editor__wire--active,.connection-editor__wire--trace,.connection-editor__wire--halo.connection-editor__wire--trace,.connection-editor__wire-endpoint,.connection-editor__connection-tooltip,.connection-editor__dock-link--new,.connection-editor__trace-overlay,.connection-editor__trace-overlay-step,.connection-editor__drag-wire,.connection-editor__drag-wire--halo,.connection-editor__drag-endpoint,.connection-editor__drag-tip,.connection-editor__node-ring,.connection-editor__node--connection-focus .connection-editor__node-ring,.connection-editor__node--trace-source .connection-editor__node-ring,.connection-editor__node--trace-source:before,.connection-editor__node--trace-reacting .connection-editor__node-ring,.connection-editor__node--rotating .connection-editor__node-ring,.connection-editor__node-segment--connection-focus,.connection-editor__node-segment--compatible,.connection-editor__node-segment--invalid-drop,.connection-editor__segment-popover,.connection-editor__port--compatible,.connection-editor__port--invalid-drop,.connection-editor__port--connection-focus,.connection-editor__invalid-drop,.connection-editor__invalid-drop-pulse{animation:none}.connection-editor__wire{stroke-dashoffset:0}.connection-editor__wire--new{stroke-dasharray:10 8;stroke-dashoffset:0;opacity:1}.connection-editor__wire--halo.connection-editor__wire--new{stroke-width:12;stroke-opacity:.16}.connection-editor__wire-endpoint,.connection-editor__drag-endpoint,.connection-editor__node-ring,.connection-editor__node--trace-source:before{transform:none}.connection-editor__invalid-drop-pulse{opacity:0}}@media(max-width:900px){:host{inset:0}.connection-editor{inset:8px;height:calc(100vh - 16px);padding:12px;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) minmax(76px,112px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(260px,1fr) minmax(150px,30vh) 48px}.connection-editor__header,.connection-editor__stage,.connection-editor__summary,.connection-editor__side-panel,.connection-editor__dock{grid-column:1}.connection-editor__header{align-items:stretch;flex-wrap:wrap;border-radius:18px}.connection-editor__mode-frame{order:3;width:100%;max-width:100%}.connection-editor__close{margin-inline-start:auto}.connection-editor__mode-frame:before,.connection-editor__mode-frame:after{content:\"\";position:absolute;z-index:2;inset-block:4px;width:24px;border-radius:999px;pointer-events:none}.connection-editor__mode-frame:before{inset-inline-start:1px;background:linear-gradient(90deg,#080d18f0,#080d1800)}.connection-editor__mode-frame:after{inset-inline-end:1px;background:linear-gradient(270deg,#080d18f0,#080d1800)}.connection-editor__mode-shell{width:100%;max-width:100%;overflow-x:auto;scroll-padding-inline:28px;-webkit-overflow-scrolling:touch}.connection-editor__subtitle{margin-inline-start:auto}.connection-editor__stage{grid-row:2;min-height:260px}.connection-editor__summary{grid-row:2;max-width:calc(100% - 24px)}.connection-editor__side-panel{grid-row:3;max-height:30vh}.connection-editor__dock{grid-row:4;min-height:0}.connection-editor__connection-tooltip{width:min(620px,calc(100% - 24px));max-height:min(260px,calc(100% - 24px));overflow:auto}.connection-editor__dock-tabs{width:100%;min-width:0;min-height:0;flex-wrap:wrap;align-items:flex-start}.connection-editor__dock-count{flex:1 1 100%;margin-inline-start:0}.connection-editor__dock-body{width:100%;min-width:0;max-height:76px;box-sizing:border-box}.connection-editor__dock-body pre{white-space:pre-wrap;overflow-wrap:anywhere}.connection-editor__dock-link{grid-template-columns:1fr;align-items:start}.connection-editor__dock-link-route{flex-wrap:wrap}.connection-editor__dock-link-badges{justify-content:flex-start}.connection-editor__trace-overlay{inset-inline-start:14px;width:min(420px,calc(100% - 28px));min-width:0;transform:none}.connection-editor__drag-tip{width:min(300px,calc(100% - 28px))}.connection-editor__segment-popover{width:min(280px,calc(100% - 28px));max-height:min(280px,calc(100% - 28px))}.connection-editor__minimap{inset-inline-end:10px;inset-block-end:10px;width:132px;height:94px;padding:16px 8px 8px;border-radius:14px}.connection-editor__minimap:before{inset:20px 8px 8px;background-size:18px 18px}.connection-editor__minimap-title{inset-block-start:6px;inset-inline-start:10px;font-size:.54rem}}@media(max-width:640px){.connection-editor{inset:4px;height:calc(100vh - 8px);padding:8px;gap:8px;grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) minmax(72px,104px)}.connection-editor--dock-collapsed{grid-template-rows:auto minmax(240px,1fr) minmax(140px,28vh) 46px}.connection-editor__header{gap:8px;padding:10px}.connection-editor__mode-shell{padding:4px;gap:2px}.connection-editor__mode{min-height:28px;gap:4px;padding:0 7px;font-size:.68rem}.connection-editor__mode-glyph{font-size:.64rem}.connection-editor__stage{min-height:240px}.connection-editor__zoom-controls{inset-inline-start:8px;inset-block-start:8px;gap:6px;width:42px}.connection-editor__tool-group,.connection-editor__trace-source{gap:6px;padding:8px;border-radius:12px}.connection-editor__tool-group{grid-template-columns:28px}.connection-editor__tool-group:nth-of-type(2){grid-template-columns:28px}.connection-editor__tool-button{width:28px;height:28px}.connection-editor__arrange-button,.connection-editor__simulate-button{width:30px;min-height:30px}.connection-editor__summary{gap:6px;padding-inline-end:8px}.connection-editor__side-panel{max-height:28vh}.connection-editor__dock{border-radius:16px}.connection-editor__dock-tabs{gap:4px}.connection-editor__dock-tab{padding:0 9px}.connection-editor__dock-count{font-size:.62rem}.connection-editor__dock-body{max-height:66px;padding:8px}.connection-editor__minimap{width:116px;height:84px}.connection-editor__segment-row{grid-template-columns:24px minmax(54px,.55fr) minmax(0,1fr) auto}}\n"] }]
9118
9968
  }], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], page: [{ type: i0.Input, args: [{ isSignal: true, alias: "page", required: false }] }], pageChange: [{ type: i0.Output, args: ["pageChange"] }], focusWidget: [{ type: i0.Output, args: ["focusWidget"] }], openPageSettings: [{ type: i0.Output, args: ["openPageSettings"] }], close: [{ type: i0.Output, args: ["close"] }] } });
9119
9969
 
9120
- const LAYOUT_PRESET_ENTRIES = [{ id: 'analytics-overview', label: 'Analytics Overview' }, { id: 'master-detail-dashboard', label: 'Master Detail Dashboard' }, { id: 'workspace-balanced', label: 'Workspace Balanced' }];
9121
- const THEME_PRESET_ENTRIES = [{ id: 'workspace-balanced', label: 'Workspace Balanced' }, { id: 'analytics-calm', label: 'Analytics Calm' }, { id: 'ops-monitoring', label: 'Ops Monitoring' }];
9970
+ const LAYOUT_PRESET_ENTRIES = Object.values(BUILTIN_PAGE_LAYOUT_PRESETS).map((preset) => ({
9971
+ id: preset.id,
9972
+ label: preset.label,
9973
+ description: preset.description || '',
9974
+ category: preset.category || 'workspace',
9975
+ defaultColumns: preset.defaultLayout.columns || 1,
9976
+ defaultGap: preset.defaultLayout.gap || '',
9977
+ slotLabels: preset.slotModel.map((slot) => slot.label),
9978
+ requiredSlotLabels: preset.slotModel.filter((slot) => slot.required).map((slot) => slot.label),
9979
+ deviceStacking: preset.devicePolicy?.stacking || '',
9980
+ preferTabsOnMobile: !!preset.devicePolicy?.preferTabsOnMobile,
9981
+ hideSecondaryContentOnMobile: !!preset.devicePolicy?.hideSecondaryContentOnMobile,
9982
+ defaultThemePreset: preset.defaultThemePreset || '',
9983
+ }));
9984
+ const THEME_PRESET_ENTRIES = Object.values(BUILTIN_PAGE_THEME_PRESETS).map((preset) => ({
9985
+ id: preset.id,
9986
+ label: preset.label,
9987
+ description: preset.description || '',
9988
+ density: preset.density || 'comfortable',
9989
+ motion: preset.motion || 'subtle',
9990
+ shellPreset: preset.shellPreset || '',
9991
+ chartThemePreset: preset.chartThemePreset || '',
9992
+ }));
9122
9993
  const SHELL_PRESET_ENTRIES = [{ id: 'graphite', label: 'Graphite' }, { id: 'light-neutral', label: 'Light Neutral' }, { id: 'dark-glass', label: 'Dark Glass' }];
9123
9994
  const integerColumnValidator = (control) => control.value == null || Number.isInteger(control.value) ? null : { integer: true };
9124
9995
  class DynamicPageConfigEditorComponent {
@@ -9153,6 +10024,7 @@ class DynamicPageConfigEditorComponent {
9153
10024
  stateError = signal(null, ...(ngDevMode ? [{ debugName: "stateError" }] : /* istanbul ignore next */ []));
9154
10025
  deviceError = signal(null, ...(ngDevMode ? [{ debugName: "deviceError" }] : /* istanbul ignore next */ []));
9155
10026
  injectedData = inject(SETTINGS_PANEL_DATA$1, { optional: true });
10027
+ i18n = inject(PraxisI18nService);
9156
10028
  pageInput = null;
9157
10029
  snapshot = '';
9158
10030
  hydrating = false;
@@ -9166,17 +10038,36 @@ class DynamicPageConfigEditorComponent {
9166
10038
  get isConfigurationValid() { return this.isValid$.value; }
9167
10039
  get hasPendingChanges() { return this.isDirty$.value; }
9168
10040
  get validationStateLabel() { const issue = this.canvasError() || this.groupingError() || this.deviceError() || this.contextError() || this.stateError(); if (issue)
9169
- return `Validacao pendente: ${issue}`; return this.isValid$.value ? 'Configuracao valida' : 'Configuracao invalida'; }
9170
- get dirtyStateLabel() { return this.hasPendingChanges ? 'Alteracoes pendentes' : 'Sem alteracoes'; }
9171
- get selectedLayoutPresetLabel() { return `Layout: ${this.lookupPresetLabel(this.layoutPresetEntries, this.layoutPresetControl.value, 'Nenhum')}`; }
9172
- get selectedThemePresetLabel() { return `Tema: ${this.lookupPresetLabel(this.themePresetEntries, this.themePresetControl.value, 'Padrao')}`; }
9173
- get canvasSummaryLabel() { return `Canvas: ${this.canvasColumnsControl.value} colunas`; }
10041
+ return this.tx('editor.status.validationIssue', 'Review: {{issue}}').replace('{{issue}}', issue); return this.isValid$.value ? this.tx('editor.status.valid', 'Valid configuration') : this.tx('editor.status.review', 'Review errors before saving'); }
10042
+ get dirtyStateLabel() { return this.hasPendingChanges ? this.tx('editor.status.pending', 'Pending changes') : this.tx('editor.status.clean', 'No changes'); }
10043
+ get selectedLayoutPresetLabel() { return this.tx('editor.summary.layout', 'Layout: {{label}}').replace('{{label}}', this.lookupPresetLabel(this.layoutPresetEntries, this.layoutPresetControl.value, this.tx('editor.fallback.manual', 'manual'))); }
10044
+ get selectedThemePresetLabel() { return this.tx('editor.summary.theme', 'Theme: {{label}}').replace('{{label}}', this.lookupPresetLabel(this.themePresetEntries, this.themePresetControl.value, this.tx('editor.layout.layoutDefault', 'Layout default'))); }
10045
+ get selectedLayoutPresetEntry() { return this.layoutPresetEntries.find((entry) => entry.id === this.layoutPresetControl.value) || null; }
10046
+ get selectedThemePresetEntry() { return this.themePresetEntries.find((entry) => entry.id === this.themePresetControl.value) || null; }
10047
+ get recommendedThemePresetEntry() { const themeId = this.selectedLayoutPresetEntry?.defaultThemePreset; return themeId ? this.themePresetEntries.find((entry) => entry.id === themeId) || null : null; }
10048
+ get canvasSummaryLabel() { return this.tx('editor.summary.canvasColumns', 'Canvas: {{count}} columns').replace('{{count}}', String(this.canvasColumnsControl.value)); }
9174
10049
  onSelectedTabIndexChange(index) { this.activeTab.set(this.tabOrder[index] || 'canvas'); }
9175
10050
  getSettingsValue() { return this.buildCurrentPage(true); }
9176
10051
  onSave() { return this.getSettingsValue(); }
9177
10052
  reset() { this.hydrate(); }
10053
+ pinRecommendedThemePreset() { const theme = this.recommendedThemePresetEntry; if (theme)
10054
+ this.themePresetControl.setValue(theme.id); }
9178
10055
  addGroupingNode(seed) { this.groupingNodes.push(this.createGroupingNodeGroup(seed)); this.refreshPanelState(); }
9179
10056
  removeGroupingNode(index) { this.groupingNodes.removeAt(index); this.refreshPanelState(); }
10057
+ layoutPresetSummary(preset) { return this.tx('editor.preview.layoutSummary', '{{columns}} columns · {{gap}}').replace('{{columns}}', String(preset.defaultColumns)).replace('{{gap}}', preset.defaultGap || this.tx('editor.preview.defaultGap', 'default gap')); }
10058
+ slotsSummary(preset) { return this.tx('editor.preview.slotsChip', 'Slots: {{value}}').replace('{{value}}', preset.slotLabels.join(', ') || this.tx('editor.preview.none', 'none')); }
10059
+ requiredSlotsSummary(preset) { return this.tx('editor.preview.requiredSlotsChip', 'Required: {{value}}').replace('{{value}}', preset.requiredSlotLabels.join(', ') || this.tx('editor.preview.noRequiredSlots', 'No required slots')); }
10060
+ devicePolicySummary(preset) {
10061
+ const policies = [
10062
+ preset.deviceStacking ? this.tx('editor.preview.mobileStacking', 'mobile {{value}}').replace('{{value}}', preset.deviceStacking) : '',
10063
+ preset.preferTabsOnMobile ? this.tx('editor.preview.prefersMobileTabs', 'prefers mobile tabs') : '',
10064
+ preset.hideSecondaryContentOnMobile ? this.tx('editor.preview.hidesSecondaryContent', 'hides secondary content') : '',
10065
+ ].filter(Boolean);
10066
+ return policies.join(' · ') || this.tx('editor.preview.noDevicePolicy', 'No specific mobile policy');
10067
+ }
10068
+ inheritedThemeHelp(theme) { return this.themePresetControl.value ? theme.description : this.tx('editor.preview.inheritedThemeHelp', '{{description}} This theme is inherited automatically while the theme field stays on layout default.').replace('{{description}}', theme.description); }
10069
+ groupLabel(index) { return this.tx('editor.grouping.groupN', 'Group {{index}}').replace('{{index}}', String(index + 1)); }
10070
+ tx(key, fallback) { return resolvePraxisPageBuilderText(this.i18n, key, fallback); }
9180
10071
  createDeviceVariantForm() { return new FormGroup({ columns: new FormControl(null, { validators: [Validators.min(1), integerColumnValidator] }), rowUnit: new FormControl('', { nonNullable: true }), gap: new FormControl('', { nonNullable: true }), autoRows: new FormControl('', { nonNullable: true }), groupingOverrides: new FormControl('', { nonNullable: true }), widgetOverrides: new FormControl('', { nonNullable: true }) }); }
9181
10072
  createGroupingNodeGroup(seed) { const label = seed && 'label' in seed && typeof seed.label === 'string' ? seed.label : ''; return new FormGroup({ kind: new FormControl(seed?.kind || 'section', { nonNullable: true }), id: new FormControl(seed?.id || '', { nonNullable: true, validators: [Validators.required] }), label: new FormControl(label, { nonNullable: true }), widgetKeysCsv: new FormControl(this.stringifyGroupingWidgetKeys(seed), { nonNullable: true }), layout: new FormControl(seed?.kind === 'section' ? seed.layout || '' : '', { nonNullable: true }), emphasis: new FormControl(seed?.kind === 'hero' ? seed.emphasis || '' : '', { nonNullable: true }), side: new FormControl(seed?.kind === 'rail' ? seed.side || 'right' : 'right', { nonNullable: true }), tabsJson: new FormControl(seed?.kind === 'tabs' ? JSON.stringify(seed.tabs || [], null, 2) : '', { nonNullable: true }) }); }
9182
10073
  hydrate() { const page = this.currentPageInput() || { widgets: [] }; const canvas = page.canvas || this.defaultCanvas(); const context = this.clone(page.context || {}); this.hydrating = true; this.canvasColumnsControl.setValue(canvas.columns || 12, { emitEvent: false }); this.canvasRowUnitControl.setValue(canvas.rowUnit || '80px', { emitEvent: false }); this.canvasGapControl.setValue(canvas.gap || '16px', { emitEvent: false }); this.canvasAutoRowsControl.setValue(canvas.autoRows || 'fixed', { emitEvent: false }); this.layoutPresetControl.setValue(page.layoutPreset || '', { emitEvent: false }); this.themePresetControl.setValue(page.themePreset || '', { emitEvent: false }); this.shellPresetControl.setValue(this.extractShellPreset(context) || this.pagePreset || '', { emitEvent: false }); this.replaceGroupingNodes(page.grouping); this.contextControl.setValue(this.stringify(this.removeShellPresetFromContext(context)), { emitEvent: false }); this.stateControl.setValue(this.stringify(page.state || {}), { emitEvent: false }); for (const device of this.deviceKeys) {
@@ -9186,10 +10077,10 @@ class DynamicPageConfigEditorComponent {
9186
10077
  replaceGroupingNodes(grouping) { this.groupingNodes.clear({ emitEvent: false }); for (const group of grouping || [])
9187
10078
  this.groupingNodes.push(this.createGroupingNodeGroup(group), { emitEvent: false }); }
9188
10079
  buildCurrentPage(reportErrors) { const next = this.clone(this.currentPageInput() || { widgets: [] }); if (this.canvasColumnsControl.invalid)
9189
- return this.invalidate('canvas', this.canvasError, reportErrors, 'Canvas invalido'); this.canvasError.set(null); const grouping = this.buildGrouping(reportErrors); if (grouping === null)
10080
+ return this.invalidate('canvas', this.canvasError, reportErrors, this.tx('editor.errors.canvasInvalid', 'Invalid canvas')); this.canvasError.set(null); const grouping = this.buildGrouping(reportErrors); if (grouping === null)
9190
10081
  return null; this.groupingError.set(null); const context = this.parseRecordJson(this.contextControl.value, {}); if (context === null)
9191
- return this.invalidate('context', this.contextError, reportErrors, 'Contexto invalido'); this.contextError.set(null); const state = this.parseRecordJson(this.stateControl.value, {}); if (state === null)
9192
- return this.invalidate('state', this.stateError, reportErrors, 'Estado invalido'); this.stateError.set(null); const deviceLayouts = this.buildDeviceLayouts(reportErrors, next.deviceLayouts); if (deviceLayouts === null)
10082
+ return this.invalidate('context', this.contextError, reportErrors, this.tx('editor.errors.contextInvalid', 'Invalid context')); this.contextError.set(null); const state = this.parseRecordJson(this.stateControl.value, {}); if (state === null)
10083
+ return this.invalidate('state', this.stateError, reportErrors, this.tx('editor.errors.stateInvalid', 'Invalid state')); this.stateError.set(null); const deviceLayouts = this.buildDeviceLayouts(reportErrors, next.deviceLayouts); if (deviceLayouts === null)
9193
10084
  return null; next.canvas = { ...(next.canvas || this.defaultCanvas()), mode: 'grid', columns: this.canvasColumnsControl.value, rowUnit: this.canvasRowUnitControl.value.trim() || '80px', gap: this.canvasGapControl.value.trim() || '16px', autoRows: this.canvasAutoRowsControl.value, items: next.canvas?.items || {} }; next.layoutPreset = this.layoutPresetControl.value.trim() || undefined; next.themePreset = this.themePresetControl.value.trim() || undefined; next.grouping = grouping.length ? grouping : undefined; next.deviceLayouts = Object.keys(deviceLayouts).length ? deviceLayouts : undefined; next.context = this.applyShellPresetToContext(context, this.shellPresetControl.value.trim()); next.state = Object.keys(state).length ? state : undefined; return next; }
9194
10085
  buildGrouping(reportErrors) { const grouping = []; const seenIds = new Set(); for (const group of this.groupingNodes.controls) {
9195
10086
  const kind = group.controls.kind.value;
@@ -9197,19 +10088,19 @@ class DynamicPageConfigEditorComponent {
9197
10088
  if (!id)
9198
10089
  continue;
9199
10090
  if (seenIds.has(id))
9200
- return this.invalidate('grouping', this.groupingError, reportErrors, 'Ids de grupo duplicados');
10091
+ return this.invalidate('grouping', this.groupingError, reportErrors, this.tx('editor.errors.duplicateGroupIds', 'Duplicate group ids'));
9201
10092
  seenIds.add(id);
9202
10093
  const label = group.controls.label.value.trim();
9203
10094
  if (kind === 'tabs') {
9204
10095
  const tabs = this.parseGroupingTabs(group.controls.tabsJson.value);
9205
10096
  if (tabs === null)
9206
- return this.invalidate('grouping', this.groupingError, reportErrors, 'Tabs invalidas');
10097
+ return this.invalidate('grouping', this.groupingError, reportErrors, this.tx('editor.errors.invalidTabs', 'Invalid tabs'));
9207
10098
  grouping.push({ kind: 'tabs', id, ...(label ? { label } : {}), tabs });
9208
10099
  continue;
9209
10100
  }
9210
10101
  const widgetKeys = group.controls.widgetKeysCsv.value.split(',').map((item) => item.trim()).filter(Boolean);
9211
10102
  if (this.hasDuplicateStrings(widgetKeys))
9212
- return this.invalidate('grouping', this.groupingError, reportErrors, 'Widget keys duplicadas');
10103
+ return this.invalidate('grouping', this.groupingError, reportErrors, this.tx('editor.errors.duplicateWidgetKeys', 'Duplicate widget keys'));
9213
10104
  if (kind === 'section') {
9214
10105
  grouping.push({ kind: 'section', id, ...(label ? { label } : {}), widgetKeys, ...(group.controls.layout.value ? { layout: group.controls.layout.value } : {}) });
9215
10106
  continue;
@@ -9223,11 +10114,11 @@ class DynamicPageConfigEditorComponent {
9223
10114
  buildDeviceLayouts(reportErrors, base) { const next = {}; for (const device of this.deviceKeys) {
9224
10115
  const form = this.deviceForms[device];
9225
10116
  if (form.controls.columns.invalid)
9226
- return this.invalidate('devices', this.deviceError, reportErrors, 'Columns invalidas');
10117
+ return this.invalidate('devices', this.deviceError, reportErrors, this.tx('editor.errors.invalidColumns', 'Invalid columns'));
9227
10118
  const groupingOverrides = this.parseGroupingOverrides(form.controls.groupingOverrides.value);
9228
10119
  const widgetOverrides = this.parseWidgetOverrides(form.controls.widgetOverrides.value);
9229
10120
  if (groupingOverrides === null || widgetOverrides === null)
9230
- return this.invalidate('devices', this.deviceError, reportErrors, 'Overrides invalidos');
10121
+ return this.invalidate('devices', this.deviceError, reportErrors, this.tx('editor.errors.invalidOverrides', 'Invalid overrides'));
9231
10122
  const baseVariant = this.clone(base?.[device] || {});
9232
10123
  const baseCanvas = this.clone(baseVariant.canvas || {});
9233
10124
  delete baseVariant.canvas;
@@ -9321,13 +10212,13 @@ class DynamicPageConfigEditorComponent {
9321
10212
  clone(value) { if (value == null || typeof value !== 'object')
9322
10213
  return value; return JSON.parse(JSON.stringify(value)); }
9323
10214
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicPageConfigEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9324
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicPageConfigEditorComponent, isStandalone: true, selector: "praxis-dynamic-page-config-editor", inputs: { page: "page", layout: "layout", presets: "presets", pagePreset: "pagePreset" }, outputs: { pageChange: "pageChange" }, ngImport: i0, template: `
10215
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: DynamicPageConfigEditorComponent, isStandalone: true, selector: "praxis-dynamic-page-config-editor", inputs: { page: "page", layout: "layout", presets: "presets", pagePreset: "pagePreset" }, outputs: { pageChange: "pageChange" }, providers: [providePraxisPageBuilderI18n()], ngImport: i0, template: `
9325
10216
  <div class="editor">
9326
10217
  <div class="head">
9327
- <div>Configuracao da pagina</div>
9328
- <button mat-stroked-button type="button" (click)="reset()">Recarregar</button>
10218
+ <div>{{ tx('editor.title', 'Page settings') }}</div>
10219
+ <button mat-stroked-button type="button" (click)="reset()">{{ tx('editor.reload', 'Reload') }}</button>
9329
10220
  </div>
9330
- <div class="summary">
10221
+ <div class="summary" [attr.aria-label]="tx('editor.summaryAria', 'Configuration summary')">
9331
10222
  <span>{{ validationStateLabel }}</span>
9332
10223
  <span>{{ dirtyStateLabel }}</span>
9333
10224
  <span>{{ selectedLayoutPresetLabel }}</span>
@@ -9335,24 +10226,24 @@ class DynamicPageConfigEditorComponent {
9335
10226
  <span>{{ canvasSummaryLabel }}</span>
9336
10227
  </div>
9337
10228
  <mat-tab-group [selectedIndex]="selectedTabIndex" (selectedIndexChange)="onSelectedTabIndexChange($event)">
9338
- <mat-tab label="Canvas"><div class="grid"><mat-form-field appearance="outline"><mat-label>Colunas</mat-label><input matInput type="number" min="1" [formControl]="canvasColumnsControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Row unit</mat-label><input matInput [formControl]="canvasRowUnitControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Gap</mat-label><input matInput [formControl]="canvasGapControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Auto rows</mat-label><mat-select [formControl]="canvasAutoRowsControl"><mat-option value="fixed">fixed</mat-option><mat-option value="content">content</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>Layout preset</mat-label><mat-select [formControl]="layoutPresetControl"><mat-option value="">Nenhum</mat-option>@for (preset of layoutPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>Theme preset</mat-label><mat-select [formControl]="themePresetControl"><mat-option value="">Padrao</mat-option>@for (preset of themePresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>Shell preset</mat-label><mat-select [formControl]="shellPresetControl"><mat-option value="">Nenhum</mat-option>@for (preset of shellPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field></div></mat-tab>
9339
- <mat-tab label="Grouping"><div class="panel"><div class="head"><span>Grupos</span><button mat-stroked-button type="button" (click)="addGroupingNode()"><mat-icon>add</mat-icon>Adicionar grupo</button></div>@for (group of groupingNodes.controls; track $index) {<div class="card" [formGroup]="group"><div class="head"><span>Grupo {{ $index + 1 }}</span><button mat-icon-button type="button" (click)="removeGroupingNode($index)"><mat-icon>delete</mat-icon></button></div><div class="grid"><mat-form-field appearance="outline"><mat-label>Kind</mat-label><mat-select formControlName="kind"><mat-option value="section">section</mat-option><mat-option value="tabs">tabs</mat-option><mat-option value="hero">hero</mat-option><mat-option value="rail">rail</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>Id</mat-label><input matInput formControlName="id" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Label</mat-label><input matInput formControlName="label" /></mat-form-field>@if (group.controls.kind.value === 'section') {<mat-form-field appearance="outline"><mat-label>Layout</mat-label><mat-select formControlName="layout"><mat-option value="">Padrao</mat-option><mat-option value="stack">stack</mat-option><mat-option value="grid">grid</mat-option><mat-option value="row">row</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'hero') {<mat-form-field appearance="outline"><mat-label>Emphasis</mat-label><mat-select formControlName="emphasis"><mat-option value="">Padrao</mat-option><mat-option value="high">high</mat-option><mat-option value="medium">medium</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'rail') {<mat-form-field appearance="outline"><mat-label>Side</mat-label><mat-select formControlName="side"><mat-option value="left">left</mat-option><mat-option value="right">right</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'tabs') {<mat-form-field appearance="outline" class="wide"><mat-label>Tabs (JSON)</mat-label><textarea matInput rows="4" formControlName="tabsJson"></textarea></mat-form-field>} @else {<mat-form-field appearance="outline" class="wide"><mat-label>Widget keys (virgula)</mat-label><input matInput formControlName="widgetKeysCsv" /></mat-form-field>}</div></div>}</div></mat-tab>
9340
- <mat-tab label="Device Layouts"><div class="panel">@for (device of deviceKeys; track device) {<div class="card"><div>{{ deviceLabels[device] }}</div><div class="grid"><mat-form-field appearance="outline"><mat-label>Columns</mat-label><input matInput type="number" min="1" [formControl]="deviceForms[device].controls.columns" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Row unit</mat-label><input matInput [formControl]="deviceForms[device].controls.rowUnit" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Gap</mat-label><input matInput [formControl]="deviceForms[device].controls.gap" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Auto rows</mat-label><mat-select [formControl]="deviceForms[device].controls.autoRows"><mat-option value="">Padrao</mat-option><mat-option value="fixed">fixed</mat-option><mat-option value="content">content</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline" class="wide"><mat-label>Grouping overrides (JSON)</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.groupingOverrides"></textarea></mat-form-field><mat-form-field appearance="outline" class="wide"><mat-label>Widget overrides (JSON)</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.widgetOverrides"></textarea></mat-form-field></div><div class="hint">Item overrides de canvas existentes sao preservados.</div></div>}</div></mat-tab>
9341
- <mat-tab label="Contexto"><mat-form-field appearance="outline" class="wide"><mat-label>Context (JSON)</mat-label><textarea matInput rows="12" [formControl]="contextControl"></textarea></mat-form-field></mat-tab>
9342
- <mat-tab label="Estado da Pagina"><mat-form-field appearance="outline" class="wide"><mat-label>State (JSON)</mat-label><textarea matInput rows="14" [formControl]="stateControl"></textarea></mat-form-field></mat-tab>
10229
+ <mat-tab [label]="tx('editor.tabs.layout', 'Layout')"><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.cols', 'Columns') }}</mat-label><input matInput type="number" min="1" [formControl]="canvasColumnsControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.rowUnit', 'Row unit') }}</mat-label><input matInput [formControl]="canvasRowUnitControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.gap', 'Gap') }}</mat-label><input matInput [formControl]="canvasGapControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.autoRows', 'Auto rows') }}</mat-label><mat-select [formControl]="canvasAutoRowsControl"><mat-option value="fixed">fixed</mat-option><mat-option value="content">content</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.layoutPreset', 'Layout preset') }}</mat-label><mat-select [formControl]="layoutPresetControl"><mat-option value="">{{ tx('editor.layout.none', 'None') }}</mat-option>@for (preset of layoutPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.themePreset', 'Theme preset') }}</mat-label><mat-select [formControl]="themePresetControl"><mat-option value="">{{ tx('editor.layout.layoutDefault', 'Layout default') }}</mat-option>@for (preset of themePresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.shellPreset', 'Shell visual preset') }}</mat-label><mat-select [formControl]="shellPresetControl"><mat-option value="">{{ tx('editor.layout.none', 'None') }}</mat-option>@for (preset of shellPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field></div>@if (selectedLayoutPresetEntry; as preset) {<div class="preset-preview"><div class="preset-preview__head"><div><span class="eyebrow">{{ tx('editor.preview.layoutEyebrow', 'Layout template') }} · {{ preset.category }}</span><strong>{{ preset.label }}</strong></div><span>{{ layoutPresetSummary(preset) }}</span></div><p>{{ preset.description || tx('editor.preview.layoutFallbackDescription', 'Page organization preset.') }}</p><div class="preset-preview__chips"><span>{{ slotsSummary(preset) }}</span><span>{{ requiredSlotsSummary(preset) }}</span><span>{{ devicePolicySummary(preset) }}</span></div>@if (recommendedThemePresetEntry; as theme) {<div class="preset-preview__recommendation"><div><span class="eyebrow">{{ tx('editor.preview.inheritedTheme', 'Inherited theme') }}</span><strong>{{ theme.label }}</strong><span>{{ inheritedThemeHelp(theme) }}</span></div><button mat-stroked-button type="button" [disabled]="themePresetControl.value === theme.id" (click)="pinRecommendedThemePreset()">{{ tx('editor.preview.pinTheme', 'Pin theme') }}</button></div>}</div>} @if (selectedThemePresetEntry; as theme) {<div class="preset-preview preset-preview--theme"><div class="preset-preview__head"><div><span class="eyebrow">{{ tx('editor.preview.explicitTheme', 'Explicit theme') }}</span><strong>{{ theme.label }}</strong></div><span>{{ theme.density }} · {{ theme.motion }}</span></div><p>{{ theme.description || tx('editor.preview.themeFallbackDescription', 'Page visual preset.') }}</p><div class="preset-preview__chips"><span>{{ tx('editor.preview.shellChip', 'Shell: {{value}}').replace('{{value}}', theme.shellPreset) }}</span><span>{{ tx('editor.preview.chartsChip', 'Charts: {{value}}').replace('{{value}}', theme.chartThemePreset) }}</span></div></div>}</mat-tab>
10230
+ <mat-tab [label]="tx('editor.tabs.grouping', 'Grouping')"><div class="panel"><div class="head"><span>{{ tx('editor.grouping.title', 'Grouping') }}</span><button mat-stroked-button type="button" (click)="addGroupingNode()"><mat-icon>add</mat-icon>{{ tx('editor.grouping.add', 'Add group') }}</button></div>@for (group of groupingNodes.controls; track $index) {<div class="card" [formGroup]="group"><div class="head"><span>{{ groupLabel($index) }}</span><button mat-icon-button type="button" [attr.aria-label]="tx('editor.grouping.removeAria', 'Remove group')" (click)="removeGroupingNode($index)"><mat-icon>delete</mat-icon></button></div><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.kind', 'Kind') }}</mat-label><mat-select formControlName="kind"><mat-option value="section">section</mat-option><mat-option value="tabs">tabs</mat-option><mat-option value="hero">hero</mat-option><mat-option value="rail">rail</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.id', 'Id') }}</mat-label><input matInput formControlName="id" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.label', 'Label') }}</mat-label><input matInput formControlName="label" /></mat-form-field>@if (group.controls.kind.value === 'section') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.layout', 'Layout') }}</mat-label><mat-select formControlName="layout"><mat-option value="">{{ tx('editor.grouping.layoutDefault', 'Default') }}</mat-option><mat-option value="stack">stack</mat-option><mat-option value="grid">grid</mat-option><mat-option value="row">row</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'hero') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.emphasis', 'Emphasis') }}</mat-label><mat-select formControlName="emphasis"><mat-option value="">{{ tx('editor.grouping.layoutDefault', 'Default') }}</mat-option><mat-option value="high">high</mat-option><mat-option value="medium">medium</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'rail') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.side', 'Side') }}</mat-label><mat-select formControlName="side"><mat-option value="left">left</mat-option><mat-option value="right">right</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'tabs') {<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.grouping.tabsJson', 'Tabs (JSON)') }}</mat-label><textarea matInput rows="4" formControlName="tabsJson"></textarea></mat-form-field>} @else {<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.grouping.widgetKeysCsv', 'Widget keys (comma-separated)') }}</mat-label><input matInput formControlName="widgetKeysCsv" /></mat-form-field>}</div></div>}</div></mat-tab>
10231
+ <mat-tab [label]="tx('editor.tabs.devices', 'Device Layouts')"><div class="panel">@for (device of deviceKeys; track device) {<div class="card"><div>{{ deviceLabels[device] }}</div><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.devices.columns', 'Columns') }}</mat-label><input matInput type="number" min="1" [formControl]="deviceForms[device].controls.columns" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.rowUnit', 'Row unit') }}</mat-label><input matInput [formControl]="deviceForms[device].controls.rowUnit" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.devices.gap', 'Gap') }}</mat-label><input matInput [formControl]="deviceForms[device].controls.gap" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.autoRows', 'Auto rows') }}</mat-label><mat-select [formControl]="deviceForms[device].controls.autoRows"><mat-option value="">{{ tx('editor.devices.orientationDefault', 'Default') }}</mat-option><mat-option value="fixed">fixed</mat-option><mat-option value="content">content</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.devices.groupingOverridesJson', 'Grouping overrides (JSON)') }}</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.groupingOverrides"></textarea></mat-form-field><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.devices.widgetOverridesJson', 'Widget overrides (JSON)') }}</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.widgetOverrides"></textarea></mat-form-field></div><div class="hint">{{ tx('editor.preview.deviceCanvasHint', 'Existing canvas item overrides are preserved.') }}</div></div>}</div></mat-tab>
10232
+ <mat-tab [label]="tx('editor.tabs.context', 'Context')"><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.context.json', 'Context (JSON)') }}</mat-label><textarea matInput rows="12" [formControl]="contextControl"></textarea></mat-form-field></mat-tab>
10233
+ <mat-tab [label]="tx('editor.tabs.state', 'Page State')"><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.state.valuesJson', 'Primary values (JSON)') }}</mat-label><textarea matInput rows="14" [formControl]="stateControl"></textarea></mat-form-field></mat-tab>
9343
10234
  </mat-tab-group>
9344
10235
  </div>
9345
- `, isInline: true, styles: [".editor,.panel{display:grid;gap:16px;color:var(--md-sys-color-on-surface, currentColor)}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
10236
+ `, isInline: true, styles: [".editor,.panel{display:grid;gap:16px;color:var(--md-sys-color-on-surface, currentColor)}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}.preset-preview{display:grid;gap:12px;margin-top:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, transparent) 88%,var(--md-sys-color-primary-container, transparent) 12%)}.preset-preview--theme{background:var(--md-sys-color-surface-container-low, transparent)}.preset-preview__head,.preset-preview__recommendation{display:flex;justify-content:space-between;align-items:center;gap:16px}.preset-preview__head>div,.preset-preview__recommendation>div{display:grid;gap:4px;min-width:0}.preset-preview p{margin:0;color:var(--md-sys-color-on-surface-variant, currentColor);line-height:1.45}.preset-preview__chips{display:flex;flex-wrap:wrap;gap:8px}.preset-preview__chips span{padding:5px 9px;border-radius:999px;background:var(--md-sys-color-surface-container, color-mix(in srgb, currentColor 8%, transparent));color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px;line-height:1.3}.preset-preview__recommendation{padding-top:12px;border-top:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 14%, transparent))}.preset-preview__recommendation span:last-child{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:13px;line-height:1.35}.eyebrow{color:var(--md-sys-color-primary, currentColor);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
9346
10237
  }
9347
10238
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicPageConfigEditorComponent, decorators: [{
9348
10239
  type: Component,
9349
- args: [{ selector: 'praxis-dynamic-page-config-editor', standalone: true, imports: [ReactiveFormsModule, MatButtonModule, MatFormFieldModule, MatIconModule, MatInputModule, MatSelectModule, MatTabsModule], template: `
10240
+ args: [{ selector: 'praxis-dynamic-page-config-editor', standalone: true, imports: [ReactiveFormsModule, MatButtonModule, MatFormFieldModule, MatIconModule, MatInputModule, MatSelectModule, MatTabsModule], providers: [providePraxisPageBuilderI18n()], template: `
9350
10241
  <div class="editor">
9351
10242
  <div class="head">
9352
- <div>Configuracao da pagina</div>
9353
- <button mat-stroked-button type="button" (click)="reset()">Recarregar</button>
10243
+ <div>{{ tx('editor.title', 'Page settings') }}</div>
10244
+ <button mat-stroked-button type="button" (click)="reset()">{{ tx('editor.reload', 'Reload') }}</button>
9354
10245
  </div>
9355
- <div class="summary">
10246
+ <div class="summary" [attr.aria-label]="tx('editor.summaryAria', 'Configuration summary')">
9356
10247
  <span>{{ validationStateLabel }}</span>
9357
10248
  <span>{{ dirtyStateLabel }}</span>
9358
10249
  <span>{{ selectedLayoutPresetLabel }}</span>
@@ -9360,14 +10251,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
9360
10251
  <span>{{ canvasSummaryLabel }}</span>
9361
10252
  </div>
9362
10253
  <mat-tab-group [selectedIndex]="selectedTabIndex" (selectedIndexChange)="onSelectedTabIndexChange($event)">
9363
- <mat-tab label="Canvas"><div class="grid"><mat-form-field appearance="outline"><mat-label>Colunas</mat-label><input matInput type="number" min="1" [formControl]="canvasColumnsControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Row unit</mat-label><input matInput [formControl]="canvasRowUnitControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Gap</mat-label><input matInput [formControl]="canvasGapControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Auto rows</mat-label><mat-select [formControl]="canvasAutoRowsControl"><mat-option value="fixed">fixed</mat-option><mat-option value="content">content</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>Layout preset</mat-label><mat-select [formControl]="layoutPresetControl"><mat-option value="">Nenhum</mat-option>@for (preset of layoutPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>Theme preset</mat-label><mat-select [formControl]="themePresetControl"><mat-option value="">Padrao</mat-option>@for (preset of themePresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>Shell preset</mat-label><mat-select [formControl]="shellPresetControl"><mat-option value="">Nenhum</mat-option>@for (preset of shellPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field></div></mat-tab>
9364
- <mat-tab label="Grouping"><div class="panel"><div class="head"><span>Grupos</span><button mat-stroked-button type="button" (click)="addGroupingNode()"><mat-icon>add</mat-icon>Adicionar grupo</button></div>@for (group of groupingNodes.controls; track $index) {<div class="card" [formGroup]="group"><div class="head"><span>Grupo {{ $index + 1 }}</span><button mat-icon-button type="button" (click)="removeGroupingNode($index)"><mat-icon>delete</mat-icon></button></div><div class="grid"><mat-form-field appearance="outline"><mat-label>Kind</mat-label><mat-select formControlName="kind"><mat-option value="section">section</mat-option><mat-option value="tabs">tabs</mat-option><mat-option value="hero">hero</mat-option><mat-option value="rail">rail</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>Id</mat-label><input matInput formControlName="id" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Label</mat-label><input matInput formControlName="label" /></mat-form-field>@if (group.controls.kind.value === 'section') {<mat-form-field appearance="outline"><mat-label>Layout</mat-label><mat-select formControlName="layout"><mat-option value="">Padrao</mat-option><mat-option value="stack">stack</mat-option><mat-option value="grid">grid</mat-option><mat-option value="row">row</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'hero') {<mat-form-field appearance="outline"><mat-label>Emphasis</mat-label><mat-select formControlName="emphasis"><mat-option value="">Padrao</mat-option><mat-option value="high">high</mat-option><mat-option value="medium">medium</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'rail') {<mat-form-field appearance="outline"><mat-label>Side</mat-label><mat-select formControlName="side"><mat-option value="left">left</mat-option><mat-option value="right">right</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'tabs') {<mat-form-field appearance="outline" class="wide"><mat-label>Tabs (JSON)</mat-label><textarea matInput rows="4" formControlName="tabsJson"></textarea></mat-form-field>} @else {<mat-form-field appearance="outline" class="wide"><mat-label>Widget keys (virgula)</mat-label><input matInput formControlName="widgetKeysCsv" /></mat-form-field>}</div></div>}</div></mat-tab>
9365
- <mat-tab label="Device Layouts"><div class="panel">@for (device of deviceKeys; track device) {<div class="card"><div>{{ deviceLabels[device] }}</div><div class="grid"><mat-form-field appearance="outline"><mat-label>Columns</mat-label><input matInput type="number" min="1" [formControl]="deviceForms[device].controls.columns" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Row unit</mat-label><input matInput [formControl]="deviceForms[device].controls.rowUnit" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Gap</mat-label><input matInput [formControl]="deviceForms[device].controls.gap" /></mat-form-field><mat-form-field appearance="outline"><mat-label>Auto rows</mat-label><mat-select [formControl]="deviceForms[device].controls.autoRows"><mat-option value="">Padrao</mat-option><mat-option value="fixed">fixed</mat-option><mat-option value="content">content</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline" class="wide"><mat-label>Grouping overrides (JSON)</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.groupingOverrides"></textarea></mat-form-field><mat-form-field appearance="outline" class="wide"><mat-label>Widget overrides (JSON)</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.widgetOverrides"></textarea></mat-form-field></div><div class="hint">Item overrides de canvas existentes sao preservados.</div></div>}</div></mat-tab>
9366
- <mat-tab label="Contexto"><mat-form-field appearance="outline" class="wide"><mat-label>Context (JSON)</mat-label><textarea matInput rows="12" [formControl]="contextControl"></textarea></mat-form-field></mat-tab>
9367
- <mat-tab label="Estado da Pagina"><mat-form-field appearance="outline" class="wide"><mat-label>State (JSON)</mat-label><textarea matInput rows="14" [formControl]="stateControl"></textarea></mat-form-field></mat-tab>
10254
+ <mat-tab [label]="tx('editor.tabs.layout', 'Layout')"><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.cols', 'Columns') }}</mat-label><input matInput type="number" min="1" [formControl]="canvasColumnsControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.rowUnit', 'Row unit') }}</mat-label><input matInput [formControl]="canvasRowUnitControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.gap', 'Gap') }}</mat-label><input matInput [formControl]="canvasGapControl" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.autoRows', 'Auto rows') }}</mat-label><mat-select [formControl]="canvasAutoRowsControl"><mat-option value="fixed">fixed</mat-option><mat-option value="content">content</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.layoutPreset', 'Layout preset') }}</mat-label><mat-select [formControl]="layoutPresetControl"><mat-option value="">{{ tx('editor.layout.none', 'None') }}</mat-option>@for (preset of layoutPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.themePreset', 'Theme preset') }}</mat-label><mat-select [formControl]="themePresetControl"><mat-option value="">{{ tx('editor.layout.layoutDefault', 'Layout default') }}</mat-option>@for (preset of themePresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.shellPreset', 'Shell visual preset') }}</mat-label><mat-select [formControl]="shellPresetControl"><mat-option value="">{{ tx('editor.layout.none', 'None') }}</mat-option>@for (preset of shellPresetEntries; track preset.id) {<mat-option [value]="preset.id">{{ preset.label }}</mat-option>}</mat-select></mat-form-field></div>@if (selectedLayoutPresetEntry; as preset) {<div class="preset-preview"><div class="preset-preview__head"><div><span class="eyebrow">{{ tx('editor.preview.layoutEyebrow', 'Layout template') }} · {{ preset.category }}</span><strong>{{ preset.label }}</strong></div><span>{{ layoutPresetSummary(preset) }}</span></div><p>{{ preset.description || tx('editor.preview.layoutFallbackDescription', 'Page organization preset.') }}</p><div class="preset-preview__chips"><span>{{ slotsSummary(preset) }}</span><span>{{ requiredSlotsSummary(preset) }}</span><span>{{ devicePolicySummary(preset) }}</span></div>@if (recommendedThemePresetEntry; as theme) {<div class="preset-preview__recommendation"><div><span class="eyebrow">{{ tx('editor.preview.inheritedTheme', 'Inherited theme') }}</span><strong>{{ theme.label }}</strong><span>{{ inheritedThemeHelp(theme) }}</span></div><button mat-stroked-button type="button" [disabled]="themePresetControl.value === theme.id" (click)="pinRecommendedThemePreset()">{{ tx('editor.preview.pinTheme', 'Pin theme') }}</button></div>}</div>} @if (selectedThemePresetEntry; as theme) {<div class="preset-preview preset-preview--theme"><div class="preset-preview__head"><div><span class="eyebrow">{{ tx('editor.preview.explicitTheme', 'Explicit theme') }}</span><strong>{{ theme.label }}</strong></div><span>{{ theme.density }} · {{ theme.motion }}</span></div><p>{{ theme.description || tx('editor.preview.themeFallbackDescription', 'Page visual preset.') }}</p><div class="preset-preview__chips"><span>{{ tx('editor.preview.shellChip', 'Shell: {{value}}').replace('{{value}}', theme.shellPreset) }}</span><span>{{ tx('editor.preview.chartsChip', 'Charts: {{value}}').replace('{{value}}', theme.chartThemePreset) }}</span></div></div>}</mat-tab>
10255
+ <mat-tab [label]="tx('editor.tabs.grouping', 'Grouping')"><div class="panel"><div class="head"><span>{{ tx('editor.grouping.title', 'Grouping') }}</span><button mat-stroked-button type="button" (click)="addGroupingNode()"><mat-icon>add</mat-icon>{{ tx('editor.grouping.add', 'Add group') }}</button></div>@for (group of groupingNodes.controls; track $index) {<div class="card" [formGroup]="group"><div class="head"><span>{{ groupLabel($index) }}</span><button mat-icon-button type="button" [attr.aria-label]="tx('editor.grouping.removeAria', 'Remove group')" (click)="removeGroupingNode($index)"><mat-icon>delete</mat-icon></button></div><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.kind', 'Kind') }}</mat-label><mat-select formControlName="kind"><mat-option value="section">section</mat-option><mat-option value="tabs">tabs</mat-option><mat-option value="hero">hero</mat-option><mat-option value="rail">rail</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.id', 'Id') }}</mat-label><input matInput formControlName="id" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.label', 'Label') }}</mat-label><input matInput formControlName="label" /></mat-form-field>@if (group.controls.kind.value === 'section') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.layout', 'Layout') }}</mat-label><mat-select formControlName="layout"><mat-option value="">{{ tx('editor.grouping.layoutDefault', 'Default') }}</mat-option><mat-option value="stack">stack</mat-option><mat-option value="grid">grid</mat-option><mat-option value="row">row</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'hero') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.emphasis', 'Emphasis') }}</mat-label><mat-select formControlName="emphasis"><mat-option value="">{{ tx('editor.grouping.layoutDefault', 'Default') }}</mat-option><mat-option value="high">high</mat-option><mat-option value="medium">medium</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'rail') {<mat-form-field appearance="outline"><mat-label>{{ tx('editor.grouping.side', 'Side') }}</mat-label><mat-select formControlName="side"><mat-option value="left">left</mat-option><mat-option value="right">right</mat-option></mat-select></mat-form-field>}@if (group.controls.kind.value === 'tabs') {<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.grouping.tabsJson', 'Tabs (JSON)') }}</mat-label><textarea matInput rows="4" formControlName="tabsJson"></textarea></mat-form-field>} @else {<mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.grouping.widgetKeysCsv', 'Widget keys (comma-separated)') }}</mat-label><input matInput formControlName="widgetKeysCsv" /></mat-form-field>}</div></div>}</div></mat-tab>
10256
+ <mat-tab [label]="tx('editor.tabs.devices', 'Device Layouts')"><div class="panel">@for (device of deviceKeys; track device) {<div class="card"><div>{{ deviceLabels[device] }}</div><div class="grid"><mat-form-field appearance="outline"><mat-label>{{ tx('editor.devices.columns', 'Columns') }}</mat-label><input matInput type="number" min="1" [formControl]="deviceForms[device].controls.columns" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.rowUnit', 'Row unit') }}</mat-label><input matInput [formControl]="deviceForms[device].controls.rowUnit" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.devices.gap', 'Gap') }}</mat-label><input matInput [formControl]="deviceForms[device].controls.gap" /></mat-form-field><mat-form-field appearance="outline"><mat-label>{{ tx('editor.layout.autoRows', 'Auto rows') }}</mat-label><mat-select [formControl]="deviceForms[device].controls.autoRows"><mat-option value="">{{ tx('editor.devices.orientationDefault', 'Default') }}</mat-option><mat-option value="fixed">fixed</mat-option><mat-option value="content">content</mat-option></mat-select></mat-form-field><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.devices.groupingOverridesJson', 'Grouping overrides (JSON)') }}</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.groupingOverrides"></textarea></mat-form-field><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.devices.widgetOverridesJson', 'Widget overrides (JSON)') }}</mat-label><textarea matInput rows="4" [formControl]="deviceForms[device].controls.widgetOverrides"></textarea></mat-form-field></div><div class="hint">{{ tx('editor.preview.deviceCanvasHint', 'Existing canvas item overrides are preserved.') }}</div></div>}</div></mat-tab>
10257
+ <mat-tab [label]="tx('editor.tabs.context', 'Context')"><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.context.json', 'Context (JSON)') }}</mat-label><textarea matInput rows="12" [formControl]="contextControl"></textarea></mat-form-field></mat-tab>
10258
+ <mat-tab [label]="tx('editor.tabs.state', 'Page State')"><mat-form-field appearance="outline" class="wide"><mat-label>{{ tx('editor.state.valuesJson', 'Primary values (JSON)') }}</mat-label><textarea matInput rows="14" [formControl]="stateControl"></textarea></mat-form-field></mat-tab>
9368
10259
  </mat-tab-group>
9369
10260
  </div>
9370
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".editor,.panel{display:grid;gap:16px;color:var(--md-sys-color-on-surface, currentColor)}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"] }]
10261
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".editor,.panel{display:grid;gap:16px;color:var(--md-sys-color-on-surface, currentColor)}.head,.summary{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.summary{color:var(--md-sys-color-on-surface-variant, currentColor)}.grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.card{display:grid;gap:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:var(--md-sys-color-surface-container-low, var(--md-sys-color-surface-container, transparent));color:var(--md-sys-color-on-surface, currentColor)}.wide{grid-column:1 / -1}.hint{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px}.preset-preview{display:grid;gap:12px;margin-top:12px;padding:16px;border:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 18%, transparent));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, transparent) 88%,var(--md-sys-color-primary-container, transparent) 12%)}.preset-preview--theme{background:var(--md-sys-color-surface-container-low, transparent)}.preset-preview__head,.preset-preview__recommendation{display:flex;justify-content:space-between;align-items:center;gap:16px}.preset-preview__head>div,.preset-preview__recommendation>div{display:grid;gap:4px;min-width:0}.preset-preview p{margin:0;color:var(--md-sys-color-on-surface-variant, currentColor);line-height:1.45}.preset-preview__chips{display:flex;flex-wrap:wrap;gap:8px}.preset-preview__chips span{padding:5px 9px;border-radius:999px;background:var(--md-sys-color-surface-container, color-mix(in srgb, currentColor 8%, transparent));color:var(--md-sys-color-on-surface-variant, currentColor);font-size:12px;line-height:1.3}.preset-preview__recommendation{padding-top:12px;border-top:1px solid var(--md-sys-color-outline-variant, color-mix(in srgb, currentColor 14%, transparent))}.preset-preview__recommendation span:last-child{color:var(--md-sys-color-on-surface-variant, currentColor);font-size:13px;line-height:1.35}.eyebrow{color:var(--md-sys-color-primary, currentColor);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}:host ::ng-deep .mat-mdc-tab-body-content{padding-top:12px;box-sizing:border-box}\n"] }]
9371
10262
  }], ctorParameters: () => [], propDecorators: { page: [{
9372
10263
  type: Input
9373
10264
  }], layout: [{
@@ -12393,6 +13284,7 @@ const pageSchema = {
12393
13284
  properties: {
12394
13285
  title: { type: 'string' },
12395
13286
  layoutPreset: { type: 'string' },
13287
+ themePreset: { type: 'string' },
12396
13288
  context: { type: 'object' },
12397
13289
  metadata: { type: 'object' },
12398
13290
  },
@@ -12546,14 +13438,14 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
12546
13438
  inputSchema: pageSchema,
12547
13439
  effects: [{ kind: 'compile-domain-patch', handler: 'page-builder-page-configure', handlerContract: {
12548
13440
  reads: ['WidgetPageDefinition', 'DynamicPageConfigEditorComponent', 'SettingsPanelBridge'],
12549
- writes: ['page.title', 'page.layoutPreset', 'page.context', 'page.metadata'],
13441
+ writes: ['page.title', 'page.layoutPreset', 'page.themePreset', 'page.context', 'page.metadata'],
12550
13442
  identityKeys: ['pageIdentity.componentId', 'pageIdentity.scope'],
12551
13443
  inputSchema: pageSchema,
12552
13444
  failureModes: ['page-not-loaded', 'context-not-json', 'settings-panel-bridge-missing'],
12553
13445
  description: 'Updates root page metadata while preserving the renderable WidgetPageDefinition shape.',
12554
13446
  } }],
12555
13447
  validators: ['widget-page-definition-valid', 'no-legacy-grid-page-definition', 'page-context-json-valid', 'settings-panel-round-trip-valid'],
12556
- affectedPaths: ['title', 'layoutPreset', 'context', 'metadata'],
13448
+ affectedPaths: ['title', 'layoutPreset', 'themePreset', 'context', 'metadata'],
12557
13449
  submissionImpact: 'config-only',
12558
13450
  preconditions: ['page-loaded'],
12559
13451
  },
@@ -12989,7 +13881,7 @@ function compileUiCompositionPlan(plan) {
12989
13881
  page: {
12990
13882
  layoutPreset: plan.layoutPreset,
12991
13883
  layoutPresetOptions: clone(plan.layoutPresetOptions),
12992
- canvas: clone(plan.canvas),
13884
+ canvas: resolveCanvas(plan),
12993
13885
  deviceLayouts: clone(plan.deviceLayouts),
12994
13886
  grouping: clone(plan.grouping),
12995
13887
  slotAssignments: clone(plan.slotAssignments),
@@ -13004,6 +13896,88 @@ function compileUiCompositionPlan(plan) {
13004
13896
  diagnostics: [],
13005
13897
  };
13006
13898
  }
13899
+ function resolveCanvas(plan) {
13900
+ if (plan.canvas) {
13901
+ return clone(plan.canvas);
13902
+ }
13903
+ if (!plan.widgets?.length) {
13904
+ return undefined;
13905
+ }
13906
+ if (isMasterDetailPlan(plan)) {
13907
+ return masterDetailCanvas(plan.widgets);
13908
+ }
13909
+ return stackedCanvas(plan.widgets);
13910
+ }
13911
+ function isMasterDetailPlan(plan) {
13912
+ const preset = (plan.layoutPreset ?? '').toLocaleLowerCase('en-US');
13913
+ const hasPreset = preset.includes('master-detail') || preset.includes('master detail');
13914
+ const hasSemanticRoles = plan.widgets.some((widget) => widget.role === 'master')
13915
+ && plan.widgets.some((widget) => widget.role === 'detail');
13916
+ return hasPreset || hasSemanticRoles;
13917
+ }
13918
+ function masterDetailCanvas(widgets) {
13919
+ const master = widgets.find((widget) => widget.role === 'master') ?? widgets[0];
13920
+ const details = widgets.filter((widget) => widget.key !== master.key);
13921
+ const items = {};
13922
+ let row = 1;
13923
+ items[master.key] = {
13924
+ col: 1,
13925
+ row,
13926
+ colSpan: 12,
13927
+ rowSpan: preferredRowSpan(master),
13928
+ };
13929
+ row += items[master.key].rowSpan;
13930
+ for (const widget of details) {
13931
+ const rowSpan = preferredRowSpan(widget);
13932
+ items[widget.key] = {
13933
+ col: 1,
13934
+ row,
13935
+ colSpan: 12,
13936
+ rowSpan,
13937
+ };
13938
+ row += rowSpan;
13939
+ }
13940
+ return defaultCanvas(items);
13941
+ }
13942
+ function stackedCanvas(widgets) {
13943
+ const items = {};
13944
+ let row = 1;
13945
+ for (const widget of widgets) {
13946
+ const rowSpan = preferredRowSpan(widget);
13947
+ items[widget.key] = {
13948
+ col: 1,
13949
+ row,
13950
+ colSpan: 12,
13951
+ rowSpan,
13952
+ };
13953
+ row += rowSpan;
13954
+ }
13955
+ return defaultCanvas(items);
13956
+ }
13957
+ function defaultCanvas(items) {
13958
+ return {
13959
+ mode: 'grid',
13960
+ columns: 12,
13961
+ rowUnit: '80px',
13962
+ gap: '16px',
13963
+ autoRows: 'fixed',
13964
+ items,
13965
+ };
13966
+ }
13967
+ function preferredRowSpan(widget) {
13968
+ const componentId = widget.componentId.toLocaleLowerCase('en-US');
13969
+ if (componentId.includes('dynamic-form') || widget.role === 'detail')
13970
+ return 8;
13971
+ if (componentId.includes('table') || componentId.includes('list'))
13972
+ return 7;
13973
+ if (componentId.includes('chart'))
13974
+ return 5;
13975
+ if (componentId.includes('kpi') || componentId.includes('filter'))
13976
+ return 2;
13977
+ if (componentId.includes('rich-content'))
13978
+ return 3;
13979
+ return 4;
13980
+ }
13007
13981
  function validateUiCompositionPlan(plan) {
13008
13982
  const diagnostics = [];
13009
13983
  const widgetKeys = new Set();
@@ -14155,6 +15129,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
14155
15129
  diagnostics: this.buildTurnDiagnostics(intentResolution, preview),
14156
15130
  };
14157
15131
  }
15132
+ this.normalizeDashboardPreviewPresentation(intentResolution, preview);
14158
15133
  const applied = await this.context.applyLocalPreview(preview);
14159
15134
  if (!applied.success) {
14160
15135
  const message = applied.error || this.context.tx('agentic.errors.applyLocal', 'Preview could not be applied.');
@@ -14175,7 +15150,9 @@ class PageBuilderAgenticAuthoringTurnFlow {
14175
15150
  state: 'review',
14176
15151
  phase: 'review',
14177
15152
  assistantMessage: status,
14178
- quickReplies: this.reviewQuickReplies([], intentResolution, preview),
15153
+ quickReplies: reviewCanApply
15154
+ ? this.reviewQuickReplies([], intentResolution, preview)
15155
+ : this.governedBlockedReviewQuickReplies([], intentResolution, preview),
14179
15156
  canApply: reviewCanApply,
14180
15157
  statusText: this.reviewStatusText(status, reviewCanApply),
14181
15158
  errorText: '',
@@ -14316,6 +15293,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
14316
15293
  return this.completeExecutableStreamPreview(request, prompt, intentResolution, undefined);
14317
15294
  }
14318
15295
  async applyDashboardRepairPreview(preview, intentResolution) {
15296
+ this.normalizeDashboardPreviewPresentation(intentResolution, preview);
14319
15297
  const applied = await this.context.applyLocalPreview(preview);
14320
15298
  if (!applied.success) {
14321
15299
  const message = applied.error || this.context.tx('agentic.errors.applyLocal', 'Preview could not be applied.');
@@ -14413,16 +15391,16 @@ class PageBuilderAgenticAuthoringTurnFlow {
14413
15391
  }
14414
15392
  dashboardRepairBasePage(contextHints) {
14415
15393
  const materializedPage = this.cloneJsonObject(this.toJsonObject(contextHints['materializedPage']));
14416
- if (this.hasDashboardSnapshotWidgets(materializedPage)) {
15394
+ if (this.hasPageWidgets(materializedPage)) {
14417
15395
  return materializedPage;
14418
15396
  }
14419
15397
  const currentPage = this.cloneJsonObject(this.toJsonObject(this.context.currentPage()));
14420
- if (this.hasDashboardSnapshotWidgets(currentPage)) {
15398
+ if (this.hasPageWidgets(currentPage)) {
14421
15399
  return currentPage;
14422
15400
  }
14423
15401
  const plan = this.toJsonObject(contextHints['uiCompositionPlan']);
14424
15402
  const pageFromPlan = this.pageFromUiCompositionPlan(plan);
14425
- return this.hasDashboardSnapshotWidgets(pageFromPlan) ? pageFromPlan : null;
15403
+ return this.hasPageWidgets(pageFromPlan) ? pageFromPlan : null;
14426
15404
  }
14427
15405
  pageFromUiCompositionPlan(plan) {
14428
15406
  if (!plan) {
@@ -15312,7 +16290,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
15312
16290
  return {
15313
16291
  state: 'processing',
15314
16292
  phase: this.phaseForStreamPayload({ ...payload, phase: 'intent.resolve' }),
15315
- assistantMessage,
16293
+ assistantMessage: undefined,
15316
16294
  canApply: false,
15317
16295
  statusText: assistantMessage ?? this.statusForStreamPayload(payload),
15318
16296
  errorText: '',
@@ -15472,13 +16450,15 @@ class PageBuilderAgenticAuthoringTurnFlow {
15472
16450
  diagnostics: this.buildTurnDiagnostics(intentResolution, preview),
15473
16451
  };
15474
16452
  }
15475
- const status = this.decorateDashboardReviewStatus(assistantMessage || this.context.describePreviewStatus(preview), intentResolution, preview);
16453
+ const status = this.decorateDashboardReviewStatus(this.context.describePreviewStatus(preview), intentResolution, preview);
15476
16454
  const reviewCanApply = this.reviewCanApply(intentResolution, preview);
15477
16455
  return {
15478
16456
  state: 'review',
15479
16457
  phase: 'review',
15480
16458
  assistantMessage: status,
15481
- quickReplies: this.reviewQuickReplies(quickReplies, intentResolution, preview),
16459
+ quickReplies: reviewCanApply
16460
+ ? this.reviewQuickReplies(quickReplies, intentResolution, preview)
16461
+ : this.governedBlockedReviewQuickReplies(quickReplies, intentResolution, preview),
15482
16462
  canApply: reviewCanApply,
15483
16463
  statusText: this.reviewStatusText(status, reviewCanApply),
15484
16464
  errorText: '',
@@ -15533,6 +16513,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
15533
16513
  diagnostics: this.buildTurnDiagnostics(intentResolution, preview),
15534
16514
  };
15535
16515
  }
16516
+ this.normalizeDashboardPreviewPresentation(intentResolution, preview);
15536
16517
  const applied = await this.context.applyLocalPreview(preview);
15537
16518
  if (!applied.success) {
15538
16519
  const message = applied.error || this.context.tx('agentic.errors.applyLocal', 'Preview could not be applied.');
@@ -15553,7 +16534,9 @@ class PageBuilderAgenticAuthoringTurnFlow {
15553
16534
  state: 'review',
15554
16535
  phase: 'review',
15555
16536
  assistantMessage: status,
15556
- quickReplies: this.reviewQuickReplies([], intentResolution, preview),
16537
+ quickReplies: reviewCanApply
16538
+ ? this.reviewQuickReplies([], intentResolution, preview)
16539
+ : this.governedBlockedReviewQuickReplies([], intentResolution, preview),
15557
16540
  canApply: reviewCanApply,
15558
16541
  statusText: this.reviewStatusText(status, reviewCanApply),
15559
16542
  errorText: '',
@@ -15636,7 +16619,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
15636
16619
  return diagnostics;
15637
16620
  }
15638
16621
  buildDashboardAuthoringDiagnostics(intentResolution, preview) {
15639
- if (intentResolution.artifactKind !== 'dashboard' && !preview?.uiCompositionPlan) {
16622
+ if (!this.isDashboardQualityPreview(intentResolution, preview)) {
15640
16623
  return null;
15641
16624
  }
15642
16625
  const plan = this.toJsonObject(preview?.uiCompositionPlan);
@@ -15682,6 +16665,139 @@ class PageBuilderAgenticAuthoringTurnFlow {
15682
16665
  validation,
15683
16666
  };
15684
16667
  }
16668
+ normalizeDashboardPreviewPresentation(intentResolution, preview) {
16669
+ if (!this.isDashboardQualityPreview(intentResolution, preview)) {
16670
+ return;
16671
+ }
16672
+ const patch = this.toJsonObject(preview.compiledFormPatch)?.['patch'];
16673
+ const page = this.toJsonObject(this.toJsonObject(patch)?.['page']);
16674
+ if (page) {
16675
+ this.normalizeDashboardPagePresentation(intentResolution, page);
16676
+ }
16677
+ const plan = this.toJsonObject(preview.uiCompositionPlan);
16678
+ if (plan) {
16679
+ this.normalizeDashboardPagePresentation(intentResolution, plan);
16680
+ for (const widget of this.arrayFromUnknown(plan['widgets'])) {
16681
+ const normalizedWidget = this.toJsonObject(widget);
16682
+ if (normalizedWidget) {
16683
+ this.normalizeDashboardWidgetPresentation(intentResolution, normalizedWidget);
16684
+ }
16685
+ }
16686
+ }
16687
+ }
16688
+ normalizeDashboardPagePresentation(intentResolution, page) {
16689
+ for (const widget of this.dashboardPageWidgets(page)) {
16690
+ this.normalizeDashboardWidgetPresentation(intentResolution, widget);
16691
+ }
16692
+ }
16693
+ normalizeDashboardWidgetPresentation(intentResolution, widget) {
16694
+ const resourcePath = this.dashboardWidgetResourcePath(widget)
16695
+ ?? this.intentResourcePath(intentResolution);
16696
+ const businessTitle = this.dashboardBusinessTitle(resourcePath);
16697
+ if (!businessTitle) {
16698
+ return;
16699
+ }
16700
+ const shell = this.toJsonObject(widget['shell']);
16701
+ if (shell) {
16702
+ if (this.isTechnicalDashboardResourceTitle(this.readString(shell, 'title'), resourcePath)) {
16703
+ shell['title'] = businessTitle;
16704
+ }
16705
+ const subtitle = this.readString(shell, 'subtitle');
16706
+ if (subtitle && this.containsTechnicalDashboardResourceLabel(subtitle, resourcePath)) {
16707
+ shell['subtitle'] = this.dashboardBusinessSubtitle(businessTitle);
16708
+ }
16709
+ widget['shell'] = shell;
16710
+ }
16711
+ const inputs = this.dashboardWidgetInputs(widget);
16712
+ let inputsChanged = false;
16713
+ if (this.isTechnicalDashboardResourceTitle(this.readString(inputs, 'title'), resourcePath)) {
16714
+ inputs['title'] = businessTitle;
16715
+ inputsChanged = true;
16716
+ }
16717
+ const inputSubtitle = this.readString(inputs, 'subtitle');
16718
+ if (inputSubtitle && this.containsTechnicalDashboardResourceLabel(inputSubtitle, resourcePath)) {
16719
+ inputs['subtitle'] = this.dashboardBusinessSubtitle(businessTitle);
16720
+ inputsChanged = true;
16721
+ }
16722
+ if (inputsChanged) {
16723
+ this.setDashboardWidgetInputs(widget, inputs);
16724
+ }
16725
+ }
16726
+ dashboardWidgetResourcePath(widget) {
16727
+ const inputs = this.dashboardWidgetInputs(widget);
16728
+ const source = this.toJsonObject(inputs['source']);
16729
+ return this.readString(inputs, 'resourcePath')
16730
+ ?? this.readString(source ?? {}, 'resource')
16731
+ ?? this.readString(source ?? {}, 'resourcePath')
16732
+ ?? null;
16733
+ }
16734
+ intentResourcePath(intentResolution) {
16735
+ const selectedCandidate = this.toJsonObject(intentResolution.selectedCandidate);
16736
+ const target = this.toJsonObject(intentResolution.target);
16737
+ const contextHints = this.toJsonObject(intentResolution.contextHints);
16738
+ return this.readString(selectedCandidate ?? {}, 'resourcePath')
16739
+ ?? this.readString(target ?? {}, 'resourcePath')
16740
+ ?? this.readString(contextHints ?? {}, 'resourcePath')
16741
+ ?? null;
16742
+ }
16743
+ isTechnicalDashboardResourceTitle(value, resourcePath) {
16744
+ const normalized = this.normalizeText(value ?? '');
16745
+ if (!normalized) {
16746
+ return false;
16747
+ }
16748
+ if (normalized.includes('/api/')) {
16749
+ return true;
16750
+ }
16751
+ const resourceLabel = this.normalizeText(this.resourceLabelFromPath(resourcePath));
16752
+ if (resourceLabel && normalized === resourceLabel) {
16753
+ return true;
16754
+ }
16755
+ return /\b(vw|view|analytics|analytic|indicadores)\b/.test(normalized);
16756
+ }
16757
+ containsTechnicalDashboardResourceLabel(value, resourcePath) {
16758
+ const normalized = this.normalizeText(value);
16759
+ if (normalized.includes('/api/') || /\b(vw|view)\b/.test(normalized)) {
16760
+ return true;
16761
+ }
16762
+ const resourceLabel = this.normalizeText(this.resourceLabelFromPath(resourcePath));
16763
+ return !!resourceLabel && normalized.includes(resourceLabel);
16764
+ }
16765
+ dashboardBusinessTitle(resourcePath) {
16766
+ const subject = this.dashboardBusinessSubject(resourcePath);
16767
+ return subject ? `Dashboard de ${subject}` : null;
16768
+ }
16769
+ dashboardBusinessSubtitle(title) {
16770
+ return `Visao executiva orientada a decisao para ${title.replace(/^Dashboard de\s+/i, '')}.`;
16771
+ }
16772
+ dashboardBusinessSubject(resourcePath) {
16773
+ const label = this.resourceLabelFromPath(resourcePath);
16774
+ if (!label) {
16775
+ return null;
16776
+ }
16777
+ const words = label
16778
+ .replace(/\b(vw|view|analytics|analytic|indicadores|dashboard|resource)\b/gi, ' ')
16779
+ .replace(/[_-]+/g, ' ')
16780
+ .replace(/\s+/g, ' ')
16781
+ .trim()
16782
+ .toLowerCase();
16783
+ if (!words) {
16784
+ return null;
16785
+ }
16786
+ return words;
16787
+ }
16788
+ resourceLabelFromPath(resourcePath) {
16789
+ if (!resourcePath) {
16790
+ return '';
16791
+ }
16792
+ return resourcePath
16793
+ .split('?')[0]
16794
+ .split('/')
16795
+ .filter(Boolean)
16796
+ .pop()
16797
+ ?.replace(/[_-]+/g, ' ')
16798
+ .replace(/\s+/g, ' ')
16799
+ .trim() ?? '';
16800
+ }
15685
16801
  extractDashboardPlannerDiagnostics(plan) {
15686
16802
  const diagnostics = this.toJsonObject(plan?.['diagnostics']);
15687
16803
  if (!diagnostics) {
@@ -16050,7 +17166,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
16050
17166
  return Array.isArray(value) ? value : [];
16051
17167
  }
16052
17168
  decorateDashboardReviewStatus(status, intentResolution, preview) {
16053
- if (!preview.uiCompositionPlan) {
17169
+ if (!this.isDashboardQualityPreview(intentResolution, preview)) {
16054
17170
  return status;
16055
17171
  }
16056
17172
  const diagnostics = this.buildDashboardAuthoringDiagnostics(intentResolution, preview);
@@ -16136,9 +17252,12 @@ class PageBuilderAgenticAuthoringTurnFlow {
16136
17252
  ];
16137
17253
  }
16138
17254
  dashboardQualityQuickReplies(intentResolution, preview) {
17255
+ if (!this.isDashboardQualityPreview(intentResolution, preview)) {
17256
+ return [];
17257
+ }
16139
17258
  const patch = this.toJsonObject(preview.compiledFormPatch)?.['patch'];
16140
17259
  const materializedPage = this.toJsonObject(this.toJsonObject(patch)?.['page']);
16141
- if (!preview.uiCompositionPlan && !this.hasDashboardSnapshotWidgets(materializedPage)) {
17260
+ if (!preview.uiCompositionPlan && !this.hasPageWidgets(materializedPage)) {
16142
17261
  return [];
16143
17262
  }
16144
17263
  const diagnostics = this.buildDashboardAuthoringDiagnostics(intentResolution, preview);
@@ -16236,17 +17355,39 @@ class PageBuilderAgenticAuthoringTurnFlow {
16236
17355
  }
16237
17356
  return replies.slice(0, 4);
16238
17357
  }
17358
+ isDashboardQualityPreview(intentResolution, preview) {
17359
+ if (intentResolution.artifactKind === 'dashboard') {
17360
+ return true;
17361
+ }
17362
+ const patch = this.toJsonObject(preview?.compiledFormPatch)?.['patch'];
17363
+ const materializedPage = this.toJsonObject(this.toJsonObject(patch)?.['page']);
17364
+ return this.hasDashboardQualityWidgets(materializedPage);
17365
+ }
16239
17366
  dashboardRepairSnapshot(preview) {
16240
17367
  const patch = this.toJsonObject(preview.compiledFormPatch)?.['patch'];
16241
17368
  const materializedPage = this.toJsonObject(this.toJsonObject(patch)?.['page']);
16242
- if (this.hasDashboardSnapshotWidgets(materializedPage)) {
17369
+ if (this.hasDashboardQualityWidgets(materializedPage)) {
16243
17370
  return { materializedPage };
16244
17371
  }
16245
17372
  const uiCompositionPlan = this.toJsonObject(preview.uiCompositionPlan);
16246
17373
  return uiCompositionPlan ? { uiCompositionPlan } : {};
16247
17374
  }
16248
- hasDashboardSnapshotWidgets(page) {
16249
- return Array.isArray(page?.['widgets']) && page?.['widgets'].length > 0;
17375
+ hasDashboardQualityWidgets(page) {
17376
+ const widgets = Array.isArray(page?.['widgets']) ? page?.['widgets'] : [];
17377
+ return widgets.some((widget) => {
17378
+ const item = this.toJsonObject(widget);
17379
+ const componentId = this.readString(item ?? {}, 'componentId')
17380
+ || this.readString(item ?? {}, 'type')
17381
+ || this.readString(this.toJsonObject(item?.['definition']) ?? {}, 'componentId')
17382
+ || this.readString(this.toJsonObject(item?.['definition']) ?? {}, 'type');
17383
+ return componentId === 'praxis-chart'
17384
+ || componentId === 'praxis-kpi'
17385
+ || componentId === 'praxis-filter'
17386
+ || componentId === 'praxis-dashboard';
17387
+ });
17388
+ }
17389
+ hasPageWidgets(page) {
17390
+ return Array.isArray(page?.['widgets']) && page.widgets.length > 0;
16250
17391
  }
16251
17392
  toDashboardQualityRepairContext(diagnostics) {
16252
17393
  if (!diagnostics) {
@@ -16344,7 +17485,7 @@ class PageBuilderAgenticAuthoringTurnFlow {
16344
17485
  const dashboardQuality = this.toDashboardQualityRepairContext(diagnostics);
16345
17486
  return this.dashboardQualityQuickReply({
16346
17487
  id: 'dashboard-quality-refine',
16347
- label: this.context.tx('agentic.dashboardQuality.quickReply.refine', 'Refinar painel'),
17488
+ label: this.context.tx('agentic.dashboardQuality.quickReply.refine', 'Pré-visualizar ajuste'),
16348
17489
  prompt: this.context.tx('agentic.dashboardQuality.prompt.refine', 'Ajuste o painel para resolver os pontos pendentes e manter apenas decisões compatíveis com os dados confirmados.'),
16349
17490
  icon: 'auto_fix_high',
16350
17491
  changeKind: 'refine_dashboard_quality',
@@ -16419,7 +17560,10 @@ class PageBuilderAgenticAuthoringTurnFlow {
16419
17560
  status = this.context.tx('agentic.status.streamFirstEventReceived', 'Criação iniciada.');
16420
17561
  break;
16421
17562
  default:
16422
- status = this.readString(payload, 'summary') || this.readString(payload, 'message');
17563
+ status = this.readDisplayString(payload, 'statusText')
17564
+ || this.readDisplayString(payload, 'message')
17565
+ || this.readDisplayString(payload, 'label')
17566
+ || this.readDisplayString(payload, 'summary');
16423
17567
  }
16424
17568
  return this.decorateBackendProcessingProgressStatus(payload, status ?? '');
16425
17569
  }
@@ -17763,12 +18907,17 @@ class PageBuilderAgenticAuthoringTurnFlow {
17763
18907
  const base = this.toJsonObject(request.action?.contextHints)
17764
18908
  ?? this.toJsonObject(request.contextHints);
17765
18909
  const normalizedBase = this.normalizeAmbientDomainCatalogContextHints(base);
18910
+ const scopedBase = withAuthoringScopePolicyContextHints(normalizedBase, {
18911
+ componentId: this.context.targetComponentId,
18912
+ componentType: 'page-builder',
18913
+ componentLabel: 'page builder',
18914
+ });
17766
18915
  const includeLlmDiagnostics = this.context.includeLlmDiagnostics?.() === true;
17767
18916
  if (!includeLlmDiagnostics) {
17768
- return normalizedBase ?? undefined;
18917
+ return scopedBase;
17769
18918
  }
17770
18919
  return {
17771
- ...(normalizedBase ?? {}),
18920
+ ...scopedBase,
17772
18921
  includeLlmDiagnostics: true,
17773
18922
  };
17774
18923
  }
@@ -17844,6 +18993,14 @@ class PageBuilderAgenticAuthoringTurnFlow {
17844
18993
  const raw = value?.[key];
17845
18994
  return typeof raw === 'string' ? raw.trim() : '';
17846
18995
  }
18996
+ readDisplayString(value, key) {
18997
+ const text = this.readString(value, key);
18998
+ return this.isRedactedDisplayText(text) ? '' : text;
18999
+ }
19000
+ isRedactedDisplayText(value) {
19001
+ const normalized = value.trim().toLocaleLowerCase();
19002
+ return normalized === 'redacted' || normalized === '[redacted]';
19003
+ }
17847
19004
  readNumber(value, key) {
17848
19005
  const raw = value?.[key];
17849
19006
  return typeof raw === 'number' && Number.isFinite(raw) ? raw : null;
@@ -18039,6 +19196,8 @@ class DynamicPageBuilderComponent {
18039
19196
  savedPageDeleteRequested = new EventEmitter();
18040
19197
  currentPage = signal({ widgets: [] }, ...(ngDevMode ? [{ debugName: "currentPage" }] : /* istanbul ignore next */ []));
18041
19198
  hasPageWidgets = computed(() => (this.currentPage().widgets || []).length > 0, ...(ngDevMode ? [{ debugName: "hasPageWidgets" }] : /* istanbul ignore next */ []));
19199
+ hasRecommendedConnectionSuggestion = computed(() => deriveConnectionEditorSuggestions(deriveConnectionEditorGraph(this.currentPage()), 5)
19200
+ .some((suggestion) => suggestion.reason === 'row-selection-to-id'), ...(ngDevMode ? [{ debugName: "hasRecommendedConnectionSuggestion" }] : /* istanbul ignore next */ []));
18042
19201
  premiumReadinessIssues = computed(() => this.evaluatePremiumReadiness(this.currentPage()).slice(0, 3), ...(ngDevMode ? [{ debugName: "premiumReadinessIssues" }] : /* istanbul ignore next */ []));
18043
19202
  connectionsViewerOpen = signal(false, ...(ngDevMode ? [{ debugName: "connectionsViewerOpen" }] : /* istanbul ignore next */ []));
18044
19203
  agenticAuthoringOpen = signal(false, ...(ngDevMode ? [{ debugName: "agenticAuthoringOpen" }] : /* istanbul ignore next */ []));
@@ -18081,6 +19240,7 @@ class DynamicPageBuilderComponent {
18081
19240
  margin: 24,
18082
19241
  }), ...(ngDevMode ? [{ debugName: "agenticAuthoringPanelLayout" }] : /* istanbul ignore next */ []));
18083
19242
  previewMode = false;
19243
+ runtimePreviewPageCache;
18084
19244
  agenticComponentCapabilities;
18085
19245
  agenticComponentCapabilitiesPromise;
18086
19246
  agenticTurnController;
@@ -18118,6 +19278,18 @@ class DynamicPageBuilderComponent {
18118
19278
  isPreviewMode() {
18119
19279
  return this.previewMode;
18120
19280
  }
19281
+ runtimePage() {
19282
+ const page = this.currentPage();
19283
+ if (!this.previewMode) {
19284
+ return page;
19285
+ }
19286
+ if (this.runtimePreviewPageCache?.source === page) {
19287
+ return this.runtimePreviewPageCache.value;
19288
+ }
19289
+ const value = this.toPresentationRuntimePage(page);
19290
+ this.runtimePreviewPageCache = { source: page, value };
19291
+ return value;
19292
+ }
18121
19293
  builderModeLabel() {
18122
19294
  if (this.previewMode) {
18123
19295
  return this.tx('builderMode.preview', 'Prévia');
@@ -18173,11 +19345,7 @@ class DynamicPageBuilderComponent {
18173
19345
  togglePreview() {
18174
19346
  this.previewMode = !this.previewMode;
18175
19347
  if (this.previewMode) {
18176
- this.connectionsViewerOpen.set(false);
18177
- this.agenticAuthoringLlmDiagnostics.set(null);
18178
- this.sharedRuleCockpitCollapsed.set(true);
18179
- this.projectKnowledgeCockpitCollapsed.set(true);
18180
- this.selectedWidgetKey.set(null);
19348
+ this.enterPreviewMode();
18181
19349
  }
18182
19350
  }
18183
19351
  toggleAgenticAuthoringLlmDiagnostics() {
@@ -18196,6 +19364,9 @@ class DynamicPageBuilderComponent {
18196
19364
  if (this.connectionsViewerOpen()) {
18197
19365
  return this.tx('connections.close', 'Close connections');
18198
19366
  }
19367
+ if (this.hasRecommendedConnectionSuggestion()) {
19368
+ return this.tx('connections.toggleRecommended', 'Review suggested page interactions');
19369
+ }
18199
19370
  return this.tx('connections.toggle', 'Edit connections');
18200
19371
  }
18201
19372
  onAddComponent() {
@@ -18514,12 +19685,19 @@ class DynamicPageBuilderComponent {
18514
19685
  this.agenticAuthoringPanelLayout.set(layout);
18515
19686
  }
18516
19687
  agenticAuthoringReviewRailActive() {
18517
- return this.showSettings()
18518
- && this.enableAgenticAuthoring
18519
- && this.agenticAuthoringOpen()
19688
+ return this.showAgenticAuthoringPanel()
18520
19689
  && !!this.agenticAuthoringPreviewResult()?.valid
18521
19690
  && !this.agenticAuthoringPanelLayoutTouched;
18522
19691
  }
19692
+ showAgenticAuthoringPanel() {
19693
+ if (!this.enableAgenticAuthoring || !this.agenticAuthoringOpen()) {
19694
+ return false;
19695
+ }
19696
+ if (this.showSettings()) {
19697
+ return true;
19698
+ }
19699
+ return this.previewMode && this.hasAgenticAuthoringSession();
19700
+ }
18523
19701
  showAgenticAuthoringDock() {
18524
19702
  return this.showSettings()
18525
19703
  && this.enableAgenticAuthoring
@@ -19101,7 +20279,7 @@ class DynamicPageBuilderComponent {
19101
20279
  id: 'semantic-decision-resource',
19102
20280
  kind: 'custom',
19103
20281
  label: this.tx('agentic.context.semanticDecisionResource', 'Fonte'),
19104
- value: this.humanizeAgenticResourcePath(resourcePath),
20282
+ value: this.agenticSemanticResourceLabel(selectedResource) ?? this.humanizeAgenticResourcePath(resourcePath),
19105
20283
  icon: 'dataset',
19106
20284
  });
19107
20285
  }
@@ -19156,6 +20334,15 @@ class DynamicPageBuilderComponent {
19156
20334
  .replace(/[-_]+/g, ' ')
19157
20335
  .replace(/\b\w/g, (char) => char.toUpperCase());
19158
20336
  }
20337
+ agenticSemanticResourceLabel(resource) {
20338
+ return this.trimmedString(resource?.['selectedResourceLabel'])
20339
+ ?? this.trimmedString(resource?.['resourceLabel'])
20340
+ ?? this.trimmedString(resource?.['publicLabel'])
20341
+ ?? this.trimmedString(resource?.['displayName'])
20342
+ ?? this.trimmedString(resource?.['title'])
20343
+ ?? this.trimmedString(resource?.['label'])
20344
+ ?? this.trimmedString(resource?.['name']);
20345
+ }
19159
20346
  humanizeAgenticDecisionSummary(operationKind, artifactKind, changeKind) {
19160
20347
  const operation = this.humanizeAgenticOperationKind(operationKind);
19161
20348
  const artifact = this.humanizeAgenticArtifactKind(artifactKind);
@@ -20433,8 +21620,41 @@ class DynamicPageBuilderComponent {
20433
21620
  error: this.tx('agentic.errors.invalidTableContract', 'Encontrei a fonte de dados, mas a tabela proposta usa informações que esse componente não aceita. Vou ajustar para usar apenas campos compatíveis.'),
20434
21621
  };
20435
21622
  }
21623
+ if (applied.success && this.enableCustomization) {
21624
+ this.enterPreviewMode();
21625
+ }
20436
21626
  return applied;
20437
21627
  }
21628
+ enterPreviewMode() {
21629
+ this.previewMode = true;
21630
+ this.runtimePreviewPageCache = undefined;
21631
+ this.connectionsViewerOpen.set(false);
21632
+ this.agenticAuthoringLlmDiagnostics.set(null);
21633
+ this.sharedRuleCockpitCollapsed.set(true);
21634
+ this.projectKnowledgeCockpitCollapsed.set(true);
21635
+ this.selectedWidgetKey.set(null);
21636
+ }
21637
+ toPresentationRuntimePage(page) {
21638
+ const cloned = this.clonePage(page);
21639
+ cloned.widgets = (cloned.widgets || []).map((widget) => this.toPresentationRuntimeWidget(widget));
21640
+ return cloned;
21641
+ }
21642
+ toPresentationRuntimeWidget(widget) {
21643
+ const inputs = widget.definition?.inputs;
21644
+ if (!inputs || inputs['enableCustomization'] !== true) {
21645
+ return widget;
21646
+ }
21647
+ return {
21648
+ ...widget,
21649
+ definition: {
21650
+ ...widget.definition,
21651
+ inputs: {
21652
+ ...inputs,
21653
+ enableCustomization: false,
21654
+ },
21655
+ },
21656
+ };
21657
+ }
20438
21658
  async applyAgenticTurnState(state) {
20439
21659
  const preview = state.preview ?? null;
20440
21660
  const handoff = this.resolveAgenticSharedRuleHandoff(state);
@@ -20743,7 +21963,32 @@ class DynamicPageBuilderComponent {
20743
21963
  resolveAgenticSemanticDecision(diagnostics) {
20744
21964
  const intentResolution = this.toRecord(diagnostics?.['intentResolution']);
20745
21965
  const semanticDecision = this.toRecord(intentResolution?.['semanticDecision']);
20746
- return semanticDecision ? semanticDecision : null;
21966
+ if (!semanticDecision) {
21967
+ return null;
21968
+ }
21969
+ const selectedResource = this.toRecord(semanticDecision['selectedResource']);
21970
+ if (!selectedResource) {
21971
+ return semanticDecision;
21972
+ }
21973
+ const selectedResourceLabel = this.agenticSemanticResourceLabel(selectedResource);
21974
+ if (selectedResourceLabel) {
21975
+ return semanticDecision;
21976
+ }
21977
+ const selectedCandidate = this.toRecord(intentResolution?.['selectedCandidate']);
21978
+ const contextHints = this.toRecord(intentResolution?.['contextHints']);
21979
+ const label = this.agenticSemanticResourceLabel(semanticDecision)
21980
+ ?? this.agenticSemanticResourceLabel(selectedCandidate)
21981
+ ?? this.agenticSemanticResourceLabel(contextHints);
21982
+ if (!label) {
21983
+ return semanticDecision;
21984
+ }
21985
+ return {
21986
+ ...semanticDecision,
21987
+ selectedResource: {
21988
+ ...selectedResource,
21989
+ label,
21990
+ },
21991
+ };
20747
21992
  }
20748
21993
  cloneAgenticContextHints(contextHints) {
20749
21994
  if (!contextHints || typeof contextHints !== 'object' || Array.isArray(contextHints)) {
@@ -20752,9 +21997,10 @@ class DynamicPageBuilderComponent {
20752
21997
  return { ...contextHints };
20753
21998
  }
20754
21999
  resolveGovernedDomainContextSummary(llmDiagnostics) {
20755
- const request = this.toRecord(llmDiagnostics?.['request']);
22000
+ const effectiveDiagnostics = this.toRecord(llmDiagnostics?.['llmDiagnostics']) ?? llmDiagnostics;
22001
+ const request = this.toRecord(effectiveDiagnostics?.['request']);
20756
22002
  const requestContextBundle = this.toRecord(request?.['contextBundle']);
20757
- const rootContextBundle = this.toRecord(llmDiagnostics?.['contextBundle']);
22003
+ const rootContextBundle = this.toRecord(effectiveDiagnostics?.['contextBundle']);
20758
22004
  const governedDomainContext = this.toRecord(requestContextBundle?.['governedDomainContext'] ?? rootContextBundle?.['governedDomainContext']);
20759
22005
  if (!governedDomainContext) {
20760
22006
  return null;
@@ -21080,7 +22326,7 @@ class DynamicPageBuilderComponent {
21080
22326
 
21081
22327
  <praxis-dynamic-page
21082
22328
  #runtime
21083
- [page]="currentPage()"
22329
+ [page]="runtimePage()"
21084
22330
  [context]="context"
21085
22331
  [strictValidation]="strictValidation"
21086
22332
  [autoPersist]="false"
@@ -21089,7 +22335,7 @@ class DynamicPageBuilderComponent {
21089
22335
  [pageIdentity]="pageIdentity"
21090
22336
  [componentInstanceId]="componentInstanceId"
21091
22337
  [pageEditorComponent]="pageEditorComponent"
21092
- [showWidgetAssistantButton]="enableAgenticAuthoring"
22338
+ [showWidgetAssistantButton]="showSettings() && enableAgenticAuthoring"
21093
22339
  (pageChange)="onRuntimePageChange($event)"
21094
22340
  (widgetEvent)="onRuntimeWidgetEvent($event)"
21095
22341
  (widgetSelectionChange)="onRuntimeWidgetSelectionChange($event)"
@@ -21105,7 +22351,7 @@ class DynamicPageBuilderComponent {
21105
22351
  (close)="connectionsViewerOpen.set(false)"
21106
22352
  />
21107
22353
 
21108
- @if (showSettings() && enableAgenticAuthoring && agenticAuthoringOpen()) {
22354
+ @if (showAgenticAuthoringPanel()) {
21109
22355
  <praxis-ai-assistant-shell
21110
22356
  panelTestId="page-builder-agentic-authoring-panel"
21111
22357
  testIdPrefix="page-builder-agentic"
@@ -21496,6 +22742,7 @@ class DynamicPageBuilderComponent {
21496
22742
  type="button"
21497
22743
  class="builder-shell__connections-toggle"
21498
22744
  [class.builder-shell__connections-toggle--open]="connectionsViewerOpen()"
22745
+ [class.builder-shell__connections-toggle--recommended]="hasRecommendedConnectionSuggestion()"
21499
22746
  [attr.data-testid]="'page-builder-connections-toggle'"
21500
22747
  [matTooltip]="connectionsToggleLabel()"
21501
22748
  [attr.aria-label]="connectionsToggleLabel()"
@@ -21503,11 +22750,17 @@ class DynamicPageBuilderComponent {
21503
22750
  (click)="toggleConnectionsViewer()"
21504
22751
  >
21505
22752
  <mat-icon [praxisIcon]="'hub'"></mat-icon>
22753
+ @if (hasRecommendedConnectionSuggestion() && !connectionsViewerOpen()) {
22754
+ <span
22755
+ class="builder-shell__connections-toggle-badge"
22756
+ aria-hidden="true"
22757
+ ></span>
22758
+ }
21506
22759
  </button>
21507
22760
  }
21508
22761
  </praxis-floating-toolbar>
21509
22762
  </div>
21510
- `, isInline: true, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.builder-shell:has(.pdx-shell.fullscreen) praxis-floating-toolbar{display:none}.builder-premium-readiness{display:grid;grid-template-columns:minmax(220px,.72fr) minmax(0,1.28fr);gap:12px;width:100%;margin:0 0 14px;padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 72%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 10%,transparent),transparent 36%),color-mix(in srgb,var(--md-sys-color-surface-container-lowest, #fff) 96%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);box-shadow:inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface, #1d1b20) 5%,transparent)}.builder-premium-readiness__header{display:flex;align-items:flex-start;gap:10px;min-width:0}.builder-premium-readiness__header strong{display:block;font-size:13px;line-height:1.25}.builder-premium-readiness__header p,.builder-premium-readiness__item p{margin:2px 0 0;color:var(--md-sys-color-on-surface-variant, #49454f);font-size:11px;line-height:1.35}.builder-premium-readiness__icon{color:var(--md-sys-color-primary, #6750a4);font-size:20px;line-height:1}.builder-premium-readiness__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px;margin:0;padding:0;list-style:none}.builder-premium-readiness__item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 64%,transparent);border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, #f7f2fa) 84%,transparent)}.builder-premium-readiness__item strong{display:block;font-size:12px;line-height:1.25}.builder-premium-readiness__action{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-height:26px;margin-top:7px;padding:4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 34%,transparent);border-radius:7px;background:color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 9%,var(--md-sys-color-surface, #fff));color:var(--md-sys-color-primary, #6750a4);cursor:pointer;font:inherit;font-size:11px;font-weight:700;line-height:1.2;text-align:left}.builder-premium-readiness__severity{width:8px;height:8px;margin-top:4px;border-radius:999px;background:var(--md-sys-color-primary, #6750a4)}.builder-premium-readiness__item[data-severity=warning] .builder-premium-readiness__severity{background:var(--praxis-warning, #b26a00)}.builder-premium-readiness__item[data-severity=error] .builder-premium-readiness__severity{background:var(--md-sys-color-error, #b3261e)}@media(max-width:760px){.builder-premium-readiness{grid-template-columns:1fr}}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:fixed;inset:0;z-index:140;pointer-events:none}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.builder-shell__connections-toggle--open{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 52%,transparent);outline-offset:2px}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: DynamicWidgetPageComponent, selector: "praxis-dynamic-page", inputs: ["page", "context", "strictValidation", "enableCustomization", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId", "showWidgetAssistantButton"], outputs: ["pageChange", "widgetEvent", "widgetSelectionChange", "widgetAssistantRequested", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo", "showSave", "showPreview", "editingEnabled", "previewActive", "connectionMode", "modeLabel", "previewLabel", "exitPreviewLabel"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings", "close"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }] });
22763
+ `, isInline: true, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.builder-shell:has(.pdx-shell.fullscreen) praxis-floating-toolbar{display:none}.builder-premium-readiness{display:grid;grid-template-columns:minmax(220px,.72fr) minmax(0,1.28fr);gap:12px;width:100%;margin:0 0 14px;padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 72%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 10%,transparent),transparent 36%),color-mix(in srgb,var(--md-sys-color-surface-container-lowest, #fff) 96%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);box-shadow:inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface, #1d1b20) 5%,transparent)}.builder-premium-readiness__header{display:flex;align-items:flex-start;gap:10px;min-width:0}.builder-premium-readiness__header strong{display:block;font-size:13px;line-height:1.25}.builder-premium-readiness__header p,.builder-premium-readiness__item p{margin:2px 0 0;color:var(--md-sys-color-on-surface-variant, #49454f);font-size:11px;line-height:1.35}.builder-premium-readiness__icon{color:var(--md-sys-color-primary, #6750a4);font-size:20px;line-height:1}.builder-premium-readiness__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px;margin:0;padding:0;list-style:none}.builder-premium-readiness__item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 64%,transparent);border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, #f7f2fa) 84%,transparent)}.builder-premium-readiness__item strong{display:block;font-size:12px;line-height:1.25}.builder-premium-readiness__action{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-height:26px;margin-top:7px;padding:4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 34%,transparent);border-radius:7px;background:color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 9%,var(--md-sys-color-surface, #fff));color:var(--md-sys-color-primary, #6750a4);cursor:pointer;font:inherit;font-size:11px;font-weight:700;line-height:1.2;text-align:left}.builder-premium-readiness__severity{width:8px;height:8px;margin-top:4px;border-radius:999px;background:var(--md-sys-color-primary, #6750a4)}.builder-premium-readiness__item[data-severity=warning] .builder-premium-readiness__severity{background:var(--praxis-warning, #b26a00)}.builder-premium-readiness__item[data-severity=error] .builder-premium-readiness__severity{background:var(--md-sys-color-error, #b3261e)}@media(max-width:760px){.builder-premium-readiness{grid-template-columns:1fr}}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:fixed;inset:0;z-index:140;pointer-events:none}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.builder-shell__connections-toggle--open{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 52%,transparent);outline-offset:2px}.builder-shell__connections-toggle{position:relative}.builder-shell__connections-toggle--recommended:not(.builder-shell__connections-toggle--open){outline:2px solid rgba(34,211,238,.48);outline-offset:2px}.builder-shell__connections-toggle-badge{position:absolute;top:5px;right:5px;width:9px;height:9px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#22d3ee;box-shadow:0 0 0 3px #22d3ee2e}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: DynamicWidgetPageComponent, selector: "praxis-dynamic-page", inputs: ["page", "context", "strictValidation", "enableCustomization", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId", "showWidgetAssistantButton"], outputs: ["pageChange", "widgetEvent", "widgetSelectionChange", "widgetAssistantRequested", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo", "showSave", "showPreview", "editingEnabled", "previewActive", "connectionMode", "modeLabel", "previewLabel", "exitPreviewLabel"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings", "close"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }] });
21511
22764
  }
21512
22765
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicPageBuilderComponent, decorators: [{
21513
22766
  type: Component,
@@ -21571,7 +22824,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
21571
22824
 
21572
22825
  <praxis-dynamic-page
21573
22826
  #runtime
21574
- [page]="currentPage()"
22827
+ [page]="runtimePage()"
21575
22828
  [context]="context"
21576
22829
  [strictValidation]="strictValidation"
21577
22830
  [autoPersist]="false"
@@ -21580,7 +22833,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
21580
22833
  [pageIdentity]="pageIdentity"
21581
22834
  [componentInstanceId]="componentInstanceId"
21582
22835
  [pageEditorComponent]="pageEditorComponent"
21583
- [showWidgetAssistantButton]="enableAgenticAuthoring"
22836
+ [showWidgetAssistantButton]="showSettings() && enableAgenticAuthoring"
21584
22837
  (pageChange)="onRuntimePageChange($event)"
21585
22838
  (widgetEvent)="onRuntimeWidgetEvent($event)"
21586
22839
  (widgetSelectionChange)="onRuntimeWidgetSelectionChange($event)"
@@ -21596,7 +22849,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
21596
22849
  (close)="connectionsViewerOpen.set(false)"
21597
22850
  />
21598
22851
 
21599
- @if (showSettings() && enableAgenticAuthoring && agenticAuthoringOpen()) {
22852
+ @if (showAgenticAuthoringPanel()) {
21600
22853
  <praxis-ai-assistant-shell
21601
22854
  panelTestId="page-builder-agentic-authoring-panel"
21602
22855
  testIdPrefix="page-builder-agentic"
@@ -21987,6 +23240,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
21987
23240
  type="button"
21988
23241
  class="builder-shell__connections-toggle"
21989
23242
  [class.builder-shell__connections-toggle--open]="connectionsViewerOpen()"
23243
+ [class.builder-shell__connections-toggle--recommended]="hasRecommendedConnectionSuggestion()"
21990
23244
  [attr.data-testid]="'page-builder-connections-toggle'"
21991
23245
  [matTooltip]="connectionsToggleLabel()"
21992
23246
  [attr.aria-label]="connectionsToggleLabel()"
@@ -21994,11 +23248,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
21994
23248
  (click)="toggleConnectionsViewer()"
21995
23249
  >
21996
23250
  <mat-icon [praxisIcon]="'hub'"></mat-icon>
23251
+ @if (hasRecommendedConnectionSuggestion() && !connectionsViewerOpen()) {
23252
+ <span
23253
+ class="builder-shell__connections-toggle-badge"
23254
+ aria-hidden="true"
23255
+ ></span>
23256
+ }
21997
23257
  </button>
21998
23258
  }
21999
23259
  </praxis-floating-toolbar>
22000
23260
  </div>
22001
- `, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.builder-shell:has(.pdx-shell.fullscreen) praxis-floating-toolbar{display:none}.builder-premium-readiness{display:grid;grid-template-columns:minmax(220px,.72fr) minmax(0,1.28fr);gap:12px;width:100%;margin:0 0 14px;padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 72%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 10%,transparent),transparent 36%),color-mix(in srgb,var(--md-sys-color-surface-container-lowest, #fff) 96%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);box-shadow:inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface, #1d1b20) 5%,transparent)}.builder-premium-readiness__header{display:flex;align-items:flex-start;gap:10px;min-width:0}.builder-premium-readiness__header strong{display:block;font-size:13px;line-height:1.25}.builder-premium-readiness__header p,.builder-premium-readiness__item p{margin:2px 0 0;color:var(--md-sys-color-on-surface-variant, #49454f);font-size:11px;line-height:1.35}.builder-premium-readiness__icon{color:var(--md-sys-color-primary, #6750a4);font-size:20px;line-height:1}.builder-premium-readiness__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px;margin:0;padding:0;list-style:none}.builder-premium-readiness__item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 64%,transparent);border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, #f7f2fa) 84%,transparent)}.builder-premium-readiness__item strong{display:block;font-size:12px;line-height:1.25}.builder-premium-readiness__action{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-height:26px;margin-top:7px;padding:4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 34%,transparent);border-radius:7px;background:color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 9%,var(--md-sys-color-surface, #fff));color:var(--md-sys-color-primary, #6750a4);cursor:pointer;font:inherit;font-size:11px;font-weight:700;line-height:1.2;text-align:left}.builder-premium-readiness__severity{width:8px;height:8px;margin-top:4px;border-radius:999px;background:var(--md-sys-color-primary, #6750a4)}.builder-premium-readiness__item[data-severity=warning] .builder-premium-readiness__severity{background:var(--praxis-warning, #b26a00)}.builder-premium-readiness__item[data-severity=error] .builder-premium-readiness__severity{background:var(--md-sys-color-error, #b3261e)}@media(max-width:760px){.builder-premium-readiness{grid-template-columns:1fr}}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:fixed;inset:0;z-index:140;pointer-events:none}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.builder-shell__connections-toggle--open{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 52%,transparent);outline-offset:2px}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"] }]
23261
+ `, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%}.builder-shell:has(.pdx-shell.fullscreen) praxis-floating-toolbar{display:none}.builder-premium-readiness{display:grid;grid-template-columns:minmax(220px,.72fr) minmax(0,1.28fr);gap:12px;width:100%;margin:0 0 14px;padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 72%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 10%,transparent),transparent 36%),color-mix(in srgb,var(--md-sys-color-surface-container-lowest, #fff) 96%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);box-shadow:inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface, #1d1b20) 5%,transparent)}.builder-premium-readiness__header{display:flex;align-items:flex-start;gap:10px;min-width:0}.builder-premium-readiness__header strong{display:block;font-size:13px;line-height:1.25}.builder-premium-readiness__header p,.builder-premium-readiness__item p{margin:2px 0 0;color:var(--md-sys-color-on-surface-variant, #49454f);font-size:11px;line-height:1.35}.builder-premium-readiness__icon{color:var(--md-sys-color-primary, #6750a4);font-size:20px;line-height:1}.builder-premium-readiness__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px;margin:0;padding:0;list-style:none}.builder-premium-readiness__item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 64%,transparent);border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, #f7f2fa) 84%,transparent)}.builder-premium-readiness__item strong{display:block;font-size:12px;line-height:1.25}.builder-premium-readiness__action{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-height:26px;margin-top:7px;padding:4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 34%,transparent);border-radius:7px;background:color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 9%,var(--md-sys-color-surface, #fff));color:var(--md-sys-color-primary, #6750a4);cursor:pointer;font:inherit;font-size:11px;font-weight:700;line-height:1.2;text-align:left}.builder-premium-readiness__severity{width:8px;height:8px;margin-top:4px;border-radius:999px;background:var(--md-sys-color-primary, #6750a4)}.builder-premium-readiness__item[data-severity=warning] .builder-premium-readiness__severity{background:var(--praxis-warning, #b26a00)}.builder-premium-readiness__item[data-severity=error] .builder-premium-readiness__severity{background:var(--md-sys-color-error, #b3261e)}@media(max-width:760px){.builder-premium-readiness{grid-template-columns:1fr}}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid rgba(30,64,175,.18);border-radius:999px;background:#ffffffd6;color:#1e3a8a;cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}praxis-ai-assistant-shell{position:fixed;inset:0;z-index:140;pointer-events:none}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.builder-shell__connections-toggle--open{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 52%,transparent);outline-offset:2px}.builder-shell__connections-toggle{position:relative}.builder-shell__connections-toggle--recommended:not(.builder-shell__connections-toggle--open){outline:2px solid rgba(34,211,238,.48);outline-offset:2px}.builder-shell__connections-toggle-badge{position:absolute;top:5px;right:5px;width:9px;height:9px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#22d3ee;box-shadow:0 0 0 3px #22d3ee2e}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid rgba(30,64,175,.22);border-radius:12px;background:linear-gradient(135deg,#eff6fffa,#fffbebf5);color:#172554;box-shadow:0 18px 46px #0f172a38;overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:#475569;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid rgba(30,64,175,.2);border-radius:999px;background:#ffffffbd;color:#1e3a8a;font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:#334155;font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:#991b1b;font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:#ffffffb8}.shared-rule-cockpit__facts dt{color:#64748b;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:#0f172a;font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid rgba(30,64,175,.14);border-radius:12px;background:#ffffff94}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid rgba(15,23,42,.08);border-radius:11px;background:#f8fafcd1}.shared-rule-cockpit__projection[data-status=ready]{border-color:#16a34a33;background:#f0fdf4d1}.shared-rule-cockpit__projection span{color:#1d4ed8;font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:#0f172a;font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:#475569;font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid rgba(30,64,175,.12);border-radius:12px;background:#ffffffc2}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:#1e3a8a;font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:#0f172a;font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:#475569;font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:#0ea5e91f;color:#075985;font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:#ffffffa3}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"] }]
22002
23262
  }], ctorParameters: () => [{ type: i1.MatDialog }, { type: undefined, decorators: [{
22003
23263
  type: Optional
22004
23264
  }, {
@@ -22075,6 +23335,65 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
22075
23335
  type: Output
22076
23336
  }] } });
22077
23337
 
23338
+ /** Metadata for Praxis Page Builder component */
23339
+ const PRAXIS_PAGE_BUILDER_COMPONENT_METADATA = {
23340
+ id: 'praxis-page-builder',
23341
+ selector: 'praxis-dynamic-page-builder',
23342
+ component: DynamicPageBuilderComponent,
23343
+ friendlyName: 'Praxis Page Builder',
23344
+ description: 'Page builder using the canonical praxis-dynamic-page runtime.',
23345
+ tags: ['widget', 'page-builder', 'configurable'],
23346
+ lib: '@praxisui/page-builder',
23347
+ outputs: [
23348
+ {
23349
+ name: 'pageChange',
23350
+ type: 'WidgetPageDefinition',
23351
+ description: 'Emits the governed page definition after runtime or builder edits.',
23352
+ },
23353
+ {
23354
+ name: 'widgetEvent',
23355
+ type: 'WidgetEventEnvelope',
23356
+ description: 'Reemits child runtime widget events so host integrations can open governed previews, actions, and discovery surfaces.',
23357
+ },
23358
+ {
23359
+ name: 'pageSaveRequested',
23360
+ type: 'WidgetPageDefinition',
23361
+ description: 'Requests persistence for the current page definition.',
23362
+ },
23363
+ {
23364
+ name: 'agenticAuthoringApplied',
23365
+ type: 'PageBuilderApplyResult',
23366
+ description: 'Emits after an agentic authoring proposal is applied.',
23367
+ },
23368
+ {
23369
+ name: 'agenticAuthoringSharedRuleHandoff',
23370
+ type: 'PageBuilderAgenticAuthoringSharedRuleHandoff',
23371
+ description: 'Emits a governed shared-rule handoff from the agentic authoring flow.',
23372
+ },
23373
+ {
23374
+ name: 'pageRestart',
23375
+ type: 'void',
23376
+ description: 'Requests a host-confirmed page restart.',
23377
+ },
23378
+ {
23379
+ name: 'savedPageDeleteRequested',
23380
+ type: 'void',
23381
+ description: 'Requests deletion of the saved page revision.',
23382
+ },
23383
+ ],
23384
+ };
23385
+ /** Provider para auto-registrar metadados do componente Page Builder. */
23386
+ function providePraxisPageBuilderMetadata() {
23387
+ return {
23388
+ provide: ENVIRONMENT_INITIALIZER,
23389
+ multi: true,
23390
+ useFactory: (registry) => () => {
23391
+ registry.register(PRAXIS_PAGE_BUILDER_COMPONENT_METADATA);
23392
+ },
23393
+ deps: [ComponentMetadataRegistry],
23394
+ };
23395
+ }
23396
+
22078
23397
  /*
22079
23398
  * Public API Surface of @praxisui/page-builder
22080
23399
  */
@@ -22084,4 +23403,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
22084
23403
  * Generated bundle index. Do not edit.
22085
23404
  */
22086
23405
 
22087
- export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, registerWidgetAiCatalog, registerWidgetAiCatalogs, validateUiCompositionPlan };
23406
+ export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, validateUiCompositionPlan };