@praxisui/dynamic-form 10.0.0-rc.38 → 10.0.0-rc.39

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.
@@ -61,7 +61,7 @@ import { MatToolbarModule } from '@angular/material/toolbar';
61
61
  import * as i8$1 from '@angular/material/expansion';
62
62
  import { MatExpansionModule } from '@angular/material/expansion';
63
63
  import { MatListModule } from '@angular/material/list';
64
- import { CascadeManagerTabComponent } from '@praxisui/metadata-editor';
64
+ import { CascadeRulesService, CascadeManagerTabComponent } from '@praxisui/metadata-editor';
65
65
 
66
66
  const PRAXIS_DYNAMIC_FORM_I18N_NAMESPACE = 'praxisDynamicForm';
67
67
  const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
@@ -428,7 +428,8 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
428
428
  'config.navigation.note.tooltip': 'Afeta o fluxo de navegação do CRUD e pode ser sobreposto por metadados do recurso.',
429
429
  'config.rules.title': 'Regras visuais',
430
430
  'config.rules.conversionError': 'Não foi possível converter a condição visual. Revise a regra; aplicar e salvar estão bloqueados.',
431
- 'config.rules.subtitle': 'Defina visibilidade, estilos e reações baseadas em condições.',
431
+ 'config.rules.effectsDraftPending': 'Conclua ou repare o rascunho no editor visual ou no JSON para editar seus efeitos. A última configuração aceita foi preservada e não representa este rascunho.',
432
+ 'config.rules.subtitle': 'Controle a apresentação dos campos. Estas regras não executam comandos nem substituem decisões de negócio governadas.',
432
433
  'config.rules.summary.total': '{{count}} regras',
433
434
  'config.rules.summary.invalid': '{{count}} inválidas',
434
435
  'config.rules.summary.unsupported': '{{count}} com propriedades rejeitadas',
@@ -444,7 +445,7 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
444
445
  'config.rules.actions.reviewJson': 'Ver JSON',
445
446
  'config.rules.actions.reviewJson.tooltip': 'Abrir a aba JSON para revisar esta regra sem conversão visual',
446
447
  'config.rules.empty': 'Nenhuma regra definida ainda. Crie uma regra para ver alvos, condição, propriedades e compatibilidade do builder.',
447
- 'config.rules.status.invalidTarget': 'Alvo inválido',
448
+ 'config.rules.status.invalidTarget': 'Alvo indisponível',
448
449
  'config.rules.status.invalidCondition': 'Condição inválida',
449
450
  'config.rules.status.unsupportedProperty': 'Propriedade rejeitada',
450
451
  'config.rules.status.sanitizedProperty': 'Valor ajustado',
@@ -453,7 +454,7 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
453
454
  'config.rules.status.compatible': 'Compatível',
454
455
  'config.rules.status.valid': 'Válida',
455
456
  'config.rules.details.usedFields': 'Campos usados: {{fields}}',
456
- 'config.rules.details.missingTargets': 'Alvos ausentes: {{targets}}',
457
+ 'config.rules.details.missingTargets': 'Alvos indisponíveis nesta operação (ausentes ou ocultos por metadados/acesso): {{targets}}',
457
458
  'config.rules.details.rejectedPropertiesTrue': 'Propriedades rejeitadas em true: {{properties}}',
458
459
  'config.rules.details.invalidValuesTrue': 'Valores inválidos em true: {{properties}}',
459
460
  'config.rules.details.sanitizedValuesTrue': 'Valores parcialmente saneados em true: {{properties}}',
@@ -481,7 +482,7 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
481
482
  'config.rules.targets.localFieldSubmit.omit': 'Nao enviado no payload por padrao.',
482
483
  'config.rules.targets.localFieldDescription': 'Campo local/transient. {{payloadHint}}',
483
484
  'config.commandRules.title': 'Comandos condicionais',
484
- 'config.commandRules.subtitle': 'Execute ações globais quando uma condição do formulário for satisfeita.',
485
+ 'config.commandRules.subtitle': 'Canal de comandos: execute ações globais quando uma condição for satisfeita, respeitando as políticas da ação.',
485
486
  'config.commandRules.command.label': 'Comando',
486
487
  'config.commandRules.actions.add': 'Adicionar',
487
488
  'config.commandRules.actions.remove': 'Remover',
@@ -605,6 +606,12 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
605
606
  'json.editor.error.syntax': 'Erro de sintaxe JSON',
606
607
  'rules.property.invalidJson': 'Informe um JSON válido para aplicar a propriedade.',
607
608
  'rules.property.computedValue.invalidEnvelope': 'Valor calculado inválido no ramo de condição {{branch}}. Use exatamente { "expression": <JSON Logic> } ou exatamente { "literal": <valor> }.',
609
+ 'rules.property.panel.scopeHint': 'Este painel edita apenas os efeitos. A validade da regra e a aplicação no formulário são verificadas pelo editor do formulário.',
610
+ 'rules.property.panel.propertyEditable': 'Edição da propriedade disponível',
611
+ 'rules.property.panel.propertySelectionNeeded': 'Selecione regra e propriedade',
612
+ 'rules.property.panel.conditionInvalid': 'Condição inválida',
613
+ 'config.ruleProperties.preview.errors.conditionInvalid': 'A condição não é válida no runtime atual.',
614
+ 'config.ruleProperties.preview.scopeHint': 'Simule os dois ramos com dados de exemplo. O resultado não valida os alvos nem autoriza aplicar a regra.',
608
615
  'rules.property.panel.title': 'Efeito estruturado da regra',
609
616
  'rules.property.panel.subtitle': 'Escolha uma regra, edite uma propriedade permitida e confira o patch antes de aplicar.',
610
617
  'rules.property.panel.selectedRule': 'Regra selecionada',
@@ -1025,7 +1032,8 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
1025
1032
  'config.navigation.note.tooltip': 'Affects the CRUD navigation flow and may be overridden by resource metadata.',
1026
1033
  'config.rules.title': 'Visual rules',
1027
1034
  'config.rules.conversionError': 'The visual condition could not be converted. Review the rule; apply and save are blocked.',
1028
- 'config.rules.subtitle': 'Define visibility, styles, and reactions based on conditions.',
1035
+ 'config.rules.effectsDraftPending': 'Complete or repair the draft in the visual editor or JSON before editing its effects. The last accepted configuration was preserved and does not represent this draft.',
1036
+ 'config.rules.subtitle': 'Control field presentation. These rules do not execute commands or replace governed business decisions.',
1029
1037
  'config.rules.summary.total': '{{count}} rules',
1030
1038
  'config.rules.summary.invalid': '{{count}} invalid',
1031
1039
  'config.rules.summary.unsupported': '{{count}} with rejected properties',
@@ -1041,7 +1049,7 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
1041
1049
  'config.rules.actions.reviewJson': 'View JSON',
1042
1050
  'config.rules.actions.reviewJson.tooltip': 'Open the JSON tab to review this rule without visual conversion',
1043
1051
  'config.rules.empty': 'No rules defined yet. Create a rule to see targets, condition, properties, and builder compatibility.',
1044
- 'config.rules.status.invalidTarget': 'Invalid target',
1052
+ 'config.rules.status.invalidTarget': 'Unavailable target',
1045
1053
  'config.rules.status.invalidCondition': 'Invalid condition',
1046
1054
  'config.rules.status.unsupportedProperty': 'Rejected property',
1047
1055
  'config.rules.status.sanitizedProperty': 'Adjusted value',
@@ -1050,7 +1058,7 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
1050
1058
  'config.rules.status.compatible': 'Compatible',
1051
1059
  'config.rules.status.valid': 'Valid',
1052
1060
  'config.rules.details.usedFields': 'Fields used: {{fields}}',
1053
- 'config.rules.details.missingTargets': 'Missing targets: {{targets}}',
1061
+ 'config.rules.details.missingTargets': 'Targets unavailable in this operation (missing or hidden by metadata/access): {{targets}}',
1054
1062
  'config.rules.details.rejectedPropertiesTrue': 'Rejected properties in true: {{properties}}',
1055
1063
  'config.rules.details.invalidValuesTrue': 'Invalid values in true: {{properties}}',
1056
1064
  'config.rules.details.sanitizedValuesTrue': 'Partially sanitized values in true: {{properties}}',
@@ -1078,7 +1086,7 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
1078
1086
  'config.rules.targets.localFieldSubmit.omit': 'Not sent in the payload by default.',
1079
1087
  'config.rules.targets.localFieldDescription': 'Local/transient field. {{payloadHint}}',
1080
1088
  'config.commandRules.title': 'Conditional commands',
1081
- 'config.commandRules.subtitle': 'Execute global actions when a form condition is satisfied.',
1089
+ 'config.commandRules.subtitle': 'Command channel: execute global actions when a condition is met, respecting the action policies.',
1082
1090
  'config.commandRules.command.label': 'Command',
1083
1091
  'config.commandRules.actions.add': 'Add',
1084
1092
  'config.commandRules.actions.remove': 'Remove',
@@ -1202,6 +1210,12 @@ const PRAXIS_DYNAMIC_FORM_I18N_CONFIG = {
1202
1210
  'json.editor.error.syntax': 'JSON syntax error',
1203
1211
  'rules.property.invalidJson': 'Provide valid JSON before applying the property.',
1204
1212
  'rules.property.computedValue.invalidEnvelope': 'Invalid computed value in the {{branch}} condition branch. Use exactly { "expression": <JSON Logic> } or exactly { "literal": <value> }.',
1213
+ 'rules.property.panel.scopeHint': 'This panel edits effects only. Rule validity and application to the form are checked by the form editor.',
1214
+ 'rules.property.panel.propertyEditable': 'Property editing available',
1215
+ 'rules.property.panel.propertySelectionNeeded': 'Select a rule and property',
1216
+ 'rules.property.panel.conditionInvalid': 'Invalid condition',
1217
+ 'config.ruleProperties.preview.errors.conditionInvalid': 'The condition is not valid in the current runtime.',
1218
+ 'config.ruleProperties.preview.scopeHint': 'Simulate both branches with sample data. The result does not validate targets or authorize applying the rule.',
1205
1219
  'rules.property.panel.title': 'Structured rule effect',
1206
1220
  'rules.property.panel.subtitle': 'Choose a rule, edit an allowed property, and review the patch before applying it.',
1207
1221
  'rules.property.panel.selectedRule': 'Selected rule',
@@ -5808,8 +5822,8 @@ function ruleBuilderStateToFormLayoutRules(state) {
5808
5822
  * Converts an array of FormLayoutRule back into a RuleBuilderState
5809
5823
  * so that the visual builder can display the saved rules.
5810
5824
  *
5811
- * The conversion handles a limited subset of rules (visibility and
5812
- * required/validation rules with simple field conditions).
5825
+ * Every canonical effect reopens as a propertyRule, with all targets and both
5826
+ * branches intact. Conditions outside the visual vocabulary stay inline.
5813
5827
  */
5814
5828
  function formLayoutRulesToBuilderState(rules) {
5815
5829
  const state = {
@@ -5945,71 +5959,54 @@ function inferPropertiesFromNode(nodeType) {
5945
5959
  function formLayoutRuleToNodes(rule) {
5946
5960
  const normalizedRule = sanitizeRuleEffect(migrateFormLayoutRule(rule));
5947
5961
  const condition = normalizedRule.effect?.condition;
5948
- const nodes = [];
5949
- const targets = normalizedRule.targets && normalizedRule.targets.length
5950
- ? normalizedRule.targets
5951
- : [normalizedRule.id || generateId()];
5952
- targets.forEach((target, index) => {
5953
- let conditionNode;
5954
- let conditionNodes = [];
5955
- if (condition) {
5956
- conditionNode = parseConditionExpression(condition);
5957
- conditionNodes = conditionNode ? flattenConditionNodes(conditionNode) : [];
5958
- if (conditionNode) {
5959
- const allNodes = Object.fromEntries(conditionNodes.map((entry) => [entry.id, entry]));
5960
- try {
5961
- const rebuilt = buildJsonLogicFromCondition(conditionNode, allNodes);
5962
- if (JSON.stringify(rebuilt) !== JSON.stringify(condition)) {
5963
- conditionNode = undefined;
5964
- conditionNodes = [];
5965
- }
5966
- }
5967
- catch {
5968
- // Runtime-valid expressions can exceed the visual graph vocabulary.
5969
- // Preserve their complete inline condition instead of a partial graph.
5962
+ let conditionNode;
5963
+ let conditionNodes = [];
5964
+ if (condition) {
5965
+ conditionNode = parseConditionExpression(condition);
5966
+ conditionNodes = conditionNode ? flattenConditionNodes(conditionNode) : [];
5967
+ if (conditionNode) {
5968
+ const allNodes = Object.fromEntries(conditionNodes.map((entry) => [entry.id, entry]));
5969
+ try {
5970
+ const rebuilt = buildJsonLogicFromCondition(conditionNode, allNodes);
5971
+ if (JSON.stringify(rebuilt) !== JSON.stringify(condition)) {
5970
5972
  conditionNode = undefined;
5971
5973
  conditionNodes = [];
5972
5974
  }
5973
5975
  }
5976
+ catch {
5977
+ // Runtime-valid expressions can exceed the visual graph vocabulary.
5978
+ // Preserve their complete inline condition instead of a partial graph.
5979
+ conditionNode = undefined;
5980
+ conditionNodes = [];
5981
+ }
5974
5982
  }
5975
- const inferredType = inferRuleType(normalizedRule);
5976
- const rootType = inferredType === 'propertyRule'
5977
- ? 'propertyRule'
5978
- : normalizedRule.targetType === 'field' && inferredType !== 'custom'
5979
- ? inferredType
5980
- : 'custom';
5981
- const config = {
5982
- type: inferredType,
5983
- validatorType: inferredType,
5984
- targetField: prefixTarget(normalizedRule.targetType, target),
5985
- targets: [...(normalizedRule.targets || [])],
5986
- targetType: normalizedRule.targetType,
5987
- logicOperator: 'and',
5988
- properties: filterRuleProperties(normalizedRule.targetType, normalizedRule.effect?.properties),
5989
- propertiesWhenFalse: filterRuleProperties(normalizedRule.targetType, normalizedRule.effect?.propertiesWhenFalse),
5990
- ruleId: normalizedRule.id,
5991
- condition: normalizedRule.effect?.condition,
5992
- ...extractRuleAuthoringMetadata(rule),
5993
- ...extractRuleSemanticMetadataForBuilder(rule),
5994
- };
5995
- if (normalizedRule.targetType && normalizedRule.targetType !== 'field') {
5996
- config.targetType = normalizedRule.targetType;
5997
- }
5998
- if (conditionNode) {
5999
- config.conditionNodeId = conditionNode.id;
6000
- config.conditions = [conditionNode.config];
6001
- }
6002
- const rootNode = {
6003
- id: targets.length > 1
6004
- ? `${normalizedRule.id || generateId()}-${index}`
6005
- : normalizedRule.id || generateId(),
6006
- type: rootType,
6007
- label: normalizedRule.name,
6008
- config,
6009
- };
6010
- nodes.push({ rootNode, conditionNode, conditionNodes });
6011
- });
6012
- return nodes;
5983
+ }
5984
+ // Form rules already describe canonical property effects. Reopening them as
5985
+ // legacy conditional validators makes the current visual editor unselectable
5986
+ // and splits a single multi-target rule into duplicate list entries.
5987
+ const config = {
5988
+ type: 'propertyRule',
5989
+ targets: [...(normalizedRule.targets || [])],
5990
+ targetType: normalizedRule.targetType,
5991
+ properties: filterRuleProperties(normalizedRule.targetType, normalizedRule.effect?.properties),
5992
+ propertiesWhenFalse: filterRuleProperties(normalizedRule.targetType, normalizedRule.effect?.propertiesWhenFalse),
5993
+ ruleId: normalizedRule.id,
5994
+ condition: normalizedRule.effect?.condition,
5995
+ ...extractRuleAuthoringMetadata(normalizedRule),
5996
+ ...extractRuleSemanticMetadataForBuilder(normalizedRule),
5997
+ };
5998
+ if (conditionNode) {
5999
+ config.conditionNodeId = conditionNode.id;
6000
+ }
6001
+ const rootNode = {
6002
+ id: normalizedRule.id || generateId(),
6003
+ type: 'propertyRule',
6004
+ label: normalizedRule.name,
6005
+ ...(normalizedRule.description !== undefined
6006
+ ? { metadata: { description: normalizedRule.description } } : {}),
6007
+ config,
6008
+ };
6009
+ return [{ rootNode, conditionNode, conditionNodes }];
6013
6010
  }
6014
6011
  function extractRuleAuthoringMetadata(source) {
6015
6012
  if (!source || typeof source !== 'object')
@@ -6049,49 +6046,6 @@ function extractRuleSemanticMetadataForBuilder(source) {
6049
6046
  }
6050
6047
  return semantic;
6051
6048
  }
6052
- function inferRuleType(rule) {
6053
- const props = rule.effect?.properties || {};
6054
- const propsFalse = rule.effect?.propertiesWhenFalse || {};
6055
- const hasNonToggleProps = Object.keys({ ...props, ...propsFalse }).some((k) => !['visible', 'required', 'disabled', 'readonly'].includes(k));
6056
- const targetType = (rule.targetType || 'field');
6057
- if (targetType && targetType !== 'field') {
6058
- return 'propertyRule';
6059
- }
6060
- if (hasNonToggleProps) {
6061
- return 'propertyRule';
6062
- }
6063
- if (props.visible !== undefined || propsFalse.visible !== undefined) {
6064
- return 'visibleIf';
6065
- }
6066
- if (props.required !== undefined || propsFalse.required !== undefined) {
6067
- return 'requiredIf';
6068
- }
6069
- if (props.disabled !== undefined || propsFalse.disabled !== undefined) {
6070
- return 'disabledIf';
6071
- }
6072
- if (props.readonly !== undefined || propsFalse.readonly !== undefined) {
6073
- return 'readonlyIf';
6074
- }
6075
- if (targetType === 'action') {
6076
- if (props.label !== undefined || props.icon !== undefined || props.className !== undefined || props.style !== undefined) {
6077
- return 'custom';
6078
- }
6079
- if (props.disabled !== undefined || propsFalse.disabled !== undefined) {
6080
- return 'disabledIf';
6081
- }
6082
- }
6083
- if (targetType === 'section') {
6084
- if (props.collapsible !== undefined ||
6085
- props.collapsed !== undefined ||
6086
- props.title !== undefined ||
6087
- props.icon !== undefined ||
6088
- props.className !== undefined ||
6089
- props.style !== undefined) {
6090
- return 'custom';
6091
- }
6092
- }
6093
- return 'custom';
6094
- }
6095
6049
  function normalizeTargets(rawTargets, explicitTargetType) {
6096
6050
  if (!rawTargets.length) {
6097
6051
  return { targets: [], targetType: explicitTargetType || 'field' };
@@ -6136,23 +6090,6 @@ function detectTarget(value) {
6136
6090
  }
6137
6091
  return { type: 'field', value };
6138
6092
  }
6139
- function prefixTarget(targetType, value) {
6140
- if (targetType === 'action' &&
6141
- (isScopedSectionHeaderActionTarget(value) || isUnscopedSectionHeaderActionTarget(value))) {
6142
- return value;
6143
- }
6144
- if (targetType === 'section')
6145
- return `section:${value}`;
6146
- if (targetType === 'action')
6147
- return `action:${value}`;
6148
- if (targetType === 'row')
6149
- return `row:${value}`;
6150
- if (targetType === 'column')
6151
- return `column:${value}`;
6152
- if (targetType === 'visualBlock')
6153
- return `visualBlock:${value}`;
6154
- return value;
6155
- }
6156
6093
  function isScopedSectionHeaderActionTarget(value) {
6157
6094
  return !!value && value.startsWith('section:') && value.includes(':header-action:');
6158
6095
  }
@@ -11610,7 +11547,18 @@ class PraxisDynamicForm {
11610
11547
  */
11611
11548
  editorialContext = null;
11612
11549
  mode = 'create';
11613
- config = { sections: [] };
11550
+ effectiveConfig = { sections: [] };
11551
+ configAssignment = null;
11552
+ get config() { return this.effectiveConfig; }
11553
+ set config(value) {
11554
+ // Keep only the pre-assignment references until the next lifecycle pass.
11555
+ // The backing value remains the single effective runtime document.
11556
+ const previous = this.configAssignment && this.effectiveConfig === this.configAssignment.incoming
11557
+ ? this.configAssignment.previous
11558
+ : this.effectiveConfig;
11559
+ this.configAssignment = { previous, incoming: value };
11560
+ this.effectiveConfig = value;
11561
+ }
11614
11562
  hostConfigInputProvided = false;
11615
11563
  /** Optional host-level overrides for the rendered form action bar. */
11616
11564
  actions;
@@ -13077,7 +13025,7 @@ class PraxisDynamicForm {
13077
13025
  return;
13078
13026
  if (this.isInitialized || this.isLoading)
13079
13027
  return;
13080
- if (this.formId && this.hasSchemaBackedRuntime()) {
13028
+ if (this.formId && (this.hasSchemaBackedRuntime() || this.hasRenderableConfig())) {
13081
13029
  void this.initializeForm();
13082
13030
  return;
13083
13031
  }
@@ -13109,7 +13057,7 @@ class PraxisDynamicForm {
13109
13057
  const normalizedConfig = normalizeFormConfig$1(currentConfig);
13110
13058
  const canReuseExistingBuild = this.hasBuiltFormFromConfig &&
13111
13059
  this.isEquivalentFormConfig(currentConfig, normalizedConfig);
13112
- this.config = normalizedConfig;
13060
+ this.effectiveConfig = normalizedConfig;
13113
13061
  if (canReuseExistingBuild) {
13114
13062
  this.evaluateAndApplyRules();
13115
13063
  this.refreshMaterializedFormRules('standalone-reuse');
@@ -13125,7 +13073,7 @@ class PraxisDynamicForm {
13125
13073
  initializeDisconnectedEmptyState() {
13126
13074
  if (this.isLoading || this.isInitialized)
13127
13075
  return;
13128
- this.config = normalizeFormConfig$1(this.config);
13076
+ this.effectiveConfig = normalizeFormConfig$1(this.config);
13129
13077
  this.form = this.fb.group({});
13130
13078
  this.isInitialized = true;
13131
13079
  this.initializationStatus = 'success';
@@ -13133,7 +13081,7 @@ class PraxisDynamicForm {
13133
13081
  this.cdr.detectChanges();
13134
13082
  }
13135
13083
  reloadForModeChange() {
13136
- if (!this.inputsLoaded || !this.formId || !this.hasSchemaBackedRuntime()) {
13084
+ if (!this.inputsLoaded || !this.formId || (!this.hasSchemaBackedRuntime() && !this.hasRenderableConfig())) {
13137
13085
  this.cdr.markForCheck();
13138
13086
  return;
13139
13087
  }
@@ -13284,7 +13232,7 @@ class PraxisDynamicForm {
13284
13232
  change.op.correlationId === this.lastCorrelationId) {
13285
13233
  return;
13286
13234
  }
13287
- this.config = change.config;
13235
+ this.effectiveConfig = change.config;
13288
13236
  this.buildFormFromConfig({
13289
13237
  reason: 'layout-edit',
13290
13238
  preserveRuntimeState: true,
@@ -13302,7 +13250,19 @@ class PraxisDynamicForm {
13302
13250
  }
13303
13251
  }
13304
13252
  ngOnChanges(changes) {
13305
- const ownershipContextChanged = ['formId', 'componentInstanceId', 'resourcePath', 'mode', 'configPersistenceStrategy', 'config', 'notifyIfOutdated', 'snoozeMs', 'autoOpenSettingsOnOutdated'].some(key => !!changes[key]);
13253
+ const configChange = changes['config'];
13254
+ const configInputChanged = !!configChange && (configChange.firstChange ||
13255
+ !this.isEquivalentFormConfig(configChange.previousValue, configChange.currentValue));
13256
+ const assignment = this.configAssignment;
13257
+ this.configAssignment = null;
13258
+ if (configChange && !configInputChanged && assignment &&
13259
+ assignment.incoming === configChange.currentValue && this.config === configChange.currentValue) {
13260
+ // Angular already assigned an equivalent host echo. Keep the effective
13261
+ // persisted/edited document without rebuilding or invalidating its owner.
13262
+ this.effectiveConfig = assignment.previous;
13263
+ }
13264
+ const ownershipContextChanged = ['formId', 'componentInstanceId', 'resourcePath', 'mode', 'configPersistenceStrategy', 'config', 'notifyIfOutdated', 'snoozeMs', 'autoOpenSettingsOnOutdated']
13265
+ .some(key => key === 'config' ? configInputChanged : !!changes[key]);
13306
13266
  if (ownershipContextChanged) {
13307
13267
  this.persistenceContextEpoch = (this.persistenceContextEpoch ?? 0) + 1;
13308
13268
  }
@@ -13387,20 +13347,24 @@ class PraxisDynamicForm {
13387
13347
  }
13388
13348
  if (changes['initialValue'] &&
13389
13349
  !changes['initialValue'].firstChange &&
13390
- this.usesInitialValueAsAuthoritativeSnapshot() &&
13391
- Object.keys(this.form.controls || {}).length) {
13350
+ this.usesInitialValueAsAuthoritativeSnapshot()) {
13392
13351
  const normalized = this.getNormalizedInitialValue();
13393
- this.form.reset({}, { emitEvent: false });
13394
- if (normalized) {
13395
- this.form.patchValue(normalized, { emitEvent: false });
13396
- }
13397
- this.form.markAsPristine();
13398
- this.form.markAsUntouched();
13352
+ // Storage/hooks may still be initializing the controls. Keep the same
13353
+ // authoritative snapshot current so a later build cannot replay an older
13354
+ // initialValue cached by the resourceId input.
13399
13355
  this.loadedEntityData = normalized;
13400
13356
  this.loadedResourceRevision = null;
13401
13357
  this.hydratedEntityId = this.pendingEntityId;
13402
- this.flushEntityHydrationState();
13403
- this.emitPayloadPreview('entity-hydrated');
13358
+ if (Object.keys(this.form.controls || {}).length) {
13359
+ this.form.reset({}, { emitEvent: false });
13360
+ if (normalized) {
13361
+ this.form.patchValue(normalized, { emitEvent: false });
13362
+ }
13363
+ this.form.markAsPristine();
13364
+ this.form.markAsUntouched();
13365
+ this.flushEntityHydrationState();
13366
+ this.emitPayloadPreview('entity-hydrated');
13367
+ }
13404
13368
  }
13405
13369
  if (changes['schemaUrl'] && !changes['schemaUrl'].firstChange) {
13406
13370
  this.debugLog('[PDF] ngOnChanges schemaUrl=', this.schemaUrl);
@@ -13429,19 +13393,21 @@ class PraxisDynamicForm {
13429
13393
  if (changes['config']?.currentValue) {
13430
13394
  this.hostConfigInputProvided = true;
13431
13395
  const normalizedIncomingConfig = normalizeFormConfig$1(changes['config'].currentValue);
13432
- externalConfigChanged =
13433
- changes['config'].firstChange ||
13434
- !this.isEquivalentFormConfig(this.config, normalizedIncomingConfig);
13396
+ externalConfigChanged = configInputChanged;
13435
13397
  if (externalConfigChanged) {
13436
- this.config = normalizedIncomingConfig;
13398
+ this.effectiveConfig = normalizedIncomingConfig;
13437
13399
  this.logRowGapsSnapshot('config@input');
13438
- const hasRenderableConfig = (this.config?.sections?.length ?? 0) > 0
13439
- || (this.config?.fieldMetadata?.length ?? 0) > 0;
13440
- if (hasRenderableConfig) {
13441
- // External config updates must rebuild even when a resourcePath exists.
13442
- const shouldDeferToSchemaInitialization = this.hasSchemaBackedRuntime() && !!this.formId && !this.isInitialized;
13400
+ const hasRenderableConfig = this.hasRenderableConfig();
13401
+ // An explicit empty standalone replacement also clears old controls;
13402
+ // it must not fall back to an obsolete persisted document.
13403
+ const standaloneInputReplacement = !this.hasSchemaBackedRuntime() && !changes['config'].firstChange;
13404
+ if (hasRenderableConfig || standaloneInputReplacement) {
13405
+ // Identified forms share the persisted-config initializer, including
13406
+ // local-only forms. A newer standalone input still owns its update
13407
+ // while an obsolete storage read is pending.
13408
+ const shouldDeferToConfigInitialization = !!this.formId && !this.isInitialized && !standaloneInputReplacement;
13443
13409
  shouldRebuildFromExternalConfig =
13444
- !this.isLoading && !shouldDeferToSchemaInitialization;
13410
+ (!this.isLoading || standaloneInputReplacement) && !shouldDeferToConfigInitialization;
13445
13411
  }
13446
13412
  }
13447
13413
  else {
@@ -13539,7 +13505,7 @@ class PraxisDynamicForm {
13539
13505
  return;
13540
13506
  }
13541
13507
  // Validação obrigatória para cenários corporativos
13542
- if (!this.formId || !this.hasSchemaBackedRuntime()) {
13508
+ if (!this.formId || (!this.hasSchemaBackedRuntime() && !this.hasRenderableConfig())) {
13543
13509
  const error = new Error(`Form initialization failed: ${!this.formId ? 'formId' : 'resourcePath or schemaUrl'} is required for corporate form management`);
13544
13510
  this.handleInitializationError('config-load', error, {
13545
13511
  formId: this.formId,
@@ -13564,14 +13530,14 @@ class PraxisDynamicForm {
13564
13530
  this.warnMissingId();
13565
13531
  return;
13566
13532
  }
13567
- const hostConfig = this.hostConfigInputProvided || this.hasRenderableConfig()
13568
- ? normalizeFormConfig$1(this.config)
13569
- : null;
13570
13533
  const localConfig = this.shouldPersistGeneratedConfig()
13571
13534
  ? await this.loadConfigFailOpen(configKey)
13572
13535
  : null;
13573
13536
  if (!current() || initializationCycle !== this.schemaInitializationCycle)
13574
13537
  return;
13538
+ const hostConfig = this.hostConfigInputProvided || this.hasRenderableConfig()
13539
+ ? normalizeFormConfig$1(this.config)
13540
+ : null;
13575
13541
  const shouldUseHostConfig = !!hostConfig &&
13576
13542
  (this.configPersistenceStrategy !== 'local-first' ||
13577
13543
  this.hostConfigHasAuthoredLocalFieldsNotInLocalConfig(hostConfig, localConfig));
@@ -13581,11 +13547,12 @@ class PraxisDynamicForm {
13581
13547
  ? 'LOCAL_CONFIG'
13582
13548
  : 'SERVER_DEFAULT');
13583
13549
  if (shouldUseHostConfig && hostConfig) {
13584
- this.config = hostConfig;
13550
+ this.effectiveConfig = hostConfig;
13585
13551
  if (this.hasRenderableConfig(hostConfig)) {
13586
- await this.reconcileLoadedConfigWithServerSchema(false);
13552
+ if (this.hasSchemaBackedRuntime())
13553
+ await this.reconcileLoadedConfigWithServerSchema(false);
13587
13554
  }
13588
- else {
13555
+ else if (this.hasSchemaBackedRuntime()) {
13589
13556
  // An authoritative policy-only host still derives fields/layout from the
13590
13557
  // current schema; persisted fields must not become a second authority.
13591
13558
  await this.createDefaultConfig();
@@ -13593,34 +13560,43 @@ class PraxisDynamicForm {
13593
13560
  if (!current())
13594
13561
  return;
13595
13562
  this.emitLoadingState('config', 'success', 'Configuração carregada.');
13596
- this.verifyServerSchemaVersion().catch(() => { });
13563
+ if (this.hasSchemaBackedRuntime())
13564
+ this.verifyServerSchemaVersion().catch(() => { });
13597
13565
  }
13598
13566
  else if (localConfig) {
13599
13567
  // Flow 1: Has local config - load it, then refresh
13600
13568
  // server-authoritative field semantics from the current schema.
13601
13569
  this.debugLog('🔄 Loading saved form configuration');
13602
- this.config = normalizeFormConfig$1(localConfig);
13603
- await this.reconcileLoadedConfigWithServerSchema();
13570
+ this.effectiveConfig = normalizeFormConfig$1(localConfig);
13571
+ if (this.hasSchemaBackedRuntime())
13572
+ await this.reconcileLoadedConfigWithServerSchema();
13604
13573
  if (!current())
13605
13574
  return;
13606
13575
  this.emitLoadingState('config', 'success', 'Configuração carregada.');
13607
13576
  // Verify server schema version in background for outdated UX metadata.
13608
- this.verifyServerSchemaVersion().catch(() => { });
13577
+ if (this.hasSchemaBackedRuntime())
13578
+ this.verifyServerSchemaVersion().catch(() => { });
13609
13579
  }
13610
13580
  else if (this.hasRenderableConfig()) {
13611
13581
  // Flow 2: Host-provided config - reconcile local layout/fields with the server schema.
13612
13582
  this.debugLog('Creating form configuration from host config and server schema');
13613
- await this.createConfigFromHostConfig();
13583
+ if (this.hasSchemaBackedRuntime())
13584
+ await this.createConfigFromHostConfig();
13585
+ else
13586
+ this.effectiveConfig = normalizeFormConfig$1(this.config);
13614
13587
  }
13615
- else {
13616
- // Flow 2: No local config - create default from server
13588
+ else if (this.hasSchemaBackedRuntime()) {
13589
+ // Only schema-backed forms can derive a missing document from the server.
13617
13590
  this.debugLog('🆕 Creating new form configuration from server');
13618
13591
  await this.createDefaultConfig();
13619
13592
  }
13593
+ else {
13594
+ this.effectiveConfig = normalizeFormConfig$1(this.config);
13595
+ }
13620
13596
  if (!current() || initializationCycle !== this.schemaInitializationCycle)
13621
13597
  return;
13622
13598
  // Ensure config has stable IDs before any drag-and-drop operations
13623
- this.config = normalizeFormConfig$1(this.config);
13599
+ this.effectiveConfig = normalizeFormConfig$1(this.config);
13624
13600
  this.debugLog('[PDF] initializeForm:buildForm');
13625
13601
  // Build the form
13626
13602
  this.buildFormFromConfig({ reason: 'initialization' });
@@ -13779,7 +13755,7 @@ class PraxisDynamicForm {
13779
13755
  return;
13780
13756
  const source = String(snapshot.metadata?.source || '').trim().toLowerCase();
13781
13757
  if (remote && source === 'default') {
13782
- this.config = normalizeFormConfig$1(remote);
13758
+ this.effectiveConfig = normalizeFormConfig$1(remote);
13783
13759
  this.columnFieldsCache.clear();
13784
13760
  this.cdr.markForCheck();
13785
13761
  }
@@ -13813,11 +13789,11 @@ class PraxisDynamicForm {
13813
13789
  // Generate default layout from metadata (padrão: 2 campos por linha)
13814
13790
  const hostConfig = normalizeFormConfig$1(this.config);
13815
13791
  if (this.shouldUseSchemaLayoutPolicy()) {
13816
- this.config = this.createSchemaMaterializedConfig(hostConfig, fieldMetadata);
13792
+ this.effectiveConfig = this.createSchemaMaterializedConfig(hostConfig, fieldMetadata);
13817
13793
  }
13818
13794
  else {
13819
13795
  const generatedConfig = this.dynamicLayout.generateFormConfigFromMetadata(fieldMetadata, { fieldsPerRow: 2, layoutPreset: this.generatedLayoutPreset });
13820
- this.config = normalizeFormConfig$1({
13796
+ this.effectiveConfig = normalizeFormConfig$1({
13821
13797
  ...generatedConfig,
13822
13798
  ...hostConfig,
13823
13799
  sections: generatedConfig.sections,
@@ -13873,7 +13849,7 @@ class PraxisDynamicForm {
13873
13849
  throw new Error('No field metadata received from server');
13874
13850
  }
13875
13851
  const hostConfig = normalizeFormConfig$1(this.config);
13876
- this.config = this.shouldUseSchemaLayoutPolicy()
13852
+ this.effectiveConfig = this.shouldUseSchemaLayoutPolicy()
13877
13853
  ? this.createSchemaMaterializedConfig(hostConfig, mapFieldDefinitionsToMetadata(serverDefs))
13878
13854
  : normalizeFormConfig$1(reconcileFormConfig(hostConfig, serverDefs));
13879
13855
  if (this.schemaRootHooks) {
@@ -13961,7 +13937,7 @@ class PraxisDynamicForm {
13961
13937
  return;
13962
13938
  }
13963
13939
  const before = JSON.stringify(this.config);
13964
- this.config = normalizeFormConfig$1(reconcileFormConfig(this.config, serverDefs));
13940
+ this.effectiveConfig = normalizeFormConfig$1(reconcileFormConfig(this.config, serverDefs));
13965
13941
  if (this.schemaRootHooks) {
13966
13942
  this.config.hooks = this.schemaRootHooks;
13967
13943
  }
@@ -14002,7 +13978,7 @@ class PraxisDynamicForm {
14002
13978
  const serverDefs = await this.getSchemaWithCache();
14003
13979
  const serverMetadata = mapFieldDefinitionsToMetadata(serverDefs);
14004
13980
  const syncResult = syncWithServerMetadata(this.config, serverMetadata);
14005
- this.config = syncResult.config;
13981
+ this.effectiveConfig = syncResult.config;
14006
13982
  // Update meta with last schema info
14007
13983
  if (!this.config.metadata)
14008
13984
  this.config.metadata = {};
@@ -18227,7 +18203,7 @@ class PraxisDynamicForm {
18227
18203
  mem.schemaId = metaToSave.schemaId;
18228
18204
  mem.schemaContext = metaToSave.schemaContext;
18229
18205
  mem.lastVerifiedAt = metaToSave.lastVerifiedAt;
18230
- this.config = { ...this.config, metadata: mem };
18206
+ this.effectiveConfig = { ...this.config, metadata: mem };
18231
18207
  this.cdr.markForCheck();
18232
18208
  }
18233
18209
  catch { }
@@ -18255,7 +18231,7 @@ class PraxisDynamicForm {
18255
18231
  mem.schemaId = metaToSave.schemaId;
18256
18232
  mem.schemaContext = metaToSave.schemaContext;
18257
18233
  mem.lastVerifiedAt = metaToSave.lastVerifiedAt;
18258
- this.config = { ...this.config, metadata: mem };
18234
+ this.effectiveConfig = { ...this.config, metadata: mem };
18259
18235
  this.cdr.markForCheck();
18260
18236
  }
18261
18237
  catch { }
@@ -19132,7 +19108,7 @@ class PraxisDynamicForm {
19132
19108
  ...structuredClone(value),
19133
19109
  };
19134
19110
  }
19135
- this.config = { ...this.config, sections };
19111
+ this.effectiveConfig = { ...this.config, sections };
19136
19112
  this.configChange.emit(this.config);
19137
19113
  this.emitConfigPatchChange();
19138
19114
  this.cdr.detectChanges();
@@ -19156,7 +19132,7 @@ class PraxisDynamicForm {
19156
19132
  const sectionIndex = sections.findIndex((candidate) => candidate === section ||
19157
19133
  (!!candidate?.id && !!section?.id && candidate.id === section.id));
19158
19134
  if (sectionIndex >= 0) {
19159
- this.config = produce(this.config, (draft) => {
19135
+ this.effectiveConfig = produce(this.config, (draft) => {
19160
19136
  const target = (draft.sections || [])[sectionIndex];
19161
19137
  if (target) {
19162
19138
  applyPatch(target);
@@ -19910,6 +19886,10 @@ class PraxisDynamicForm {
19910
19886
  if (fctApply === 'SLIDER') {
19911
19887
  if (patch.thumbLabel !== undefined)
19912
19888
  fm.thumbLabel = !!patch.thumbLabel;
19889
+ if (patch.discrete !== undefined)
19890
+ fm.discrete = !!patch.discrete;
19891
+ if (patch.valueLabelDisplay !== undefined)
19892
+ fm.valueLabelDisplay = patch.valueLabelDisplay;
19913
19893
  if (patch.vertical !== undefined)
19914
19894
  fm.vertical = !!patch.vertical;
19915
19895
  if (patch.showTicks !== undefined)
@@ -19925,6 +19905,8 @@ class PraxisDynamicForm {
19925
19905
  fm.mode = patch.mode;
19926
19906
  if (patch.thumbLabel !== undefined)
19927
19907
  fm.thumbLabel = !!patch.thumbLabel;
19908
+ if (patch.valueLabelDisplay !== undefined)
19909
+ fm.valueLabelDisplay = patch.valueLabelDisplay;
19928
19910
  if (patch.showTicks !== undefined)
19929
19911
  fm.showTicks = patch.showTicks;
19930
19912
  if (patch.discrete !== undefined)
@@ -20009,7 +19991,7 @@ class PraxisDynamicForm {
20009
19991
  fm.step = toNum(patch.step);
20010
19992
  }
20011
19993
  // Persist using Immer for safe immutable update
20012
- this.config = produce(this.config, (draft) => {
19994
+ this.effectiveConfig = produce(this.config, (draft) => {
20013
19995
  draft.fieldMetadata = draft.fieldMetadata || [];
20014
19996
  draft.fieldMetadata[idx] = fm;
20015
19997
  });
@@ -20230,7 +20212,7 @@ class PraxisDynamicForm {
20230
20212
  const currList = (this.config.fieldMetadata || []);
20231
20213
  const nextList = currList.slice();
20232
20214
  nextList[idx] = fmForConfig;
20233
- this.config = { ...this.config, fieldMetadata: nextList };
20215
+ this.effectiveConfig = { ...this.config, fieldMetadata: nextList };
20234
20216
  // Produce a safe preview of what will be persisted for this field
20235
20217
  const preview = {};
20236
20218
  for (const [k, v] of Object.entries(fmForConfig)) {
@@ -20436,7 +20418,7 @@ class PraxisDynamicForm {
20436
20418
  if (toIndex === fromIndex)
20437
20419
  return;
20438
20420
  const result = this.dynamicLayout.moveSectionById(this.config, last.data.id, toIndex, { correlationId, origin: 'PraxisDynamicForm' });
20439
- this.config = result.config;
20421
+ this.effectiveConfig = result.config;
20440
20422
  }
20441
20423
  else {
20442
20424
  return; // Move arrows are not supported for other types
@@ -20643,7 +20625,7 @@ class PraxisDynamicForm {
20643
20625
  try {
20644
20626
  this.lastCorrelationId = correlationId;
20645
20627
  const result = this.dynamicLayout.moveSectionById(this.config, fromId, toIndex, { correlationId, origin: 'PraxisDynamicForm' });
20646
- this.config = result.config;
20628
+ this.effectiveConfig = result.config;
20647
20629
  // Update drop list data to prevent CDK from reverting the drag operation
20648
20630
  const sections = withFormConfigSections(this.config).sections;
20649
20631
  event.container.data = sections;
@@ -20666,7 +20648,7 @@ class PraxisDynamicForm {
20666
20648
  correlationId,
20667
20649
  throttleKey: 'praxis-dynamic-form:dnd:section:rollback',
20668
20650
  });
20669
- this.config = snapshot;
20651
+ this.effectiveConfig = snapshot;
20670
20652
  this.buildFormFromConfig({
20671
20653
  reason: 'layout-edit',
20672
20654
  preserveRuntimeState: true,
@@ -20713,7 +20695,7 @@ class PraxisDynamicForm {
20713
20695
  try {
20714
20696
  this.lastCorrelationId = correlationId;
20715
20697
  const result = this.dynamicLayout.moveRowById(this.config, fromIds.sectionId, fromIds.rowId, toIds.sectionId, toIds.toIndex, { correlationId, origin: 'PraxisDynamicForm' });
20716
- this.config = result.config;
20698
+ this.effectiveConfig = result.config;
20717
20699
  // Sync CDK drop list data for source and destination containers
20718
20700
  const sections = withFormConfigSections(this.config).sections;
20719
20701
  const destSection = sections.find((s) => s.id === toIds.sectionId);
@@ -20738,7 +20720,7 @@ class PraxisDynamicForm {
20738
20720
  correlationId,
20739
20721
  throttleKey: 'praxis-dynamic-form:dnd:row:rollback',
20740
20722
  });
20741
- this.config = snapshot;
20723
+ this.effectiveConfig = snapshot;
20742
20724
  this.buildFormFromConfig({
20743
20725
  reason: 'layout-edit',
20744
20726
  preserveRuntimeState: true,
@@ -20792,7 +20774,7 @@ class PraxisDynamicForm {
20792
20774
  try {
20793
20775
  this.lastCorrelationId = correlationId;
20794
20776
  const result = this.dynamicLayout.moveColumnById(this.config, fromIds.sectionId, fromIds.rowId, fromIds.columnId, toIds.sectionId, toIds.rowId, toIds.toIndex, { correlationId, origin: 'PraxisDynamicForm' });
20795
- this.config = result.config;
20777
+ this.effectiveConfig = result.config;
20796
20778
  // Update drop list data for source and destination rows
20797
20779
  const sections = withFormConfigSections(this.config).sections;
20798
20780
  const destColumns = sections
@@ -20821,7 +20803,7 @@ class PraxisDynamicForm {
20821
20803
  correlationId,
20822
20804
  throttleKey: 'praxis-dynamic-form:dnd:column:rollback',
20823
20805
  });
20824
- this.config = snapshot;
20806
+ this.effectiveConfig = snapshot;
20825
20807
  this.buildFormFromConfig({
20826
20808
  reason: 'layout-edit',
20827
20809
  preserveRuntimeState: true,
@@ -20887,7 +20869,7 @@ class PraxisDynamicForm {
20887
20869
  try {
20888
20870
  this.lastCorrelationId = correlationId;
20889
20871
  const result = this.dynamicLayout.moveFieldById(this.config, fromIds, toIds, { correlationId, origin: 'PraxisDynamicForm' });
20890
- this.config = result.config;
20872
+ this.effectiveConfig = result.config;
20891
20873
  // Sync drop list data for source and destination columns
20892
20874
  const sections = withFormConfigSections(this.config).sections;
20893
20875
  const destFields = sections
@@ -20918,7 +20900,7 @@ class PraxisDynamicForm {
20918
20900
  correlationId,
20919
20901
  throttleKey: 'praxis-dynamic-form:dnd:field:rollback',
20920
20902
  });
20921
- this.config = snapshot;
20903
+ this.effectiveConfig = snapshot;
20922
20904
  this.buildFormFromConfig({
20923
20905
  reason: 'layout-edit',
20924
20906
  preserveRuntimeState: true,
@@ -20970,7 +20952,7 @@ class PraxisDynamicForm {
20970
20952
  // 2. Call the service's `insertSection` method, following the existing pattern.
20971
20953
  const result = this.dynamicLayout.insertSection(this.config, newSection, sectionIndex + 1);
20972
20954
  // 3. Update the component's state from the result.
20973
- this.config = result.config;
20955
+ this.effectiveConfig = result.config;
20974
20956
  this.configChange.emit(this.config); // Emit the change for parent components
20975
20957
  this.buildFormFromConfig({
20976
20958
  reason: 'layout-edit',
@@ -21282,10 +21264,10 @@ class PraxisDynamicForm {
21282
21264
  (trigger === 'adapter-apply'
21283
21265
  ? this.config?.metadata?.layoutScope
21284
21266
  : undefined));
21285
- this.config = normalizeFormConfig$1(nextConfig);
21267
+ this.effectiveConfig = normalizeFormConfig$1(nextConfig);
21286
21268
  if (isResetExecution) {
21287
21269
  const { layoutScope: _removed, ...restMetadata } = this.config?.metadata || {};
21288
- this.config = {
21270
+ this.effectiveConfig = {
21289
21271
  ...this.config,
21290
21272
  metadata: {
21291
21273
  ...restMetadata,
@@ -21295,7 +21277,7 @@ class PraxisDynamicForm {
21295
21277
  }
21296
21278
  else if (explicitLayoutScope === 'shared' ||
21297
21279
  explicitLayoutScope === 'mode-only') {
21298
- this.config = {
21280
+ this.effectiveConfig = {
21299
21281
  ...this.config,
21300
21282
  metadata: {
21301
21283
  ...(this.config.metadata || {}),
@@ -21305,7 +21287,7 @@ class PraxisDynamicForm {
21305
21287
  };
21306
21288
  }
21307
21289
  else if (plan.persistence?.saveConfig) {
21308
- this.config = {
21290
+ this.effectiveConfig = {
21309
21291
  ...this.config,
21310
21292
  metadata: {
21311
21293
  ...(this.config.metadata || {}),
@@ -21316,7 +21298,7 @@ class PraxisDynamicForm {
21316
21298
  }
21317
21299
  else if (this.config?.metadata && 'layoutScope' in this.config.metadata) {
21318
21300
  const { layoutScope: _removed, ...restMetadata } = this.config.metadata;
21319
- this.config = {
21301
+ this.effectiveConfig = {
21320
21302
  ...this.config,
21321
21303
  metadata: restMetadata,
21322
21304
  };
@@ -22150,7 +22132,7 @@ class PraxisDynamicForm {
22150
22132
  this.cdr.detectChanges();
22151
22133
  // Normalize configuration to canonical schema (constraints at top-level)
22152
22134
  if (this.config) {
22153
- this.config = normalizeFormConfig$1(this.config);
22135
+ this.effectiveConfig = normalizeFormConfig$1(this.config);
22154
22136
  }
22155
22137
  }
22156
22138
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDynamicForm, deps: [{ token: i1.GenericCrudService }, { token: i2.HttpClient }, { token: i1$3.FormBuilder }, { token: i0.ChangeDetectorRef }, { token: FormLayoutService }, { token: FormContextService }, { token: FormRulesService }, { token: i7.SettingsPanelService }, { token: i2$1.MatDialog }, { token: ASYNC_CONFIG_STORAGE }, { token: CONNECTION_STORAGE }, { token: i1.DynamicFormService }, { token: i9.MatSnackBar }, { token: CanvasStateService }, { token: DynamicFormLayoutService }, { token: ReactiveDeterminationRuntimeService }, { token: i1.ErrorMessageService }, { token: i1.SchemaNormalizerService }, { token: i1.ComponentMetadataRegistry }, { token: i1.GlobalConfigService }, { token: i1.ComponentKeyService }, { token: i1.LoadingOrchestrator }, { token: i0.NgZone }, { token: API_URL }, { token: PRAXIS_LOADING_RENDERER, optional: true }, { token: i13.Router, optional: true }, { token: i13.ActivatedRoute, optional: true }, { token: i1.FormHooksRegistry, optional: true }, { token: FORM_HOOKS_PRESETS, optional: true }, { token: i1.LoggerService, optional: true }, { token: i1.EnterpriseRuntimeContextService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
@@ -22158,7 +22140,7 @@ class PraxisDynamicForm {
22158
22140
  providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG),
22159
22141
  GenericCrudService,
22160
22142
  FormContextService,
22161
- ], viewQueries: [{ propertyName: "formHost", first: true, predicate: ["formHost"], descendants: true }, { propertyName: "fieldLoaders", predicate: DynamicFieldLoaderDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (isLoading) {\n <!-- Loading State -->\n <div class=\"form-loading\" role=\"status\" aria-live=\"polite\" aria-label=\"Carregando formul\u00E1rio\">\n <div class=\"form-loading-header\">\n <mat-progress-spinner diameter=\"32\" aria-label=\"Carregando formul\u00E1rio\"></mat-progress-spinner>\n <div class=\"form-loading-copy\">\n <p class=\"form-loading-title\">Carregando formul\u00E1rio...</p>\n <p class=\"form-loading-subtitle\">Preparando campos e op\u00E7\u00F5es do cadastro.</p>\n </div>\n </div>\n <div class=\"form-loading-skeleton\" aria-hidden=\"true\">\n <span class=\"form-loading-line form-loading-line-title\"></span>\n <span class=\"form-loading-line\"></span>\n <span class=\"form-loading-line form-loading-line-short\"></span>\n <span class=\"form-loading-field\"></span>\n <span class=\"form-loading-field form-loading-field-wide\"></span>\n </div>\n </div>\n} @else if (initializationStatus === 'error') {\n <!-- Error State -->\n <div class=\"form-error\">\n <mat-icon color=\"warn\" [praxisIcon]=\"'error'\"></mat-icon>\n <h3>{{ getErrorTitle() }}</h3>\n <p>{{ currentErrorMessage }}</p>\n @if (isRecoverable) {\n <button mat-stroked-button (click)=\"retryInitialization()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n Tentar Novamente\n </button>\n }\n <button mat-button (click)=\"showDetailedError()\" class=\"show-details\">\n Ver Detalhes T\u00E9cnicos\n </button>\n <!-- Permitir corre\u00E7\u00E3o do resourcePath diretamente do estado de erro -->\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\" class=\"connect-action\">\n <mat-icon [praxisIcon]=\"'bolt'\"></mat-icon>\n Conectar a recurso\n </button>\n </div>\n} @else if (initializationStatus === 'success') {\n <!-- Inline banner for schema change (only when customization is enabled) -->\n @if (shouldShowOutdatedInline()) {\n <div class=\"pfx-form-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"openConfigEditor()\">\n <mat-icon [praxisIcon]=\"'sync'\"></mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n </div>\n }\n\n <!-- Configuration Controls -->\n @if (shouldShowConfigControls && enableCustomization) {\n <div class=\"form-config-controls\">\n @if (showAiAssistant) {\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"dense\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('config-controls')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Abrir copiloto sem\u00E2ntico do formul\u00E1rio\">\n </button>\n }\n <button type=\"button\" praxisIconButton=\"settings\" size=\"dense\" (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [attr.aria-label]=\"configControlLabel\" [matTooltip]=\"configControlLabel\">\n </button>\n <button type=\"button\" praxisIconButton=\"link_off\" size=\"dense\" (click)=\"disconnect()\"\n [attr.aria-label]=\"disconnectControlLabel\" [matTooltip]=\"disconnectControlLabel\"\n [disabled]=\"isLoading\">\n </button>\n </div>\n }\n\n <!-- Form Content -->\n @if (!resourcePath && !hasExplicitSchemaUrl() && !hasRenderableConfig()) {\n <praxis-empty-state-card\n icon=\"link\"\n [title]=\"'Conecte o formul\u00E1rio \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para gerar automaticamente os campos do formul\u00E1rio.'\"\n [primaryAction]=\"enableCustomization ? { label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) } : undefined\"\n ></praxis-empty-state-card>\n }\n @if (shouldShowContextEmptyState()) {\n <div class=\"form-context-empty-state\" role=\"status\" aria-live=\"polite\">\n <praxis-empty-state-card\n [icon]=\"emptyState?.icon || 'touch_app'\"\n [title]=\"emptyState!.title\"\n [description]=\"emptyState?.description\"\n [tone]=\"emptyState?.tone || 'primary'\"\n [variant]=\"emptyState?.variant || 'transparent'\"\n [alignment]=\"emptyState?.alignment || 'center'\"\n [density]=\"emptyState?.density || 'compact'\"\n [iconContainer]=\"emptyState?.iconContainer || 'circle'\"\n [inline]=\"true\"\n />\n </div>\n } @else {\n <div #entityReadRegion class=\"entity-read-region\" tabindex=\"-1\" role=\"region\" [attr.aria-label]=\"entityReadText('region')\">\n <span class=\"cdk-visually-hidden\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ entityReadStatusText() }}</span>\n @if (entityHydrationPending || entityReadFailed) {\n <div class=\"entity-read-feedback\" data-testid=\"form-entity-read-feedback\">\n @if (entityHydrationPending) {\n <mat-progress-spinner diameter=\"28\" mode=\"indeterminate\" aria-hidden=\"true\"></mat-progress-spinner>\n <p aria-hidden=\"true\">{{ entityReadText('loading') }}</p>\n } @else {\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <p aria-hidden=\"true\">{{ entityReadText('error') }}</p>\n <button mat-stroked-button type=\"button\" (click)=\"retryEntityRead(entityReadRegion)\">{{ entityReadText('retry') }}</button>\n }\n </div>\n }\n <form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting || entityHydrationPending ? 'true' : null\"\n [style.opacity]=\"entityHydrationPending || entityReadFailed ? '0' : null\"\n [style.transition]=\"entityHydrationPending || entityReadFailed ? 'none' : null\"\n [attr.inert]=\"entityHydrationPending || entityReadFailed ? '' : null\"\n [attr.aria-hidden]=\"entityHydrationPending || entityReadFailed ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\"\n [class.praxis-dynamic-form--presentation]=\"effectivePresentation\"\n [class.readonly-mode]=\"effectiveReadonly\"\n [attr.data-presentation-preset]=\"effectivePresentation ? effectivePresentationPreset : null\"\n [class.praxis-dynamic-form--corporate-dossier]=\"isCorporateDossierPreset()\"\n [class.praxis-dynamic-form--editorial-card]=\"isEditorialCardPreset()\"\n [class.praxis-dynamic-form--compact-presentation]=\"isCompactPresentationPreset()\"\n [class.editorial-visual-context]=\"hasEditorialVisualContext()\"\n [class.pfx-mounting]=\"isMounting\" [formGroup]=\"form\"\n [ngClass]=\"{\n 'pres-compact': presentationVars.compact,\n 'pres-label-left': presentationVars.labelPosition === 'left',\n 'pres-label-above': presentationVars.labelPosition === 'above'\n }\" [style.--pfx-pres-label-align]=\"presentationVars.labelAlign\"\n [style.--pfx-pres-label-size]=\"presentationVars.labelSize\"\n [style.--pfx-pres-label-width]=\"presentationVars.labelWidth\"\n [style.--pfx-pres-row-gap]=\"presentationVars.density === 'compact' ? '6px' : (presentationVars.density === 'cozy' ? '8px' : '10px')\"\n [style.--pfx-pres-row-padding]=\"presentationVars.density === 'compact' ? '2px 0' : (presentationVars.density === 'cozy' ? '6px 0' : '8px 0')\"\n [style.--pfx-pres-value-align]=\"presentationVars.valueAlign\"\n [style.--pfx-pres-value-size]=\"presentationVars.valueSize\"\n [style.--pdx-form-mount-duration]=\"getMountDurationVar()\"\n [style.--pdx-form-mount-offset]=\"getMountOffsetVar()\"\n [style.--pdx-form-mount-stagger]=\"getMountStaggerVar()\"\n class=\"praxis-dynamic-form\">\n @if (enableCustomization && selectedElement) {\n <praxis-canvas-toolbar (editMetadata)=\"openSelectedElementEditor()\" (selectPath)=\"onSelectPath($event)\"\n (moveUp)=\"onToolbarMove('up')\" (moveDown)=\"onToolbarMove('down')\" (toggleReadonly)=\"onToolbarToggleReadonly()\"\n (toggleRequired)=\"onToolbarToggleRequired()\" (toggleHidden)=\"onToolbarToggleHidden()\"\n (toggleDisabled)=\"onToolbarToggleDisabled()\" (requestClose)=\"onToolbarRequestClose()\"\n [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n }\n\n @if (formBlocksBefore?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n <!-- Tab Layout Navigation Bar -->\n @if (effectiveLayoutMode === 'tabs' && effectiveTabs.length > 1) {\n <nav class=\"prx-form-tabs\" [attr.data-appearance]=\"effectiveTabsAppearance\" role=\"tablist\" aria-label=\"Navega\u00E7\u00E3o em abas do formul\u00E1rio\">\n <div class=\"prx-form-tabs__tablist prx-form-tabs__tablist--scrollable\">\n @for (tab of effectiveTabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"prx-form-tabs__tab\"\n [class.prx-form-tabs__tab--active]=\"activeTabId === tab.id\"\n [attr.aria-selected]=\"activeTabId === tab.id\"\n [attr.aria-controls]=\"getTabAriaControls(tab)\"\n [attr.id]=\"'tab-' + tab.id\"\n [disabled]=\"tab.disabled\"\n [matTooltip]=\"tab.tooltip || null\"\n [matTooltipDisabled]=\"!tab.tooltip\"\n (click)=\"selectTab(tab.id)\"\n >\n @if (tab.icon) {\n <mat-icon class=\"prx-form-tabs__tab-icon\" [praxisIcon]=\"tab.icon\" aria-hidden=\"true\"></mat-icon>\n }\n <span class=\"prx-form-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge != null) {\n <span class=\"prx-form-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n @if (getTabErrorCount(tab) > 0) {\n <span class=\"prx-form-tabs__tab-error-badge\" [attr.aria-label]=\"getTabErrorCount(tab) + ' erros na aba'\">\n {{ getTabErrorCount(tab) }}\n </span>\n }\n </button>\n }\n </div>\n </nav>\n }\n\n @for (section of (config.sections || []); track (section.id ?? $index); let sectionIndex = $index) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\" [hidden]=\"!isSectionInActiveTab(section)\"\n [attr.role]=\"effectiveLayoutMode === 'tabs' ? 'tabpanel' : null\"\n [attr.id]=\"effectiveLayoutMode === 'tabs' ? ('section-tabpanel-' + section.id) : null\"\n [attr.aria-labelledby]=\"effectiveLayoutMode === 'tabs' ? ('tab-' + (getTabIdForSection(section) || section.id)) : null\">\n @if (isSectionVisible(section)) {\n <div #sectionEl class=\"form-section canvas-element\" data-canvas-type=\"section\" [attr.data-section-id]=\"section.id\"\n [attr.data-section-index]=\"sectionIndex\" (mouseenter)=\"onElementMouseEnter($event, 'section', section, sectionEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'section', section, sectionEl)\"\n [class.selected]=\"selectedElement?.domElement === sectionEl\"\n [class.hovered]=\"hoveredElement?.domElement === sectionEl && selectedElement?.domElement !== sectionEl\"\n [attr.data-section-appearance]=\"getSectionAppearance(section) || null\"\n [attr.data-section-divider]=\"isSectionDividerEnabled(section) ? 'true' : null\"\n [attr.data-presentation-preset]=\"effectivePresentation ? getSectionPresentationPreset(section) : null\"\n [class.form-section--corporate-dossier]=\"isSectionCorporateDossier(section)\"\n [class.form-section--editorial-card]=\"isSectionEditorialCard(section)\"\n [class.form-section--compact-presentation]=\"isSectionCompactPresentation(section)\"\n [style.marginBottom.px]=\"!isLastVisibleSection(section) ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n @if (!shouldHideSectionHeader(section)) {\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n [class.title-only]=\"isSectionHeaderTitleOnly(section)\"\n >\n <div class=\"section-heading-text\" [matTooltip]=\"getSectionHeaderTooltip(section) || null\"\n [matTooltipDisabled]=\"!getSectionHeaderTooltip(section)\">\n @if (getSectionStepLabel(section)) {\n <div class=\"section-step-label\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionStepLabel(section) }}\n </div>\n }\n @if (getSectionTitle(section)) {\n <h3 class=\"section-title\" [class.title-large]=\"getSectionTitleStyle(section) === 'titleLarge'\"\n [class.title-medium]=\"getSectionTitleStyle(section) === 'titleMedium'\"\n [class.title-small]=\"getSectionTitleStyle(section) === 'titleSmall'\"\n [class.headline-small]=\"getSectionTitleStyle(section) === 'headlineSmall'\"\n [style.marginBottom.px]=\"getEffectiveSectionTitleGapBottom(section)\" [style.color]=\"getSectionTitleColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [attr.id]=\"sectionPanelId(section, sectionIndex) + '-title'\">\n @let sectionHeaderVisual = getSectionHeaderVisual(section);\n @let sectionHeaderAvatarSize = getSectionHeaderAvatarSize(section);\n @if (sectionHeaderVisual.kind === 'icon') {\n <mat-icon class=\"section-title-icon\" aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.kind === 'image') {\n <img class=\"section-title-avatar section-title-avatar-image\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\"\n [src]=\"sectionHeaderVisual.src\" [alt]=\"sectionHeaderVisual.alt\" />\n }\n @if (sectionHeaderVisual.kind === 'initials') {\n <span class=\"section-title-avatar section-title-avatar-text\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n {{ sectionHeaderVisual.text }}\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n @if (sectionHeaderVisual.kind === 'placeholder') {\n <span class=\"section-title-avatar section-title-avatar-placeholder\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n @if (sectionHeaderVisual.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.text) {\n <span>{{ sectionHeaderVisual.text }}</span>\n }\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n {{ getSectionTitle(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" praxisIconButton=\"edit\" size=\"dense\" (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\n </button>\n }\n </h3>\n }\n @if (getSectionDescription(section)) {\n <p class=\"section-description\" [class.body-large]=\"getSectionDescriptionStyle(section) === 'bodyLarge'\"\n [class.body-medium]=\"getSectionDescriptionStyle(section) === 'bodyMedium'\"\n [class.body-small]=\"getSectionDescriptionStyle(section) === 'bodySmall'\"\n [style.marginBottom.px]=\"getSectionDescriptionGapBottom(section) ?? 8\" [style.color]=\"getSectionDescriptionColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionDescription(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" praxisIconButton=\"edit\" size=\"dense\"\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\n </button>\n }\n </p>\n }\n </div>\n @if (getSectionHeaderActions(section).length) {\n <div class=\"section-heading-actions\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n @for (action of getSectionHeaderActions(section); track action.id) {\n <button\n type=\"button\"\n class=\"section-heading-action-btn\"\n [praxisIconButton]=\"action.icon\"\n size=\"compact\"\n [busy]=\"action.loading\"\n [disabled]=\"isSectionHeaderActionDisabled(action)\"\n [matTooltip]=\"getSectionHeaderActionTooltip(action)\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-busy]=\"action.loading ? 'true' : null\"\n [ngClass]=\"getSectionHeaderActionNgClass(action)\"\n [ngStyle]=\"getSectionHeaderActionStyles(action)\"\n (click)=\"onSectionHeaderActionClick(section, action, $event)\"\n >\n @if (action.loading) {\n <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" [praxisIconButton]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\" size=\"compact\"\n (click)=\"toggleSectionCollapse($event, section)\" [attr.aria-expanded]=\"!isSectionCollapsed(section)\"\n [attr.aria-controls]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-label]=\"isSectionCollapsed(section) ? 'Expandir se\u00E7\u00E3o' : 'Recolher se\u00E7\u00E3o'\">\n </button>\n }\n </div>\n }\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.role]=\"getSectionTitle(section) ? 'region' : null\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @for (row of section.rows; track (row.id ?? $index); let rowIndex = $index) {\n @if (isRowVisible(row)) {\n <div class=\"row-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n <div #rowEl class=\"form-row grid-12 canvas-element\" data-canvas-type=\"row\" [attr.data-row-index]=\"rowIndex\"\n [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\" [style.--pfx-grid-gap.px]=\"getRowGap(row)\"\n [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [style.--pfx-mount-index]=\"rowIndex\"\n [style.marginBottom.px]=\"rowIndex < section.rows.length - 1 ? (getRowRowGap(row) ?? null) : null\"\n [ngClass]=\"getRowClasses(row)\" [ngStyle]=\"getRowStyles(row)\"\n (mouseenter)=\"onElementMouseEnter($event, 'row', row, rowEl)\" (mouseleave)=\"onElementMouseLeave($event)\"\n (click)=\"onElementClick($event, 'row', row, rowEl)\" [class.selected]=\"selectedElement?.domElement === rowEl\"\n [class.hovered]=\"hoveredElement?.domElement === rowEl && selectedElement?.domElement !== rowEl\">\n @for (column of row.columns; track (column.id ?? $index); let colIndex = $index) {\n @if (isColumnVisible(column)) {\n <div class=\"column-drop-wrapper\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\">\n <div #colEl class=\"form-column canvas-element\" [ngClass]=\"getColumnClasses(column, row)\"\n [style.padding.px]=\"getColumnPadding(column)\" [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [ngStyle]=\"getColumnStyles(column)\" [attr.data-testid]=\"column.testId || null\"\n [attr.data-row-gap]=\"getRowRowGap(row)\" data-canvas-type=\"column\" [attr.data-column-index]=\"colIndex\"\n [attr.data-row-index]=\"rowIndex\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\"\n [attr.data-column-id]=\"column.id\" (mouseenter)=\"onElementMouseEnter($event, 'column', column, colEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'column', column, colEl)\"\n [class.selected]=\"selectedElement?.domElement === colEl\"\n [class.hovered]=\"hoveredElement?.domElement === colEl && selectedElement?.domElement !== colEl\">\n @for (renderItem of getColumnRenderItems(column); track renderItem.id) {\n @if (renderItem.kind === 'fields') {\n <ng-container dynamicFieldLoader [fields]=\"getRenderableFieldsForLoader(renderItem.fields)\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"effectiveReadonly\"\n [disabledMode]=\"effectiveDisabledMode\"\n [presentationMode]=\"presentationForLoader\" [visible]=\"visibleGlobal === null ? null : visibleGlobal\"\n [canvasMode]=\"enableCustomization\" (canvasMouseEnter)=\"onFieldMouseEnter($event)\"\n (canvasMouseLeave)=\"onFieldMouseLeave($event)\" (canvasClick)=\"onFieldClick($event)\"\n (canvasFocus)=\"onFieldFocus($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [ngClass]=\"renderItem.className || null\"\n [ngStyle]=\"renderItem.style || null\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n }\n }\n </div>\n </div>\n } }\n </div>\n </div>\n }\n }\n } @else {\n <div class=\"section-collapsed-placeholder\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'unfold_more'\"></mat-icon>\n <span>{{ getSectionCollapsedSummary(section) }}</span>\n </div>\n }\n @if (isLastVisibleSection(section) && beforeActionsPlacement === 'insideLastSection' && formBlocksBeforeActions?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && isLastVisibleSection(section) && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"effectiveActions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n </div>\n <!-- Overlay de bloqueio durante submiss\u00E3o -->\n @if (submitting) {\n <div class=\"form-blocking-overlay\" aria-live=\"polite\">\n <mat-progress-spinner\n diameter=\"40\"\n color=\"primary\"\n [attr.aria-label]=\"config.messages?.loading?.submit || 'Salvando formul\u00E1rio'\"\n ></mat-progress-spinner>\n <p>{{ config.messages?.loading?.submit || 'Salvando...' }}</p>\n </div>\n }\n </div>\n\n @if (enableCustomization && selectedElement?.domElement === sectionEl) {\n <div class=\"add-section-container\">\n <div class=\"add-section-line\"></div>\n <button mat-fab color=\"primary\" aria-label=\"Adicionar nova se\u00E7\u00E3o\" (click)=\"addNewSectionAfter(sectionIndex)\"\n matTooltip=\"Adicionar nova se\u00E7\u00E3o aqui\">\n <mat-icon [praxisIcon]=\"'add'\"></mat-icon>\n </button>\n <div class=\"add-section-line\"></div>\n </div>\n }\n }\n </div>\n }\n\n @if (beforeActionsPlacement !== 'insideLastSection' && formBlocksBeforeActions?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n <praxis-rich-content\n [document]=\"formBlocksAfterDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n </form>\n </div>\n }\n @if (showAiAssistant && !enableCustomization && (mode === 'view' || mode === 'presentation' || mode === 'dossier') && !shouldShowContextEmptyState()) {\n <div class=\"ai-floating-assistant\">\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"compact\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading || entityHydrationPending || entityReadFailed\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('view-floating')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Pedir ajuda sobre este formul\u00E1rio\">\n </button>\n </div>\n }\n @if (showAiAssistant && aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"dynamic-form-ai-assistant\"\n panelTestId=\"dynamic-form-ai-assistant-panel\"\n submitTestId=\"dynamic-form-ai-assistant-submit\"\n applyTestId=\"dynamic-form-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\n }\n }\n", styles: ["@charset \"UTF-8\";.span-xs-1{grid-column:span 1}.span-xs-2{grid-column:span 2}.span-xs-3{grid-column:span 3}.span-xs-4{grid-column:span 4}.span-xs-5{grid-column:span 5}.span-xs-6{grid-column:span 6}.span-xs-7{grid-column:span 7}.span-xs-8{grid-column:span 8}.span-xs-9{grid-column:span 9}.span-xs-10{grid-column:span 10}.span-xs-11{grid-column:span 11}.span-xs-12{grid-column:span 12}.offset-xs-0{margin-left:0%}.offset-xs-1{margin-left:calc(1 / 12 * 100%)}.offset-xs-2{margin-left:calc(2 / 12 * 100%)}.offset-xs-3{margin-left:25%}.offset-xs-4{margin-left:calc(4 / 12 * 100%)}.offset-xs-5{margin-left:calc(5 / 12 * 100%)}.offset-xs-6{margin-left:50%}.offset-xs-7{margin-left:calc(7 / 12 * 100%)}.offset-xs-8{margin-left:calc(8 / 12 * 100%)}.offset-xs-9{margin-left:75%}.offset-xs-10{margin-left:calc(10 / 12 * 100%)}.offset-xs-11{margin-left:calc(11 / 12 * 100%)}.order-xs--12{order:-12}.order-xs--11{order:-11}.order-xs--10{order:-10}.order-xs--9{order:-9}.order-xs--8{order:-8}.order-xs--7{order:-7}.order-xs--6{order:-6}.order-xs--5{order:-5}.order-xs--4{order:-4}.order-xs--3{order:-3}.order-xs--2{order:-2}.order-xs--1{order:-1}.order-xs-0{order:0}.order-xs-1{order:1}.order-xs-2{order:2}.order-xs-3{order:3}.order-xs-4{order:4}.order-xs-5{order:5}.order-xs-6{order:6}.order-xs-7{order:7}.order-xs-8{order:8}.order-xs-9{order:9}.order-xs-10{order:10}.order-xs-11{order:11}.order-xs-12{order:12}.hidden-xs{display:none}@container praxis-form-row (min-width: 600px){.span-sm-1{grid-column:span 1}.span-sm-2{grid-column:span 2}.span-sm-3{grid-column:span 3}.span-sm-4{grid-column:span 4}.span-sm-5{grid-column:span 5}.span-sm-6{grid-column:span 6}.span-sm-7{grid-column:span 7}.span-sm-8{grid-column:span 8}.span-sm-9{grid-column:span 9}.span-sm-10{grid-column:span 10}.span-sm-11{grid-column:span 11}.span-sm-12{grid-column:span 12}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:calc(1 / 12 * 100%)}.offset-sm-2{margin-left:calc(2 / 12 * 100%)}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:calc(4 / 12 * 100%)}.offset-sm-5{margin-left:calc(5 / 12 * 100%)}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:calc(7 / 12 * 100%)}.offset-sm-8{margin-left:calc(8 / 12 * 100%)}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:calc(10 / 12 * 100%)}.offset-sm-11{margin-left:calc(11 / 12 * 100%)}.order-sm--12{order:-12}.order-sm--11{order:-11}.order-sm--10{order:-10}.order-sm--9{order:-9}.order-sm--8{order:-8}.order-sm--7{order:-7}.order-sm--6{order:-6}.order-sm--5{order:-5}.order-sm--4{order:-4}.order-sm--3{order:-3}.order-sm--2{order:-2}.order-sm--1{order:-1}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.hidden-sm{display:none}}@container praxis-form-row (min-width: 900px){.span-md-1{grid-column:span 1}.span-md-2{grid-column:span 2}.span-md-3{grid-column:span 3}.span-md-4{grid-column:span 4}.span-md-5{grid-column:span 5}.span-md-6{grid-column:span 6}.span-md-7{grid-column:span 7}.span-md-8{grid-column:span 8}.span-md-9{grid-column:span 9}.span-md-10{grid-column:span 10}.span-md-11{grid-column:span 11}.span-md-12{grid-column:span 12}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:calc(1 / 12 * 100%)}.offset-md-2{margin-left:calc(2 / 12 * 100%)}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:calc(4 / 12 * 100%)}.offset-md-5{margin-left:calc(5 / 12 * 100%)}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:calc(7 / 12 * 100%)}.offset-md-8{margin-left:calc(8 / 12 * 100%)}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:calc(10 / 12 * 100%)}.offset-md-11{margin-left:calc(11 / 12 * 100%)}.order-md--12{order:-12}.order-md--11{order:-11}.order-md--10{order:-10}.order-md--9{order:-9}.order-md--8{order:-8}.order-md--7{order:-7}.order-md--6{order:-6}.order-md--5{order:-5}.order-md--4{order:-4}.order-md--3{order:-3}.order-md--2{order:-2}.order-md--1{order:-1}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.hidden-md{display:none}}@container praxis-form-row (min-width: 1200px){.span-lg-1{grid-column:span 1}.span-lg-2{grid-column:span 2}.span-lg-3{grid-column:span 3}.span-lg-4{grid-column:span 4}.span-lg-5{grid-column:span 5}.span-lg-6{grid-column:span 6}.span-lg-7{grid-column:span 7}.span-lg-8{grid-column:span 8}.span-lg-9{grid-column:span 9}.span-lg-10{grid-column:span 10}.span-lg-11{grid-column:span 11}.span-lg-12{grid-column:span 12}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:calc(1 / 12 * 100%)}.offset-lg-2{margin-left:calc(2 / 12 * 100%)}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:calc(4 / 12 * 100%)}.offset-lg-5{margin-left:calc(5 / 12 * 100%)}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:calc(7 / 12 * 100%)}.offset-lg-8{margin-left:calc(8 / 12 * 100%)}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:calc(10 / 12 * 100%)}.offset-lg-11{margin-left:calc(11 / 12 * 100%)}.order-lg--12{order:-12}.order-lg--11{order:-11}.order-lg--10{order:-10}.order-lg--9{order:-9}.order-lg--8{order:-8}.order-lg--7{order:-7}.order-lg--6{order:-6}.order-lg--5{order:-5}.order-lg--4{order:-4}.order-lg--3{order:-3}.order-lg--2{order:-2}.order-lg--1{order:-1}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.hidden-lg{display:none}}@container praxis-form-row (min-width: 1536px){.span-xl-1{grid-column:span 1}.span-xl-2{grid-column:span 2}.span-xl-3{grid-column:span 3}.span-xl-4{grid-column:span 4}.span-xl-5{grid-column:span 5}.span-xl-6{grid-column:span 6}.span-xl-7{grid-column:span 7}.span-xl-8{grid-column:span 8}.span-xl-9{grid-column:span 9}.span-xl-10{grid-column:span 10}.span-xl-11{grid-column:span 11}.span-xl-12{grid-column:span 12}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:calc(1 / 12 * 100%)}.offset-xl-2{margin-left:calc(2 / 12 * 100%)}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:calc(4 / 12 * 100%)}.offset-xl-5{margin-left:calc(5 / 12 * 100%)}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:calc(7 / 12 * 100%)}.offset-xl-8{margin-left:calc(8 / 12 * 100%)}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:calc(10 / 12 * 100%)}.offset-xl-11{margin-left:calc(11 / 12 * 100%)}.order-xl--12{order:-12}.order-xl--11{order:-11}.order-xl--10{order:-10}.order-xl--9{order:-9}.order-xl--8{order:-8}.order-xl--7{order:-7}.order-xl--6{order:-6}.order-xl--5{order:-5}.order-xl--4{order:-4}.order-xl--3{order:-3}.order-xl--2{order:-2}.order-xl--1{order:-1}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.hidden-xl{display:none}}.canvas-mode-enabled{--canvas-hit: 14px}.canvas-mode-enabled .canvas-element{position:relative;z-index:0;border-radius:8px;outline:2px solid transparent;outline-offset:2px;transition:outline-color .2s ease,outline-style .2s ease}.canvas-mode-enabled .canvas-element:before{content:\"\";position:absolute;inset:calc(-1 * var(--canvas-hit));pointer-events:none;border-radius:inherit;background:transparent}.canvas-mode-enabled .canvas-element[data-canvas-type=section]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element[data-canvas-type=row]{--outline-color: var(--md-sys-color-secondary)}.canvas-mode-enabled .canvas-element[data-canvas-type=column],.canvas-mode-enabled .canvas-element[data-canvas-type=field]{--outline-color: var(--md-sys-color-tertiary)}.canvas-mode-enabled .canvas-element[data-canvas-type=actions]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element.hovered:not(.selected){outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:dashed}.canvas-mode-enabled .canvas-element.selected{outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:solid;box-shadow:0 0 0 2px var(--outline-color, var(--md-sys-color-primary))}.canvas-mode-enabled .canvas-element.hovered{z-index:var(--praxis-layer-authoring-hover, 300)}.canvas-mode-enabled .canvas-element.selected{z-index:var(--praxis-layer-authoring-selected, 320)}.section-drop-wrapper,.row-drop-wrapper,.column-drop-wrapper{display:contents}.add-section-container{display:flex;align-items:center;justify-content:center;padding:.5rem 0;margin:-.5rem 0;position:relative;z-index:var(--praxis-layer-authoring-insert, 280)}.add-section-container .add-section-line{flex-grow:1;height:1px;background:repeating-linear-gradient(90deg,var(--md-sys-color-outline-variant),var(--md-sys-color-outline-variant) 4px,transparent 4px,transparent 8px)}.add-section-container button{margin:0 1rem;transform:scale(.85)}:host{display:block;position:relative;--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--pdx-color-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent );--pfx-form-shell-padding: clamp(.9rem, 1.4vw, 1.2rem)}.form-config-controls{position:relative;top:auto;margin:0;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--pfx-form-shell-surface) 88%,var(--md-sys-color-surface) 12%);padding:8px var(--pfx-form-shell-padding);border:1px solid var(--pfx-form-footer-border);border-bottom-color:color-mix(in srgb,var(--pfx-form-footer-border) 72%,transparent);border-radius:var(--pfx-editorial-form-radius) var(--pfx-editorial-form-radius) 0 0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:none;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.96;transition:opacity .16s ease,border-color .16s ease}.form-config-controls>*{pointer-events:auto}.form-config-controls:hover,.form-config-controls:focus-within{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%)}.form-config-controls .praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}.form-config-controls .praxis-icon-button:hover{color:var(--md-sys-color-primary)}.ai-floating-assistant{position:sticky;right:0;bottom:12px;margin-top:14px;margin-left:auto;width:fit-content;z-index:70;pointer-events:none}.ai-floating-assistant button{pointer-events:auto;display:inline-flex}.ai-floating-assistant .ai-trigger-btn{box-shadow:0 12px 28px #0f172a24}.config-button{color:var(--md-sys-color-primary)}.form-loading{display:flex;flex-direction:column;align-items:stretch;justify-content:center;padding:1.25rem;text-align:left;color:var(--md-sys-color-on-surface);gap:1rem;min-height:220px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,var(--md-sys-color-outline-variant) 86%);border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent 42%),color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,var(--md-sys-color-surface) 22%);box-shadow:0 12px 28px #0f172a14}.entity-read-region{position:relative;min-width:0}.entity-read-feedback{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:1rem;padding:2rem 1rem;box-sizing:border-box;text-align:center;color:var(--md-sys-color-on-surface)}.entity-read-feedback p{margin:0;max-width:40ch}.form-loading-header{display:flex;align-items:center;gap:.85rem}.form-loading-copy{min-width:0}.form-loading p{margin:0}.form-loading-title{font-weight:700;color:var(--md-sys-color-on-surface)}.form-loading-subtitle{margin-top:.2rem;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.form-loading-skeleton{display:grid;gap:.7rem}.form-loading-line,.form-loading-field{display:block;overflow:hidden;position:relative;border-radius:6px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,var(--md-sys-color-primary) 6%)}.form-loading-line:after,.form-loading-field:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 16%,var(--md-sys-color-on-surface) 18%),transparent);animation:form-loading-shimmer 1.4s ease-in-out infinite}.form-loading-line{height:12px}.form-loading-line-title{width:min(42%,240px)}.form-loading-line-short{width:min(64%,360px)}.form-loading-field{height:44px}.form-loading-field-wide{height:72px}@keyframes form-loading-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.form-loading-line:after,.form-loading-field:after{animation:none;transform:none;opacity:.28}}.form-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-error);gap:1rem;border:1px solid var(--md-sys-color-error);border-radius:8px;background-color:var(--md-sys-color-error-container);margin:1rem;box-shadow:0 12px 30px #7f1d1d1f}.form-error h3{margin:0;color:var(--md-sys-color-on-error-container)}.form-error p{margin:0;color:var(--md-sys-color-on-error-container);opacity:.8}.form-error button{margin-top:.5rem}.pfx-form-info-banner{margin-bottom:14px;padding:12px 14px;border-radius:16px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant) 82%);background:color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface) 76%);color:var(--md-sys-color-on-surface);display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.pfx-form-info-banner .text{font-size:.92rem;line-height:1.5;font-weight:600}.pfx-form-info-banner .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.praxis-dynamic-form{display:flex;flex-direction:column;max-width:100%;min-width:0;transition:all .3s ease;position:relative;font-family:inherit;font-size:inherit;color:inherit;--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--md-sys-color-surface-container) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --pdx-color-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --pdx-color-text-secondary, var(--md-sys-color-on-surface-variant) );--pfx-editorial-form-field-surface: color-mix( in srgb, var(--pfx-editorial-form-surface-muted) 76%, var(--pfx-editorial-form-surface) 24% );--pfx-editorial-form-field-outline: color-mix( in srgb, var(--pfx-editorial-form-border) 88%, transparent );--pfx-editorial-form-accent: var( --pdx-color-primary, var(--md-sys-color-primary) );--pfx-editorial-form-accent-text: var(--md-sys-color-on-primary);--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-field-radius: var(--pfx-form-field-radius, 4px);--pfx-editorial-form-border-width: 1px;--pfx-editorial-form-field-border-width: 1px;--pfx-editorial-form-shadow: none;--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-surface-flat: color-mix( in srgb, var(--pfx-editorial-form-surface) 78%, var(--pfx-editorial-form-surface-muted) 22% );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-label-strong: color-mix( in srgb, var(--pfx-editorial-form-text) 96%, white 4% );--pfx-form-label-muted: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 92%, var(--pfx-editorial-form-text) 8% );--pfx-form-field-surface-rest: color-mix( in srgb, var(--pfx-editorial-form-field-surface) 82%, var(--pfx-editorial-form-surface) 18% );--pfx-form-field-surface-focus: color-mix( in srgb, var(--pfx-editorial-form-accent) 4%, var(--pfx-form-field-surface-rest) 96% );--pfx-form-field-min-height: 48px;--pfx-form-section-padding: clamp(1.1rem, 1.8vw, 1.5rem);--pfx-form-section-gap: 22px;--pdx-presentation-label-size: var(--pfx-pres-compact-label-size, .78rem);--pdx-presentation-value-size: var(--pfx-pres-compact-value-size, 1rem);--pdx-presentation-icon-size: var(--pfx-pres-icon-size, 18px);--pdx-presentation-row-gap: var(--pfx-pres-row-gap, .5rem);--pdx-presentation-column-gap: var(--pfx-pres-column-gap, .5rem);--pdx-presentation-section-gap: var(--pfx-pres-section-gap, .75rem);--pdx-presentation-label-width: var(--pfx-pres-label-width, 220px);--pdx-presentation-flag-height: var(--pfx-pres-boolean-min-height, 22px);--pdx-presentation-flag-radius: var(--pfx-pres-boolean-radius, 999px);--pdx-presentation-flag-padding: var(--pfx-pres-boolean-padding, 0 8px);--pdx-presentation-flag-active-color: var( --pfx-pres-boolean-active-color, var(--md-sys-color-primary) );--pdx-presentation-flag-active-bg: var( --pfx-pres-boolean-active-bg, color-mix(in srgb, var(--md-sys-color-primary) 14%, transparent) );--pdx-presentation-flag-inactive-color: var( --pfx-pres-boolean-inactive-color, var(--md-sys-color-on-surface-variant) );--pdx-presentation-flag-inactive-bg: var( --pfx-pres-boolean-inactive-bg, color-mix(in srgb, var(--md-sys-color-outline-variant) 34%, transparent) );--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent )}.praxis-dynamic-form.canvas-mode-enabled{border:1px solid var(--pfx-form-footer-border);border-radius:var(--pfx-editorial-form-radius);background:linear-gradient(180deg,color-mix(in srgb,var(--pfx-form-shell-surface) 86%,transparent),color-mix(in srgb,var(--pfx-editorial-form-surface-muted) 42%,transparent));overflow:visible}.form-config-controls+.praxis-dynamic-form.canvas-mode-enabled{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks{margin-inline:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper:first-of-type,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks:first-child{margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>praxis-form-actions[data-actions-placement=afterSections]{display:block;margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.editorial-visual-context{--_pfx-editorial-host-text: var( --editorial-text-primary, var(--foreground, var(--mat-sys-on-surface, #1d1b20)) );--_pfx-editorial-host-text-muted: var( --editorial-text-secondary, var( --muted-foreground, color-mix(in srgb, var(--_pfx-editorial-host-text) 64%, transparent) ) );--_pfx-editorial-host-surface: var( --editorial-surface-primary, var(--card, var(--mat-sys-surface-container, #ffffff)) );--_pfx-editorial-host-surface-muted: var( --editorial-surface-secondary, var(--surface-dim, var(--muted, var(--mat-sys-surface-container-low, #f7f2fa))) );--_pfx-editorial-host-border: var( --editorial-border-color, var(--border, var(--mat-sys-outline-variant, #cac4d0)) );--_pfx-editorial-host-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--primary, var(--mat-sys-primary, #6750a4))) );--_pfx-editorial-host-accent-text: var( --editorial-cta-primary-text, var( --editorial-accent-contrast, var(--primary-foreground, var(--mat-sys-on-primary, #ffffff)) ) );--_pfx-editorial-host-accent-container: var( --primary-container, color-mix(in srgb, var(--_pfx-editorial-host-accent) 16%, var(--_pfx-editorial-host-surface) 84%) );--_pfx-editorial-host-accent-container-text: var( --primary-container-fg, var(--_pfx-editorial-host-accent) );font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--_pfx-editorial-host-text);--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--_pfx-editorial-host-surface)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--_pfx-editorial-host-surface-muted) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--_pfx-editorial-host-border)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--_pfx-editorial-host-text) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, color-mix( in srgb, var(--_pfx-editorial-host-text-muted) 86%, var(--_pfx-editorial-host-text) 14% ) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--_pfx-editorial-host-accent)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--_pfx-editorial-host-accent-text)) );--pfx-editorial-form-accent-container: var(--_pfx-editorial-host-accent-container);--pfx-editorial-form-accent-container-text: var(--_pfx-editorial-host-accent-container-text);--pfx-editorial-form-radius: var(--editorial-card-radius, 18px);--pfx-editorial-form-field-radius: var( --editorial-field-radius, var(--editorial-card-radius, 14px) );--pfx-editorial-form-border-width: var(--editorial-card-border-width, 1px);--pfx-editorial-form-field-border-width: var(--editorial-field-border-width, 1px);--pfx-editorial-form-shadow: var(--editorial-card-shadow, none);--md-sys-color-surface: var( --pfx-editorial-form-surface, var(--md-sys-color-surface) );--md-sys-color-surface-container: var( --pfx-editorial-form-surface, var(--md-sys-color-surface-container) );--md-sys-color-surface-container-low: var( --pfx-editorial-form-surface-muted, var(--md-sys-color-surface-container-low) );--md-sys-color-surface-variant: var( --pfx-editorial-form-field-surface, var(--md-sys-color-surface-variant) );--md-sys-color-outline: var( --pfx-editorial-form-field-outline, var(--md-sys-color-outline) );--md-sys-color-outline-variant: var( --pfx-editorial-form-border, var(--md-sys-color-outline-variant) );--md-sys-color-on-surface: var( --editorial-text-primary, inherit );--md-sys-color-on-surface-variant: var( --editorial-text-secondary, inherit );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-primary-container: var( --pfx-editorial-form-accent-container, var(--md-sys-color-primary-container) );--md-sys-color-on-primary-container: var( --pfx-editorial-form-accent-container-text, var(--md-sys-color-on-primary-container) );--md-sys-color-on-primary: var( --pfx-editorial-form-accent-text, var(--md-sys-color-on-primary) );--md-sys-color-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );--mat-sys-on-surface: var( --editorial-text-primary, inherit );--mat-sys-on-surface-variant: var( --editorial-text-secondary, inherit );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );color:inherit;color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:var(--pdx-presentation-column-gap);margin-bottom:var(--pdx-presentation-row-gap)}.praxis-dynamic-form.presentation-mode{--pfx-pres-on-surface: var( --pdx-color-text-primary, var(--pfx-editorial-form-text, var(--pfx-form-label-strong, currentColor)) );--pfx-pres-on-surface-variant: var( --pdx-color-text-secondary, var( --pfx-editorial-form-text-muted, var( --pfx-form-label-muted, color-mix(in srgb, var(--pfx-pres-on-surface) 78%, transparent) ) ) )}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:var(--pdx-presentation-section-gap) .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:var(--pdx-presentation-column-gap, .35rem);margin-bottom:var(--pdx-presentation-row-gap, .35rem)}.praxis-dynamic-form.pres-compact .form-section{padding:var(--pdx-presentation-section-gap, .5rem) .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:minmax(0,var(--pfx-presentation-label-w, var(--pdx-presentation-label-width))) minmax(0,1fr);align-items:baseline;column-gap:var(--pdx-presentation-column-gap, 10px)}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}@media(max-width:480px){.praxis-dynamic-form.pres-label-left .praxis-presentation{grid-template-columns:minmax(0,1fr);row-gap:4px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:start}}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low, #f8f9fa);border:1px solid var(--md-sys-color-outline-variant, #e0e2ec);border-radius:16px;padding:16px 20px;box-shadow:0 1px 3px #0000000a}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-heading{margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--md-sys-color-outline-variant, #e0e2ec)}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-title,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-title{font-size:.88rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--md-sys-color-primary, #005ac1)}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation{padding:8px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep .form-section--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=corporate-dossier] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__label,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:3px}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__value,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__value{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.4}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low, var(--mat-sys-surface-container-low)));border:1px solid var(--pfx-editorial-form-border, var(--md-sys-color-outline-variant, #e0e2ec));border-radius:20px;padding:24px;box-shadow:0 2px 8px #0000000d}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--editorial-card .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-heading{margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 40%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-title,.praxis-dynamic-form .form-section.form-section--editorial-card .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-title{font-size:1.15rem;font-weight:700;color:var(--pfx-editorial-form-accent, var(--md-sys-color-primary, #005ac1))}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation{padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 35%,transparent)}:host ::ng-deep .praxis-dynamic-form--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation:last-child,:host ::ng-deep .form-section--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=editorial-card] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__label,:host ::ng-deep .form-section--editorial-card .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__label{font-size:.8rem;font-weight:500;color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant, #44474f));margin-bottom:4px}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__value,:host ::ng-deep .form-section--editorial-card .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__value{font-size:1rem;font-weight:600;color:var(--pfx-editorial-form-text, var(--md-sys-color-on-surface, #1a1c1e));line-height:1.5}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--compact-presentation:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation]:not(.section-appearance-plain){background:transparent;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 50%,transparent);border-radius:8px;padding:10px 14px;box-shadow:none}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-heading{margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 25%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-title,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-title{font-size:.82rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #44474f)}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation,:host ::ng-deep .form-section--compact-presentation .praxis-presentation,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation{padding:4px 0;border-bottom:none}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__label,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__label{font-size:.72rem;font-weight:600;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:2px}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__value,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__value{font-size:.88rem;font-weight:500;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.35}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 2px 8px #0000004d}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low));border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 4px 16px #0006}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);max-width:100%;min-width:0;background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section:not(.section-appearance-plain){border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;color:var(--pfx-editorial-form-text);box-shadow:var(--editorial-card-shadow, none)}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{background-color:var(--pfx-editorial-form-surface)!important;background-image:linear-gradient(180deg,color-mix(in srgb,var(--editorial-accent, var(--md-sys-color-primary)) 6%,transparent) 0%,transparent 132px)!important;background-repeat:no-repeat!important}.section-drop-wrapper>.form-section{margin-bottom:var(--pfx-section-gap, 20px)}.section-drop-wrapper:last-of-type>.form-section{margin-bottom:0}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections]{margin-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}.section-title{margin:0 0 var(--pfx-section-title-mb, 12px) 0;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.12rem);font-weight:700;color:var(--pfx-form-label-strong)}.section-heading{position:relative;display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 18px)}.section-heading:after{content:\"\";position:absolute;right:0;bottom:0;left:0;height:2px;pointer-events:none;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 8%,var(--pfx-form-section-divider) 46%,var(--pfx-form-section-divider) 54%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 92%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%);mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 10px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:none}.section-heading.align-center{flex-direction:column;align-items:center;text-align:center}.section-heading.align-center .section-heading-text{display:grid;justify-items:center}.section-step-label{display:inline-flex;align-items:center;min-height:24px;padding:0 10px;margin:0 0 8px;border-radius:999px;background:color-mix(in srgb,var(--pfx-editorial-form-accent) 10%,transparent);color:color-mix(in srgb,var(--pfx-editorial-form-accent) 84%,var(--pfx-form-label-strong) 16%);font-size:.72rem;font-weight:800;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));letter-spacing:.08em;text-transform:uppercase}.section-heading-text{flex:1 1 auto;min-width:0}.section-heading-actions{display:inline-flex;align-items:center;align-self:flex-start;flex-wrap:wrap;gap:4px;margin-left:auto}.section-heading-actions.align-center{align-self:center;margin-left:0}.section-heading-action-btn{color:var(--pfx-form-label-muted)}.section-heading-action-btn.tone-primary{color:var(--md-sys-color-primary)}.section-heading-action-btn.tone-accent,.section-heading-action-btn.tone-secondary{color:var(--md-sys-color-tertiary)}.section-heading-action-btn.tone-warn,.section-heading-action-btn.tone-danger,.section-heading-action-btn.tone-error{color:var(--md-sys-color-error)}.section-heading-action-btn .mat-mdc-progress-spinner,.section-heading-action-btn mat-progress-spinner{--mdc-circular-progress-active-indicator-color: currentColor}.section-heading-action-btn.loading{opacity:.72;pointer-events:none}.section-heading-action-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.section-collapse-btn{margin-left:4px;color:var(--pfx-form-label-muted)}.section-title.title-large{font:var(--mdc-typography-title-large, 500 22px/28px system-ui)}.section-title.title-medium{font:var(--mdc-typography-title-medium, 500 16px/24px system-ui)}.section-title.title-small{font:var(--mdc-typography-title-small, 500 14px/20px system-ui)}.section-title.headline-small{font:var(--mdc-typography-headline-small, 600 24px/32px system-ui)}.section-title.title-large,.section-title.title-medium,.section-title.title-small,.section-title.headline-small{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-weight:var(--editorial-title-weight, 600)}.section-description{margin:0;font-family:var(--editorial-body-font-family, inherit);font-size:.93rem;color:var(--pfx-form-label-muted);line-height:1.6}.section-description.body-large{font:var(--mdc-typography-body-large, 400 16px/24px system-ui)}.section-description.body-medium{font:var(--mdc-typography-body-medium, 400 14px/20px system-ui)}.section-description.body-small{font:var(--mdc-typography-body-small, 400 12px/16px system-ui)}.section-description.body-large,.section-description.body-medium,.section-description.body-small{font-family:var(--editorial-body-font-family, inherit);font-weight:var(--editorial-body-weight, 400)}.section-title.align-center,.section-description.align-center,.section-step-label.align-center{text-align:center}.praxis-dynamic-form .form-section.section-appearance-plain{border-color:transparent;border-width:0;border-radius:0;padding:0;background:transparent;box-shadow:none}.praxis-dynamic-form .form-section.section-appearance-plain.section-has-divider{padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider, var(--md-sys-color-outline-variant, #e0e2ec))}.praxis-dynamic-form .section-drop-wrapper:last-of-type>.form-section.section-appearance-plain.section-has-divider,.praxis-dynamic-form>.form-section.section-appearance-plain.section-has-divider:last-of-type{border-bottom:none;padding-bottom:0}.form-section.section-appearance-plain .section-heading{margin-bottom:14px}.form-section.section-appearance-step{border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);border-color:var(--pfx-form-section-divider);box-shadow:none}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{border-radius:var(--editorial-card-radius, 20px);box-shadow:none}.form-section.section-appearance-step .section-heading{margin-bottom:22px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 16px)}.form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 16px)}:host(.pfx-form-section-divider-inline-title) .form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}.form-section.section-appearance-step .section-title{font:var(--mdc-typography-title-large, 700 22px/28px system-ui);color:var(--pfx-form-label-strong);margin-bottom:8px}.form-section.section-appearance-step .section-description{color:var(--pfx-form-label-muted);max-width:60ch}.form-section.section-appearance-step .section-step-label{min-height:24px;padding:0 10px;margin-bottom:10px;box-shadow:none}.form-section.section-appearance-step .section-heading.align-center .section-description{max-width:52ch}.form-section.section-appearance-step .section-body{display:grid;gap:8px;padding-top:0}.form-section.section-appearance-step .form-row{margin-bottom:var(--pfx-field-gap, 1rem)}.form-section.section-appearance-step .form-column{gap:var(--pfx-field-gap, 12px)}.form-section .form-editorial-blocks{display:grid;gap:16px}.form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{margin-top:24px;padding-top:18px;border-top:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]{gap:18px}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]>*+*{margin-top:2px}.praxis-dynamic-form:not(.canvas-mode-enabled)>praxis-form-actions[data-actions-placement=afterSections]{margin-top:18px}.praxis-dynamic-form>.form-editorial-blocks[data-editorial-placement=after]{margin-top:6px}:host-context(.mdc-theme-dark) .form-section.section-appearance-step,:host-context(.theme-dark) .form-section.section-appearance-step{border-color:color-mix(in srgb,var(--pfx-editorial-form-border) 82%,transparent);box-shadow:none}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-title,:host-context(.theme-dark) .form-section.section-appearance-step .section-title{color:color-mix(in srgb,var(--pfx-editorial-form-text) 96%,white)}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-description,:host-context(.theme-dark) .form-section.section-appearance-step .section-description{color:color-mix(in srgb,var(--pfx-editorial-form-text-muted) 86%,var(--pfx-editorial-form-text) 14%)}:host-context(.mdc-theme-dark) .section-step-label,:host-context(.theme-dark) .section-step-label{background:color-mix(in srgb,var(--md-sys-color-primary-container) 54%,transparent);color:color-mix(in srgb,var(--md-sys-color-primary) 88%,white)}:host-context(.mdc-theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions],:host-context(.theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{border-top-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 90%,transparent)}.inline-edit-btn{margin-left:6px;vertical-align:middle}.section-body.collapsed{border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);border-radius:6px;padding:8px 10px}.section-collapsed-placeholder{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.95rem}.section-collapsed-placeholder mat-icon{font-size:20px;width:20px;height:20px}.form-row{display:flex;gap:1.1rem;margin-bottom:var(--pfx-field-gap, 1.1rem);max-width:100%;min-width:0;transition:all .2s ease;border-radius:6px;position:relative}.praxis-dynamic-form.pfx-mounting .form-row{opacity:0;transform:translateY(var(--pdx-form-mount-offset, 6px));animation:pdxFormMount var(--pdx-form-mount-duration, .16s) ease-out both;animation-delay:calc(var(--pfx-mount-index, 0) * var(--pdx-form-mount-stagger, 20ms))}@media(prefers-reduced-motion:reduce){.praxis-dynamic-form.pfx-mounting .form-row{animation:none;opacity:1;transform:none}}@keyframes pdxFormMount{to{opacity:1;transform:translateY(0)}}.praxis-dynamic-form .mat-mdc-form-field{width:100%;margin-bottom:var(--pfx-field-gap, 10px);font-family:inherit;--mdc-filled-text-field-container-color: var(--pfx-form-field-surface-rest);--mdc-filled-text-field-focus-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-active-indicator-color: var(--pfx-editorial-form-field-outline);--mdc-filled-text-field-hover-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-filled-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-caret-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-input-text-placeholder-color: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 82%, transparent );--mdc-outlined-text-field-outline-color: var(--pfx-editorial-form-field-outline);--mdc-outlined-text-field-hover-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-outlined-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-outlined-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-filled-text-field-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-filled-text-field-focus-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-outline-width: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-focus-outline-width: var(--pfx-editorial-form-field-border-width);--mat-select-enabled-trigger-text-color: var(--pfx-editorial-form-text);--mat-select-enabled-arrow-color: var(--pfx-form-label-muted);--mat-form-field-enabled-select-arrow-color: var(--pfx-form-label-muted);--mat-form-field-focus-select-arrow-color: var(--pfx-editorial-form-accent);--mat-form-field-hover-state-layer-opacity: 0;--mat-form-field-focus-state-layer-opacity: 0}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field{font-family:var(--editorial-body-font-family, inherit)}.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{background:var(--pfx-form-field-surface-rest);border-radius:var(--pfx-editorial-form-field-radius);min-height:var(--pfx-form-field-min-height);transition:background-color .16s ease,box-shadow .16s ease,border-color .16s ease}.praxis-dynamic-form.editorial-visual-context .mat-mdc-text-field-wrapper,.praxis-dynamic-form.editorial-visual-context .mdc-text-field,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--filled,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--outlined{background-color:var(--pfx-form-field-surface-rest)!important;background:var(--pfx-form-field-surface-rest)!important}.praxis-dynamic-form .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-form-label-muted)}.praxis-dynamic-form .mat-mdc-input-element,.praxis-dynamic-form .mat-mdc-select-value-text,.praxis-dynamic-form .mat-mdc-form-field-infix,.praxis-dynamic-form .mat-mdc-select-min-line{color:var(--pfx-editorial-form-text)}.praxis-dynamic-form .mat-mdc-form-field:hover .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field:hover .mdc-text-field,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mdc-text-field{background:var(--pfx-form-field-surface-focus)}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-value-text,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field-infix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-min-line,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input{color:var(--pfx-editorial-form-text)!important;-webkit-text-fill-color:var(--pfx-editorial-form-text)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-editorial-form-text-muted)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 68%,transparent)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element::placeholder,.praxis-dynamic-form.editorial-visual-context textarea.mat-mdc-input-element::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 58%,transparent)!important}.praxis-dynamic-form .mat-mdc-radio-button,.praxis-dynamic-form .mat-mdc-checkbox,.praxis-dynamic-form .mat-mdc-slide-toggle{--mdc-radio-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-checkmark-color: var(--pfx-editorial-form-accent-text);--mdc-checkbox-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-focus-state-layer-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-handle-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-track-color: color-mix(in srgb, var(--pfx-editorial-form-accent) 45%, #fff)}.praxis-dynamic-form [data-field-type=input],.praxis-dynamic-form [data-field-type=textarea],.praxis-dynamic-form [data-field-type=email],.praxis-dynamic-form [data-field-type=password],.praxis-dynamic-form [data-field-type=url],.praxis-dynamic-form [data-field-type=search],.praxis-dynamic-form [data-field-type=phone],.praxis-dynamic-form [data-field-type=numericTextBox],.praxis-dynamic-form [data-field-type=currency],.praxis-dynamic-form [data-field-type=cpfCnpj],.praxis-dynamic-form [data-field-type=date],.praxis-dynamic-form [data-field-type=dateInput],.praxis-dynamic-form [data-field-type=dateRange],.praxis-dynamic-form [data-field-type=dateTimeLocal],.praxis-dynamic-form [data-field-type=time],.praxis-dynamic-form [data-field-type=timePicker],.praxis-dynamic-form [data-field-type=timeRange],.praxis-dynamic-form [data-field-type=month],.praxis-dynamic-form [data-field-type=week],.praxis-dynamic-form [data-field-type=yearInput],.praxis-dynamic-form [data-field-type=select],.praxis-dynamic-form [data-field-type=multi-select],.praxis-dynamic-form [data-field-type=searchable-select],.praxis-dynamic-form [data-field-type=async-select],.praxis-dynamic-form [data-field-type=autocomplete],.praxis-dynamic-form [data-field-type=entityLookup],.praxis-dynamic-form [data-field-type=tree-select],.praxis-dynamic-form [data-field-type=multi-select-tree],.praxis-dynamic-form [data-field-type=priceRange],.praxis-dynamic-form [data-field-type=file-upload]{display:block;width:100%;min-width:0}.praxis-dynamic-form .mat-mdc-form-field-subscript-wrapper{min-height:var(--pfx-subscript-min-h, 22px)}.form-row:last-child{margin-bottom:0}.form-column{display:grid;grid-template-columns:minmax(0,1fr);align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;max-width:100%;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-layout-rich-content{display:block;width:100%;max-width:100%;min-width:0;margin-bottom:var(--pfx-field-gap, 10px);color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant));font:var(--mdc-typography-body-medium, 400 14px/20px system-ui);overflow-wrap:anywhere}:host ::ng-deep .form-layout-rich-content .prx-rich-content-root{display:grid;gap:8px;min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-node{min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-text{color:inherit;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{border:1px solid color-mix(in srgb,var(--pfx-editorial-form-accent) 12%,var(--pfx-editorial-form-border) 88%);border-left:3px solid var(--pfx-editorial-form-accent);border-radius:8px;background:color-mix(in srgb,var(--pfx-editorial-form-accent-container) 12%,var(--pfx-editorial-form-surface-muted) 88%)}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;align-items:flex-start;padding:11px 12px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note:before{content:\"info\";display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--pfx-editorial-form-accent);font-family:Material Symbols Outlined;font-size:20px;font-weight:400;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{padding:10px 12px;color:var(--pfx-editorial-form-text)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-compose{align-items:flex-start;gap:10px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-icon{color:var(--pfx-editorial-form-accent);font-size:20px;line-height:20px;margin-top:1px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider{display:grid;grid-template-columns:minmax(24px,1fr) auto minmax(24px,1fr);align-items:center;gap:10px;color:var(--pfx-editorial-form-text-muted);font:var(--mdc-typography-label-small, 600 12px/16px system-ui);text-transform:uppercase}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:before,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:after{content:\"\";height:1px;background:var(--pfx-editorial-form-border)}:host ::ng-deep .form-layout-rich-content .prx-rich-card{gap:6px;padding:12px 14px;border-color:var(--pfx-editorial-form-border);border-radius:8px;background:var(--pfx-editorial-form-surface-muted);color:var(--pfx-editorial-form-text);box-shadow:none}:host ::ng-deep .form-layout-rich-content .prx-rich-card-title{color:var(--pfx-editorial-form-text);font:var(--mdc-typography-title-small, 600 14px/20px system-ui)}:host ::ng-deep .form-layout-rich-content .prx-rich-card-subtitle,:host ::ng-deep .form-layout-rich-content .prx-rich-metric-caption{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-card .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-badge{background:var(--pfx-editorial-form-accent-container);color:var(--pfx-editorial-form-accent-container-text)}.form-row.grid-12{container-type:inline-size;container-name:praxis-form-row;display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.align-start{align-self:flex-start}.align-center{align-self:center}.align-end{align-self:flex-end}.align-stretch{align-self:stretch}.form-blocking-overlay{position:absolute;inset:0;background:transparent;color:var(--md-sys-color-on-surface);backdrop-filter:blur(2px) saturate(103%);-webkit-backdrop-filter:blur(2px) saturate(103%);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;z-index:10;pointer-events:all}@media(max-width:768px){.column-drop-wrapper,.row-drop-wrapper,.form-layout-rich-content,.praxis-dynamic-form .mat-mdc-form-field,.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{max-width:100%;min-width:0}:host ::ng-deep .praxis-dynamic-form .pfx-field-shell,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-wrapper,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-host,:host ::ng-deep .praxis-dynamic-form .mat-mdc-form-field,:host ::ng-deep .praxis-dynamic-form .mat-mdc-text-field-wrapper,:host ::ng-deep .praxis-dynamic-form .mdc-text-field{width:100%;max-width:100%;min-width:0}.form-section{padding:clamp(.75rem,4vw,1rem)}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 14px)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}}.section-title{display:flex;align-items:center;gap:8px}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:100%;min-width:0}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{content:\"\";display:block;flex:1 1 auto;min-width:var(--pfx-form-section-title-inline-divider-min-width, 48px);height:2px;margin-left:var(--pfx-form-section-title-inline-divider-gap, 12px);pointer-events:none;background:linear-gradient(90deg,var(--pfx-form-section-divider) 0%,var(--pfx-form-section-divider) 62%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 88%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%);mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%)}:host(.pfx-form-section-divider-inline-title) .section-heading.align-center .section-title:after{display:none}@media(max-width:640px){:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:block}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:auto}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{display:none}}.section-title .section-title-icon{font-size:1.25em;line-height:1}.section-title-avatar{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px));display:inline-flex;align-items:center;justify-content:center;width:var(--_pfx-form-section-avatar-size);height:var(--_pfx-form-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-form-section-avatar-size);overflow:hidden}.section-title-avatar.size-sm{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-title-avatar.size-md{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-title-avatar.size-lg{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-title-avatar-image{object-fit:cover;border:1px solid color-mix(in srgb,var(--pfx-form-section-divider) 72%,transparent);background:var(--pfx-form-section-surface-flat)}.section-title-avatar-text,.section-title-avatar-placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent) 14%,var(--pfx-form-section-surface-flat));color:color-mix(in srgb,var(--pfx-editorial-form-accent) 82%,var(--pfx-form-label-strong) 18%);font-size:calc(var(--_pfx-form-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-title-avatar-placeholder mat-icon{font-size:calc(var(--_pfx-form-section-avatar-size) * .5625);width:calc(var(--_pfx-form-section-avatar-size) * .5625);height:calc(var(--_pfx-form-section-avatar-size) * .5625);line-height:calc(var(--_pfx-form-section-avatar-size) * .5625)}.section-title-avatar-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.form-context-empty-state{display:grid;min-height:var(--pdx-form-context-empty-min-height, 0);place-items:center;padding:var(--pdx-form-context-empty-padding, 0)}.form-context-empty-state praxis-empty-state-card{display:block;width:min(100%,var(--pdx-form-context-empty-max-width, 32rem))}.prx-form-tabs{display:block;margin-bottom:16px;max-width:100%}.prx-form-tabs__tablist{display:flex;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%}.prx-form-tabs__tablist--scrollable{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:4px 2px}.prx-form-tabs__tablist--scrollable::-webkit-scrollbar{display:none}.prx-form-tabs__tab{display:inline-flex;align-items:center;gap:8px;min-width:0;padding:8px 14px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:color-mix(in srgb,var(--md-sys-color-surface, transparent) 40%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);font-family:inherit;font-size:.84rem;font-weight:500;cursor:pointer;white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none;transition:all .2s cubic-bezier(.2,0,0,1)}.prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:var(--md-sys-color-surface-container-high, rgba(0, 0, 0, .05));border-color:var(--md-sys-color-outline, rgba(0, 0, 0, .24));color:var(--md-sys-color-on-surface)}.prx-form-tabs__tab:focus-visible{outline:2px solid var(--md-sys-color-primary, #005ac1);outline-offset:2px}.prx-form-tabs__tab:disabled{cursor:not-allowed;opacity:.45}.prx-form-tabs__tab--active{background:var(--md-sys-color-primary-container, color-mix(in srgb, var(--md-sys-color-primary, #005ac1) 16%, var(--md-sys-color-surface-container-high, #2b2930)));color:var(--md-sys-color-on-primary-container, var(--md-sys-color-primary, #005ac1));border-color:transparent;font-weight:600;box-shadow:0 1px 3px #00000014}.prx-form-tabs__tab-icon{font-size:18px;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center}.prx-form-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;padding:1px 7px;font-size:.72rem;font-weight:600;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent)}.prx-form-tabs__tab-error-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;font-size:.7rem;font-weight:700;background:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-on-error, #ffffff);box-shadow:0 1px 2px #0003}.prx-form-tabs[data-appearance=underline]{border-bottom:1px solid var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tablist{gap:16px;padding-bottom:0}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab{border:none;border-radius:0;border-bottom:2px solid transparent;background:transparent;padding:8px 4px 10px;margin-bottom:-1px}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:transparent;border-bottom-color:var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab--active{background:transparent;box-shadow:none;border-bottom-color:var(--md-sys-color-primary, #005ac1);color:var(--md-sys-color-primary, #005ac1)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tablist{background:var(--md-sys-color-surface-container, rgba(0, 0, 0, .04));border-radius:12px;padding:4px;gap:4px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab{border:none;border-radius:8px;padding:6px 12px;background:transparent}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:color-mix(in srgb,currentColor 8%,transparent)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab--active{background:var(--md-sys-color-surface, var(--mat-sys-surface));color:var(--md-sys-color-primary, #005ac1);box-shadow:0 1px 3px #0000001f}.section-drop-wrapper[hidden]{display:none!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick", "canvasFocus"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i17.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i19.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: CanvasToolbarComponent, selector: "praxis-canvas-toolbar", inputs: ["selectedElement"], outputs: ["editMetadata", "delete", "moveUp", "moveDown", "selectPath", "requestClose", "toggleReadonly", "toggleRequired", "toggleHidden", "toggleDisabled"] }, { kind: "component", type: PraxisFormActionsComponent, selector: "praxis-form-actions", inputs: ["actions", "editorialVisualContext", "isSubmitting", "formIsValid", "submitError", "invalidRequiredFieldLabels", "suppressInvalidSubmitHint", "formId", "actionOverrides"], outputs: ["action"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone", "variant", "alignment", "density", "iconContainer"] }, { 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"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }] });
22143
+ ], viewQueries: [{ propertyName: "formHost", first: true, predicate: ["formHost"], descendants: true }, { propertyName: "fieldLoaders", predicate: DynamicFieldLoaderDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (isLoading) {\n <!-- Loading State -->\n <div class=\"form-loading\" role=\"status\" aria-live=\"polite\" aria-label=\"Carregando formul\u00E1rio\">\n <div class=\"form-loading-header\">\n <mat-progress-spinner diameter=\"32\" aria-label=\"Carregando formul\u00E1rio\"></mat-progress-spinner>\n <div class=\"form-loading-copy\">\n <p class=\"form-loading-title\">Carregando formul\u00E1rio...</p>\n <p class=\"form-loading-subtitle\">Preparando campos e op\u00E7\u00F5es do cadastro.</p>\n </div>\n </div>\n <div class=\"form-loading-skeleton\" aria-hidden=\"true\">\n <span class=\"form-loading-line form-loading-line-title\"></span>\n <span class=\"form-loading-line\"></span>\n <span class=\"form-loading-line form-loading-line-short\"></span>\n <span class=\"form-loading-field\"></span>\n <span class=\"form-loading-field form-loading-field-wide\"></span>\n </div>\n </div>\n} @else if (initializationStatus === 'error') {\n <!-- Error State -->\n <div class=\"form-error\">\n <mat-icon color=\"warn\" [praxisIcon]=\"'error'\"></mat-icon>\n <h3>{{ getErrorTitle() }}</h3>\n <p>{{ currentErrorMessage }}</p>\n @if (isRecoverable) {\n <button mat-stroked-button (click)=\"retryInitialization()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n Tentar Novamente\n </button>\n }\n <button mat-button (click)=\"showDetailedError()\" class=\"show-details\">\n Ver Detalhes T\u00E9cnicos\n </button>\n <!-- Permitir corre\u00E7\u00E3o do resourcePath diretamente do estado de erro -->\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\" class=\"connect-action\">\n <mat-icon [praxisIcon]=\"'bolt'\"></mat-icon>\n Conectar a recurso\n </button>\n </div>\n} @else if (initializationStatus === 'success') {\n <!-- Inline banner for schema change (only when customization is enabled) -->\n @if (shouldShowOutdatedInline()) {\n <div class=\"pfx-form-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"openConfigEditor()\">\n <mat-icon [praxisIcon]=\"'sync'\"></mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n </div>\n }\n\n <!-- Configuration Controls -->\n @if (shouldShowConfigControls && enableCustomization) {\n <div class=\"form-config-controls\">\n @if (showAiAssistant) {\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"dense\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('config-controls')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Abrir copiloto sem\u00E2ntico do formul\u00E1rio\">\n </button>\n }\n <button type=\"button\" praxisIconButton=\"settings\" size=\"dense\" (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [attr.aria-label]=\"configControlLabel\" [matTooltip]=\"configControlLabel\">\n </button>\n <button type=\"button\" praxisIconButton=\"link_off\" size=\"dense\" (click)=\"disconnect()\"\n [attr.aria-label]=\"disconnectControlLabel\" [matTooltip]=\"disconnectControlLabel\"\n [disabled]=\"isLoading\">\n </button>\n </div>\n }\n\n <!-- Form Content -->\n @if (!resourcePath && !hasExplicitSchemaUrl() && !hasRenderableConfig()) {\n <praxis-empty-state-card\n icon=\"link\"\n [title]=\"'Conecte o formul\u00E1rio \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para gerar automaticamente os campos do formul\u00E1rio.'\"\n [primaryAction]=\"enableCustomization ? { label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) } : undefined\"\n ></praxis-empty-state-card>\n }\n @if (shouldShowContextEmptyState()) {\n <div class=\"form-context-empty-state\" role=\"status\" aria-live=\"polite\">\n <praxis-empty-state-card\n [icon]=\"emptyState?.icon || 'touch_app'\"\n [title]=\"emptyState!.title\"\n [description]=\"emptyState?.description\"\n [tone]=\"emptyState?.tone || 'primary'\"\n [variant]=\"emptyState?.variant || 'transparent'\"\n [alignment]=\"emptyState?.alignment || 'center'\"\n [density]=\"emptyState?.density || 'compact'\"\n [iconContainer]=\"emptyState?.iconContainer || 'circle'\"\n [inline]=\"true\"\n />\n </div>\n } @else {\n <div #entityReadRegion class=\"entity-read-region\" tabindex=\"-1\" role=\"region\" [attr.aria-label]=\"entityReadText('region')\">\n <span class=\"cdk-visually-hidden\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ entityReadStatusText() }}</span>\n @if (entityHydrationPending || entityReadFailed) {\n <div class=\"entity-read-feedback\" data-testid=\"form-entity-read-feedback\">\n @if (entityHydrationPending) {\n <mat-progress-spinner diameter=\"28\" mode=\"indeterminate\" aria-hidden=\"true\"></mat-progress-spinner>\n <p class=\"entity-read-loading-text\" aria-hidden=\"true\">{{ entityReadText('loading') }}</p>\n } @else {\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <p aria-hidden=\"true\">{{ entityReadText('error') }}</p>\n <button mat-stroked-button type=\"button\" (click)=\"retryEntityRead(entityReadRegion)\">{{ entityReadText('retry') }}</button>\n }\n </div>\n }\n <form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting || entityHydrationPending ? 'true' : null\"\n [style.opacity]=\"entityHydrationPending || entityReadFailed ? '0' : null\"\n [style.transition]=\"entityHydrationPending || entityReadFailed ? 'none' : null\"\n [attr.inert]=\"entityHydrationPending || entityReadFailed ? '' : null\"\n [attr.aria-hidden]=\"entityHydrationPending || entityReadFailed ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\"\n [class.praxis-dynamic-form--presentation]=\"effectivePresentation\"\n [class.readonly-mode]=\"effectiveReadonly\"\n [attr.data-presentation-preset]=\"effectivePresentation ? effectivePresentationPreset : null\"\n [class.praxis-dynamic-form--corporate-dossier]=\"isCorporateDossierPreset()\"\n [class.praxis-dynamic-form--editorial-card]=\"isEditorialCardPreset()\"\n [class.praxis-dynamic-form--compact-presentation]=\"isCompactPresentationPreset()\"\n [class.editorial-visual-context]=\"hasEditorialVisualContext()\"\n [class.pfx-mounting]=\"isMounting\" [formGroup]=\"form\"\n [ngClass]=\"{\n 'pres-compact': presentationVars.compact,\n 'pres-label-left': presentationVars.labelPosition === 'left',\n 'pres-label-above': presentationVars.labelPosition === 'above'\n }\" [style.--pfx-pres-label-align]=\"presentationVars.labelAlign\"\n [style.--pfx-pres-label-size]=\"presentationVars.labelSize\"\n [style.--pfx-pres-label-width]=\"presentationVars.labelWidth\"\n [style.--pfx-pres-row-gap]=\"presentationVars.density === 'compact' ? '6px' : (presentationVars.density === 'cozy' ? '8px' : '10px')\"\n [style.--pfx-pres-row-padding]=\"presentationVars.density === 'compact' ? '2px 0' : (presentationVars.density === 'cozy' ? '6px 0' : '8px 0')\"\n [style.--pfx-pres-value-align]=\"presentationVars.valueAlign\"\n [style.--pfx-pres-value-size]=\"presentationVars.valueSize\"\n [style.--pdx-form-mount-duration]=\"getMountDurationVar()\"\n [style.--pdx-form-mount-offset]=\"getMountOffsetVar()\"\n [style.--pdx-form-mount-stagger]=\"getMountStaggerVar()\"\n class=\"praxis-dynamic-form\">\n @if (enableCustomization && selectedElement) {\n <praxis-canvas-toolbar (editMetadata)=\"openSelectedElementEditor()\" (selectPath)=\"onSelectPath($event)\"\n (moveUp)=\"onToolbarMove('up')\" (moveDown)=\"onToolbarMove('down')\" (toggleReadonly)=\"onToolbarToggleReadonly()\"\n (toggleRequired)=\"onToolbarToggleRequired()\" (toggleHidden)=\"onToolbarToggleHidden()\"\n (toggleDisabled)=\"onToolbarToggleDisabled()\" (requestClose)=\"onToolbarRequestClose()\"\n [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n }\n\n @if (formBlocksBefore?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n <!-- Tab Layout Navigation Bar -->\n @if (effectiveLayoutMode === 'tabs' && effectiveTabs.length > 1) {\n <nav class=\"prx-form-tabs\" [attr.data-appearance]=\"effectiveTabsAppearance\" role=\"tablist\" aria-label=\"Navega\u00E7\u00E3o em abas do formul\u00E1rio\">\n <div class=\"prx-form-tabs__tablist prx-form-tabs__tablist--scrollable\">\n @for (tab of effectiveTabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"prx-form-tabs__tab\"\n [class.prx-form-tabs__tab--active]=\"activeTabId === tab.id\"\n [attr.aria-selected]=\"activeTabId === tab.id\"\n [attr.aria-controls]=\"getTabAriaControls(tab)\"\n [attr.id]=\"'tab-' + tab.id\"\n [disabled]=\"tab.disabled\"\n [matTooltip]=\"tab.tooltip || null\"\n [matTooltipDisabled]=\"!tab.tooltip\"\n (click)=\"selectTab(tab.id)\"\n >\n @if (tab.icon) {\n <mat-icon class=\"prx-form-tabs__tab-icon\" [praxisIcon]=\"tab.icon\" aria-hidden=\"true\"></mat-icon>\n }\n <span class=\"prx-form-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge != null) {\n <span class=\"prx-form-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n @if (getTabErrorCount(tab) > 0) {\n <span class=\"prx-form-tabs__tab-error-badge\" [attr.aria-label]=\"getTabErrorCount(tab) + ' erros na aba'\">\n {{ getTabErrorCount(tab) }}\n </span>\n }\n </button>\n }\n </div>\n </nav>\n }\n\n @for (section of (config.sections || []); track (section.id ?? $index); let sectionIndex = $index) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\" [hidden]=\"!isSectionInActiveTab(section)\"\n [attr.role]=\"effectiveLayoutMode === 'tabs' ? 'tabpanel' : null\"\n [attr.id]=\"effectiveLayoutMode === 'tabs' ? ('section-tabpanel-' + section.id) : null\"\n [attr.aria-labelledby]=\"effectiveLayoutMode === 'tabs' ? ('tab-' + (getTabIdForSection(section) || section.id)) : null\">\n @if (isSectionVisible(section)) {\n <div #sectionEl class=\"form-section canvas-element\" data-canvas-type=\"section\" [attr.data-section-id]=\"section.id\"\n [attr.data-section-index]=\"sectionIndex\" (mouseenter)=\"onElementMouseEnter($event, 'section', section, sectionEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'section', section, sectionEl)\"\n [class.selected]=\"selectedElement?.domElement === sectionEl\"\n [class.hovered]=\"hoveredElement?.domElement === sectionEl && selectedElement?.domElement !== sectionEl\"\n [attr.data-section-appearance]=\"getSectionAppearance(section) || null\"\n [attr.data-section-divider]=\"isSectionDividerEnabled(section) ? 'true' : null\"\n [attr.data-presentation-preset]=\"effectivePresentation ? getSectionPresentationPreset(section) : null\"\n [class.form-section--corporate-dossier]=\"isSectionCorporateDossier(section)\"\n [class.form-section--editorial-card]=\"isSectionEditorialCard(section)\"\n [class.form-section--compact-presentation]=\"isSectionCompactPresentation(section)\"\n [style.marginBottom.px]=\"!isLastVisibleSection(section) ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n @if (!shouldHideSectionHeader(section)) {\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n [class.title-only]=\"isSectionHeaderTitleOnly(section)\"\n >\n <div class=\"section-heading-text\" [matTooltip]=\"getSectionHeaderTooltip(section) || null\"\n [matTooltipDisabled]=\"!getSectionHeaderTooltip(section)\">\n @if (getSectionStepLabel(section)) {\n <div class=\"section-step-label\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionStepLabel(section) }}\n </div>\n }\n @if (getSectionTitle(section)) {\n <h3 class=\"section-title\" [class.title-large]=\"getSectionTitleStyle(section) === 'titleLarge'\"\n [class.title-medium]=\"getSectionTitleStyle(section) === 'titleMedium'\"\n [class.title-small]=\"getSectionTitleStyle(section) === 'titleSmall'\"\n [class.headline-small]=\"getSectionTitleStyle(section) === 'headlineSmall'\"\n [style.marginBottom.px]=\"getEffectiveSectionTitleGapBottom(section)\" [style.color]=\"getSectionTitleColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [attr.id]=\"sectionPanelId(section, sectionIndex) + '-title'\">\n @let sectionHeaderVisual = getSectionHeaderVisual(section);\n @let sectionHeaderAvatarSize = getSectionHeaderAvatarSize(section);\n @if (sectionHeaderVisual.kind === 'icon') {\n <mat-icon class=\"section-title-icon\" aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.kind === 'image') {\n <img class=\"section-title-avatar section-title-avatar-image\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\"\n [src]=\"sectionHeaderVisual.src\" [alt]=\"sectionHeaderVisual.alt\" />\n }\n @if (sectionHeaderVisual.kind === 'initials') {\n <span class=\"section-title-avatar section-title-avatar-text\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n {{ sectionHeaderVisual.text }}\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n @if (sectionHeaderVisual.kind === 'placeholder') {\n <span class=\"section-title-avatar section-title-avatar-placeholder\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n @if (sectionHeaderVisual.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.text) {\n <span>{{ sectionHeaderVisual.text }}</span>\n }\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n {{ getSectionTitle(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" praxisIconButton=\"edit\" size=\"dense\" (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\n </button>\n }\n </h3>\n }\n @if (getSectionDescription(section)) {\n <p class=\"section-description\" [class.body-large]=\"getSectionDescriptionStyle(section) === 'bodyLarge'\"\n [class.body-medium]=\"getSectionDescriptionStyle(section) === 'bodyMedium'\"\n [class.body-small]=\"getSectionDescriptionStyle(section) === 'bodySmall'\"\n [style.marginBottom.px]=\"getSectionDescriptionGapBottom(section) ?? 8\" [style.color]=\"getSectionDescriptionColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionDescription(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" praxisIconButton=\"edit\" size=\"dense\"\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\n </button>\n }\n </p>\n }\n </div>\n @if (getSectionHeaderActions(section).length) {\n <div class=\"section-heading-actions\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n @for (action of getSectionHeaderActions(section); track action.id) {\n <button\n type=\"button\"\n class=\"section-heading-action-btn\"\n [praxisIconButton]=\"action.icon\"\n size=\"compact\"\n [busy]=\"action.loading\"\n [disabled]=\"isSectionHeaderActionDisabled(action)\"\n [matTooltip]=\"getSectionHeaderActionTooltip(action)\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-busy]=\"action.loading ? 'true' : null\"\n [ngClass]=\"getSectionHeaderActionNgClass(action)\"\n [ngStyle]=\"getSectionHeaderActionStyles(action)\"\n (click)=\"onSectionHeaderActionClick(section, action, $event)\"\n >\n @if (action.loading) {\n <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" [praxisIconButton]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\" size=\"compact\"\n (click)=\"toggleSectionCollapse($event, section)\" [attr.aria-expanded]=\"!isSectionCollapsed(section)\"\n [attr.aria-controls]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-label]=\"isSectionCollapsed(section) ? 'Expandir se\u00E7\u00E3o' : 'Recolher se\u00E7\u00E3o'\">\n </button>\n }\n </div>\n }\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.role]=\"getSectionTitle(section) ? 'region' : null\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @for (row of section.rows; track (row.id ?? $index); let rowIndex = $index) {\n @if (isRowVisible(row)) {\n <div class=\"row-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n <div #rowEl class=\"form-row grid-12 canvas-element\" data-canvas-type=\"row\" [attr.data-row-index]=\"rowIndex\"\n [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\" [style.--pfx-grid-gap.px]=\"getRowGap(row)\"\n [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [style.--pfx-mount-index]=\"rowIndex\"\n [style.marginBottom.px]=\"rowIndex < section.rows.length - 1 ? (getRowRowGap(row) ?? null) : null\"\n [ngClass]=\"getRowClasses(row)\" [ngStyle]=\"getRowStyles(row)\"\n (mouseenter)=\"onElementMouseEnter($event, 'row', row, rowEl)\" (mouseleave)=\"onElementMouseLeave($event)\"\n (click)=\"onElementClick($event, 'row', row, rowEl)\" [class.selected]=\"selectedElement?.domElement === rowEl\"\n [class.hovered]=\"hoveredElement?.domElement === rowEl && selectedElement?.domElement !== rowEl\">\n @for (column of row.columns; track (column.id ?? $index); let colIndex = $index) {\n @if (isColumnVisible(column)) {\n <div class=\"column-drop-wrapper\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\">\n <div #colEl class=\"form-column canvas-element\" [ngClass]=\"getColumnClasses(column, row)\"\n [style.padding.px]=\"getColumnPadding(column)\" [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [ngStyle]=\"getColumnStyles(column)\" [attr.data-testid]=\"column.testId || null\"\n [attr.data-row-gap]=\"getRowRowGap(row)\" data-canvas-type=\"column\" [attr.data-column-index]=\"colIndex\"\n [attr.data-row-index]=\"rowIndex\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\"\n [attr.data-column-id]=\"column.id\" (mouseenter)=\"onElementMouseEnter($event, 'column', column, colEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'column', column, colEl)\"\n [class.selected]=\"selectedElement?.domElement === colEl\"\n [class.hovered]=\"hoveredElement?.domElement === colEl && selectedElement?.domElement !== colEl\">\n @for (renderItem of getColumnRenderItems(column); track renderItem.id) {\n @if (renderItem.kind === 'fields') {\n <ng-container dynamicFieldLoader [fields]=\"getRenderableFieldsForLoader(renderItem.fields)\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"effectiveReadonly\"\n [disabledMode]=\"effectiveDisabledMode\"\n [presentationMode]=\"presentationForLoader\" [visible]=\"visibleGlobal === null ? null : visibleGlobal\"\n [canvasMode]=\"enableCustomization\" (canvasMouseEnter)=\"onFieldMouseEnter($event)\"\n (canvasMouseLeave)=\"onFieldMouseLeave($event)\" (canvasClick)=\"onFieldClick($event)\"\n (canvasFocus)=\"onFieldFocus($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [ngClass]=\"renderItem.className || null\"\n [ngStyle]=\"renderItem.style || null\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n }\n }\n </div>\n </div>\n } }\n </div>\n </div>\n }\n }\n } @else {\n <div class=\"section-collapsed-placeholder\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'unfold_more'\"></mat-icon>\n <span>{{ getSectionCollapsedSummary(section) }}</span>\n </div>\n }\n @if (isLastVisibleSection(section) && beforeActionsPlacement === 'insideLastSection' && formBlocksBeforeActions?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && isLastVisibleSection(section) && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"effectiveActions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n </div>\n <!-- Overlay de bloqueio durante submiss\u00E3o -->\n @if (submitting) {\n <div class=\"form-blocking-overlay\" aria-live=\"polite\">\n <mat-progress-spinner\n diameter=\"40\"\n color=\"primary\"\n [attr.aria-label]=\"config.messages?.loading?.submit || 'Salvando formul\u00E1rio'\"\n ></mat-progress-spinner>\n <p>{{ config.messages?.loading?.submit || 'Salvando...' }}</p>\n </div>\n }\n </div>\n\n @if (enableCustomization && selectedElement?.domElement === sectionEl) {\n <div class=\"add-section-container\">\n <div class=\"add-section-line\"></div>\n <button mat-fab color=\"primary\" aria-label=\"Adicionar nova se\u00E7\u00E3o\" (click)=\"addNewSectionAfter(sectionIndex)\"\n matTooltip=\"Adicionar nova se\u00E7\u00E3o aqui\">\n <mat-icon [praxisIcon]=\"'add'\"></mat-icon>\n </button>\n <div class=\"add-section-line\"></div>\n </div>\n }\n }\n </div>\n }\n\n @if (beforeActionsPlacement !== 'insideLastSection' && formBlocksBeforeActions?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n <praxis-rich-content\n [document]=\"formBlocksAfterDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n </form>\n </div>\n }\n @if (showAiAssistant && !enableCustomization && (mode === 'view' || mode === 'presentation' || mode === 'dossier') && !shouldShowContextEmptyState()) {\n <div class=\"ai-floating-assistant\">\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"compact\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading || entityHydrationPending || entityReadFailed\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('view-floating')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Pedir ajuda sobre este formul\u00E1rio\">\n </button>\n </div>\n }\n @if (showAiAssistant && aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"dynamic-form-ai-assistant\"\n panelTestId=\"dynamic-form-ai-assistant-panel\"\n submitTestId=\"dynamic-form-ai-assistant-submit\"\n applyTestId=\"dynamic-form-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\n }\n }\n", styles: ["@charset \"UTF-8\";.span-xs-1{grid-column:span 1}.span-xs-2{grid-column:span 2}.span-xs-3{grid-column:span 3}.span-xs-4{grid-column:span 4}.span-xs-5{grid-column:span 5}.span-xs-6{grid-column:span 6}.span-xs-7{grid-column:span 7}.span-xs-8{grid-column:span 8}.span-xs-9{grid-column:span 9}.span-xs-10{grid-column:span 10}.span-xs-11{grid-column:span 11}.span-xs-12{grid-column:span 12}.offset-xs-0{margin-left:0%}.offset-xs-1{margin-left:calc(1 / 12 * 100%)}.offset-xs-2{margin-left:calc(2 / 12 * 100%)}.offset-xs-3{margin-left:25%}.offset-xs-4{margin-left:calc(4 / 12 * 100%)}.offset-xs-5{margin-left:calc(5 / 12 * 100%)}.offset-xs-6{margin-left:50%}.offset-xs-7{margin-left:calc(7 / 12 * 100%)}.offset-xs-8{margin-left:calc(8 / 12 * 100%)}.offset-xs-9{margin-left:75%}.offset-xs-10{margin-left:calc(10 / 12 * 100%)}.offset-xs-11{margin-left:calc(11 / 12 * 100%)}.order-xs--12{order:-12}.order-xs--11{order:-11}.order-xs--10{order:-10}.order-xs--9{order:-9}.order-xs--8{order:-8}.order-xs--7{order:-7}.order-xs--6{order:-6}.order-xs--5{order:-5}.order-xs--4{order:-4}.order-xs--3{order:-3}.order-xs--2{order:-2}.order-xs--1{order:-1}.order-xs-0{order:0}.order-xs-1{order:1}.order-xs-2{order:2}.order-xs-3{order:3}.order-xs-4{order:4}.order-xs-5{order:5}.order-xs-6{order:6}.order-xs-7{order:7}.order-xs-8{order:8}.order-xs-9{order:9}.order-xs-10{order:10}.order-xs-11{order:11}.order-xs-12{order:12}.hidden-xs{display:none}@container praxis-form-row (min-width: 600px){.span-sm-1{grid-column:span 1}.span-sm-2{grid-column:span 2}.span-sm-3{grid-column:span 3}.span-sm-4{grid-column:span 4}.span-sm-5{grid-column:span 5}.span-sm-6{grid-column:span 6}.span-sm-7{grid-column:span 7}.span-sm-8{grid-column:span 8}.span-sm-9{grid-column:span 9}.span-sm-10{grid-column:span 10}.span-sm-11{grid-column:span 11}.span-sm-12{grid-column:span 12}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:calc(1 / 12 * 100%)}.offset-sm-2{margin-left:calc(2 / 12 * 100%)}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:calc(4 / 12 * 100%)}.offset-sm-5{margin-left:calc(5 / 12 * 100%)}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:calc(7 / 12 * 100%)}.offset-sm-8{margin-left:calc(8 / 12 * 100%)}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:calc(10 / 12 * 100%)}.offset-sm-11{margin-left:calc(11 / 12 * 100%)}.order-sm--12{order:-12}.order-sm--11{order:-11}.order-sm--10{order:-10}.order-sm--9{order:-9}.order-sm--8{order:-8}.order-sm--7{order:-7}.order-sm--6{order:-6}.order-sm--5{order:-5}.order-sm--4{order:-4}.order-sm--3{order:-3}.order-sm--2{order:-2}.order-sm--1{order:-1}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.hidden-sm{display:none}}@container praxis-form-row (min-width: 900px){.span-md-1{grid-column:span 1}.span-md-2{grid-column:span 2}.span-md-3{grid-column:span 3}.span-md-4{grid-column:span 4}.span-md-5{grid-column:span 5}.span-md-6{grid-column:span 6}.span-md-7{grid-column:span 7}.span-md-8{grid-column:span 8}.span-md-9{grid-column:span 9}.span-md-10{grid-column:span 10}.span-md-11{grid-column:span 11}.span-md-12{grid-column:span 12}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:calc(1 / 12 * 100%)}.offset-md-2{margin-left:calc(2 / 12 * 100%)}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:calc(4 / 12 * 100%)}.offset-md-5{margin-left:calc(5 / 12 * 100%)}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:calc(7 / 12 * 100%)}.offset-md-8{margin-left:calc(8 / 12 * 100%)}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:calc(10 / 12 * 100%)}.offset-md-11{margin-left:calc(11 / 12 * 100%)}.order-md--12{order:-12}.order-md--11{order:-11}.order-md--10{order:-10}.order-md--9{order:-9}.order-md--8{order:-8}.order-md--7{order:-7}.order-md--6{order:-6}.order-md--5{order:-5}.order-md--4{order:-4}.order-md--3{order:-3}.order-md--2{order:-2}.order-md--1{order:-1}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.hidden-md{display:none}}@container praxis-form-row (min-width: 1200px){.span-lg-1{grid-column:span 1}.span-lg-2{grid-column:span 2}.span-lg-3{grid-column:span 3}.span-lg-4{grid-column:span 4}.span-lg-5{grid-column:span 5}.span-lg-6{grid-column:span 6}.span-lg-7{grid-column:span 7}.span-lg-8{grid-column:span 8}.span-lg-9{grid-column:span 9}.span-lg-10{grid-column:span 10}.span-lg-11{grid-column:span 11}.span-lg-12{grid-column:span 12}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:calc(1 / 12 * 100%)}.offset-lg-2{margin-left:calc(2 / 12 * 100%)}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:calc(4 / 12 * 100%)}.offset-lg-5{margin-left:calc(5 / 12 * 100%)}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:calc(7 / 12 * 100%)}.offset-lg-8{margin-left:calc(8 / 12 * 100%)}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:calc(10 / 12 * 100%)}.offset-lg-11{margin-left:calc(11 / 12 * 100%)}.order-lg--12{order:-12}.order-lg--11{order:-11}.order-lg--10{order:-10}.order-lg--9{order:-9}.order-lg--8{order:-8}.order-lg--7{order:-7}.order-lg--6{order:-6}.order-lg--5{order:-5}.order-lg--4{order:-4}.order-lg--3{order:-3}.order-lg--2{order:-2}.order-lg--1{order:-1}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.hidden-lg{display:none}}@container praxis-form-row (min-width: 1536px){.span-xl-1{grid-column:span 1}.span-xl-2{grid-column:span 2}.span-xl-3{grid-column:span 3}.span-xl-4{grid-column:span 4}.span-xl-5{grid-column:span 5}.span-xl-6{grid-column:span 6}.span-xl-7{grid-column:span 7}.span-xl-8{grid-column:span 8}.span-xl-9{grid-column:span 9}.span-xl-10{grid-column:span 10}.span-xl-11{grid-column:span 11}.span-xl-12{grid-column:span 12}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:calc(1 / 12 * 100%)}.offset-xl-2{margin-left:calc(2 / 12 * 100%)}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:calc(4 / 12 * 100%)}.offset-xl-5{margin-left:calc(5 / 12 * 100%)}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:calc(7 / 12 * 100%)}.offset-xl-8{margin-left:calc(8 / 12 * 100%)}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:calc(10 / 12 * 100%)}.offset-xl-11{margin-left:calc(11 / 12 * 100%)}.order-xl--12{order:-12}.order-xl--11{order:-11}.order-xl--10{order:-10}.order-xl--9{order:-9}.order-xl--8{order:-8}.order-xl--7{order:-7}.order-xl--6{order:-6}.order-xl--5{order:-5}.order-xl--4{order:-4}.order-xl--3{order:-3}.order-xl--2{order:-2}.order-xl--1{order:-1}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.hidden-xl{display:none}}.canvas-mode-enabled{--canvas-hit: 14px}.canvas-mode-enabled .canvas-element{position:relative;z-index:0;border-radius:8px;outline:2px solid transparent;outline-offset:2px;transition:outline-color .2s ease,outline-style .2s ease}.canvas-mode-enabled .canvas-element:before{content:\"\";position:absolute;inset:calc(-1 * var(--canvas-hit));pointer-events:none;border-radius:inherit;background:transparent}.canvas-mode-enabled .canvas-element[data-canvas-type=section]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element[data-canvas-type=row]{--outline-color: var(--md-sys-color-secondary)}.canvas-mode-enabled .canvas-element[data-canvas-type=column],.canvas-mode-enabled .canvas-element[data-canvas-type=field]{--outline-color: var(--md-sys-color-tertiary)}.canvas-mode-enabled .canvas-element[data-canvas-type=actions]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element.hovered:not(.selected){outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:dashed}.canvas-mode-enabled .canvas-element.selected{outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:solid;box-shadow:0 0 0 2px var(--outline-color, var(--md-sys-color-primary))}.canvas-mode-enabled .canvas-element.hovered{z-index:var(--praxis-layer-authoring-hover, 300)}.canvas-mode-enabled .canvas-element.selected{z-index:var(--praxis-layer-authoring-selected, 320)}.section-drop-wrapper,.row-drop-wrapper,.column-drop-wrapper{display:contents}.add-section-container{display:flex;align-items:center;justify-content:center;padding:.5rem 0;margin:-.5rem 0;position:relative;z-index:var(--praxis-layer-authoring-insert, 280)}.add-section-container .add-section-line{flex-grow:1;height:1px;background:repeating-linear-gradient(90deg,var(--md-sys-color-outline-variant),var(--md-sys-color-outline-variant) 4px,transparent 4px,transparent 8px)}.add-section-container button{margin:0 1rem;transform:scale(.85)}:host{display:block;position:relative;--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--pdx-color-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent );--pfx-form-shell-padding: clamp(.9rem, 1.4vw, 1.2rem)}.form-config-controls{position:relative;top:auto;margin:0;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--pfx-form-shell-surface) 88%,var(--md-sys-color-surface) 12%);padding:8px var(--pfx-form-shell-padding);border:1px solid var(--pfx-form-footer-border);border-bottom-color:color-mix(in srgb,var(--pfx-form-footer-border) 72%,transparent);border-radius:var(--pfx-editorial-form-radius) var(--pfx-editorial-form-radius) 0 0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:none;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.96;transition:opacity .16s ease,border-color .16s ease}.form-config-controls>*{pointer-events:auto}.form-config-controls:hover,.form-config-controls:focus-within{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%)}.form-config-controls .praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}.form-config-controls .praxis-icon-button:hover{color:var(--md-sys-color-primary)}.ai-floating-assistant{position:sticky;right:0;bottom:12px;margin-top:14px;margin-left:auto;width:fit-content;z-index:70;pointer-events:none}.ai-floating-assistant button{pointer-events:auto;display:inline-flex}.ai-floating-assistant .ai-trigger-btn{box-shadow:0 12px 28px #0f172a24}.config-button{color:var(--md-sys-color-primary)}.form-loading{display:flex;flex-direction:column;align-items:stretch;justify-content:center;padding:1.25rem;text-align:left;color:var(--md-sys-color-on-surface);gap:1rem;min-height:220px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,var(--md-sys-color-outline-variant) 86%);border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent 42%),color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,var(--md-sys-color-surface) 22%);box-shadow:0 12px 28px #0f172a14}.entity-read-region{position:relative;min-width:0}.entity-read-feedback{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:1rem;padding:2rem 1rem;box-sizing:border-box;text-align:center;color:var(--md-sys-color-on-surface)}.entity-read-feedback p{margin:0;max-width:40ch}.form-loading-header{display:flex;align-items:center;gap:.85rem}.form-loading-copy{min-width:0}.form-loading p{margin:0}.form-loading-title{font-weight:700;color:var(--md-sys-color-on-surface)}.form-loading-subtitle{margin-top:.2rem;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.form-loading-skeleton{display:grid;gap:.7rem}.form-loading-line,.form-loading-field{display:block;overflow:hidden;position:relative;border-radius:6px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,var(--md-sys-color-primary) 6%)}.form-loading-line:after,.form-loading-field:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 16%,var(--md-sys-color-on-surface) 18%),transparent);animation:form-loading-shimmer 1.4s ease-in-out infinite}.form-loading-line{height:12px}.form-loading-line-title{width:min(42%,240px)}.form-loading-line-short{width:min(64%,360px)}.form-loading-field{height:44px}.form-loading-field-wide{height:72px}@keyframes form-loading-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.form-loading-line:after,.form-loading-field:after{animation:none;transform:none;opacity:.28}}.form-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-error);gap:1rem;border:1px solid var(--md-sys-color-error);border-radius:8px;background-color:var(--md-sys-color-error-container);margin:1rem;box-shadow:0 12px 30px #7f1d1d1f}.form-error h3{margin:0;color:var(--md-sys-color-on-error-container)}.form-error p{margin:0;color:var(--md-sys-color-on-error-container);opacity:.8}.form-error button{margin-top:.5rem}.pfx-form-info-banner{margin-bottom:14px;padding:12px 14px;border-radius:16px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant) 82%);background:color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface) 76%);color:var(--md-sys-color-on-surface);display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.pfx-form-info-banner .text{font-size:.92rem;line-height:1.5;font-weight:600}.pfx-form-info-banner .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.praxis-dynamic-form{display:flex;flex-direction:column;max-width:100%;min-width:0;transition:all .3s ease;position:relative;font-family:inherit;font-size:inherit;color:inherit;--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--md-sys-color-surface-container) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --pdx-color-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --pdx-color-text-secondary, var(--md-sys-color-on-surface-variant) );--pfx-editorial-form-field-surface: color-mix( in srgb, var(--pfx-editorial-form-surface-muted) 76%, var(--pfx-editorial-form-surface) 24% );--pfx-editorial-form-field-outline: color-mix( in srgb, var(--pfx-editorial-form-border) 88%, transparent );--pfx-editorial-form-accent: var( --pdx-color-primary, var(--md-sys-color-primary) );--pfx-editorial-form-accent-text: var(--md-sys-color-on-primary);--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-field-radius: var(--pfx-form-field-radius, 4px);--pfx-editorial-form-border-width: 1px;--pfx-editorial-form-field-border-width: 1px;--pfx-editorial-form-shadow: none;--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-surface-flat: color-mix( in srgb, var(--pfx-editorial-form-surface) 78%, var(--pfx-editorial-form-surface-muted) 22% );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-label-strong: color-mix( in srgb, var(--pfx-editorial-form-text) 96%, white 4% );--pfx-form-label-muted: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 92%, var(--pfx-editorial-form-text) 8% );--pfx-form-field-surface-rest: color-mix( in srgb, var(--pfx-editorial-form-field-surface) 82%, var(--pfx-editorial-form-surface) 18% );--pfx-form-field-surface-focus: color-mix( in srgb, var(--pfx-editorial-form-accent) 4%, var(--pfx-form-field-surface-rest) 96% );--pfx-form-field-min-height: 48px;--pfx-form-section-padding: clamp(1.1rem, 1.8vw, 1.5rem);--pfx-form-section-gap: 22px;--pdx-presentation-label-size: var(--pfx-pres-compact-label-size, .78rem);--pdx-presentation-value-size: var(--pfx-pres-compact-value-size, 1rem);--pdx-presentation-icon-size: var(--pfx-pres-icon-size, 18px);--pdx-presentation-row-gap: var(--pfx-pres-row-gap, .5rem);--pdx-presentation-column-gap: var(--pfx-pres-column-gap, .5rem);--pdx-presentation-section-gap: var(--pfx-pres-section-gap, .75rem);--pdx-presentation-label-width: var(--pfx-pres-label-width, 220px);--pdx-presentation-flag-height: var(--pfx-pres-boolean-min-height, 22px);--pdx-presentation-flag-radius: var(--pfx-pres-boolean-radius, 999px);--pdx-presentation-flag-padding: var(--pfx-pres-boolean-padding, 0 8px);--pdx-presentation-flag-active-color: var( --pfx-pres-boolean-active-color, var(--md-sys-color-primary) );--pdx-presentation-flag-active-bg: var( --pfx-pres-boolean-active-bg, color-mix(in srgb, var(--md-sys-color-primary) 14%, transparent) );--pdx-presentation-flag-inactive-color: var( --pfx-pres-boolean-inactive-color, var(--md-sys-color-on-surface-variant) );--pdx-presentation-flag-inactive-bg: var( --pfx-pres-boolean-inactive-bg, color-mix(in srgb, var(--md-sys-color-outline-variant) 34%, transparent) );--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent )}.praxis-dynamic-form.canvas-mode-enabled{border:1px solid var(--pfx-form-footer-border);border-radius:var(--pfx-editorial-form-radius);background:linear-gradient(180deg,color-mix(in srgb,var(--pfx-form-shell-surface) 86%,transparent),color-mix(in srgb,var(--pfx-editorial-form-surface-muted) 42%,transparent));overflow:visible}.form-config-controls+.praxis-dynamic-form.canvas-mode-enabled{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks{margin-inline:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper:first-of-type,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks:first-child{margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>praxis-form-actions[data-actions-placement=afterSections]{display:block;margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.editorial-visual-context{--_pfx-editorial-host-text: var( --editorial-text-primary, var(--foreground, var(--mat-sys-on-surface, #1d1b20)) );--_pfx-editorial-host-text-muted: var( --editorial-text-secondary, var( --muted-foreground, color-mix(in srgb, var(--_pfx-editorial-host-text) 64%, transparent) ) );--_pfx-editorial-host-surface: var( --editorial-surface-primary, var(--card, var(--mat-sys-surface-container, #ffffff)) );--_pfx-editorial-host-surface-muted: var( --editorial-surface-secondary, var(--surface-dim, var(--muted, var(--mat-sys-surface-container-low, #f7f2fa))) );--_pfx-editorial-host-border: var( --editorial-border-color, var(--border, var(--mat-sys-outline-variant, #cac4d0)) );--_pfx-editorial-host-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--primary, var(--mat-sys-primary, #6750a4))) );--_pfx-editorial-host-accent-text: var( --editorial-cta-primary-text, var( --editorial-accent-contrast, var(--primary-foreground, var(--mat-sys-on-primary, #ffffff)) ) );--_pfx-editorial-host-accent-container: var( --primary-container, color-mix(in srgb, var(--_pfx-editorial-host-accent) 16%, var(--_pfx-editorial-host-surface) 84%) );--_pfx-editorial-host-accent-container-text: var( --primary-container-fg, var(--_pfx-editorial-host-accent) );font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--_pfx-editorial-host-text);--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--_pfx-editorial-host-surface)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--_pfx-editorial-host-surface-muted) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--_pfx-editorial-host-border)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--_pfx-editorial-host-text) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, color-mix( in srgb, var(--_pfx-editorial-host-text-muted) 86%, var(--_pfx-editorial-host-text) 14% ) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--_pfx-editorial-host-accent)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--_pfx-editorial-host-accent-text)) );--pfx-editorial-form-accent-container: var(--_pfx-editorial-host-accent-container);--pfx-editorial-form-accent-container-text: var(--_pfx-editorial-host-accent-container-text);--pfx-editorial-form-radius: var(--editorial-card-radius, 18px);--pfx-editorial-form-field-radius: var( --editorial-field-radius, var(--editorial-card-radius, 14px) );--pfx-editorial-form-border-width: var(--editorial-card-border-width, 1px);--pfx-editorial-form-field-border-width: var(--editorial-field-border-width, 1px);--pfx-editorial-form-shadow: var(--editorial-card-shadow, none);--md-sys-color-surface: var( --pfx-editorial-form-surface, var(--md-sys-color-surface) );--md-sys-color-surface-container: var( --pfx-editorial-form-surface, var(--md-sys-color-surface-container) );--md-sys-color-surface-container-low: var( --pfx-editorial-form-surface-muted, var(--md-sys-color-surface-container-low) );--md-sys-color-surface-variant: var( --pfx-editorial-form-field-surface, var(--md-sys-color-surface-variant) );--md-sys-color-outline: var( --pfx-editorial-form-field-outline, var(--md-sys-color-outline) );--md-sys-color-outline-variant: var( --pfx-editorial-form-border, var(--md-sys-color-outline-variant) );--md-sys-color-on-surface: var( --editorial-text-primary, inherit );--md-sys-color-on-surface-variant: var( --editorial-text-secondary, inherit );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-primary-container: var( --pfx-editorial-form-accent-container, var(--md-sys-color-primary-container) );--md-sys-color-on-primary-container: var( --pfx-editorial-form-accent-container-text, var(--md-sys-color-on-primary-container) );--md-sys-color-on-primary: var( --pfx-editorial-form-accent-text, var(--md-sys-color-on-primary) );--md-sys-color-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );--mat-sys-on-surface: var( --editorial-text-primary, inherit );--mat-sys-on-surface-variant: var( --editorial-text-secondary, inherit );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );color:inherit;color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:var(--pdx-presentation-column-gap);margin-bottom:var(--pdx-presentation-row-gap)}.praxis-dynamic-form.presentation-mode{--pfx-pres-on-surface: var( --pdx-color-text-primary, var(--pfx-editorial-form-text, var(--pfx-form-label-strong, currentColor)) );--pfx-pres-on-surface-variant: var( --pdx-color-text-secondary, var( --pfx-editorial-form-text-muted, var( --pfx-form-label-muted, color-mix(in srgb, var(--pfx-pres-on-surface) 78%, transparent) ) ) )}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:var(--pdx-presentation-section-gap) .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:var(--pdx-presentation-column-gap, .35rem);margin-bottom:var(--pdx-presentation-row-gap, .35rem)}.praxis-dynamic-form.pres-compact .form-section{padding:var(--pdx-presentation-section-gap, .5rem) .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:minmax(0,var(--pfx-presentation-label-w, var(--pdx-presentation-label-width))) minmax(0,1fr);align-items:baseline;column-gap:var(--pdx-presentation-column-gap, 10px)}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}@media(max-width:480px){.praxis-dynamic-form.pres-label-left .praxis-presentation{grid-template-columns:minmax(0,1fr);row-gap:4px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:start}}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low, #f8f9fa);border:1px solid var(--md-sys-color-outline-variant, #e0e2ec);border-radius:16px;padding:16px 20px;box-shadow:0 1px 3px #0000000a}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-heading{margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--md-sys-color-outline-variant, #e0e2ec)}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-title,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-title{font-size:.88rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--md-sys-color-primary, #005ac1)}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation{padding:8px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep .form-section--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=corporate-dossier] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__label,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:3px}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__value,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__value{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.4}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low, var(--mat-sys-surface-container-low)));border:1px solid var(--pfx-editorial-form-border, var(--md-sys-color-outline-variant, #e0e2ec));border-radius:20px;padding:24px;box-shadow:0 2px 8px #0000000d}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--editorial-card .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-heading{margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 40%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-title,.praxis-dynamic-form .form-section.form-section--editorial-card .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-title{font-size:1.15rem;font-weight:700;color:var(--pfx-editorial-form-accent, var(--md-sys-color-primary, #005ac1))}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation{padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 35%,transparent)}:host ::ng-deep .praxis-dynamic-form--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation:last-child,:host ::ng-deep .form-section--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=editorial-card] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__label,:host ::ng-deep .form-section--editorial-card .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__label{font-size:.8rem;font-weight:500;color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant, #44474f));margin-bottom:4px}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__value,:host ::ng-deep .form-section--editorial-card .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__value{font-size:1rem;font-weight:600;color:var(--pfx-editorial-form-text, var(--md-sys-color-on-surface, #1a1c1e));line-height:1.5}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--compact-presentation:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation]:not(.section-appearance-plain){background:transparent;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 50%,transparent);border-radius:8px;padding:10px 14px;box-shadow:none}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-heading{margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 25%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-title,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-title{font-size:.82rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #44474f)}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation,:host ::ng-deep .form-section--compact-presentation .praxis-presentation,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation{padding:4px 0;border-bottom:none}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__label,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__label{font-size:.72rem;font-weight:600;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:2px}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__value,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__value{font-size:.88rem;font-weight:500;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.35}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 2px 8px #0000004d}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low));border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 4px 16px #0006}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);max-width:100%;min-width:0;background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section:not(.section-appearance-plain){border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;color:var(--pfx-editorial-form-text);box-shadow:var(--editorial-card-shadow, none)}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{background-color:var(--pfx-editorial-form-surface)!important;background-image:linear-gradient(180deg,color-mix(in srgb,var(--editorial-accent, var(--md-sys-color-primary)) 6%,transparent) 0%,transparent 132px)!important;background-repeat:no-repeat!important}.section-drop-wrapper>.form-section{margin-bottom:var(--pfx-section-gap, 20px)}.section-drop-wrapper:last-of-type>.form-section{margin-bottom:0}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections]{margin-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}.section-title{margin:0 0 var(--pfx-section-title-mb, 12px) 0;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.12rem);font-weight:700;color:var(--pfx-form-label-strong)}.section-heading{position:relative;display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 18px)}.section-heading:after{content:\"\";position:absolute;right:0;bottom:0;left:0;height:2px;pointer-events:none;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 8%,var(--pfx-form-section-divider) 46%,var(--pfx-form-section-divider) 54%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 92%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%);mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 10px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:none}.section-heading.align-center{flex-direction:column;align-items:center;text-align:center}.section-heading.align-center .section-heading-text{display:grid;justify-items:center}.section-step-label{display:inline-flex;align-items:center;min-height:24px;padding:0 10px;margin:0 0 8px;border-radius:999px;background:color-mix(in srgb,var(--pfx-editorial-form-accent) 10%,transparent);color:color-mix(in srgb,var(--pfx-editorial-form-accent) 84%,var(--pfx-form-label-strong) 16%);font-size:.72rem;font-weight:800;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));letter-spacing:.08em;text-transform:uppercase}.section-heading-text{flex:1 1 auto;min-width:0}.section-heading-actions{display:inline-flex;align-items:center;align-self:flex-start;flex-wrap:wrap;gap:4px;margin-left:auto}.section-heading-actions.align-center{align-self:center;margin-left:0}.section-heading-action-btn{color:var(--pfx-form-label-muted)}.section-heading-action-btn.tone-primary{color:var(--md-sys-color-primary)}.section-heading-action-btn.tone-accent,.section-heading-action-btn.tone-secondary{color:var(--md-sys-color-tertiary)}.section-heading-action-btn.tone-warn,.section-heading-action-btn.tone-danger,.section-heading-action-btn.tone-error{color:var(--md-sys-color-error)}.section-heading-action-btn .mat-mdc-progress-spinner,.section-heading-action-btn mat-progress-spinner{--mdc-circular-progress-active-indicator-color: currentColor}.section-heading-action-btn.loading{opacity:.72;pointer-events:none}.section-heading-action-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.section-collapse-btn{margin-left:4px;color:var(--pfx-form-label-muted)}.section-title.title-large{font:var(--mdc-typography-title-large, 500 22px/28px system-ui)}.section-title.title-medium{font:var(--mdc-typography-title-medium, 500 16px/24px system-ui)}.section-title.title-small{font:var(--mdc-typography-title-small, 500 14px/20px system-ui)}.section-title.headline-small{font:var(--mdc-typography-headline-small, 600 24px/32px system-ui)}.section-title.title-large,.section-title.title-medium,.section-title.title-small,.section-title.headline-small{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-weight:var(--editorial-title-weight, 600)}.section-description{margin:0;font-family:var(--editorial-body-font-family, inherit);font-size:.93rem;color:var(--pfx-form-label-muted);line-height:1.6}.section-description.body-large{font:var(--mdc-typography-body-large, 400 16px/24px system-ui)}.section-description.body-medium{font:var(--mdc-typography-body-medium, 400 14px/20px system-ui)}.section-description.body-small{font:var(--mdc-typography-body-small, 400 12px/16px system-ui)}.section-description.body-large,.section-description.body-medium,.section-description.body-small{font-family:var(--editorial-body-font-family, inherit);font-weight:var(--editorial-body-weight, 400)}.section-title.align-center,.section-description.align-center,.section-step-label.align-center{text-align:center}.praxis-dynamic-form .form-section.section-appearance-plain{border-color:transparent;border-width:0;border-radius:0;padding:0;background:transparent;box-shadow:none}.praxis-dynamic-form .form-section.section-appearance-plain.section-has-divider{padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider, var(--md-sys-color-outline-variant, #e0e2ec))}.praxis-dynamic-form .section-drop-wrapper:last-of-type>.form-section.section-appearance-plain.section-has-divider,.praxis-dynamic-form>.form-section.section-appearance-plain.section-has-divider:last-of-type{border-bottom:none;padding-bottom:0}.form-section.section-appearance-plain .section-heading{margin-bottom:14px}.form-section.section-appearance-step{border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);border-color:var(--pfx-form-section-divider);box-shadow:none}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{border-radius:var(--editorial-card-radius, 20px);box-shadow:none}.form-section.section-appearance-step .section-heading{margin-bottom:22px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 16px)}.form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 16px)}:host(.pfx-form-section-divider-inline-title) .form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}.form-section.section-appearance-step .section-title{font:var(--mdc-typography-title-large, 700 22px/28px system-ui);color:var(--pfx-form-label-strong);margin-bottom:8px}.form-section.section-appearance-step .section-description{color:var(--pfx-form-label-muted);max-width:60ch}.form-section.section-appearance-step .section-step-label{min-height:24px;padding:0 10px;margin-bottom:10px;box-shadow:none}.form-section.section-appearance-step .section-heading.align-center .section-description{max-width:52ch}.form-section.section-appearance-step .section-body{display:grid;gap:8px;padding-top:0}.form-section.section-appearance-step .form-row{margin-bottom:var(--pfx-field-gap, 1rem)}.form-section.section-appearance-step .form-column{gap:var(--pfx-field-gap, 12px)}.form-section .form-editorial-blocks{display:grid;gap:16px}.form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{margin-top:24px;padding-top:18px;border-top:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]{gap:18px}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]>*+*{margin-top:2px}.praxis-dynamic-form:not(.canvas-mode-enabled)>praxis-form-actions[data-actions-placement=afterSections]{margin-top:18px}.praxis-dynamic-form>.form-editorial-blocks[data-editorial-placement=after]{margin-top:6px}:host-context(.mdc-theme-dark) .form-section.section-appearance-step,:host-context(.theme-dark) .form-section.section-appearance-step{border-color:color-mix(in srgb,var(--pfx-editorial-form-border) 82%,transparent);box-shadow:none}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-title,:host-context(.theme-dark) .form-section.section-appearance-step .section-title{color:color-mix(in srgb,var(--pfx-editorial-form-text) 96%,white)}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-description,:host-context(.theme-dark) .form-section.section-appearance-step .section-description{color:color-mix(in srgb,var(--pfx-editorial-form-text-muted) 86%,var(--pfx-editorial-form-text) 14%)}:host-context(.mdc-theme-dark) .section-step-label,:host-context(.theme-dark) .section-step-label{background:color-mix(in srgb,var(--md-sys-color-primary-container) 54%,transparent);color:color-mix(in srgb,var(--md-sys-color-primary) 88%,white)}:host-context(.mdc-theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions],:host-context(.theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{border-top-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 90%,transparent)}.inline-edit-btn{margin-left:6px;vertical-align:middle}.section-body.collapsed{border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);border-radius:6px;padding:8px 10px}.section-collapsed-placeholder{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.95rem}.section-collapsed-placeholder mat-icon{font-size:20px;width:20px;height:20px}.form-row{display:flex;gap:1.1rem;margin-bottom:var(--pfx-field-gap, 1.1rem);max-width:100%;min-width:0;transition:all .2s ease;border-radius:6px;position:relative}.praxis-dynamic-form.pfx-mounting .form-row{opacity:0;transform:translateY(var(--pdx-form-mount-offset, 6px));animation:pdxFormMount var(--pdx-form-mount-duration, .16s) ease-out both;animation-delay:calc(var(--pfx-mount-index, 0) * var(--pdx-form-mount-stagger, 20ms))}@media(prefers-reduced-motion:reduce){.praxis-dynamic-form.pfx-mounting .form-row{animation:none;opacity:1;transform:none}}@keyframes pdxFormMount{to{opacity:1;transform:translateY(0)}}.praxis-dynamic-form .mat-mdc-form-field{width:100%;margin-bottom:var(--pfx-field-gap, 10px);font-family:inherit;--mdc-filled-text-field-container-color: var(--pfx-form-field-surface-rest);--mdc-filled-text-field-focus-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-active-indicator-color: var(--pfx-editorial-form-field-outline);--mdc-filled-text-field-hover-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-filled-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-caret-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-input-text-placeholder-color: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 82%, transparent );--mdc-outlined-text-field-outline-color: var(--pfx-editorial-form-field-outline);--mdc-outlined-text-field-hover-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-outlined-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-outlined-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-filled-text-field-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-filled-text-field-focus-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-outline-width: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-focus-outline-width: var(--pfx-editorial-form-field-border-width);--mat-select-enabled-trigger-text-color: var(--pfx-editorial-form-text);--mat-select-enabled-arrow-color: var(--pfx-form-label-muted);--mat-form-field-enabled-select-arrow-color: var(--pfx-form-label-muted);--mat-form-field-focus-select-arrow-color: var(--pfx-editorial-form-accent);--mat-form-field-hover-state-layer-opacity: 0;--mat-form-field-focus-state-layer-opacity: 0}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field{font-family:var(--editorial-body-font-family, inherit)}.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{background:var(--pfx-form-field-surface-rest);border-radius:var(--pfx-editorial-form-field-radius);min-height:var(--pfx-form-field-min-height);transition:background-color .16s ease,box-shadow .16s ease,border-color .16s ease}.praxis-dynamic-form.editorial-visual-context .mat-mdc-text-field-wrapper,.praxis-dynamic-form.editorial-visual-context .mdc-text-field,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--filled,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--outlined{background-color:var(--pfx-form-field-surface-rest)!important;background:var(--pfx-form-field-surface-rest)!important}.praxis-dynamic-form .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-form-label-muted)}.praxis-dynamic-form .mat-mdc-input-element,.praxis-dynamic-form .mat-mdc-select-value-text,.praxis-dynamic-form .mat-mdc-form-field-infix,.praxis-dynamic-form .mat-mdc-select-min-line{color:var(--pfx-editorial-form-text)}.praxis-dynamic-form .mat-mdc-form-field:hover .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field:hover .mdc-text-field,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mdc-text-field{background:var(--pfx-form-field-surface-focus)}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-value-text,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field-infix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-min-line,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input{color:var(--pfx-editorial-form-text)!important;-webkit-text-fill-color:var(--pfx-editorial-form-text)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-editorial-form-text-muted)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 68%,transparent)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element::placeholder,.praxis-dynamic-form.editorial-visual-context textarea.mat-mdc-input-element::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 58%,transparent)!important}.praxis-dynamic-form .mat-mdc-radio-button,.praxis-dynamic-form .mat-mdc-checkbox,.praxis-dynamic-form .mat-mdc-slide-toggle{--mdc-radio-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-checkmark-color: var(--pfx-editorial-form-accent-text);--mdc-checkbox-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-focus-state-layer-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-handle-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-track-color: color-mix(in srgb, var(--pfx-editorial-form-accent) 45%, #fff)}.praxis-dynamic-form [data-field-type=input],.praxis-dynamic-form [data-field-type=textarea],.praxis-dynamic-form [data-field-type=email],.praxis-dynamic-form [data-field-type=password],.praxis-dynamic-form [data-field-type=url],.praxis-dynamic-form [data-field-type=search],.praxis-dynamic-form [data-field-type=phone],.praxis-dynamic-form [data-field-type=numericTextBox],.praxis-dynamic-form [data-field-type=currency],.praxis-dynamic-form [data-field-type=cpfCnpj],.praxis-dynamic-form [data-field-type=date],.praxis-dynamic-form [data-field-type=dateInput],.praxis-dynamic-form [data-field-type=dateRange],.praxis-dynamic-form [data-field-type=dateTimeLocal],.praxis-dynamic-form [data-field-type=time],.praxis-dynamic-form [data-field-type=timePicker],.praxis-dynamic-form [data-field-type=timeRange],.praxis-dynamic-form [data-field-type=month],.praxis-dynamic-form [data-field-type=week],.praxis-dynamic-form [data-field-type=yearInput],.praxis-dynamic-form [data-field-type=select],.praxis-dynamic-form [data-field-type=multi-select],.praxis-dynamic-form [data-field-type=searchable-select],.praxis-dynamic-form [data-field-type=async-select],.praxis-dynamic-form [data-field-type=autocomplete],.praxis-dynamic-form [data-field-type=entityLookup],.praxis-dynamic-form [data-field-type=tree-select],.praxis-dynamic-form [data-field-type=multi-select-tree],.praxis-dynamic-form [data-field-type=priceRange],.praxis-dynamic-form [data-field-type=file-upload]{display:block;width:100%;min-width:0}.praxis-dynamic-form .mat-mdc-form-field-subscript-wrapper{min-height:var(--pfx-subscript-min-h, 22px)}.form-row:last-child{margin-bottom:0}.form-column{display:grid;grid-template-columns:minmax(0,1fr);align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;max-width:100%;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-layout-rich-content{display:block;width:100%;max-width:100%;min-width:0;margin-bottom:var(--pfx-field-gap, 10px);color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant));font:var(--mdc-typography-body-medium, 400 14px/20px system-ui);overflow-wrap:anywhere}:host ::ng-deep .form-layout-rich-content .prx-rich-content-root{display:grid;gap:8px;min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-node{min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-text{color:inherit;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{border:1px solid color-mix(in srgb,var(--pfx-editorial-form-accent) 12%,var(--pfx-editorial-form-border) 88%);border-left:3px solid var(--pfx-editorial-form-accent);border-radius:8px;background:color-mix(in srgb,var(--pfx-editorial-form-accent-container) 12%,var(--pfx-editorial-form-surface-muted) 88%)}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;align-items:flex-start;padding:11px 12px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note:before{content:\"info\";display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--pfx-editorial-form-accent);font-family:Material Symbols Outlined;font-size:20px;font-weight:400;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{padding:10px 12px;color:var(--pfx-editorial-form-text)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-compose{align-items:flex-start;gap:10px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-icon{color:var(--pfx-editorial-form-accent);font-size:20px;line-height:20px;margin-top:1px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider{display:grid;grid-template-columns:minmax(24px,1fr) auto minmax(24px,1fr);align-items:center;gap:10px;color:var(--pfx-editorial-form-text-muted);font:var(--mdc-typography-label-small, 600 12px/16px system-ui);text-transform:uppercase}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:before,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:after{content:\"\";height:1px;background:var(--pfx-editorial-form-border)}:host ::ng-deep .form-layout-rich-content .prx-rich-card{gap:6px;padding:12px 14px;border-color:var(--pfx-editorial-form-border);border-radius:8px;background:var(--pfx-editorial-form-surface-muted);color:var(--pfx-editorial-form-text);box-shadow:none}:host ::ng-deep .form-layout-rich-content .prx-rich-card-title{color:var(--pfx-editorial-form-text);font:var(--mdc-typography-title-small, 600 14px/20px system-ui)}:host ::ng-deep .form-layout-rich-content .prx-rich-card-subtitle,:host ::ng-deep .form-layout-rich-content .prx-rich-metric-caption{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-card .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-badge{background:var(--pfx-editorial-form-accent-container);color:var(--pfx-editorial-form-accent-container-text)}.form-row.grid-12{container-type:inline-size;container-name:praxis-form-row;display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.align-start{align-self:flex-start}.align-center{align-self:center}.align-end{align-self:flex-end}.align-stretch{align-self:stretch}.form-blocking-overlay{position:absolute;inset:0;background:transparent;color:var(--md-sys-color-on-surface);backdrop-filter:blur(2px) saturate(103%);-webkit-backdrop-filter:blur(2px) saturate(103%);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;z-index:10;pointer-events:all}@media(max-width:768px){.column-drop-wrapper,.row-drop-wrapper,.form-layout-rich-content,.praxis-dynamic-form .mat-mdc-form-field,.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{max-width:100%;min-width:0}:host ::ng-deep .praxis-dynamic-form .pfx-field-shell,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-wrapper,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-host,:host ::ng-deep .praxis-dynamic-form .mat-mdc-form-field,:host ::ng-deep .praxis-dynamic-form .mat-mdc-text-field-wrapper,:host ::ng-deep .praxis-dynamic-form .mdc-text-field{width:100%;max-width:100%;min-width:0}.form-section{padding:clamp(.75rem,4vw,1rem)}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 14px)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}}.section-title{display:flex;align-items:center;gap:8px}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:100%;min-width:0}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{content:\"\";display:block;flex:1 1 auto;min-width:var(--pfx-form-section-title-inline-divider-min-width, 48px);height:2px;margin-left:var(--pfx-form-section-title-inline-divider-gap, 12px);pointer-events:none;background:linear-gradient(90deg,var(--pfx-form-section-divider) 0%,var(--pfx-form-section-divider) 62%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 88%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%);mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%)}:host(.pfx-form-section-divider-inline-title) .section-heading.align-center .section-title:after{display:none}@media(max-width:640px){:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:block}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:auto}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{display:none}}.section-title .section-title-icon{font-size:1.25em;line-height:1}.section-title-avatar{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px));display:inline-flex;align-items:center;justify-content:center;width:var(--_pfx-form-section-avatar-size);height:var(--_pfx-form-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-form-section-avatar-size);overflow:hidden}.section-title-avatar.size-sm{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-title-avatar.size-md{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-title-avatar.size-lg{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-title-avatar-image{object-fit:cover;border:1px solid color-mix(in srgb,var(--pfx-form-section-divider) 72%,transparent);background:var(--pfx-form-section-surface-flat)}.section-title-avatar-text,.section-title-avatar-placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent) 14%,var(--pfx-form-section-surface-flat));color:color-mix(in srgb,var(--pfx-editorial-form-accent) 82%,var(--pfx-form-label-strong) 18%);font-size:calc(var(--_pfx-form-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-title-avatar-placeholder mat-icon{font-size:calc(var(--_pfx-form-section-avatar-size) * .5625);width:calc(var(--_pfx-form-section-avatar-size) * .5625);height:calc(var(--_pfx-form-section-avatar-size) * .5625);line-height:calc(var(--_pfx-form-section-avatar-size) * .5625)}.section-title-avatar-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.form-context-empty-state{display:grid;min-height:var(--pdx-form-context-empty-min-height, 0);place-items:center;padding:var(--pdx-form-context-empty-padding, 0)}.form-context-empty-state praxis-empty-state-card{display:block;width:min(100%,var(--pdx-form-context-empty-max-width, 32rem))}.prx-form-tabs{display:block;margin-bottom:16px;max-width:100%}.prx-form-tabs__tablist{display:flex;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%}.prx-form-tabs__tablist--scrollable{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:4px 2px}.prx-form-tabs__tablist--scrollable::-webkit-scrollbar{display:none}.prx-form-tabs__tab{display:inline-flex;align-items:center;gap:8px;min-width:0;padding:8px 14px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:color-mix(in srgb,var(--md-sys-color-surface, transparent) 40%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);font-family:inherit;font-size:.84rem;font-weight:500;cursor:pointer;white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none;transition:all .2s cubic-bezier(.2,0,0,1)}.prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:var(--md-sys-color-surface-container-high, rgba(0, 0, 0, .05));border-color:var(--md-sys-color-outline, rgba(0, 0, 0, .24));color:var(--md-sys-color-on-surface)}.prx-form-tabs__tab:focus-visible{outline:2px solid var(--md-sys-color-primary, #005ac1);outline-offset:2px}.prx-form-tabs__tab:disabled{cursor:not-allowed;opacity:.45}.prx-form-tabs__tab--active{background:var(--md-sys-color-primary-container, color-mix(in srgb, var(--md-sys-color-primary, #005ac1) 16%, var(--md-sys-color-surface-container-high, #2b2930)));color:var(--md-sys-color-on-primary-container, var(--md-sys-color-primary, #005ac1));border-color:transparent;font-weight:600;box-shadow:0 1px 3px #00000014}.prx-form-tabs__tab-icon{font-size:18px;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center}.prx-form-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;padding:1px 7px;font-size:.72rem;font-weight:600;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent)}.prx-form-tabs__tab-error-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;font-size:.7rem;font-weight:700;background:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-on-error, #ffffff);box-shadow:0 1px 2px #0003}.prx-form-tabs[data-appearance=underline]{border-bottom:1px solid var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tablist{gap:16px;padding-bottom:0}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab{border:none;border-radius:0;border-bottom:2px solid transparent;background:transparent;padding:8px 4px 10px;margin-bottom:-1px}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:transparent;border-bottom-color:var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab--active{background:transparent;box-shadow:none;border-bottom-color:var(--md-sys-color-primary, #005ac1);color:var(--md-sys-color-primary, #005ac1)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tablist{background:var(--md-sys-color-surface-container, rgba(0, 0, 0, .04));border-radius:12px;padding:4px;gap:4px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab{border:none;border-radius:8px;padding:6px 12px;background:transparent}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:color-mix(in srgb,currentColor 8%,transparent)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab--active{background:var(--md-sys-color-surface, var(--mat-sys-surface));color:var(--md-sys-color-primary, #005ac1);box-shadow:0 1px 3px #0000001f}.section-drop-wrapper[hidden]{display:none!important}.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:var(--pdx-text-shimmer-base, var(--md-sys-color-on-surface-variant));font-weight:550;text-shadow:none}@supports (-webkit-background-clip: text) or (background-clip: text){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{background-image:var(--pdx-text-shimmer-gradient, linear-gradient(105deg, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 0%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 26%, color-mix(in oklab, var(--md-sys-color-tertiary, #6366f1) 66%, #a855f7 34%) 40%, var(--pdx-text-shimmer-peak, var(--md-sys-color-on-surface, #ffffff)) 50%, color-mix(in oklab, var(--md-sys-color-primary, #006a6a) 66%, #ec4899 34%) 60%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 74%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 100%));background-size:300% 100%;background-position:100% 50%;background-repeat:no-repeat;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent;animation:praxisFormTextShimmer var(--pdx-text-shimmer-duration, 2.6s) linear infinite;will-change:background-position}}@media(prefers-reduced-motion:reduce),(forced-colors:active),print{.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{animation:none!important;background-image:none!important;-webkit-text-fill-color:currentColor!important;color:var(--md-sys-color-primary)!important;will-change:auto}}@media(forced-colors:active){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:CanvasText!important;-webkit-text-fill-color:CanvasText!important}}@keyframes praxisFormTextShimmer{0%{background-position:100% 50%}to{background-position:0% 50%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick", "canvasFocus"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i17.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i19.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: CanvasToolbarComponent, selector: "praxis-canvas-toolbar", inputs: ["selectedElement"], outputs: ["editMetadata", "delete", "moveUp", "moveDown", "selectPath", "requestClose", "toggleReadonly", "toggleRequired", "toggleHidden", "toggleDisabled"] }, { kind: "component", type: PraxisFormActionsComponent, selector: "praxis-form-actions", inputs: ["actions", "editorialVisualContext", "isSubmitting", "formIsValid", "submitError", "invalidRequiredFieldLabels", "suppressInvalidSubmitHint", "formId", "actionOverrides"], outputs: ["action"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone", "variant", "alignment", "density", "iconContainer"] }, { 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"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"], outputs: ["nodeAction"] }] });
22162
22144
  }
22163
22145
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDynamicForm, decorators: [{
22164
22146
  type: Component,
@@ -22184,7 +22166,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
22184
22166
  EmptyStateCardComponent,
22185
22167
  PraxisAiAssistantShellComponent,
22186
22168
  PraxisRichContent,
22187
- ], template: "@if (isLoading) {\n <!-- Loading State -->\n <div class=\"form-loading\" role=\"status\" aria-live=\"polite\" aria-label=\"Carregando formul\u00E1rio\">\n <div class=\"form-loading-header\">\n <mat-progress-spinner diameter=\"32\" aria-label=\"Carregando formul\u00E1rio\"></mat-progress-spinner>\n <div class=\"form-loading-copy\">\n <p class=\"form-loading-title\">Carregando formul\u00E1rio...</p>\n <p class=\"form-loading-subtitle\">Preparando campos e op\u00E7\u00F5es do cadastro.</p>\n </div>\n </div>\n <div class=\"form-loading-skeleton\" aria-hidden=\"true\">\n <span class=\"form-loading-line form-loading-line-title\"></span>\n <span class=\"form-loading-line\"></span>\n <span class=\"form-loading-line form-loading-line-short\"></span>\n <span class=\"form-loading-field\"></span>\n <span class=\"form-loading-field form-loading-field-wide\"></span>\n </div>\n </div>\n} @else if (initializationStatus === 'error') {\n <!-- Error State -->\n <div class=\"form-error\">\n <mat-icon color=\"warn\" [praxisIcon]=\"'error'\"></mat-icon>\n <h3>{{ getErrorTitle() }}</h3>\n <p>{{ currentErrorMessage }}</p>\n @if (isRecoverable) {\n <button mat-stroked-button (click)=\"retryInitialization()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n Tentar Novamente\n </button>\n }\n <button mat-button (click)=\"showDetailedError()\" class=\"show-details\">\n Ver Detalhes T\u00E9cnicos\n </button>\n <!-- Permitir corre\u00E7\u00E3o do resourcePath diretamente do estado de erro -->\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\" class=\"connect-action\">\n <mat-icon [praxisIcon]=\"'bolt'\"></mat-icon>\n Conectar a recurso\n </button>\n </div>\n} @else if (initializationStatus === 'success') {\n <!-- Inline banner for schema change (only when customization is enabled) -->\n @if (shouldShowOutdatedInline()) {\n <div class=\"pfx-form-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"openConfigEditor()\">\n <mat-icon [praxisIcon]=\"'sync'\"></mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n </div>\n }\n\n <!-- Configuration Controls -->\n @if (shouldShowConfigControls && enableCustomization) {\n <div class=\"form-config-controls\">\n @if (showAiAssistant) {\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"dense\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('config-controls')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Abrir copiloto sem\u00E2ntico do formul\u00E1rio\">\n </button>\n }\n <button type=\"button\" praxisIconButton=\"settings\" size=\"dense\" (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [attr.aria-label]=\"configControlLabel\" [matTooltip]=\"configControlLabel\">\n </button>\n <button type=\"button\" praxisIconButton=\"link_off\" size=\"dense\" (click)=\"disconnect()\"\n [attr.aria-label]=\"disconnectControlLabel\" [matTooltip]=\"disconnectControlLabel\"\n [disabled]=\"isLoading\">\n </button>\n </div>\n }\n\n <!-- Form Content -->\n @if (!resourcePath && !hasExplicitSchemaUrl() && !hasRenderableConfig()) {\n <praxis-empty-state-card\n icon=\"link\"\n [title]=\"'Conecte o formul\u00E1rio \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para gerar automaticamente os campos do formul\u00E1rio.'\"\n [primaryAction]=\"enableCustomization ? { label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) } : undefined\"\n ></praxis-empty-state-card>\n }\n @if (shouldShowContextEmptyState()) {\n <div class=\"form-context-empty-state\" role=\"status\" aria-live=\"polite\">\n <praxis-empty-state-card\n [icon]=\"emptyState?.icon || 'touch_app'\"\n [title]=\"emptyState!.title\"\n [description]=\"emptyState?.description\"\n [tone]=\"emptyState?.tone || 'primary'\"\n [variant]=\"emptyState?.variant || 'transparent'\"\n [alignment]=\"emptyState?.alignment || 'center'\"\n [density]=\"emptyState?.density || 'compact'\"\n [iconContainer]=\"emptyState?.iconContainer || 'circle'\"\n [inline]=\"true\"\n />\n </div>\n } @else {\n <div #entityReadRegion class=\"entity-read-region\" tabindex=\"-1\" role=\"region\" [attr.aria-label]=\"entityReadText('region')\">\n <span class=\"cdk-visually-hidden\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ entityReadStatusText() }}</span>\n @if (entityHydrationPending || entityReadFailed) {\n <div class=\"entity-read-feedback\" data-testid=\"form-entity-read-feedback\">\n @if (entityHydrationPending) {\n <mat-progress-spinner diameter=\"28\" mode=\"indeterminate\" aria-hidden=\"true\"></mat-progress-spinner>\n <p aria-hidden=\"true\">{{ entityReadText('loading') }}</p>\n } @else {\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <p aria-hidden=\"true\">{{ entityReadText('error') }}</p>\n <button mat-stroked-button type=\"button\" (click)=\"retryEntityRead(entityReadRegion)\">{{ entityReadText('retry') }}</button>\n }\n </div>\n }\n <form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting || entityHydrationPending ? 'true' : null\"\n [style.opacity]=\"entityHydrationPending || entityReadFailed ? '0' : null\"\n [style.transition]=\"entityHydrationPending || entityReadFailed ? 'none' : null\"\n [attr.inert]=\"entityHydrationPending || entityReadFailed ? '' : null\"\n [attr.aria-hidden]=\"entityHydrationPending || entityReadFailed ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\"\n [class.praxis-dynamic-form--presentation]=\"effectivePresentation\"\n [class.readonly-mode]=\"effectiveReadonly\"\n [attr.data-presentation-preset]=\"effectivePresentation ? effectivePresentationPreset : null\"\n [class.praxis-dynamic-form--corporate-dossier]=\"isCorporateDossierPreset()\"\n [class.praxis-dynamic-form--editorial-card]=\"isEditorialCardPreset()\"\n [class.praxis-dynamic-form--compact-presentation]=\"isCompactPresentationPreset()\"\n [class.editorial-visual-context]=\"hasEditorialVisualContext()\"\n [class.pfx-mounting]=\"isMounting\" [formGroup]=\"form\"\n [ngClass]=\"{\n 'pres-compact': presentationVars.compact,\n 'pres-label-left': presentationVars.labelPosition === 'left',\n 'pres-label-above': presentationVars.labelPosition === 'above'\n }\" [style.--pfx-pres-label-align]=\"presentationVars.labelAlign\"\n [style.--pfx-pres-label-size]=\"presentationVars.labelSize\"\n [style.--pfx-pres-label-width]=\"presentationVars.labelWidth\"\n [style.--pfx-pres-row-gap]=\"presentationVars.density === 'compact' ? '6px' : (presentationVars.density === 'cozy' ? '8px' : '10px')\"\n [style.--pfx-pres-row-padding]=\"presentationVars.density === 'compact' ? '2px 0' : (presentationVars.density === 'cozy' ? '6px 0' : '8px 0')\"\n [style.--pfx-pres-value-align]=\"presentationVars.valueAlign\"\n [style.--pfx-pres-value-size]=\"presentationVars.valueSize\"\n [style.--pdx-form-mount-duration]=\"getMountDurationVar()\"\n [style.--pdx-form-mount-offset]=\"getMountOffsetVar()\"\n [style.--pdx-form-mount-stagger]=\"getMountStaggerVar()\"\n class=\"praxis-dynamic-form\">\n @if (enableCustomization && selectedElement) {\n <praxis-canvas-toolbar (editMetadata)=\"openSelectedElementEditor()\" (selectPath)=\"onSelectPath($event)\"\n (moveUp)=\"onToolbarMove('up')\" (moveDown)=\"onToolbarMove('down')\" (toggleReadonly)=\"onToolbarToggleReadonly()\"\n (toggleRequired)=\"onToolbarToggleRequired()\" (toggleHidden)=\"onToolbarToggleHidden()\"\n (toggleDisabled)=\"onToolbarToggleDisabled()\" (requestClose)=\"onToolbarRequestClose()\"\n [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n }\n\n @if (formBlocksBefore?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n <!-- Tab Layout Navigation Bar -->\n @if (effectiveLayoutMode === 'tabs' && effectiveTabs.length > 1) {\n <nav class=\"prx-form-tabs\" [attr.data-appearance]=\"effectiveTabsAppearance\" role=\"tablist\" aria-label=\"Navega\u00E7\u00E3o em abas do formul\u00E1rio\">\n <div class=\"prx-form-tabs__tablist prx-form-tabs__tablist--scrollable\">\n @for (tab of effectiveTabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"prx-form-tabs__tab\"\n [class.prx-form-tabs__tab--active]=\"activeTabId === tab.id\"\n [attr.aria-selected]=\"activeTabId === tab.id\"\n [attr.aria-controls]=\"getTabAriaControls(tab)\"\n [attr.id]=\"'tab-' + tab.id\"\n [disabled]=\"tab.disabled\"\n [matTooltip]=\"tab.tooltip || null\"\n [matTooltipDisabled]=\"!tab.tooltip\"\n (click)=\"selectTab(tab.id)\"\n >\n @if (tab.icon) {\n <mat-icon class=\"prx-form-tabs__tab-icon\" [praxisIcon]=\"tab.icon\" aria-hidden=\"true\"></mat-icon>\n }\n <span class=\"prx-form-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge != null) {\n <span class=\"prx-form-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n @if (getTabErrorCount(tab) > 0) {\n <span class=\"prx-form-tabs__tab-error-badge\" [attr.aria-label]=\"getTabErrorCount(tab) + ' erros na aba'\">\n {{ getTabErrorCount(tab) }}\n </span>\n }\n </button>\n }\n </div>\n </nav>\n }\n\n @for (section of (config.sections || []); track (section.id ?? $index); let sectionIndex = $index) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\" [hidden]=\"!isSectionInActiveTab(section)\"\n [attr.role]=\"effectiveLayoutMode === 'tabs' ? 'tabpanel' : null\"\n [attr.id]=\"effectiveLayoutMode === 'tabs' ? ('section-tabpanel-' + section.id) : null\"\n [attr.aria-labelledby]=\"effectiveLayoutMode === 'tabs' ? ('tab-' + (getTabIdForSection(section) || section.id)) : null\">\n @if (isSectionVisible(section)) {\n <div #sectionEl class=\"form-section canvas-element\" data-canvas-type=\"section\" [attr.data-section-id]=\"section.id\"\n [attr.data-section-index]=\"sectionIndex\" (mouseenter)=\"onElementMouseEnter($event, 'section', section, sectionEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'section', section, sectionEl)\"\n [class.selected]=\"selectedElement?.domElement === sectionEl\"\n [class.hovered]=\"hoveredElement?.domElement === sectionEl && selectedElement?.domElement !== sectionEl\"\n [attr.data-section-appearance]=\"getSectionAppearance(section) || null\"\n [attr.data-section-divider]=\"isSectionDividerEnabled(section) ? 'true' : null\"\n [attr.data-presentation-preset]=\"effectivePresentation ? getSectionPresentationPreset(section) : null\"\n [class.form-section--corporate-dossier]=\"isSectionCorporateDossier(section)\"\n [class.form-section--editorial-card]=\"isSectionEditorialCard(section)\"\n [class.form-section--compact-presentation]=\"isSectionCompactPresentation(section)\"\n [style.marginBottom.px]=\"!isLastVisibleSection(section) ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n @if (!shouldHideSectionHeader(section)) {\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n [class.title-only]=\"isSectionHeaderTitleOnly(section)\"\n >\n <div class=\"section-heading-text\" [matTooltip]=\"getSectionHeaderTooltip(section) || null\"\n [matTooltipDisabled]=\"!getSectionHeaderTooltip(section)\">\n @if (getSectionStepLabel(section)) {\n <div class=\"section-step-label\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionStepLabel(section) }}\n </div>\n }\n @if (getSectionTitle(section)) {\n <h3 class=\"section-title\" [class.title-large]=\"getSectionTitleStyle(section) === 'titleLarge'\"\n [class.title-medium]=\"getSectionTitleStyle(section) === 'titleMedium'\"\n [class.title-small]=\"getSectionTitleStyle(section) === 'titleSmall'\"\n [class.headline-small]=\"getSectionTitleStyle(section) === 'headlineSmall'\"\n [style.marginBottom.px]=\"getEffectiveSectionTitleGapBottom(section)\" [style.color]=\"getSectionTitleColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [attr.id]=\"sectionPanelId(section, sectionIndex) + '-title'\">\n @let sectionHeaderVisual = getSectionHeaderVisual(section);\n @let sectionHeaderAvatarSize = getSectionHeaderAvatarSize(section);\n @if (sectionHeaderVisual.kind === 'icon') {\n <mat-icon class=\"section-title-icon\" aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.kind === 'image') {\n <img class=\"section-title-avatar section-title-avatar-image\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\"\n [src]=\"sectionHeaderVisual.src\" [alt]=\"sectionHeaderVisual.alt\" />\n }\n @if (sectionHeaderVisual.kind === 'initials') {\n <span class=\"section-title-avatar section-title-avatar-text\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n {{ sectionHeaderVisual.text }}\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n @if (sectionHeaderVisual.kind === 'placeholder') {\n <span class=\"section-title-avatar section-title-avatar-placeholder\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n @if (sectionHeaderVisual.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.text) {\n <span>{{ sectionHeaderVisual.text }}</span>\n }\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n {{ getSectionTitle(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" praxisIconButton=\"edit\" size=\"dense\" (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\n </button>\n }\n </h3>\n }\n @if (getSectionDescription(section)) {\n <p class=\"section-description\" [class.body-large]=\"getSectionDescriptionStyle(section) === 'bodyLarge'\"\n [class.body-medium]=\"getSectionDescriptionStyle(section) === 'bodyMedium'\"\n [class.body-small]=\"getSectionDescriptionStyle(section) === 'bodySmall'\"\n [style.marginBottom.px]=\"getSectionDescriptionGapBottom(section) ?? 8\" [style.color]=\"getSectionDescriptionColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionDescription(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" praxisIconButton=\"edit\" size=\"dense\"\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\n </button>\n }\n </p>\n }\n </div>\n @if (getSectionHeaderActions(section).length) {\n <div class=\"section-heading-actions\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n @for (action of getSectionHeaderActions(section); track action.id) {\n <button\n type=\"button\"\n class=\"section-heading-action-btn\"\n [praxisIconButton]=\"action.icon\"\n size=\"compact\"\n [busy]=\"action.loading\"\n [disabled]=\"isSectionHeaderActionDisabled(action)\"\n [matTooltip]=\"getSectionHeaderActionTooltip(action)\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-busy]=\"action.loading ? 'true' : null\"\n [ngClass]=\"getSectionHeaderActionNgClass(action)\"\n [ngStyle]=\"getSectionHeaderActionStyles(action)\"\n (click)=\"onSectionHeaderActionClick(section, action, $event)\"\n >\n @if (action.loading) {\n <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" [praxisIconButton]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\" size=\"compact\"\n (click)=\"toggleSectionCollapse($event, section)\" [attr.aria-expanded]=\"!isSectionCollapsed(section)\"\n [attr.aria-controls]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-label]=\"isSectionCollapsed(section) ? 'Expandir se\u00E7\u00E3o' : 'Recolher se\u00E7\u00E3o'\">\n </button>\n }\n </div>\n }\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.role]=\"getSectionTitle(section) ? 'region' : null\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @for (row of section.rows; track (row.id ?? $index); let rowIndex = $index) {\n @if (isRowVisible(row)) {\n <div class=\"row-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n <div #rowEl class=\"form-row grid-12 canvas-element\" data-canvas-type=\"row\" [attr.data-row-index]=\"rowIndex\"\n [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\" [style.--pfx-grid-gap.px]=\"getRowGap(row)\"\n [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [style.--pfx-mount-index]=\"rowIndex\"\n [style.marginBottom.px]=\"rowIndex < section.rows.length - 1 ? (getRowRowGap(row) ?? null) : null\"\n [ngClass]=\"getRowClasses(row)\" [ngStyle]=\"getRowStyles(row)\"\n (mouseenter)=\"onElementMouseEnter($event, 'row', row, rowEl)\" (mouseleave)=\"onElementMouseLeave($event)\"\n (click)=\"onElementClick($event, 'row', row, rowEl)\" [class.selected]=\"selectedElement?.domElement === rowEl\"\n [class.hovered]=\"hoveredElement?.domElement === rowEl && selectedElement?.domElement !== rowEl\">\n @for (column of row.columns; track (column.id ?? $index); let colIndex = $index) {\n @if (isColumnVisible(column)) {\n <div class=\"column-drop-wrapper\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\">\n <div #colEl class=\"form-column canvas-element\" [ngClass]=\"getColumnClasses(column, row)\"\n [style.padding.px]=\"getColumnPadding(column)\" [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [ngStyle]=\"getColumnStyles(column)\" [attr.data-testid]=\"column.testId || null\"\n [attr.data-row-gap]=\"getRowRowGap(row)\" data-canvas-type=\"column\" [attr.data-column-index]=\"colIndex\"\n [attr.data-row-index]=\"rowIndex\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\"\n [attr.data-column-id]=\"column.id\" (mouseenter)=\"onElementMouseEnter($event, 'column', column, colEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'column', column, colEl)\"\n [class.selected]=\"selectedElement?.domElement === colEl\"\n [class.hovered]=\"hoveredElement?.domElement === colEl && selectedElement?.domElement !== colEl\">\n @for (renderItem of getColumnRenderItems(column); track renderItem.id) {\n @if (renderItem.kind === 'fields') {\n <ng-container dynamicFieldLoader [fields]=\"getRenderableFieldsForLoader(renderItem.fields)\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"effectiveReadonly\"\n [disabledMode]=\"effectiveDisabledMode\"\n [presentationMode]=\"presentationForLoader\" [visible]=\"visibleGlobal === null ? null : visibleGlobal\"\n [canvasMode]=\"enableCustomization\" (canvasMouseEnter)=\"onFieldMouseEnter($event)\"\n (canvasMouseLeave)=\"onFieldMouseLeave($event)\" (canvasClick)=\"onFieldClick($event)\"\n (canvasFocus)=\"onFieldFocus($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [ngClass]=\"renderItem.className || null\"\n [ngStyle]=\"renderItem.style || null\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n }\n }\n </div>\n </div>\n } }\n </div>\n </div>\n }\n }\n } @else {\n <div class=\"section-collapsed-placeholder\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'unfold_more'\"></mat-icon>\n <span>{{ getSectionCollapsedSummary(section) }}</span>\n </div>\n }\n @if (isLastVisibleSection(section) && beforeActionsPlacement === 'insideLastSection' && formBlocksBeforeActions?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && isLastVisibleSection(section) && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"effectiveActions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n </div>\n <!-- Overlay de bloqueio durante submiss\u00E3o -->\n @if (submitting) {\n <div class=\"form-blocking-overlay\" aria-live=\"polite\">\n <mat-progress-spinner\n diameter=\"40\"\n color=\"primary\"\n [attr.aria-label]=\"config.messages?.loading?.submit || 'Salvando formul\u00E1rio'\"\n ></mat-progress-spinner>\n <p>{{ config.messages?.loading?.submit || 'Salvando...' }}</p>\n </div>\n }\n </div>\n\n @if (enableCustomization && selectedElement?.domElement === sectionEl) {\n <div class=\"add-section-container\">\n <div class=\"add-section-line\"></div>\n <button mat-fab color=\"primary\" aria-label=\"Adicionar nova se\u00E7\u00E3o\" (click)=\"addNewSectionAfter(sectionIndex)\"\n matTooltip=\"Adicionar nova se\u00E7\u00E3o aqui\">\n <mat-icon [praxisIcon]=\"'add'\"></mat-icon>\n </button>\n <div class=\"add-section-line\"></div>\n </div>\n }\n }\n </div>\n }\n\n @if (beforeActionsPlacement !== 'insideLastSection' && formBlocksBeforeActions?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n <praxis-rich-content\n [document]=\"formBlocksAfterDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n </form>\n </div>\n }\n @if (showAiAssistant && !enableCustomization && (mode === 'view' || mode === 'presentation' || mode === 'dossier') && !shouldShowContextEmptyState()) {\n <div class=\"ai-floating-assistant\">\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"compact\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading || entityHydrationPending || entityReadFailed\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('view-floating')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Pedir ajuda sobre este formul\u00E1rio\">\n </button>\n </div>\n }\n @if (showAiAssistant && aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"dynamic-form-ai-assistant\"\n panelTestId=\"dynamic-form-ai-assistant-panel\"\n submitTestId=\"dynamic-form-ai-assistant-submit\"\n applyTestId=\"dynamic-form-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\n }\n }\n", styles: ["@charset \"UTF-8\";.span-xs-1{grid-column:span 1}.span-xs-2{grid-column:span 2}.span-xs-3{grid-column:span 3}.span-xs-4{grid-column:span 4}.span-xs-5{grid-column:span 5}.span-xs-6{grid-column:span 6}.span-xs-7{grid-column:span 7}.span-xs-8{grid-column:span 8}.span-xs-9{grid-column:span 9}.span-xs-10{grid-column:span 10}.span-xs-11{grid-column:span 11}.span-xs-12{grid-column:span 12}.offset-xs-0{margin-left:0%}.offset-xs-1{margin-left:calc(1 / 12 * 100%)}.offset-xs-2{margin-left:calc(2 / 12 * 100%)}.offset-xs-3{margin-left:25%}.offset-xs-4{margin-left:calc(4 / 12 * 100%)}.offset-xs-5{margin-left:calc(5 / 12 * 100%)}.offset-xs-6{margin-left:50%}.offset-xs-7{margin-left:calc(7 / 12 * 100%)}.offset-xs-8{margin-left:calc(8 / 12 * 100%)}.offset-xs-9{margin-left:75%}.offset-xs-10{margin-left:calc(10 / 12 * 100%)}.offset-xs-11{margin-left:calc(11 / 12 * 100%)}.order-xs--12{order:-12}.order-xs--11{order:-11}.order-xs--10{order:-10}.order-xs--9{order:-9}.order-xs--8{order:-8}.order-xs--7{order:-7}.order-xs--6{order:-6}.order-xs--5{order:-5}.order-xs--4{order:-4}.order-xs--3{order:-3}.order-xs--2{order:-2}.order-xs--1{order:-1}.order-xs-0{order:0}.order-xs-1{order:1}.order-xs-2{order:2}.order-xs-3{order:3}.order-xs-4{order:4}.order-xs-5{order:5}.order-xs-6{order:6}.order-xs-7{order:7}.order-xs-8{order:8}.order-xs-9{order:9}.order-xs-10{order:10}.order-xs-11{order:11}.order-xs-12{order:12}.hidden-xs{display:none}@container praxis-form-row (min-width: 600px){.span-sm-1{grid-column:span 1}.span-sm-2{grid-column:span 2}.span-sm-3{grid-column:span 3}.span-sm-4{grid-column:span 4}.span-sm-5{grid-column:span 5}.span-sm-6{grid-column:span 6}.span-sm-7{grid-column:span 7}.span-sm-8{grid-column:span 8}.span-sm-9{grid-column:span 9}.span-sm-10{grid-column:span 10}.span-sm-11{grid-column:span 11}.span-sm-12{grid-column:span 12}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:calc(1 / 12 * 100%)}.offset-sm-2{margin-left:calc(2 / 12 * 100%)}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:calc(4 / 12 * 100%)}.offset-sm-5{margin-left:calc(5 / 12 * 100%)}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:calc(7 / 12 * 100%)}.offset-sm-8{margin-left:calc(8 / 12 * 100%)}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:calc(10 / 12 * 100%)}.offset-sm-11{margin-left:calc(11 / 12 * 100%)}.order-sm--12{order:-12}.order-sm--11{order:-11}.order-sm--10{order:-10}.order-sm--9{order:-9}.order-sm--8{order:-8}.order-sm--7{order:-7}.order-sm--6{order:-6}.order-sm--5{order:-5}.order-sm--4{order:-4}.order-sm--3{order:-3}.order-sm--2{order:-2}.order-sm--1{order:-1}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.hidden-sm{display:none}}@container praxis-form-row (min-width: 900px){.span-md-1{grid-column:span 1}.span-md-2{grid-column:span 2}.span-md-3{grid-column:span 3}.span-md-4{grid-column:span 4}.span-md-5{grid-column:span 5}.span-md-6{grid-column:span 6}.span-md-7{grid-column:span 7}.span-md-8{grid-column:span 8}.span-md-9{grid-column:span 9}.span-md-10{grid-column:span 10}.span-md-11{grid-column:span 11}.span-md-12{grid-column:span 12}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:calc(1 / 12 * 100%)}.offset-md-2{margin-left:calc(2 / 12 * 100%)}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:calc(4 / 12 * 100%)}.offset-md-5{margin-left:calc(5 / 12 * 100%)}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:calc(7 / 12 * 100%)}.offset-md-8{margin-left:calc(8 / 12 * 100%)}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:calc(10 / 12 * 100%)}.offset-md-11{margin-left:calc(11 / 12 * 100%)}.order-md--12{order:-12}.order-md--11{order:-11}.order-md--10{order:-10}.order-md--9{order:-9}.order-md--8{order:-8}.order-md--7{order:-7}.order-md--6{order:-6}.order-md--5{order:-5}.order-md--4{order:-4}.order-md--3{order:-3}.order-md--2{order:-2}.order-md--1{order:-1}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.hidden-md{display:none}}@container praxis-form-row (min-width: 1200px){.span-lg-1{grid-column:span 1}.span-lg-2{grid-column:span 2}.span-lg-3{grid-column:span 3}.span-lg-4{grid-column:span 4}.span-lg-5{grid-column:span 5}.span-lg-6{grid-column:span 6}.span-lg-7{grid-column:span 7}.span-lg-8{grid-column:span 8}.span-lg-9{grid-column:span 9}.span-lg-10{grid-column:span 10}.span-lg-11{grid-column:span 11}.span-lg-12{grid-column:span 12}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:calc(1 / 12 * 100%)}.offset-lg-2{margin-left:calc(2 / 12 * 100%)}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:calc(4 / 12 * 100%)}.offset-lg-5{margin-left:calc(5 / 12 * 100%)}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:calc(7 / 12 * 100%)}.offset-lg-8{margin-left:calc(8 / 12 * 100%)}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:calc(10 / 12 * 100%)}.offset-lg-11{margin-left:calc(11 / 12 * 100%)}.order-lg--12{order:-12}.order-lg--11{order:-11}.order-lg--10{order:-10}.order-lg--9{order:-9}.order-lg--8{order:-8}.order-lg--7{order:-7}.order-lg--6{order:-6}.order-lg--5{order:-5}.order-lg--4{order:-4}.order-lg--3{order:-3}.order-lg--2{order:-2}.order-lg--1{order:-1}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.hidden-lg{display:none}}@container praxis-form-row (min-width: 1536px){.span-xl-1{grid-column:span 1}.span-xl-2{grid-column:span 2}.span-xl-3{grid-column:span 3}.span-xl-4{grid-column:span 4}.span-xl-5{grid-column:span 5}.span-xl-6{grid-column:span 6}.span-xl-7{grid-column:span 7}.span-xl-8{grid-column:span 8}.span-xl-9{grid-column:span 9}.span-xl-10{grid-column:span 10}.span-xl-11{grid-column:span 11}.span-xl-12{grid-column:span 12}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:calc(1 / 12 * 100%)}.offset-xl-2{margin-left:calc(2 / 12 * 100%)}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:calc(4 / 12 * 100%)}.offset-xl-5{margin-left:calc(5 / 12 * 100%)}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:calc(7 / 12 * 100%)}.offset-xl-8{margin-left:calc(8 / 12 * 100%)}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:calc(10 / 12 * 100%)}.offset-xl-11{margin-left:calc(11 / 12 * 100%)}.order-xl--12{order:-12}.order-xl--11{order:-11}.order-xl--10{order:-10}.order-xl--9{order:-9}.order-xl--8{order:-8}.order-xl--7{order:-7}.order-xl--6{order:-6}.order-xl--5{order:-5}.order-xl--4{order:-4}.order-xl--3{order:-3}.order-xl--2{order:-2}.order-xl--1{order:-1}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.hidden-xl{display:none}}.canvas-mode-enabled{--canvas-hit: 14px}.canvas-mode-enabled .canvas-element{position:relative;z-index:0;border-radius:8px;outline:2px solid transparent;outline-offset:2px;transition:outline-color .2s ease,outline-style .2s ease}.canvas-mode-enabled .canvas-element:before{content:\"\";position:absolute;inset:calc(-1 * var(--canvas-hit));pointer-events:none;border-radius:inherit;background:transparent}.canvas-mode-enabled .canvas-element[data-canvas-type=section]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element[data-canvas-type=row]{--outline-color: var(--md-sys-color-secondary)}.canvas-mode-enabled .canvas-element[data-canvas-type=column],.canvas-mode-enabled .canvas-element[data-canvas-type=field]{--outline-color: var(--md-sys-color-tertiary)}.canvas-mode-enabled .canvas-element[data-canvas-type=actions]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element.hovered:not(.selected){outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:dashed}.canvas-mode-enabled .canvas-element.selected{outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:solid;box-shadow:0 0 0 2px var(--outline-color, var(--md-sys-color-primary))}.canvas-mode-enabled .canvas-element.hovered{z-index:var(--praxis-layer-authoring-hover, 300)}.canvas-mode-enabled .canvas-element.selected{z-index:var(--praxis-layer-authoring-selected, 320)}.section-drop-wrapper,.row-drop-wrapper,.column-drop-wrapper{display:contents}.add-section-container{display:flex;align-items:center;justify-content:center;padding:.5rem 0;margin:-.5rem 0;position:relative;z-index:var(--praxis-layer-authoring-insert, 280)}.add-section-container .add-section-line{flex-grow:1;height:1px;background:repeating-linear-gradient(90deg,var(--md-sys-color-outline-variant),var(--md-sys-color-outline-variant) 4px,transparent 4px,transparent 8px)}.add-section-container button{margin:0 1rem;transform:scale(.85)}:host{display:block;position:relative;--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--pdx-color-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent );--pfx-form-shell-padding: clamp(.9rem, 1.4vw, 1.2rem)}.form-config-controls{position:relative;top:auto;margin:0;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--pfx-form-shell-surface) 88%,var(--md-sys-color-surface) 12%);padding:8px var(--pfx-form-shell-padding);border:1px solid var(--pfx-form-footer-border);border-bottom-color:color-mix(in srgb,var(--pfx-form-footer-border) 72%,transparent);border-radius:var(--pfx-editorial-form-radius) var(--pfx-editorial-form-radius) 0 0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:none;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.96;transition:opacity .16s ease,border-color .16s ease}.form-config-controls>*{pointer-events:auto}.form-config-controls:hover,.form-config-controls:focus-within{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%)}.form-config-controls .praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}.form-config-controls .praxis-icon-button:hover{color:var(--md-sys-color-primary)}.ai-floating-assistant{position:sticky;right:0;bottom:12px;margin-top:14px;margin-left:auto;width:fit-content;z-index:70;pointer-events:none}.ai-floating-assistant button{pointer-events:auto;display:inline-flex}.ai-floating-assistant .ai-trigger-btn{box-shadow:0 12px 28px #0f172a24}.config-button{color:var(--md-sys-color-primary)}.form-loading{display:flex;flex-direction:column;align-items:stretch;justify-content:center;padding:1.25rem;text-align:left;color:var(--md-sys-color-on-surface);gap:1rem;min-height:220px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,var(--md-sys-color-outline-variant) 86%);border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent 42%),color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,var(--md-sys-color-surface) 22%);box-shadow:0 12px 28px #0f172a14}.entity-read-region{position:relative;min-width:0}.entity-read-feedback{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:1rem;padding:2rem 1rem;box-sizing:border-box;text-align:center;color:var(--md-sys-color-on-surface)}.entity-read-feedback p{margin:0;max-width:40ch}.form-loading-header{display:flex;align-items:center;gap:.85rem}.form-loading-copy{min-width:0}.form-loading p{margin:0}.form-loading-title{font-weight:700;color:var(--md-sys-color-on-surface)}.form-loading-subtitle{margin-top:.2rem;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.form-loading-skeleton{display:grid;gap:.7rem}.form-loading-line,.form-loading-field{display:block;overflow:hidden;position:relative;border-radius:6px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,var(--md-sys-color-primary) 6%)}.form-loading-line:after,.form-loading-field:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 16%,var(--md-sys-color-on-surface) 18%),transparent);animation:form-loading-shimmer 1.4s ease-in-out infinite}.form-loading-line{height:12px}.form-loading-line-title{width:min(42%,240px)}.form-loading-line-short{width:min(64%,360px)}.form-loading-field{height:44px}.form-loading-field-wide{height:72px}@keyframes form-loading-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.form-loading-line:after,.form-loading-field:after{animation:none;transform:none;opacity:.28}}.form-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-error);gap:1rem;border:1px solid var(--md-sys-color-error);border-radius:8px;background-color:var(--md-sys-color-error-container);margin:1rem;box-shadow:0 12px 30px #7f1d1d1f}.form-error h3{margin:0;color:var(--md-sys-color-on-error-container)}.form-error p{margin:0;color:var(--md-sys-color-on-error-container);opacity:.8}.form-error button{margin-top:.5rem}.pfx-form-info-banner{margin-bottom:14px;padding:12px 14px;border-radius:16px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant) 82%);background:color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface) 76%);color:var(--md-sys-color-on-surface);display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.pfx-form-info-banner .text{font-size:.92rem;line-height:1.5;font-weight:600}.pfx-form-info-banner .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.praxis-dynamic-form{display:flex;flex-direction:column;max-width:100%;min-width:0;transition:all .3s ease;position:relative;font-family:inherit;font-size:inherit;color:inherit;--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--md-sys-color-surface-container) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --pdx-color-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --pdx-color-text-secondary, var(--md-sys-color-on-surface-variant) );--pfx-editorial-form-field-surface: color-mix( in srgb, var(--pfx-editorial-form-surface-muted) 76%, var(--pfx-editorial-form-surface) 24% );--pfx-editorial-form-field-outline: color-mix( in srgb, var(--pfx-editorial-form-border) 88%, transparent );--pfx-editorial-form-accent: var( --pdx-color-primary, var(--md-sys-color-primary) );--pfx-editorial-form-accent-text: var(--md-sys-color-on-primary);--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-field-radius: var(--pfx-form-field-radius, 4px);--pfx-editorial-form-border-width: 1px;--pfx-editorial-form-field-border-width: 1px;--pfx-editorial-form-shadow: none;--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-surface-flat: color-mix( in srgb, var(--pfx-editorial-form-surface) 78%, var(--pfx-editorial-form-surface-muted) 22% );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-label-strong: color-mix( in srgb, var(--pfx-editorial-form-text) 96%, white 4% );--pfx-form-label-muted: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 92%, var(--pfx-editorial-form-text) 8% );--pfx-form-field-surface-rest: color-mix( in srgb, var(--pfx-editorial-form-field-surface) 82%, var(--pfx-editorial-form-surface) 18% );--pfx-form-field-surface-focus: color-mix( in srgb, var(--pfx-editorial-form-accent) 4%, var(--pfx-form-field-surface-rest) 96% );--pfx-form-field-min-height: 48px;--pfx-form-section-padding: clamp(1.1rem, 1.8vw, 1.5rem);--pfx-form-section-gap: 22px;--pdx-presentation-label-size: var(--pfx-pres-compact-label-size, .78rem);--pdx-presentation-value-size: var(--pfx-pres-compact-value-size, 1rem);--pdx-presentation-icon-size: var(--pfx-pres-icon-size, 18px);--pdx-presentation-row-gap: var(--pfx-pres-row-gap, .5rem);--pdx-presentation-column-gap: var(--pfx-pres-column-gap, .5rem);--pdx-presentation-section-gap: var(--pfx-pres-section-gap, .75rem);--pdx-presentation-label-width: var(--pfx-pres-label-width, 220px);--pdx-presentation-flag-height: var(--pfx-pres-boolean-min-height, 22px);--pdx-presentation-flag-radius: var(--pfx-pres-boolean-radius, 999px);--pdx-presentation-flag-padding: var(--pfx-pres-boolean-padding, 0 8px);--pdx-presentation-flag-active-color: var( --pfx-pres-boolean-active-color, var(--md-sys-color-primary) );--pdx-presentation-flag-active-bg: var( --pfx-pres-boolean-active-bg, color-mix(in srgb, var(--md-sys-color-primary) 14%, transparent) );--pdx-presentation-flag-inactive-color: var( --pfx-pres-boolean-inactive-color, var(--md-sys-color-on-surface-variant) );--pdx-presentation-flag-inactive-bg: var( --pfx-pres-boolean-inactive-bg, color-mix(in srgb, var(--md-sys-color-outline-variant) 34%, transparent) );--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent )}.praxis-dynamic-form.canvas-mode-enabled{border:1px solid var(--pfx-form-footer-border);border-radius:var(--pfx-editorial-form-radius);background:linear-gradient(180deg,color-mix(in srgb,var(--pfx-form-shell-surface) 86%,transparent),color-mix(in srgb,var(--pfx-editorial-form-surface-muted) 42%,transparent));overflow:visible}.form-config-controls+.praxis-dynamic-form.canvas-mode-enabled{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks{margin-inline:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper:first-of-type,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks:first-child{margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>praxis-form-actions[data-actions-placement=afterSections]{display:block;margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.editorial-visual-context{--_pfx-editorial-host-text: var( --editorial-text-primary, var(--foreground, var(--mat-sys-on-surface, #1d1b20)) );--_pfx-editorial-host-text-muted: var( --editorial-text-secondary, var( --muted-foreground, color-mix(in srgb, var(--_pfx-editorial-host-text) 64%, transparent) ) );--_pfx-editorial-host-surface: var( --editorial-surface-primary, var(--card, var(--mat-sys-surface-container, #ffffff)) );--_pfx-editorial-host-surface-muted: var( --editorial-surface-secondary, var(--surface-dim, var(--muted, var(--mat-sys-surface-container-low, #f7f2fa))) );--_pfx-editorial-host-border: var( --editorial-border-color, var(--border, var(--mat-sys-outline-variant, #cac4d0)) );--_pfx-editorial-host-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--primary, var(--mat-sys-primary, #6750a4))) );--_pfx-editorial-host-accent-text: var( --editorial-cta-primary-text, var( --editorial-accent-contrast, var(--primary-foreground, var(--mat-sys-on-primary, #ffffff)) ) );--_pfx-editorial-host-accent-container: var( --primary-container, color-mix(in srgb, var(--_pfx-editorial-host-accent) 16%, var(--_pfx-editorial-host-surface) 84%) );--_pfx-editorial-host-accent-container-text: var( --primary-container-fg, var(--_pfx-editorial-host-accent) );font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--_pfx-editorial-host-text);--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--_pfx-editorial-host-surface)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--_pfx-editorial-host-surface-muted) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--_pfx-editorial-host-border)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--_pfx-editorial-host-text) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, color-mix( in srgb, var(--_pfx-editorial-host-text-muted) 86%, var(--_pfx-editorial-host-text) 14% ) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--_pfx-editorial-host-accent)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--_pfx-editorial-host-accent-text)) );--pfx-editorial-form-accent-container: var(--_pfx-editorial-host-accent-container);--pfx-editorial-form-accent-container-text: var(--_pfx-editorial-host-accent-container-text);--pfx-editorial-form-radius: var(--editorial-card-radius, 18px);--pfx-editorial-form-field-radius: var( --editorial-field-radius, var(--editorial-card-radius, 14px) );--pfx-editorial-form-border-width: var(--editorial-card-border-width, 1px);--pfx-editorial-form-field-border-width: var(--editorial-field-border-width, 1px);--pfx-editorial-form-shadow: var(--editorial-card-shadow, none);--md-sys-color-surface: var( --pfx-editorial-form-surface, var(--md-sys-color-surface) );--md-sys-color-surface-container: var( --pfx-editorial-form-surface, var(--md-sys-color-surface-container) );--md-sys-color-surface-container-low: var( --pfx-editorial-form-surface-muted, var(--md-sys-color-surface-container-low) );--md-sys-color-surface-variant: var( --pfx-editorial-form-field-surface, var(--md-sys-color-surface-variant) );--md-sys-color-outline: var( --pfx-editorial-form-field-outline, var(--md-sys-color-outline) );--md-sys-color-outline-variant: var( --pfx-editorial-form-border, var(--md-sys-color-outline-variant) );--md-sys-color-on-surface: var( --editorial-text-primary, inherit );--md-sys-color-on-surface-variant: var( --editorial-text-secondary, inherit );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-primary-container: var( --pfx-editorial-form-accent-container, var(--md-sys-color-primary-container) );--md-sys-color-on-primary-container: var( --pfx-editorial-form-accent-container-text, var(--md-sys-color-on-primary-container) );--md-sys-color-on-primary: var( --pfx-editorial-form-accent-text, var(--md-sys-color-on-primary) );--md-sys-color-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );--mat-sys-on-surface: var( --editorial-text-primary, inherit );--mat-sys-on-surface-variant: var( --editorial-text-secondary, inherit );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );color:inherit;color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:var(--pdx-presentation-column-gap);margin-bottom:var(--pdx-presentation-row-gap)}.praxis-dynamic-form.presentation-mode{--pfx-pres-on-surface: var( --pdx-color-text-primary, var(--pfx-editorial-form-text, var(--pfx-form-label-strong, currentColor)) );--pfx-pres-on-surface-variant: var( --pdx-color-text-secondary, var( --pfx-editorial-form-text-muted, var( --pfx-form-label-muted, color-mix(in srgb, var(--pfx-pres-on-surface) 78%, transparent) ) ) )}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:var(--pdx-presentation-section-gap) .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:var(--pdx-presentation-column-gap, .35rem);margin-bottom:var(--pdx-presentation-row-gap, .35rem)}.praxis-dynamic-form.pres-compact .form-section{padding:var(--pdx-presentation-section-gap, .5rem) .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:minmax(0,var(--pfx-presentation-label-w, var(--pdx-presentation-label-width))) minmax(0,1fr);align-items:baseline;column-gap:var(--pdx-presentation-column-gap, 10px)}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}@media(max-width:480px){.praxis-dynamic-form.pres-label-left .praxis-presentation{grid-template-columns:minmax(0,1fr);row-gap:4px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:start}}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low, #f8f9fa);border:1px solid var(--md-sys-color-outline-variant, #e0e2ec);border-radius:16px;padding:16px 20px;box-shadow:0 1px 3px #0000000a}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-heading{margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--md-sys-color-outline-variant, #e0e2ec)}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-title,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-title{font-size:.88rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--md-sys-color-primary, #005ac1)}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation{padding:8px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep .form-section--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=corporate-dossier] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__label,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:3px}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__value,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__value{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.4}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low, var(--mat-sys-surface-container-low)));border:1px solid var(--pfx-editorial-form-border, var(--md-sys-color-outline-variant, #e0e2ec));border-radius:20px;padding:24px;box-shadow:0 2px 8px #0000000d}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--editorial-card .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-heading{margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 40%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-title,.praxis-dynamic-form .form-section.form-section--editorial-card .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-title{font-size:1.15rem;font-weight:700;color:var(--pfx-editorial-form-accent, var(--md-sys-color-primary, #005ac1))}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation{padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 35%,transparent)}:host ::ng-deep .praxis-dynamic-form--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation:last-child,:host ::ng-deep .form-section--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=editorial-card] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__label,:host ::ng-deep .form-section--editorial-card .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__label{font-size:.8rem;font-weight:500;color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant, #44474f));margin-bottom:4px}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__value,:host ::ng-deep .form-section--editorial-card .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__value{font-size:1rem;font-weight:600;color:var(--pfx-editorial-form-text, var(--md-sys-color-on-surface, #1a1c1e));line-height:1.5}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--compact-presentation:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation]:not(.section-appearance-plain){background:transparent;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 50%,transparent);border-radius:8px;padding:10px 14px;box-shadow:none}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-heading{margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 25%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-title,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-title{font-size:.82rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #44474f)}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation,:host ::ng-deep .form-section--compact-presentation .praxis-presentation,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation{padding:4px 0;border-bottom:none}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__label,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__label{font-size:.72rem;font-weight:600;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:2px}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__value,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__value{font-size:.88rem;font-weight:500;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.35}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 2px 8px #0000004d}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low));border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 4px 16px #0006}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);max-width:100%;min-width:0;background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section:not(.section-appearance-plain){border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;color:var(--pfx-editorial-form-text);box-shadow:var(--editorial-card-shadow, none)}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{background-color:var(--pfx-editorial-form-surface)!important;background-image:linear-gradient(180deg,color-mix(in srgb,var(--editorial-accent, var(--md-sys-color-primary)) 6%,transparent) 0%,transparent 132px)!important;background-repeat:no-repeat!important}.section-drop-wrapper>.form-section{margin-bottom:var(--pfx-section-gap, 20px)}.section-drop-wrapper:last-of-type>.form-section{margin-bottom:0}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections]{margin-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}.section-title{margin:0 0 var(--pfx-section-title-mb, 12px) 0;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.12rem);font-weight:700;color:var(--pfx-form-label-strong)}.section-heading{position:relative;display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 18px)}.section-heading:after{content:\"\";position:absolute;right:0;bottom:0;left:0;height:2px;pointer-events:none;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 8%,var(--pfx-form-section-divider) 46%,var(--pfx-form-section-divider) 54%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 92%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%);mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 10px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:none}.section-heading.align-center{flex-direction:column;align-items:center;text-align:center}.section-heading.align-center .section-heading-text{display:grid;justify-items:center}.section-step-label{display:inline-flex;align-items:center;min-height:24px;padding:0 10px;margin:0 0 8px;border-radius:999px;background:color-mix(in srgb,var(--pfx-editorial-form-accent) 10%,transparent);color:color-mix(in srgb,var(--pfx-editorial-form-accent) 84%,var(--pfx-form-label-strong) 16%);font-size:.72rem;font-weight:800;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));letter-spacing:.08em;text-transform:uppercase}.section-heading-text{flex:1 1 auto;min-width:0}.section-heading-actions{display:inline-flex;align-items:center;align-self:flex-start;flex-wrap:wrap;gap:4px;margin-left:auto}.section-heading-actions.align-center{align-self:center;margin-left:0}.section-heading-action-btn{color:var(--pfx-form-label-muted)}.section-heading-action-btn.tone-primary{color:var(--md-sys-color-primary)}.section-heading-action-btn.tone-accent,.section-heading-action-btn.tone-secondary{color:var(--md-sys-color-tertiary)}.section-heading-action-btn.tone-warn,.section-heading-action-btn.tone-danger,.section-heading-action-btn.tone-error{color:var(--md-sys-color-error)}.section-heading-action-btn .mat-mdc-progress-spinner,.section-heading-action-btn mat-progress-spinner{--mdc-circular-progress-active-indicator-color: currentColor}.section-heading-action-btn.loading{opacity:.72;pointer-events:none}.section-heading-action-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.section-collapse-btn{margin-left:4px;color:var(--pfx-form-label-muted)}.section-title.title-large{font:var(--mdc-typography-title-large, 500 22px/28px system-ui)}.section-title.title-medium{font:var(--mdc-typography-title-medium, 500 16px/24px system-ui)}.section-title.title-small{font:var(--mdc-typography-title-small, 500 14px/20px system-ui)}.section-title.headline-small{font:var(--mdc-typography-headline-small, 600 24px/32px system-ui)}.section-title.title-large,.section-title.title-medium,.section-title.title-small,.section-title.headline-small{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-weight:var(--editorial-title-weight, 600)}.section-description{margin:0;font-family:var(--editorial-body-font-family, inherit);font-size:.93rem;color:var(--pfx-form-label-muted);line-height:1.6}.section-description.body-large{font:var(--mdc-typography-body-large, 400 16px/24px system-ui)}.section-description.body-medium{font:var(--mdc-typography-body-medium, 400 14px/20px system-ui)}.section-description.body-small{font:var(--mdc-typography-body-small, 400 12px/16px system-ui)}.section-description.body-large,.section-description.body-medium,.section-description.body-small{font-family:var(--editorial-body-font-family, inherit);font-weight:var(--editorial-body-weight, 400)}.section-title.align-center,.section-description.align-center,.section-step-label.align-center{text-align:center}.praxis-dynamic-form .form-section.section-appearance-plain{border-color:transparent;border-width:0;border-radius:0;padding:0;background:transparent;box-shadow:none}.praxis-dynamic-form .form-section.section-appearance-plain.section-has-divider{padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider, var(--md-sys-color-outline-variant, #e0e2ec))}.praxis-dynamic-form .section-drop-wrapper:last-of-type>.form-section.section-appearance-plain.section-has-divider,.praxis-dynamic-form>.form-section.section-appearance-plain.section-has-divider:last-of-type{border-bottom:none;padding-bottom:0}.form-section.section-appearance-plain .section-heading{margin-bottom:14px}.form-section.section-appearance-step{border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);border-color:var(--pfx-form-section-divider);box-shadow:none}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{border-radius:var(--editorial-card-radius, 20px);box-shadow:none}.form-section.section-appearance-step .section-heading{margin-bottom:22px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 16px)}.form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 16px)}:host(.pfx-form-section-divider-inline-title) .form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}.form-section.section-appearance-step .section-title{font:var(--mdc-typography-title-large, 700 22px/28px system-ui);color:var(--pfx-form-label-strong);margin-bottom:8px}.form-section.section-appearance-step .section-description{color:var(--pfx-form-label-muted);max-width:60ch}.form-section.section-appearance-step .section-step-label{min-height:24px;padding:0 10px;margin-bottom:10px;box-shadow:none}.form-section.section-appearance-step .section-heading.align-center .section-description{max-width:52ch}.form-section.section-appearance-step .section-body{display:grid;gap:8px;padding-top:0}.form-section.section-appearance-step .form-row{margin-bottom:var(--pfx-field-gap, 1rem)}.form-section.section-appearance-step .form-column{gap:var(--pfx-field-gap, 12px)}.form-section .form-editorial-blocks{display:grid;gap:16px}.form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{margin-top:24px;padding-top:18px;border-top:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]{gap:18px}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]>*+*{margin-top:2px}.praxis-dynamic-form:not(.canvas-mode-enabled)>praxis-form-actions[data-actions-placement=afterSections]{margin-top:18px}.praxis-dynamic-form>.form-editorial-blocks[data-editorial-placement=after]{margin-top:6px}:host-context(.mdc-theme-dark) .form-section.section-appearance-step,:host-context(.theme-dark) .form-section.section-appearance-step{border-color:color-mix(in srgb,var(--pfx-editorial-form-border) 82%,transparent);box-shadow:none}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-title,:host-context(.theme-dark) .form-section.section-appearance-step .section-title{color:color-mix(in srgb,var(--pfx-editorial-form-text) 96%,white)}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-description,:host-context(.theme-dark) .form-section.section-appearance-step .section-description{color:color-mix(in srgb,var(--pfx-editorial-form-text-muted) 86%,var(--pfx-editorial-form-text) 14%)}:host-context(.mdc-theme-dark) .section-step-label,:host-context(.theme-dark) .section-step-label{background:color-mix(in srgb,var(--md-sys-color-primary-container) 54%,transparent);color:color-mix(in srgb,var(--md-sys-color-primary) 88%,white)}:host-context(.mdc-theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions],:host-context(.theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{border-top-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 90%,transparent)}.inline-edit-btn{margin-left:6px;vertical-align:middle}.section-body.collapsed{border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);border-radius:6px;padding:8px 10px}.section-collapsed-placeholder{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.95rem}.section-collapsed-placeholder mat-icon{font-size:20px;width:20px;height:20px}.form-row{display:flex;gap:1.1rem;margin-bottom:var(--pfx-field-gap, 1.1rem);max-width:100%;min-width:0;transition:all .2s ease;border-radius:6px;position:relative}.praxis-dynamic-form.pfx-mounting .form-row{opacity:0;transform:translateY(var(--pdx-form-mount-offset, 6px));animation:pdxFormMount var(--pdx-form-mount-duration, .16s) ease-out both;animation-delay:calc(var(--pfx-mount-index, 0) * var(--pdx-form-mount-stagger, 20ms))}@media(prefers-reduced-motion:reduce){.praxis-dynamic-form.pfx-mounting .form-row{animation:none;opacity:1;transform:none}}@keyframes pdxFormMount{to{opacity:1;transform:translateY(0)}}.praxis-dynamic-form .mat-mdc-form-field{width:100%;margin-bottom:var(--pfx-field-gap, 10px);font-family:inherit;--mdc-filled-text-field-container-color: var(--pfx-form-field-surface-rest);--mdc-filled-text-field-focus-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-active-indicator-color: var(--pfx-editorial-form-field-outline);--mdc-filled-text-field-hover-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-filled-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-caret-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-input-text-placeholder-color: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 82%, transparent );--mdc-outlined-text-field-outline-color: var(--pfx-editorial-form-field-outline);--mdc-outlined-text-field-hover-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-outlined-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-outlined-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-filled-text-field-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-filled-text-field-focus-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-outline-width: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-focus-outline-width: var(--pfx-editorial-form-field-border-width);--mat-select-enabled-trigger-text-color: var(--pfx-editorial-form-text);--mat-select-enabled-arrow-color: var(--pfx-form-label-muted);--mat-form-field-enabled-select-arrow-color: var(--pfx-form-label-muted);--mat-form-field-focus-select-arrow-color: var(--pfx-editorial-form-accent);--mat-form-field-hover-state-layer-opacity: 0;--mat-form-field-focus-state-layer-opacity: 0}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field{font-family:var(--editorial-body-font-family, inherit)}.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{background:var(--pfx-form-field-surface-rest);border-radius:var(--pfx-editorial-form-field-radius);min-height:var(--pfx-form-field-min-height);transition:background-color .16s ease,box-shadow .16s ease,border-color .16s ease}.praxis-dynamic-form.editorial-visual-context .mat-mdc-text-field-wrapper,.praxis-dynamic-form.editorial-visual-context .mdc-text-field,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--filled,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--outlined{background-color:var(--pfx-form-field-surface-rest)!important;background:var(--pfx-form-field-surface-rest)!important}.praxis-dynamic-form .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-form-label-muted)}.praxis-dynamic-form .mat-mdc-input-element,.praxis-dynamic-form .mat-mdc-select-value-text,.praxis-dynamic-form .mat-mdc-form-field-infix,.praxis-dynamic-form .mat-mdc-select-min-line{color:var(--pfx-editorial-form-text)}.praxis-dynamic-form .mat-mdc-form-field:hover .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field:hover .mdc-text-field,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mdc-text-field{background:var(--pfx-form-field-surface-focus)}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-value-text,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field-infix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-min-line,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input{color:var(--pfx-editorial-form-text)!important;-webkit-text-fill-color:var(--pfx-editorial-form-text)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-editorial-form-text-muted)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 68%,transparent)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element::placeholder,.praxis-dynamic-form.editorial-visual-context textarea.mat-mdc-input-element::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 58%,transparent)!important}.praxis-dynamic-form .mat-mdc-radio-button,.praxis-dynamic-form .mat-mdc-checkbox,.praxis-dynamic-form .mat-mdc-slide-toggle{--mdc-radio-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-checkmark-color: var(--pfx-editorial-form-accent-text);--mdc-checkbox-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-focus-state-layer-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-handle-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-track-color: color-mix(in srgb, var(--pfx-editorial-form-accent) 45%, #fff)}.praxis-dynamic-form [data-field-type=input],.praxis-dynamic-form [data-field-type=textarea],.praxis-dynamic-form [data-field-type=email],.praxis-dynamic-form [data-field-type=password],.praxis-dynamic-form [data-field-type=url],.praxis-dynamic-form [data-field-type=search],.praxis-dynamic-form [data-field-type=phone],.praxis-dynamic-form [data-field-type=numericTextBox],.praxis-dynamic-form [data-field-type=currency],.praxis-dynamic-form [data-field-type=cpfCnpj],.praxis-dynamic-form [data-field-type=date],.praxis-dynamic-form [data-field-type=dateInput],.praxis-dynamic-form [data-field-type=dateRange],.praxis-dynamic-form [data-field-type=dateTimeLocal],.praxis-dynamic-form [data-field-type=time],.praxis-dynamic-form [data-field-type=timePicker],.praxis-dynamic-form [data-field-type=timeRange],.praxis-dynamic-form [data-field-type=month],.praxis-dynamic-form [data-field-type=week],.praxis-dynamic-form [data-field-type=yearInput],.praxis-dynamic-form [data-field-type=select],.praxis-dynamic-form [data-field-type=multi-select],.praxis-dynamic-form [data-field-type=searchable-select],.praxis-dynamic-form [data-field-type=async-select],.praxis-dynamic-form [data-field-type=autocomplete],.praxis-dynamic-form [data-field-type=entityLookup],.praxis-dynamic-form [data-field-type=tree-select],.praxis-dynamic-form [data-field-type=multi-select-tree],.praxis-dynamic-form [data-field-type=priceRange],.praxis-dynamic-form [data-field-type=file-upload]{display:block;width:100%;min-width:0}.praxis-dynamic-form .mat-mdc-form-field-subscript-wrapper{min-height:var(--pfx-subscript-min-h, 22px)}.form-row:last-child{margin-bottom:0}.form-column{display:grid;grid-template-columns:minmax(0,1fr);align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;max-width:100%;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-layout-rich-content{display:block;width:100%;max-width:100%;min-width:0;margin-bottom:var(--pfx-field-gap, 10px);color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant));font:var(--mdc-typography-body-medium, 400 14px/20px system-ui);overflow-wrap:anywhere}:host ::ng-deep .form-layout-rich-content .prx-rich-content-root{display:grid;gap:8px;min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-node{min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-text{color:inherit;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{border:1px solid color-mix(in srgb,var(--pfx-editorial-form-accent) 12%,var(--pfx-editorial-form-border) 88%);border-left:3px solid var(--pfx-editorial-form-accent);border-radius:8px;background:color-mix(in srgb,var(--pfx-editorial-form-accent-container) 12%,var(--pfx-editorial-form-surface-muted) 88%)}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;align-items:flex-start;padding:11px 12px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note:before{content:\"info\";display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--pfx-editorial-form-accent);font-family:Material Symbols Outlined;font-size:20px;font-weight:400;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{padding:10px 12px;color:var(--pfx-editorial-form-text)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-compose{align-items:flex-start;gap:10px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-icon{color:var(--pfx-editorial-form-accent);font-size:20px;line-height:20px;margin-top:1px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider{display:grid;grid-template-columns:minmax(24px,1fr) auto minmax(24px,1fr);align-items:center;gap:10px;color:var(--pfx-editorial-form-text-muted);font:var(--mdc-typography-label-small, 600 12px/16px system-ui);text-transform:uppercase}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:before,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:after{content:\"\";height:1px;background:var(--pfx-editorial-form-border)}:host ::ng-deep .form-layout-rich-content .prx-rich-card{gap:6px;padding:12px 14px;border-color:var(--pfx-editorial-form-border);border-radius:8px;background:var(--pfx-editorial-form-surface-muted);color:var(--pfx-editorial-form-text);box-shadow:none}:host ::ng-deep .form-layout-rich-content .prx-rich-card-title{color:var(--pfx-editorial-form-text);font:var(--mdc-typography-title-small, 600 14px/20px system-ui)}:host ::ng-deep .form-layout-rich-content .prx-rich-card-subtitle,:host ::ng-deep .form-layout-rich-content .prx-rich-metric-caption{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-card .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-badge{background:var(--pfx-editorial-form-accent-container);color:var(--pfx-editorial-form-accent-container-text)}.form-row.grid-12{container-type:inline-size;container-name:praxis-form-row;display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.align-start{align-self:flex-start}.align-center{align-self:center}.align-end{align-self:flex-end}.align-stretch{align-self:stretch}.form-blocking-overlay{position:absolute;inset:0;background:transparent;color:var(--md-sys-color-on-surface);backdrop-filter:blur(2px) saturate(103%);-webkit-backdrop-filter:blur(2px) saturate(103%);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;z-index:10;pointer-events:all}@media(max-width:768px){.column-drop-wrapper,.row-drop-wrapper,.form-layout-rich-content,.praxis-dynamic-form .mat-mdc-form-field,.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{max-width:100%;min-width:0}:host ::ng-deep .praxis-dynamic-form .pfx-field-shell,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-wrapper,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-host,:host ::ng-deep .praxis-dynamic-form .mat-mdc-form-field,:host ::ng-deep .praxis-dynamic-form .mat-mdc-text-field-wrapper,:host ::ng-deep .praxis-dynamic-form .mdc-text-field{width:100%;max-width:100%;min-width:0}.form-section{padding:clamp(.75rem,4vw,1rem)}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 14px)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}}.section-title{display:flex;align-items:center;gap:8px}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:100%;min-width:0}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{content:\"\";display:block;flex:1 1 auto;min-width:var(--pfx-form-section-title-inline-divider-min-width, 48px);height:2px;margin-left:var(--pfx-form-section-title-inline-divider-gap, 12px);pointer-events:none;background:linear-gradient(90deg,var(--pfx-form-section-divider) 0%,var(--pfx-form-section-divider) 62%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 88%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%);mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%)}:host(.pfx-form-section-divider-inline-title) .section-heading.align-center .section-title:after{display:none}@media(max-width:640px){:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:block}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:auto}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{display:none}}.section-title .section-title-icon{font-size:1.25em;line-height:1}.section-title-avatar{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px));display:inline-flex;align-items:center;justify-content:center;width:var(--_pfx-form-section-avatar-size);height:var(--_pfx-form-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-form-section-avatar-size);overflow:hidden}.section-title-avatar.size-sm{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-title-avatar.size-md{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-title-avatar.size-lg{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-title-avatar-image{object-fit:cover;border:1px solid color-mix(in srgb,var(--pfx-form-section-divider) 72%,transparent);background:var(--pfx-form-section-surface-flat)}.section-title-avatar-text,.section-title-avatar-placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent) 14%,var(--pfx-form-section-surface-flat));color:color-mix(in srgb,var(--pfx-editorial-form-accent) 82%,var(--pfx-form-label-strong) 18%);font-size:calc(var(--_pfx-form-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-title-avatar-placeholder mat-icon{font-size:calc(var(--_pfx-form-section-avatar-size) * .5625);width:calc(var(--_pfx-form-section-avatar-size) * .5625);height:calc(var(--_pfx-form-section-avatar-size) * .5625);line-height:calc(var(--_pfx-form-section-avatar-size) * .5625)}.section-title-avatar-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.form-context-empty-state{display:grid;min-height:var(--pdx-form-context-empty-min-height, 0);place-items:center;padding:var(--pdx-form-context-empty-padding, 0)}.form-context-empty-state praxis-empty-state-card{display:block;width:min(100%,var(--pdx-form-context-empty-max-width, 32rem))}.prx-form-tabs{display:block;margin-bottom:16px;max-width:100%}.prx-form-tabs__tablist{display:flex;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%}.prx-form-tabs__tablist--scrollable{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:4px 2px}.prx-form-tabs__tablist--scrollable::-webkit-scrollbar{display:none}.prx-form-tabs__tab{display:inline-flex;align-items:center;gap:8px;min-width:0;padding:8px 14px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:color-mix(in srgb,var(--md-sys-color-surface, transparent) 40%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);font-family:inherit;font-size:.84rem;font-weight:500;cursor:pointer;white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none;transition:all .2s cubic-bezier(.2,0,0,1)}.prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:var(--md-sys-color-surface-container-high, rgba(0, 0, 0, .05));border-color:var(--md-sys-color-outline, rgba(0, 0, 0, .24));color:var(--md-sys-color-on-surface)}.prx-form-tabs__tab:focus-visible{outline:2px solid var(--md-sys-color-primary, #005ac1);outline-offset:2px}.prx-form-tabs__tab:disabled{cursor:not-allowed;opacity:.45}.prx-form-tabs__tab--active{background:var(--md-sys-color-primary-container, color-mix(in srgb, var(--md-sys-color-primary, #005ac1) 16%, var(--md-sys-color-surface-container-high, #2b2930)));color:var(--md-sys-color-on-primary-container, var(--md-sys-color-primary, #005ac1));border-color:transparent;font-weight:600;box-shadow:0 1px 3px #00000014}.prx-form-tabs__tab-icon{font-size:18px;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center}.prx-form-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;padding:1px 7px;font-size:.72rem;font-weight:600;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent)}.prx-form-tabs__tab-error-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;font-size:.7rem;font-weight:700;background:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-on-error, #ffffff);box-shadow:0 1px 2px #0003}.prx-form-tabs[data-appearance=underline]{border-bottom:1px solid var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tablist{gap:16px;padding-bottom:0}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab{border:none;border-radius:0;border-bottom:2px solid transparent;background:transparent;padding:8px 4px 10px;margin-bottom:-1px}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:transparent;border-bottom-color:var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab--active{background:transparent;box-shadow:none;border-bottom-color:var(--md-sys-color-primary, #005ac1);color:var(--md-sys-color-primary, #005ac1)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tablist{background:var(--md-sys-color-surface-container, rgba(0, 0, 0, .04));border-radius:12px;padding:4px;gap:4px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab{border:none;border-radius:8px;padding:6px 12px;background:transparent}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:color-mix(in srgb,currentColor 8%,transparent)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab--active{background:var(--md-sys-color-surface, var(--mat-sys-surface));color:var(--md-sys-color-primary, #005ac1);box-shadow:0 1px 3px #0000001f}.section-drop-wrapper[hidden]{display:none!important}\n"] }]
22169
+ ], template: "@if (isLoading) {\n <!-- Loading State -->\n <div class=\"form-loading\" role=\"status\" aria-live=\"polite\" aria-label=\"Carregando formul\u00E1rio\">\n <div class=\"form-loading-header\">\n <mat-progress-spinner diameter=\"32\" aria-label=\"Carregando formul\u00E1rio\"></mat-progress-spinner>\n <div class=\"form-loading-copy\">\n <p class=\"form-loading-title\">Carregando formul\u00E1rio...</p>\n <p class=\"form-loading-subtitle\">Preparando campos e op\u00E7\u00F5es do cadastro.</p>\n </div>\n </div>\n <div class=\"form-loading-skeleton\" aria-hidden=\"true\">\n <span class=\"form-loading-line form-loading-line-title\"></span>\n <span class=\"form-loading-line\"></span>\n <span class=\"form-loading-line form-loading-line-short\"></span>\n <span class=\"form-loading-field\"></span>\n <span class=\"form-loading-field form-loading-field-wide\"></span>\n </div>\n </div>\n} @else if (initializationStatus === 'error') {\n <!-- Error State -->\n <div class=\"form-error\">\n <mat-icon color=\"warn\" [praxisIcon]=\"'error'\"></mat-icon>\n <h3>{{ getErrorTitle() }}</h3>\n <p>{{ currentErrorMessage }}</p>\n @if (isRecoverable) {\n <button mat-stroked-button (click)=\"retryInitialization()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n Tentar Novamente\n </button>\n }\n <button mat-button (click)=\"showDetailedError()\" class=\"show-details\">\n Ver Detalhes T\u00E9cnicos\n </button>\n <!-- Permitir corre\u00E7\u00E3o do resourcePath diretamente do estado de erro -->\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\" class=\"connect-action\">\n <mat-icon [praxisIcon]=\"'bolt'\"></mat-icon>\n Conectar a recurso\n </button>\n </div>\n} @else if (initializationStatus === 'success') {\n <!-- Inline banner for schema change (only when customization is enabled) -->\n @if (shouldShowOutdatedInline()) {\n <div class=\"pfx-form-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"openConfigEditor()\">\n <mat-icon [praxisIcon]=\"'sync'\"></mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n </div>\n }\n\n <!-- Configuration Controls -->\n @if (shouldShowConfigControls && enableCustomization) {\n <div class=\"form-config-controls\">\n @if (showAiAssistant) {\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"dense\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('config-controls')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Abrir copiloto sem\u00E2ntico do formul\u00E1rio\">\n </button>\n }\n <button type=\"button\" praxisIconButton=\"settings\" size=\"dense\" (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [attr.aria-label]=\"configControlLabel\" [matTooltip]=\"configControlLabel\">\n </button>\n <button type=\"button\" praxisIconButton=\"link_off\" size=\"dense\" (click)=\"disconnect()\"\n [attr.aria-label]=\"disconnectControlLabel\" [matTooltip]=\"disconnectControlLabel\"\n [disabled]=\"isLoading\">\n </button>\n </div>\n }\n\n <!-- Form Content -->\n @if (!resourcePath && !hasExplicitSchemaUrl() && !hasRenderableConfig()) {\n <praxis-empty-state-card\n icon=\"link\"\n [title]=\"'Conecte o formul\u00E1rio \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para gerar automaticamente os campos do formul\u00E1rio.'\"\n [primaryAction]=\"enableCustomization ? { label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) } : undefined\"\n ></praxis-empty-state-card>\n }\n @if (shouldShowContextEmptyState()) {\n <div class=\"form-context-empty-state\" role=\"status\" aria-live=\"polite\">\n <praxis-empty-state-card\n [icon]=\"emptyState?.icon || 'touch_app'\"\n [title]=\"emptyState!.title\"\n [description]=\"emptyState?.description\"\n [tone]=\"emptyState?.tone || 'primary'\"\n [variant]=\"emptyState?.variant || 'transparent'\"\n [alignment]=\"emptyState?.alignment || 'center'\"\n [density]=\"emptyState?.density || 'compact'\"\n [iconContainer]=\"emptyState?.iconContainer || 'circle'\"\n [inline]=\"true\"\n />\n </div>\n } @else {\n <div #entityReadRegion class=\"entity-read-region\" tabindex=\"-1\" role=\"region\" [attr.aria-label]=\"entityReadText('region')\">\n <span class=\"cdk-visually-hidden\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">{{ entityReadStatusText() }}</span>\n @if (entityHydrationPending || entityReadFailed) {\n <div class=\"entity-read-feedback\" data-testid=\"form-entity-read-feedback\">\n @if (entityHydrationPending) {\n <mat-progress-spinner diameter=\"28\" mode=\"indeterminate\" aria-hidden=\"true\"></mat-progress-spinner>\n <p class=\"entity-read-loading-text\" aria-hidden=\"true\">{{ entityReadText('loading') }}</p>\n } @else {\n <mat-icon [praxisIcon]=\"'error_outline'\" aria-hidden=\"true\"></mat-icon>\n <p aria-hidden=\"true\">{{ entityReadText('error') }}</p>\n <button mat-stroked-button type=\"button\" (click)=\"retryEntityRead(entityReadRegion)\">{{ entityReadText('retry') }}</button>\n }\n </div>\n }\n <form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting || entityHydrationPending ? 'true' : null\"\n [style.opacity]=\"entityHydrationPending || entityReadFailed ? '0' : null\"\n [style.transition]=\"entityHydrationPending || entityReadFailed ? 'none' : null\"\n [attr.inert]=\"entityHydrationPending || entityReadFailed ? '' : null\"\n [attr.aria-hidden]=\"entityHydrationPending || entityReadFailed ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\"\n [class.praxis-dynamic-form--presentation]=\"effectivePresentation\"\n [class.readonly-mode]=\"effectiveReadonly\"\n [attr.data-presentation-preset]=\"effectivePresentation ? effectivePresentationPreset : null\"\n [class.praxis-dynamic-form--corporate-dossier]=\"isCorporateDossierPreset()\"\n [class.praxis-dynamic-form--editorial-card]=\"isEditorialCardPreset()\"\n [class.praxis-dynamic-form--compact-presentation]=\"isCompactPresentationPreset()\"\n [class.editorial-visual-context]=\"hasEditorialVisualContext()\"\n [class.pfx-mounting]=\"isMounting\" [formGroup]=\"form\"\n [ngClass]=\"{\n 'pres-compact': presentationVars.compact,\n 'pres-label-left': presentationVars.labelPosition === 'left',\n 'pres-label-above': presentationVars.labelPosition === 'above'\n }\" [style.--pfx-pres-label-align]=\"presentationVars.labelAlign\"\n [style.--pfx-pres-label-size]=\"presentationVars.labelSize\"\n [style.--pfx-pres-label-width]=\"presentationVars.labelWidth\"\n [style.--pfx-pres-row-gap]=\"presentationVars.density === 'compact' ? '6px' : (presentationVars.density === 'cozy' ? '8px' : '10px')\"\n [style.--pfx-pres-row-padding]=\"presentationVars.density === 'compact' ? '2px 0' : (presentationVars.density === 'cozy' ? '6px 0' : '8px 0')\"\n [style.--pfx-pres-value-align]=\"presentationVars.valueAlign\"\n [style.--pfx-pres-value-size]=\"presentationVars.valueSize\"\n [style.--pdx-form-mount-duration]=\"getMountDurationVar()\"\n [style.--pdx-form-mount-offset]=\"getMountOffsetVar()\"\n [style.--pdx-form-mount-stagger]=\"getMountStaggerVar()\"\n class=\"praxis-dynamic-form\">\n @if (enableCustomization && selectedElement) {\n <praxis-canvas-toolbar (editMetadata)=\"openSelectedElementEditor()\" (selectPath)=\"onSelectPath($event)\"\n (moveUp)=\"onToolbarMove('up')\" (moveDown)=\"onToolbarMove('down')\" (toggleReadonly)=\"onToolbarToggleReadonly()\"\n (toggleRequired)=\"onToolbarToggleRequired()\" (toggleHidden)=\"onToolbarToggleHidden()\"\n (toggleDisabled)=\"onToolbarToggleDisabled()\" (requestClose)=\"onToolbarRequestClose()\"\n [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n }\n\n @if (formBlocksBefore?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n <!-- Tab Layout Navigation Bar -->\n @if (effectiveLayoutMode === 'tabs' && effectiveTabs.length > 1) {\n <nav class=\"prx-form-tabs\" [attr.data-appearance]=\"effectiveTabsAppearance\" role=\"tablist\" aria-label=\"Navega\u00E7\u00E3o em abas do formul\u00E1rio\">\n <div class=\"prx-form-tabs__tablist prx-form-tabs__tablist--scrollable\">\n @for (tab of effectiveTabs; track tab.id) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"prx-form-tabs__tab\"\n [class.prx-form-tabs__tab--active]=\"activeTabId === tab.id\"\n [attr.aria-selected]=\"activeTabId === tab.id\"\n [attr.aria-controls]=\"getTabAriaControls(tab)\"\n [attr.id]=\"'tab-' + tab.id\"\n [disabled]=\"tab.disabled\"\n [matTooltip]=\"tab.tooltip || null\"\n [matTooltipDisabled]=\"!tab.tooltip\"\n (click)=\"selectTab(tab.id)\"\n >\n @if (tab.icon) {\n <mat-icon class=\"prx-form-tabs__tab-icon\" [praxisIcon]=\"tab.icon\" aria-hidden=\"true\"></mat-icon>\n }\n <span class=\"prx-form-tabs__tab-label\">{{ tab.label }}</span>\n @if (tab.badge != null) {\n <span class=\"prx-form-tabs__tab-badge\">{{ tab.badge }}</span>\n }\n @if (getTabErrorCount(tab) > 0) {\n <span class=\"prx-form-tabs__tab-error-badge\" [attr.aria-label]=\"getTabErrorCount(tab) + ' erros na aba'\">\n {{ getTabErrorCount(tab) }}\n </span>\n }\n </button>\n }\n </div>\n </nav>\n }\n\n @for (section of (config.sections || []); track (section.id ?? $index); let sectionIndex = $index) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\" [hidden]=\"!isSectionInActiveTab(section)\"\n [attr.role]=\"effectiveLayoutMode === 'tabs' ? 'tabpanel' : null\"\n [attr.id]=\"effectiveLayoutMode === 'tabs' ? ('section-tabpanel-' + section.id) : null\"\n [attr.aria-labelledby]=\"effectiveLayoutMode === 'tabs' ? ('tab-' + (getTabIdForSection(section) || section.id)) : null\">\n @if (isSectionVisible(section)) {\n <div #sectionEl class=\"form-section canvas-element\" data-canvas-type=\"section\" [attr.data-section-id]=\"section.id\"\n [attr.data-section-index]=\"sectionIndex\" (mouseenter)=\"onElementMouseEnter($event, 'section', section, sectionEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'section', section, sectionEl)\"\n [class.selected]=\"selectedElement?.domElement === sectionEl\"\n [class.hovered]=\"hoveredElement?.domElement === sectionEl && selectedElement?.domElement !== sectionEl\"\n [attr.data-section-appearance]=\"getSectionAppearance(section) || null\"\n [attr.data-section-divider]=\"isSectionDividerEnabled(section) ? 'true' : null\"\n [attr.data-presentation-preset]=\"effectivePresentation ? getSectionPresentationPreset(section) : null\"\n [class.form-section--corporate-dossier]=\"isSectionCorporateDossier(section)\"\n [class.form-section--editorial-card]=\"isSectionEditorialCard(section)\"\n [class.form-section--compact-presentation]=\"isSectionCompactPresentation(section)\"\n [style.marginBottom.px]=\"!isLastVisibleSection(section) ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n @if (!shouldHideSectionHeader(section)) {\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n [class.title-only]=\"isSectionHeaderTitleOnly(section)\"\n >\n <div class=\"section-heading-text\" [matTooltip]=\"getSectionHeaderTooltip(section) || null\"\n [matTooltipDisabled]=\"!getSectionHeaderTooltip(section)\">\n @if (getSectionStepLabel(section)) {\n <div class=\"section-step-label\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionStepLabel(section) }}\n </div>\n }\n @if (getSectionTitle(section)) {\n <h3 class=\"section-title\" [class.title-large]=\"getSectionTitleStyle(section) === 'titleLarge'\"\n [class.title-medium]=\"getSectionTitleStyle(section) === 'titleMedium'\"\n [class.title-small]=\"getSectionTitleStyle(section) === 'titleSmall'\"\n [class.headline-small]=\"getSectionTitleStyle(section) === 'headlineSmall'\"\n [style.marginBottom.px]=\"getEffectiveSectionTitleGapBottom(section)\" [style.color]=\"getSectionTitleColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [attr.id]=\"sectionPanelId(section, sectionIndex) + '-title'\">\n @let sectionHeaderVisual = getSectionHeaderVisual(section);\n @let sectionHeaderAvatarSize = getSectionHeaderAvatarSize(section);\n @if (sectionHeaderVisual.kind === 'icon') {\n <mat-icon class=\"section-title-icon\" aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.kind === 'image') {\n <img class=\"section-title-avatar section-title-avatar-image\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\"\n [src]=\"sectionHeaderVisual.src\" [alt]=\"sectionHeaderVisual.alt\" />\n }\n @if (sectionHeaderVisual.kind === 'initials') {\n <span class=\"section-title-avatar section-title-avatar-text\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n {{ sectionHeaderVisual.text }}\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n @if (sectionHeaderVisual.kind === 'placeholder') {\n <span class=\"section-title-avatar section-title-avatar-placeholder\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n @if (sectionHeaderVisual.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.text) {\n <span>{{ sectionHeaderVisual.text }}</span>\n }\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n {{ getSectionTitle(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" praxisIconButton=\"edit\" size=\"dense\" (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\n </button>\n }\n </h3>\n }\n @if (getSectionDescription(section)) {\n <p class=\"section-description\" [class.body-large]=\"getSectionDescriptionStyle(section) === 'bodyLarge'\"\n [class.body-medium]=\"getSectionDescriptionStyle(section) === 'bodyMedium'\"\n [class.body-small]=\"getSectionDescriptionStyle(section) === 'bodySmall'\"\n [style.marginBottom.px]=\"getSectionDescriptionGapBottom(section) ?? 8\" [style.color]=\"getSectionDescriptionColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionDescription(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" praxisIconButton=\"edit\" size=\"dense\"\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\n </button>\n }\n </p>\n }\n </div>\n @if (getSectionHeaderActions(section).length) {\n <div class=\"section-heading-actions\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n @for (action of getSectionHeaderActions(section); track action.id) {\n <button\n type=\"button\"\n class=\"section-heading-action-btn\"\n [praxisIconButton]=\"action.icon\"\n size=\"compact\"\n [busy]=\"action.loading\"\n [disabled]=\"isSectionHeaderActionDisabled(action)\"\n [matTooltip]=\"getSectionHeaderActionTooltip(action)\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-busy]=\"action.loading ? 'true' : null\"\n [ngClass]=\"getSectionHeaderActionNgClass(action)\"\n [ngStyle]=\"getSectionHeaderActionStyles(action)\"\n (click)=\"onSectionHeaderActionClick(section, action, $event)\"\n >\n @if (action.loading) {\n <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" [praxisIconButton]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\" size=\"compact\"\n (click)=\"toggleSectionCollapse($event, section)\" [attr.aria-expanded]=\"!isSectionCollapsed(section)\"\n [attr.aria-controls]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-label]=\"isSectionCollapsed(section) ? 'Expandir se\u00E7\u00E3o' : 'Recolher se\u00E7\u00E3o'\">\n </button>\n }\n </div>\n }\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.role]=\"getSectionTitle(section) ? 'region' : null\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @for (row of section.rows; track (row.id ?? $index); let rowIndex = $index) {\n @if (isRowVisible(row)) {\n <div class=\"row-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n <div #rowEl class=\"form-row grid-12 canvas-element\" data-canvas-type=\"row\" [attr.data-row-index]=\"rowIndex\"\n [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\" [style.--pfx-grid-gap.px]=\"getRowGap(row)\"\n [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [style.--pfx-mount-index]=\"rowIndex\"\n [style.marginBottom.px]=\"rowIndex < section.rows.length - 1 ? (getRowRowGap(row) ?? null) : null\"\n [ngClass]=\"getRowClasses(row)\" [ngStyle]=\"getRowStyles(row)\"\n (mouseenter)=\"onElementMouseEnter($event, 'row', row, rowEl)\" (mouseleave)=\"onElementMouseLeave($event)\"\n (click)=\"onElementClick($event, 'row', row, rowEl)\" [class.selected]=\"selectedElement?.domElement === rowEl\"\n [class.hovered]=\"hoveredElement?.domElement === rowEl && selectedElement?.domElement !== rowEl\">\n @for (column of row.columns; track (column.id ?? $index); let colIndex = $index) {\n @if (isColumnVisible(column)) {\n <div class=\"column-drop-wrapper\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\">\n <div #colEl class=\"form-column canvas-element\" [ngClass]=\"getColumnClasses(column, row)\"\n [style.padding.px]=\"getColumnPadding(column)\" [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [ngStyle]=\"getColumnStyles(column)\" [attr.data-testid]=\"column.testId || null\"\n [attr.data-row-gap]=\"getRowRowGap(row)\" data-canvas-type=\"column\" [attr.data-column-index]=\"colIndex\"\n [attr.data-row-index]=\"rowIndex\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\"\n [attr.data-column-id]=\"column.id\" (mouseenter)=\"onElementMouseEnter($event, 'column', column, colEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'column', column, colEl)\"\n [class.selected]=\"selectedElement?.domElement === colEl\"\n [class.hovered]=\"hoveredElement?.domElement === colEl && selectedElement?.domElement !== colEl\">\n @for (renderItem of getColumnRenderItems(column); track renderItem.id) {\n @if (renderItem.kind === 'fields') {\n <ng-container dynamicFieldLoader [fields]=\"getRenderableFieldsForLoader(renderItem.fields)\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"effectiveReadonly\"\n [disabledMode]=\"effectiveDisabledMode\"\n [presentationMode]=\"presentationForLoader\" [visible]=\"visibleGlobal === null ? null : visibleGlobal\"\n [canvasMode]=\"enableCustomization\" (canvasMouseEnter)=\"onFieldMouseEnter($event)\"\n (canvasMouseLeave)=\"onFieldMouseLeave($event)\" (canvasClick)=\"onFieldClick($event)\"\n (canvasFocus)=\"onFieldFocus($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [ngClass]=\"renderItem.className || null\"\n [ngStyle]=\"renderItem.style || null\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n }\n }\n </div>\n </div>\n } }\n </div>\n </div>\n }\n }\n } @else {\n <div class=\"section-collapsed-placeholder\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'unfold_more'\"></mat-icon>\n <span>{{ getSectionCollapsedSummary(section) }}</span>\n </div>\n }\n @if (isLastVisibleSection(section) && beforeActionsPlacement === 'insideLastSection' && formBlocksBeforeActions?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && isLastVisibleSection(section) && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"effectiveActions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n </div>\n <!-- Overlay de bloqueio durante submiss\u00E3o -->\n @if (submitting) {\n <div class=\"form-blocking-overlay\" aria-live=\"polite\">\n <mat-progress-spinner\n diameter=\"40\"\n color=\"primary\"\n [attr.aria-label]=\"config.messages?.loading?.submit || 'Salvando formul\u00E1rio'\"\n ></mat-progress-spinner>\n <p>{{ config.messages?.loading?.submit || 'Salvando...' }}</p>\n </div>\n }\n </div>\n\n @if (enableCustomization && selectedElement?.domElement === sectionEl) {\n <div class=\"add-section-container\">\n <div class=\"add-section-line\"></div>\n <button mat-fab color=\"primary\" aria-label=\"Adicionar nova se\u00E7\u00E3o\" (click)=\"addNewSectionAfter(sectionIndex)\"\n matTooltip=\"Adicionar nova se\u00E7\u00E3o aqui\">\n <mat-icon [praxisIcon]=\"'add'\"></mat-icon>\n </button>\n <div class=\"add-section-line\"></div>\n </div>\n }\n }\n </div>\n }\n\n @if (beforeActionsPlacement !== 'insideLastSection' && formBlocksBeforeActions?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [suppressInvalidSubmitHint]=\"entityHydrationPending\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n <praxis-rich-content\n [document]=\"formBlocksAfterDocument\"\n [context]=\"getEditorialRichContentContext()\"\n [hostCapabilities]=\"richContentHostCapabilities\"\n ></praxis-rich-content>\n </section>\n }\n </form>\n </div>\n }\n @if (showAiAssistant && !enableCustomization && (mode === 'view' || mode === 'presentation' || mode === 'dossier') && !shouldShowContextEmptyState()) {\n <div class=\"ai-floating-assistant\">\n <button type=\"button\" praxisIconButton=\"auto_awesome\" size=\"compact\" (click)=\"openAiAssistant()\" [disabled]=\"isLoading || entityHydrationPending || entityReadFailed\"\n [attr.data-testid]=\"aiAssistantTriggerTestId('view-floating')\"\n aria-label=\"Abrir copiloto semantico Praxis do formulario\"\n matTooltip=\"Pedir ajuda sobre este formul\u00E1rio\">\n </button>\n </div>\n }\n @if (showAiAssistant && aiAssistantOpen && aiAssistantViewState) {\n <praxis-ai-assistant-shell\n [labels]=\"aiAssistantLabels\"\n [mode]=\"aiAssistantViewState.mode\"\n [state]=\"aiAssistantViewState.state\"\n [contextItems]=\"aiAssistantViewState.contextItems\"\n [attachments]=\"aiAssistantViewState.attachments\"\n [messages]=\"aiAssistantViewState.messages\"\n [quickReplies]=\"aiAssistantViewState.quickReplies\"\n [prompt]=\"aiAssistantPrompt\"\n [statusText]=\"aiAssistantViewState.statusText\"\n [errorText]=\"aiAssistantViewState.errorText\"\n [busy]=\"aiAssistantViewState.state === 'processing' || aiAssistantViewState.state === 'applying'\"\n [canApply]=\"aiAssistantViewState.canApply\"\n [layout]=\"aiAssistantLayout\"\n testIdPrefix=\"dynamic-form-ai-assistant\"\n panelTestId=\"dynamic-form-ai-assistant-panel\"\n submitTestId=\"dynamic-form-ai-assistant-submit\"\n applyTestId=\"dynamic-form-ai-assistant-apply\"\n (promptChange)=\"onAiAssistantPromptChange($event)\"\n (submitPrompt)=\"onAiAssistantSubmit($event)\"\n (apply)=\"onAiAssistantApply()\"\n (retryTurn)=\"onAiAssistantRetry()\"\n (cancelTurn)=\"onAiAssistantCancel()\"\n (quickReply)=\"onAiAssistantQuickReply($event)\"\n (editMessage)=\"onAiAssistantEditMessage($event)\"\n (resendMessage)=\"onAiAssistantResendMessage($event)\"\n (layoutChange)=\"onAiAssistantLayoutChange($event)\"\n (close)=\"closeAiAssistant()\"\n ></praxis-ai-assistant-shell>\n }\n }\n", styles: ["@charset \"UTF-8\";.span-xs-1{grid-column:span 1}.span-xs-2{grid-column:span 2}.span-xs-3{grid-column:span 3}.span-xs-4{grid-column:span 4}.span-xs-5{grid-column:span 5}.span-xs-6{grid-column:span 6}.span-xs-7{grid-column:span 7}.span-xs-8{grid-column:span 8}.span-xs-9{grid-column:span 9}.span-xs-10{grid-column:span 10}.span-xs-11{grid-column:span 11}.span-xs-12{grid-column:span 12}.offset-xs-0{margin-left:0%}.offset-xs-1{margin-left:calc(1 / 12 * 100%)}.offset-xs-2{margin-left:calc(2 / 12 * 100%)}.offset-xs-3{margin-left:25%}.offset-xs-4{margin-left:calc(4 / 12 * 100%)}.offset-xs-5{margin-left:calc(5 / 12 * 100%)}.offset-xs-6{margin-left:50%}.offset-xs-7{margin-left:calc(7 / 12 * 100%)}.offset-xs-8{margin-left:calc(8 / 12 * 100%)}.offset-xs-9{margin-left:75%}.offset-xs-10{margin-left:calc(10 / 12 * 100%)}.offset-xs-11{margin-left:calc(11 / 12 * 100%)}.order-xs--12{order:-12}.order-xs--11{order:-11}.order-xs--10{order:-10}.order-xs--9{order:-9}.order-xs--8{order:-8}.order-xs--7{order:-7}.order-xs--6{order:-6}.order-xs--5{order:-5}.order-xs--4{order:-4}.order-xs--3{order:-3}.order-xs--2{order:-2}.order-xs--1{order:-1}.order-xs-0{order:0}.order-xs-1{order:1}.order-xs-2{order:2}.order-xs-3{order:3}.order-xs-4{order:4}.order-xs-5{order:5}.order-xs-6{order:6}.order-xs-7{order:7}.order-xs-8{order:8}.order-xs-9{order:9}.order-xs-10{order:10}.order-xs-11{order:11}.order-xs-12{order:12}.hidden-xs{display:none}@container praxis-form-row (min-width: 600px){.span-sm-1{grid-column:span 1}.span-sm-2{grid-column:span 2}.span-sm-3{grid-column:span 3}.span-sm-4{grid-column:span 4}.span-sm-5{grid-column:span 5}.span-sm-6{grid-column:span 6}.span-sm-7{grid-column:span 7}.span-sm-8{grid-column:span 8}.span-sm-9{grid-column:span 9}.span-sm-10{grid-column:span 10}.span-sm-11{grid-column:span 11}.span-sm-12{grid-column:span 12}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:calc(1 / 12 * 100%)}.offset-sm-2{margin-left:calc(2 / 12 * 100%)}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:calc(4 / 12 * 100%)}.offset-sm-5{margin-left:calc(5 / 12 * 100%)}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:calc(7 / 12 * 100%)}.offset-sm-8{margin-left:calc(8 / 12 * 100%)}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:calc(10 / 12 * 100%)}.offset-sm-11{margin-left:calc(11 / 12 * 100%)}.order-sm--12{order:-12}.order-sm--11{order:-11}.order-sm--10{order:-10}.order-sm--9{order:-9}.order-sm--8{order:-8}.order-sm--7{order:-7}.order-sm--6{order:-6}.order-sm--5{order:-5}.order-sm--4{order:-4}.order-sm--3{order:-3}.order-sm--2{order:-2}.order-sm--1{order:-1}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.hidden-sm{display:none}}@container praxis-form-row (min-width: 900px){.span-md-1{grid-column:span 1}.span-md-2{grid-column:span 2}.span-md-3{grid-column:span 3}.span-md-4{grid-column:span 4}.span-md-5{grid-column:span 5}.span-md-6{grid-column:span 6}.span-md-7{grid-column:span 7}.span-md-8{grid-column:span 8}.span-md-9{grid-column:span 9}.span-md-10{grid-column:span 10}.span-md-11{grid-column:span 11}.span-md-12{grid-column:span 12}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:calc(1 / 12 * 100%)}.offset-md-2{margin-left:calc(2 / 12 * 100%)}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:calc(4 / 12 * 100%)}.offset-md-5{margin-left:calc(5 / 12 * 100%)}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:calc(7 / 12 * 100%)}.offset-md-8{margin-left:calc(8 / 12 * 100%)}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:calc(10 / 12 * 100%)}.offset-md-11{margin-left:calc(11 / 12 * 100%)}.order-md--12{order:-12}.order-md--11{order:-11}.order-md--10{order:-10}.order-md--9{order:-9}.order-md--8{order:-8}.order-md--7{order:-7}.order-md--6{order:-6}.order-md--5{order:-5}.order-md--4{order:-4}.order-md--3{order:-3}.order-md--2{order:-2}.order-md--1{order:-1}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.hidden-md{display:none}}@container praxis-form-row (min-width: 1200px){.span-lg-1{grid-column:span 1}.span-lg-2{grid-column:span 2}.span-lg-3{grid-column:span 3}.span-lg-4{grid-column:span 4}.span-lg-5{grid-column:span 5}.span-lg-6{grid-column:span 6}.span-lg-7{grid-column:span 7}.span-lg-8{grid-column:span 8}.span-lg-9{grid-column:span 9}.span-lg-10{grid-column:span 10}.span-lg-11{grid-column:span 11}.span-lg-12{grid-column:span 12}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:calc(1 / 12 * 100%)}.offset-lg-2{margin-left:calc(2 / 12 * 100%)}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:calc(4 / 12 * 100%)}.offset-lg-5{margin-left:calc(5 / 12 * 100%)}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:calc(7 / 12 * 100%)}.offset-lg-8{margin-left:calc(8 / 12 * 100%)}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:calc(10 / 12 * 100%)}.offset-lg-11{margin-left:calc(11 / 12 * 100%)}.order-lg--12{order:-12}.order-lg--11{order:-11}.order-lg--10{order:-10}.order-lg--9{order:-9}.order-lg--8{order:-8}.order-lg--7{order:-7}.order-lg--6{order:-6}.order-lg--5{order:-5}.order-lg--4{order:-4}.order-lg--3{order:-3}.order-lg--2{order:-2}.order-lg--1{order:-1}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.hidden-lg{display:none}}@container praxis-form-row (min-width: 1536px){.span-xl-1{grid-column:span 1}.span-xl-2{grid-column:span 2}.span-xl-3{grid-column:span 3}.span-xl-4{grid-column:span 4}.span-xl-5{grid-column:span 5}.span-xl-6{grid-column:span 6}.span-xl-7{grid-column:span 7}.span-xl-8{grid-column:span 8}.span-xl-9{grid-column:span 9}.span-xl-10{grid-column:span 10}.span-xl-11{grid-column:span 11}.span-xl-12{grid-column:span 12}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:calc(1 / 12 * 100%)}.offset-xl-2{margin-left:calc(2 / 12 * 100%)}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:calc(4 / 12 * 100%)}.offset-xl-5{margin-left:calc(5 / 12 * 100%)}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:calc(7 / 12 * 100%)}.offset-xl-8{margin-left:calc(8 / 12 * 100%)}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:calc(10 / 12 * 100%)}.offset-xl-11{margin-left:calc(11 / 12 * 100%)}.order-xl--12{order:-12}.order-xl--11{order:-11}.order-xl--10{order:-10}.order-xl--9{order:-9}.order-xl--8{order:-8}.order-xl--7{order:-7}.order-xl--6{order:-6}.order-xl--5{order:-5}.order-xl--4{order:-4}.order-xl--3{order:-3}.order-xl--2{order:-2}.order-xl--1{order:-1}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.hidden-xl{display:none}}.canvas-mode-enabled{--canvas-hit: 14px}.canvas-mode-enabled .canvas-element{position:relative;z-index:0;border-radius:8px;outline:2px solid transparent;outline-offset:2px;transition:outline-color .2s ease,outline-style .2s ease}.canvas-mode-enabled .canvas-element:before{content:\"\";position:absolute;inset:calc(-1 * var(--canvas-hit));pointer-events:none;border-radius:inherit;background:transparent}.canvas-mode-enabled .canvas-element[data-canvas-type=section]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element[data-canvas-type=row]{--outline-color: var(--md-sys-color-secondary)}.canvas-mode-enabled .canvas-element[data-canvas-type=column],.canvas-mode-enabled .canvas-element[data-canvas-type=field]{--outline-color: var(--md-sys-color-tertiary)}.canvas-mode-enabled .canvas-element[data-canvas-type=actions]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element.hovered:not(.selected){outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:dashed}.canvas-mode-enabled .canvas-element.selected{outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:solid;box-shadow:0 0 0 2px var(--outline-color, var(--md-sys-color-primary))}.canvas-mode-enabled .canvas-element.hovered{z-index:var(--praxis-layer-authoring-hover, 300)}.canvas-mode-enabled .canvas-element.selected{z-index:var(--praxis-layer-authoring-selected, 320)}.section-drop-wrapper,.row-drop-wrapper,.column-drop-wrapper{display:contents}.add-section-container{display:flex;align-items:center;justify-content:center;padding:.5rem 0;margin:-.5rem 0;position:relative;z-index:var(--praxis-layer-authoring-insert, 280)}.add-section-container .add-section-line{flex-grow:1;height:1px;background:repeating-linear-gradient(90deg,var(--md-sys-color-outline-variant),var(--md-sys-color-outline-variant) 4px,transparent 4px,transparent 8px)}.add-section-container button{margin:0 1rem;transform:scale(.85)}:host{display:block;position:relative;--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--pdx-color-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent );--pfx-form-shell-padding: clamp(.9rem, 1.4vw, 1.2rem)}.form-config-controls{position:relative;top:auto;margin:0;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--pfx-form-shell-surface) 88%,var(--md-sys-color-surface) 12%);padding:8px var(--pfx-form-shell-padding);border:1px solid var(--pfx-form-footer-border);border-bottom-color:color-mix(in srgb,var(--pfx-form-footer-border) 72%,transparent);border-radius:var(--pfx-editorial-form-radius) var(--pfx-editorial-form-radius) 0 0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:none;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.96;transition:opacity .16s ease,border-color .16s ease}.form-config-controls>*{pointer-events:auto}.form-config-controls:hover,.form-config-controls:focus-within{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%)}.form-config-controls .praxis-icon-button{color:var(--md-sys-color-on-surface-variant)}.form-config-controls .praxis-icon-button:hover{color:var(--md-sys-color-primary)}.ai-floating-assistant{position:sticky;right:0;bottom:12px;margin-top:14px;margin-left:auto;width:fit-content;z-index:70;pointer-events:none}.ai-floating-assistant button{pointer-events:auto;display:inline-flex}.ai-floating-assistant .ai-trigger-btn{box-shadow:0 12px 28px #0f172a24}.config-button{color:var(--md-sys-color-primary)}.form-loading{display:flex;flex-direction:column;align-items:stretch;justify-content:center;padding:1.25rem;text-align:left;color:var(--md-sys-color-on-surface);gap:1rem;min-height:220px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,var(--md-sys-color-outline-variant) 86%);border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent 42%),color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,var(--md-sys-color-surface) 22%);box-shadow:0 12px 28px #0f172a14}.entity-read-region{position:relative;min-width:0}.entity-read-feedback{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:1rem;padding:2rem 1rem;box-sizing:border-box;text-align:center;color:var(--md-sys-color-on-surface)}.entity-read-feedback p{margin:0;max-width:40ch}.form-loading-header{display:flex;align-items:center;gap:.85rem}.form-loading-copy{min-width:0}.form-loading p{margin:0}.form-loading-title{font-weight:700;color:var(--md-sys-color-on-surface)}.form-loading-subtitle{margin-top:.2rem;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.form-loading-skeleton{display:grid;gap:.7rem}.form-loading-line,.form-loading-field{display:block;overflow:hidden;position:relative;border-radius:6px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,var(--md-sys-color-primary) 6%)}.form-loading-line:after,.form-loading-field:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 16%,var(--md-sys-color-on-surface) 18%),transparent);animation:form-loading-shimmer 1.4s ease-in-out infinite}.form-loading-line{height:12px}.form-loading-line-title{width:min(42%,240px)}.form-loading-line-short{width:min(64%,360px)}.form-loading-field{height:44px}.form-loading-field-wide{height:72px}@keyframes form-loading-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.form-loading-line:after,.form-loading-field:after{animation:none;transform:none;opacity:.28}}.form-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-error);gap:1rem;border:1px solid var(--md-sys-color-error);border-radius:8px;background-color:var(--md-sys-color-error-container);margin:1rem;box-shadow:0 12px 30px #7f1d1d1f}.form-error h3{margin:0;color:var(--md-sys-color-on-error-container)}.form-error p{margin:0;color:var(--md-sys-color-on-error-container);opacity:.8}.form-error button{margin-top:.5rem}.pfx-form-info-banner{margin-bottom:14px;padding:12px 14px;border-radius:16px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant) 82%);background:color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface) 76%);color:var(--md-sys-color-on-surface);display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.pfx-form-info-banner .text{font-size:.92rem;line-height:1.5;font-weight:600}.pfx-form-info-banner .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.praxis-dynamic-form{display:flex;flex-direction:column;max-width:100%;min-width:0;transition:all .3s ease;position:relative;font-family:inherit;font-size:inherit;color:inherit;--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--md-sys-color-surface-container) );--pfx-editorial-form-surface-muted: var( --pdx-color-surface-muted, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --pfx-form-stroke, var(--pdx-color-border-subtle, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --pdx-color-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --pdx-color-text-secondary, var(--md-sys-color-on-surface-variant) );--pfx-editorial-form-field-surface: color-mix( in srgb, var(--pfx-editorial-form-surface-muted) 76%, var(--pfx-editorial-form-surface) 24% );--pfx-editorial-form-field-outline: color-mix( in srgb, var(--pfx-editorial-form-border) 88%, transparent );--pfx-editorial-form-accent: var( --pdx-color-primary, var(--md-sys-color-primary) );--pfx-editorial-form-accent-text: var(--md-sys-color-on-primary);--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-field-radius: var(--pfx-form-field-radius, 4px);--pfx-editorial-form-border-width: 1px;--pfx-editorial-form-field-border-width: 1px;--pfx-editorial-form-shadow: none;--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-surface-flat: color-mix( in srgb, var(--pfx-editorial-form-surface) 78%, var(--pfx-editorial-form-surface-muted) 22% );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-label-strong: color-mix( in srgb, var(--pfx-editorial-form-text) 96%, white 4% );--pfx-form-label-muted: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 92%, var(--pfx-editorial-form-text) 8% );--pfx-form-field-surface-rest: color-mix( in srgb, var(--pfx-editorial-form-field-surface) 82%, var(--pfx-editorial-form-surface) 18% );--pfx-form-field-surface-focus: color-mix( in srgb, var(--pfx-editorial-form-accent) 4%, var(--pfx-form-field-surface-rest) 96% );--pfx-form-field-min-height: 48px;--pfx-form-section-padding: clamp(1.1rem, 1.8vw, 1.5rem);--pfx-form-section-gap: 22px;--pdx-presentation-label-size: var(--pfx-pres-compact-label-size, .78rem);--pdx-presentation-value-size: var(--pfx-pres-compact-value-size, 1rem);--pdx-presentation-icon-size: var(--pfx-pres-icon-size, 18px);--pdx-presentation-row-gap: var(--pfx-pres-row-gap, .5rem);--pdx-presentation-column-gap: var(--pfx-pres-column-gap, .5rem);--pdx-presentation-section-gap: var(--pfx-pres-section-gap, .75rem);--pdx-presentation-label-width: var(--pfx-pres-label-width, 220px);--pdx-presentation-flag-height: var(--pfx-pres-boolean-min-height, 22px);--pdx-presentation-flag-radius: var(--pfx-pres-boolean-radius, 999px);--pdx-presentation-flag-padding: var(--pfx-pres-boolean-padding, 0 8px);--pdx-presentation-flag-active-color: var( --pfx-pres-boolean-active-color, var(--md-sys-color-primary) );--pdx-presentation-flag-active-bg: var( --pfx-pres-boolean-active-bg, color-mix(in srgb, var(--md-sys-color-primary) 14%, transparent) );--pdx-presentation-flag-inactive-color: var( --pfx-pres-boolean-inactive-color, var(--md-sys-color-on-surface-variant) );--pdx-presentation-flag-inactive-bg: var( --pfx-pres-boolean-inactive-bg, color-mix(in srgb, var(--md-sys-color-outline-variant) 34%, transparent) );--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent )}.praxis-dynamic-form.canvas-mode-enabled{border:1px solid var(--pfx-form-footer-border);border-radius:var(--pfx-editorial-form-radius);background:linear-gradient(180deg,color-mix(in srgb,var(--pfx-form-shell-surface) 86%,transparent),color-mix(in srgb,var(--pfx-editorial-form-surface-muted) 42%,transparent));overflow:visible}.form-config-controls+.praxis-dynamic-form.canvas-mode-enabled{border-top:0;border-top-left-radius:0;border-top-right-radius:0}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks{margin-inline:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>.section-drop-wrapper:first-of-type,.praxis-dynamic-form.canvas-mode-enabled>.form-editorial-blocks:first-child{margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.canvas-mode-enabled>praxis-form-actions[data-actions-placement=afterSections]{display:block;margin-top:var(--pfx-form-shell-padding)}.praxis-dynamic-form.editorial-visual-context{--_pfx-editorial-host-text: var( --editorial-text-primary, var(--foreground, var(--mat-sys-on-surface, #1d1b20)) );--_pfx-editorial-host-text-muted: var( --editorial-text-secondary, var( --muted-foreground, color-mix(in srgb, var(--_pfx-editorial-host-text) 64%, transparent) ) );--_pfx-editorial-host-surface: var( --editorial-surface-primary, var(--card, var(--mat-sys-surface-container, #ffffff)) );--_pfx-editorial-host-surface-muted: var( --editorial-surface-secondary, var(--surface-dim, var(--muted, var(--mat-sys-surface-container-low, #f7f2fa))) );--_pfx-editorial-host-border: var( --editorial-border-color, var(--border, var(--mat-sys-outline-variant, #cac4d0)) );--_pfx-editorial-host-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--primary, var(--mat-sys-primary, #6750a4))) );--_pfx-editorial-host-accent-text: var( --editorial-cta-primary-text, var( --editorial-accent-contrast, var(--primary-foreground, var(--mat-sys-on-primary, #ffffff)) ) );--_pfx-editorial-host-accent-container: var( --primary-container, color-mix(in srgb, var(--_pfx-editorial-host-accent) 16%, var(--_pfx-editorial-host-surface) 84%) );--_pfx-editorial-host-accent-container-text: var( --primary-container-fg, var(--_pfx-editorial-host-accent) );font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--_pfx-editorial-host-text);--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--_pfx-editorial-host-surface)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--_pfx-editorial-host-surface-muted) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--_pfx-editorial-host-border)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--_pfx-editorial-host-text) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, color-mix( in srgb, var(--_pfx-editorial-host-text-muted) 86%, var(--_pfx-editorial-host-text) 14% ) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--_pfx-editorial-host-accent)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--_pfx-editorial-host-accent-text)) );--pfx-editorial-form-accent-container: var(--_pfx-editorial-host-accent-container);--pfx-editorial-form-accent-container-text: var(--_pfx-editorial-host-accent-container-text);--pfx-editorial-form-radius: var(--editorial-card-radius, 18px);--pfx-editorial-form-field-radius: var( --editorial-field-radius, var(--editorial-card-radius, 14px) );--pfx-editorial-form-border-width: var(--editorial-card-border-width, 1px);--pfx-editorial-form-field-border-width: var(--editorial-field-border-width, 1px);--pfx-editorial-form-shadow: var(--editorial-card-shadow, none);--md-sys-color-surface: var( --pfx-editorial-form-surface, var(--md-sys-color-surface) );--md-sys-color-surface-container: var( --pfx-editorial-form-surface, var(--md-sys-color-surface-container) );--md-sys-color-surface-container-low: var( --pfx-editorial-form-surface-muted, var(--md-sys-color-surface-container-low) );--md-sys-color-surface-variant: var( --pfx-editorial-form-field-surface, var(--md-sys-color-surface-variant) );--md-sys-color-outline: var( --pfx-editorial-form-field-outline, var(--md-sys-color-outline) );--md-sys-color-outline-variant: var( --pfx-editorial-form-border, var(--md-sys-color-outline-variant) );--md-sys-color-on-surface: var( --editorial-text-primary, inherit );--md-sys-color-on-surface-variant: var( --editorial-text-secondary, inherit );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-primary-container: var( --pfx-editorial-form-accent-container, var(--md-sys-color-primary-container) );--md-sys-color-on-primary-container: var( --pfx-editorial-form-accent-container-text, var(--md-sys-color-on-primary-container) );--md-sys-color-on-primary: var( --pfx-editorial-form-accent-text, var(--md-sys-color-on-primary) );--md-sys-color-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );--mat-sys-on-surface: var( --editorial-text-primary, inherit );--mat-sys-on-surface-variant: var( --editorial-text-secondary, inherit );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, inherit );color:inherit;color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:var(--pdx-presentation-column-gap);margin-bottom:var(--pdx-presentation-row-gap)}.praxis-dynamic-form.presentation-mode{--pfx-pres-on-surface: var( --pdx-color-text-primary, var(--pfx-editorial-form-text, var(--pfx-form-label-strong, currentColor)) );--pfx-pres-on-surface-variant: var( --pdx-color-text-secondary, var( --pfx-editorial-form-text-muted, var( --pfx-form-label-muted, color-mix(in srgb, var(--pfx-pres-on-surface) 78%, transparent) ) ) )}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:var(--pdx-presentation-section-gap) .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:var(--pdx-presentation-column-gap, .35rem);margin-bottom:var(--pdx-presentation-row-gap, .35rem)}.praxis-dynamic-form.pres-compact .form-section{padding:var(--pdx-presentation-section-gap, .5rem) .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:minmax(0,var(--pfx-presentation-label-w, var(--pdx-presentation-label-width))) minmax(0,1fr);align-items:baseline;column-gap:var(--pdx-presentation-column-gap, 10px)}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}@media(max-width:480px){.praxis-dynamic-form.pres-label-left .praxis-presentation{grid-template-columns:minmax(0,1fr);row-gap:4px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:start}}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low, #f8f9fa);border:1px solid var(--md-sys-color-outline-variant, #e0e2ec);border-radius:16px;padding:16px 20px;box-shadow:0 1px 3px #0000000a}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-heading{margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid var(--md-sys-color-outline-variant, #e0e2ec)}.praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section .section-title,.praxis-dynamic-form .form-section.form-section--corporate-dossier .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier] .section-title{font-size:.88rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--md-sys-color-primary, #005ac1)}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation{padding:8px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep .form-section--corporate-dossier .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=corporate-dossier] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__label,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:3px}:host ::ng-deep .praxis-dynamic-form--corporate-dossier .praxis-presentation__value,:host ::ng-deep .form-section--corporate-dossier .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=corporate-dossier] .praxis-presentation__value{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.4}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low, var(--mat-sys-surface-container-low)));border:1px solid var(--pfx-editorial-form-border, var(--md-sys-color-outline-variant, #e0e2ec));border-radius:20px;padding:24px;box-shadow:0 2px 8px #0000000d}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--editorial-card .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-heading{margin-bottom:16px;padding-bottom:10px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 40%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section .section-title,.praxis-dynamic-form .form-section.form-section--editorial-card .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=editorial-card] .section-title{font-size:1.15rem;font-weight:700;color:var(--pfx-editorial-form-accent, var(--md-sys-color-primary, #005ac1))}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation{padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 35%,transparent)}:host ::ng-deep .praxis-dynamic-form--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation:last-child,:host ::ng-deep .form-section--editorial-card .form-row:last-child .praxis-presentation,:host ::ng-deep .form-section--editorial-card .praxis-presentation:last-child,:host ::ng-deep [data-presentation-preset=editorial-card] .form-row:last-child .praxis-presentation,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation:last-child{border-bottom:none}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__label,:host ::ng-deep .form-section--editorial-card .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__label{font-size:.8rem;font-weight:500;color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant, #44474f));margin-bottom:4px}:host ::ng-deep .praxis-dynamic-form--editorial-card .praxis-presentation__value,:host ::ng-deep .form-section--editorial-card .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=editorial-card] .praxis-presentation__value{font-size:1rem;font-weight:600;color:var(--pfx-editorial-form-text, var(--md-sys-color-on-surface, #1a1c1e));line-height:1.5}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section:not(.section-appearance-plain),.praxis-dynamic-form .form-section.form-section--compact-presentation:not(.section-appearance-plain),.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation]:not(.section-appearance-plain){background:transparent;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 50%,transparent);border-radius:8px;padding:10px 14px;box-shadow:none}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-heading,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-heading,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-heading{margin-bottom:8px;padding-bottom:4px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #e0e2ec) 25%,transparent)}.praxis-dynamic-form.praxis-dynamic-form--compact-presentation .form-section .section-title,.praxis-dynamic-form .form-section.form-section--compact-presentation .section-title,.praxis-dynamic-form .form-section[data-presentation-preset=compact-presentation] .section-title{font-size:.82rem;font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #44474f)}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation,:host ::ng-deep .form-section--compact-presentation .praxis-presentation,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation{padding:4px 0;border-bottom:none}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__label,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__label,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__label{font-size:.72rem;font-weight:600;color:var(--md-sys-color-on-surface-variant, #44474f);margin-bottom:2px}:host ::ng-deep .praxis-dynamic-form--compact-presentation .praxis-presentation__value,:host ::ng-deep .form-section--compact-presentation .praxis-presentation__value,:host ::ng-deep [data-presentation-preset=compact-presentation] .praxis-presentation__value{font-size:.88rem;font-weight:500;color:var(--md-sys-color-on-surface, #1a1c1e);line-height:1.35}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--corporate-dossier .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--corporate-dossier:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=corporate-dossier]:not(.section-appearance-plain){background:var(--md-sys-color-surface-container-low);border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 2px 8px #0000004d}:host-context(.mdc-theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.mdc-theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form.praxis-dynamic-form--editorial-card .form-section:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section.form-section--editorial-card:not(.section-appearance-plain),:host-context(.theme-dark) .praxis-dynamic-form .form-section[data-presentation-preset=editorial-card]:not(.section-appearance-plain){background:var(--pfx-editorial-form-surface, var(--md-sys-color-surface-container-low));border-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);box-shadow:0 4px 16px #0006}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);max-width:100%;min-width:0;background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section:not(.section-appearance-plain){border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;color:var(--pfx-editorial-form-text);box-shadow:var(--editorial-card-shadow, none)}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{background-color:var(--pfx-editorial-form-surface)!important;background-image:linear-gradient(180deg,color-mix(in srgb,var(--editorial-accent, var(--md-sys-color-primary)) 6%,transparent) 0%,transparent 132px)!important;background-repeat:no-repeat!important}.section-drop-wrapper>.form-section{margin-bottom:var(--pfx-section-gap, 20px)}.section-drop-wrapper:last-of-type>.form-section{margin-bottom:0}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections]{margin-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}.section-title{margin:0 0 var(--pfx-section-title-mb, 12px) 0;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.12rem);font-weight:700;color:var(--pfx-form-label-strong)}.section-heading{position:relative;display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 18px)}.section-heading:after{content:\"\";position:absolute;right:0;bottom:0;left:0;height:2px;pointer-events:none;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 8%,var(--pfx-form-section-divider) 46%,var(--pfx-form-section-divider) 54%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 92%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%);mask-image:linear-gradient(90deg,transparent 0%,black 18%,black 82%,transparent 100%)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 10px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:none}.section-heading.align-center{flex-direction:column;align-items:center;text-align:center}.section-heading.align-center .section-heading-text{display:grid;justify-items:center}.section-step-label{display:inline-flex;align-items:center;min-height:24px;padding:0 10px;margin:0 0 8px;border-radius:999px;background:color-mix(in srgb,var(--pfx-editorial-form-accent) 10%,transparent);color:color-mix(in srgb,var(--pfx-editorial-form-accent) 84%,var(--pfx-form-label-strong) 16%);font-size:.72rem;font-weight:800;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));letter-spacing:.08em;text-transform:uppercase}.section-heading-text{flex:1 1 auto;min-width:0}.section-heading-actions{display:inline-flex;align-items:center;align-self:flex-start;flex-wrap:wrap;gap:4px;margin-left:auto}.section-heading-actions.align-center{align-self:center;margin-left:0}.section-heading-action-btn{color:var(--pfx-form-label-muted)}.section-heading-action-btn.tone-primary{color:var(--md-sys-color-primary)}.section-heading-action-btn.tone-accent,.section-heading-action-btn.tone-secondary{color:var(--md-sys-color-tertiary)}.section-heading-action-btn.tone-warn,.section-heading-action-btn.tone-danger,.section-heading-action-btn.tone-error{color:var(--md-sys-color-error)}.section-heading-action-btn .mat-mdc-progress-spinner,.section-heading-action-btn mat-progress-spinner{--mdc-circular-progress-active-indicator-color: currentColor}.section-heading-action-btn.loading{opacity:.72;pointer-events:none}.section-heading-action-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.section-collapse-btn{margin-left:4px;color:var(--pfx-form-label-muted)}.section-title.title-large{font:var(--mdc-typography-title-large, 500 22px/28px system-ui)}.section-title.title-medium{font:var(--mdc-typography-title-medium, 500 16px/24px system-ui)}.section-title.title-small{font:var(--mdc-typography-title-small, 500 14px/20px system-ui)}.section-title.headline-small{font:var(--mdc-typography-headline-small, 600 24px/32px system-ui)}.section-title.title-large,.section-title.title-medium,.section-title.title-small,.section-title.headline-small{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-weight:var(--editorial-title-weight, 600)}.section-description{margin:0;font-family:var(--editorial-body-font-family, inherit);font-size:.93rem;color:var(--pfx-form-label-muted);line-height:1.6}.section-description.body-large{font:var(--mdc-typography-body-large, 400 16px/24px system-ui)}.section-description.body-medium{font:var(--mdc-typography-body-medium, 400 14px/20px system-ui)}.section-description.body-small{font:var(--mdc-typography-body-small, 400 12px/16px system-ui)}.section-description.body-large,.section-description.body-medium,.section-description.body-small{font-family:var(--editorial-body-font-family, inherit);font-weight:var(--editorial-body-weight, 400)}.section-title.align-center,.section-description.align-center,.section-step-label.align-center{text-align:center}.praxis-dynamic-form .form-section.section-appearance-plain{border-color:transparent;border-width:0;border-radius:0;padding:0;background:transparent;box-shadow:none}.praxis-dynamic-form .form-section.section-appearance-plain.section-has-divider{padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider, var(--md-sys-color-outline-variant, #e0e2ec))}.praxis-dynamic-form .section-drop-wrapper:last-of-type>.form-section.section-appearance-plain.section-has-divider,.praxis-dynamic-form>.form-section.section-appearance-plain.section-has-divider:last-of-type{border-bottom:none;padding-bottom:0}.form-section.section-appearance-plain .section-heading{margin-bottom:14px}.form-section.section-appearance-step{border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);border-color:var(--pfx-form-section-divider);box-shadow:none}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{border-radius:var(--editorial-card-radius, 20px);box-shadow:none}.form-section.section-appearance-step .section-heading{margin-bottom:22px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 16px)}.form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 16px)}:host(.pfx-form-section-divider-inline-title) .form-section.section-appearance-step .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-inline-divider-gap, 0)}.form-section.section-appearance-step .section-title{font:var(--mdc-typography-title-large, 700 22px/28px system-ui);color:var(--pfx-form-label-strong);margin-bottom:8px}.form-section.section-appearance-step .section-description{color:var(--pfx-form-label-muted);max-width:60ch}.form-section.section-appearance-step .section-step-label{min-height:24px;padding:0 10px;margin-bottom:10px;box-shadow:none}.form-section.section-appearance-step .section-heading.align-center .section-description{max-width:52ch}.form-section.section-appearance-step .section-body{display:grid;gap:8px;padding-top:0}.form-section.section-appearance-step .form-row{margin-bottom:var(--pfx-field-gap, 1rem)}.form-section.section-appearance-step .form-column{gap:var(--pfx-field-gap, 12px)}.form-section .form-editorial-blocks{display:grid;gap:16px}.form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{margin-top:24px;padding-top:18px;border-top:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]{gap:18px}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]>*+*{margin-top:2px}.praxis-dynamic-form:not(.canvas-mode-enabled)>praxis-form-actions[data-actions-placement=afterSections]{margin-top:18px}.praxis-dynamic-form>.form-editorial-blocks[data-editorial-placement=after]{margin-top:6px}:host-context(.mdc-theme-dark) .form-section.section-appearance-step,:host-context(.theme-dark) .form-section.section-appearance-step{border-color:color-mix(in srgb,var(--pfx-editorial-form-border) 82%,transparent);box-shadow:none}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-title,:host-context(.theme-dark) .form-section.section-appearance-step .section-title{color:color-mix(in srgb,var(--pfx-editorial-form-text) 96%,white)}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-description,:host-context(.theme-dark) .form-section.section-appearance-step .section-description{color:color-mix(in srgb,var(--pfx-editorial-form-text-muted) 86%,var(--pfx-editorial-form-text) 14%)}:host-context(.mdc-theme-dark) .section-step-label,:host-context(.theme-dark) .section-step-label{background:color-mix(in srgb,var(--md-sys-color-primary-container) 54%,transparent);color:color-mix(in srgb,var(--md-sys-color-primary) 88%,white)}:host-context(.mdc-theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions],:host-context(.theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{border-top-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 90%,transparent)}.inline-edit-btn{margin-left:6px;vertical-align:middle}.section-body.collapsed{border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);border-radius:6px;padding:8px 10px}.section-collapsed-placeholder{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.95rem}.section-collapsed-placeholder mat-icon{font-size:20px;width:20px;height:20px}.form-row{display:flex;gap:1.1rem;margin-bottom:var(--pfx-field-gap, 1.1rem);max-width:100%;min-width:0;transition:all .2s ease;border-radius:6px;position:relative}.praxis-dynamic-form.pfx-mounting .form-row{opacity:0;transform:translateY(var(--pdx-form-mount-offset, 6px));animation:pdxFormMount var(--pdx-form-mount-duration, .16s) ease-out both;animation-delay:calc(var(--pfx-mount-index, 0) * var(--pdx-form-mount-stagger, 20ms))}@media(prefers-reduced-motion:reduce){.praxis-dynamic-form.pfx-mounting .form-row{animation:none;opacity:1;transform:none}}@keyframes pdxFormMount{to{opacity:1;transform:translateY(0)}}.praxis-dynamic-form .mat-mdc-form-field{width:100%;margin-bottom:var(--pfx-field-gap, 10px);font-family:inherit;--mdc-filled-text-field-container-color: var(--pfx-form-field-surface-rest);--mdc-filled-text-field-focus-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-active-indicator-color: var(--pfx-editorial-form-field-outline);--mdc-filled-text-field-hover-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-filled-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-caret-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-input-text-placeholder-color: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 82%, transparent );--mdc-outlined-text-field-outline-color: var(--pfx-editorial-form-field-outline);--mdc-outlined-text-field-hover-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-outlined-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-outlined-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-filled-text-field-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-filled-text-field-focus-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-outline-width: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-focus-outline-width: var(--pfx-editorial-form-field-border-width);--mat-select-enabled-trigger-text-color: var(--pfx-editorial-form-text);--mat-select-enabled-arrow-color: var(--pfx-form-label-muted);--mat-form-field-enabled-select-arrow-color: var(--pfx-form-label-muted);--mat-form-field-focus-select-arrow-color: var(--pfx-editorial-form-accent);--mat-form-field-hover-state-layer-opacity: 0;--mat-form-field-focus-state-layer-opacity: 0}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field{font-family:var(--editorial-body-font-family, inherit)}.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{background:var(--pfx-form-field-surface-rest);border-radius:var(--pfx-editorial-form-field-radius);min-height:var(--pfx-form-field-min-height);transition:background-color .16s ease,box-shadow .16s ease,border-color .16s ease}.praxis-dynamic-form.editorial-visual-context .mat-mdc-text-field-wrapper,.praxis-dynamic-form.editorial-visual-context .mdc-text-field,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--filled,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--outlined{background-color:var(--pfx-form-field-surface-rest)!important;background:var(--pfx-form-field-surface-rest)!important}.praxis-dynamic-form .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-form-label-muted)}.praxis-dynamic-form .mat-mdc-input-element,.praxis-dynamic-form .mat-mdc-select-value-text,.praxis-dynamic-form .mat-mdc-form-field-infix,.praxis-dynamic-form .mat-mdc-select-min-line{color:var(--pfx-editorial-form-text)}.praxis-dynamic-form .mat-mdc-form-field:hover .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field:hover .mdc-text-field,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mdc-text-field{background:var(--pfx-form-field-surface-focus)}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-value-text,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field-infix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-min-line,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input{color:var(--pfx-editorial-form-text)!important;-webkit-text-fill-color:var(--pfx-editorial-form-text)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-editorial-form-text-muted)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 68%,transparent)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element::placeholder,.praxis-dynamic-form.editorial-visual-context textarea.mat-mdc-input-element::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 58%,transparent)!important}.praxis-dynamic-form .mat-mdc-radio-button,.praxis-dynamic-form .mat-mdc-checkbox,.praxis-dynamic-form .mat-mdc-slide-toggle{--mdc-radio-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-checkmark-color: var(--pfx-editorial-form-accent-text);--mdc-checkbox-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-focus-state-layer-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-handle-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-track-color: color-mix(in srgb, var(--pfx-editorial-form-accent) 45%, #fff)}.praxis-dynamic-form [data-field-type=input],.praxis-dynamic-form [data-field-type=textarea],.praxis-dynamic-form [data-field-type=email],.praxis-dynamic-form [data-field-type=password],.praxis-dynamic-form [data-field-type=url],.praxis-dynamic-form [data-field-type=search],.praxis-dynamic-form [data-field-type=phone],.praxis-dynamic-form [data-field-type=numericTextBox],.praxis-dynamic-form [data-field-type=currency],.praxis-dynamic-form [data-field-type=cpfCnpj],.praxis-dynamic-form [data-field-type=date],.praxis-dynamic-form [data-field-type=dateInput],.praxis-dynamic-form [data-field-type=dateRange],.praxis-dynamic-form [data-field-type=dateTimeLocal],.praxis-dynamic-form [data-field-type=time],.praxis-dynamic-form [data-field-type=timePicker],.praxis-dynamic-form [data-field-type=timeRange],.praxis-dynamic-form [data-field-type=month],.praxis-dynamic-form [data-field-type=week],.praxis-dynamic-form [data-field-type=yearInput],.praxis-dynamic-form [data-field-type=select],.praxis-dynamic-form [data-field-type=multi-select],.praxis-dynamic-form [data-field-type=searchable-select],.praxis-dynamic-form [data-field-type=async-select],.praxis-dynamic-form [data-field-type=autocomplete],.praxis-dynamic-form [data-field-type=entityLookup],.praxis-dynamic-form [data-field-type=tree-select],.praxis-dynamic-form [data-field-type=multi-select-tree],.praxis-dynamic-form [data-field-type=priceRange],.praxis-dynamic-form [data-field-type=file-upload]{display:block;width:100%;min-width:0}.praxis-dynamic-form .mat-mdc-form-field-subscript-wrapper{min-height:var(--pfx-subscript-min-h, 22px)}.form-row:last-child{margin-bottom:0}.form-column{display:grid;grid-template-columns:minmax(0,1fr);align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;max-width:100%;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-layout-rich-content{display:block;width:100%;max-width:100%;min-width:0;margin-bottom:var(--pfx-field-gap, 10px);color:var(--pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant));font:var(--mdc-typography-body-medium, 400 14px/20px system-ui);overflow-wrap:anywhere}:host ::ng-deep .form-layout-rich-content .prx-rich-content-root{display:grid;gap:8px;min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-node{min-width:0;max-width:100%}:host ::ng-deep .form-layout-rich-content .prx-rich-text{color:inherit;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{border:1px solid color-mix(in srgb,var(--pfx-editorial-form-accent) 12%,var(--pfx-editorial-form-border) 88%);border-left:3px solid var(--pfx-editorial-form-accent);border-radius:8px;background:color-mix(in srgb,var(--pfx-editorial-form-accent-container) 12%,var(--pfx-editorial-form-surface-muted) 88%)}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note{display:grid;grid-template-columns:20px minmax(0,1fr);gap:10px;align-items:flex-start;padding:11px 12px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note:before{content:\"info\";display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;color:var(--pfx-editorial-form-accent);font-family:Material Symbols Outlined;font-size:20px;font-weight:400;line-height:20px}:host ::ng-deep .form-layout-rich-content .praxis-form-visual-block--note .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice{padding:10px 12px;color:var(--pfx-editorial-form-text)}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-compose{align-items:flex-start;gap:10px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-notice .prx-rich-icon{color:var(--pfx-editorial-form-accent);font-size:20px;line-height:20px;margin-top:1px}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider{display:grid;grid-template-columns:minmax(24px,1fr) auto minmax(24px,1fr);align-items:center;gap:10px;color:var(--pfx-editorial-form-text-muted);font:var(--mdc-typography-label-small, 600 12px/16px system-ui);text-transform:uppercase}:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:before,:host ::ng-deep .form-layout-rich-content .praxis-rich-content-divider:after{content:\"\";height:1px;background:var(--pfx-editorial-form-border)}:host ::ng-deep .form-layout-rich-content .prx-rich-card{gap:6px;padding:12px 14px;border-color:var(--pfx-editorial-form-border);border-radius:8px;background:var(--pfx-editorial-form-surface-muted);color:var(--pfx-editorial-form-text);box-shadow:none}:host ::ng-deep .form-layout-rich-content .prx-rich-card-title{color:var(--pfx-editorial-form-text);font:var(--mdc-typography-title-small, 600 14px/20px system-ui)}:host ::ng-deep .form-layout-rich-content .prx-rich-card-subtitle,:host ::ng-deep .form-layout-rich-content .prx-rich-metric-caption{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-card .prx-rich-text{color:var(--pfx-editorial-form-text-muted)}:host ::ng-deep .form-layout-rich-content .prx-rich-badge{background:var(--pfx-editorial-form-accent-container);color:var(--pfx-editorial-form-accent-container-text)}.form-row.grid-12{container-type:inline-size;container-name:praxis-form-row;display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.align-start{align-self:flex-start}.align-center{align-self:center}.align-end{align-self:flex-end}.align-stretch{align-self:stretch}.form-blocking-overlay{position:absolute;inset:0;background:transparent;color:var(--md-sys-color-on-surface);backdrop-filter:blur(2px) saturate(103%);-webkit-backdrop-filter:blur(2px) saturate(103%);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;z-index:10;pointer-events:all}@media(max-width:768px){.column-drop-wrapper,.row-drop-wrapper,.form-layout-rich-content,.praxis-dynamic-form .mat-mdc-form-field,.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{max-width:100%;min-width:0}:host ::ng-deep .praxis-dynamic-form .pfx-field-shell,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-wrapper,:host ::ng-deep .praxis-dynamic-form .pfx-field-shell-host,:host ::ng-deep .praxis-dynamic-form .mat-mdc-form-field,:host ::ng-deep .praxis-dynamic-form .mat-mdc-text-field-wrapper,:host ::ng-deep .praxis-dynamic-form .mdc-text-field{width:100%;max-width:100%;min-width:0}.form-section{padding:clamp(.75rem,4vw,1rem)}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:var(--pfx-form-section-heading-divider-gap, 14px)}.section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}}.section-title{display:flex;align-items:center;gap:8px}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:100%;min-width:0}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{content:\"\";display:block;flex:1 1 auto;min-width:var(--pfx-form-section-title-inline-divider-min-width, 48px);height:2px;margin-left:var(--pfx-form-section-title-inline-divider-gap, 12px);pointer-events:none;background:linear-gradient(90deg,var(--pfx-form-section-divider) 0%,var(--pfx-form-section-divider) 62%,color-mix(in srgb,var(--pfx-form-section-divider) 18%,transparent) 88%,transparent 100%);border-radius:999px;-webkit-mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%);mask-image:linear-gradient(90deg,black 0%,black 72%,transparent 100%)}:host(.pfx-form-section-divider-inline-title) .section-heading.align-center .section-title:after{display:none}@media(max-width:640px){:host(.pfx-form-section-divider-inline-title) .section-heading.title-only{padding-bottom:var(--pfx-form-section-heading-title-only-divider-gap, 8px)}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only:after{display:block}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title{width:auto}:host(.pfx-form-section-divider-inline-title) .section-heading.title-only .section-title:after{display:none}}.section-title .section-title-icon{font-size:1.25em;line-height:1}.section-title-avatar{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px));display:inline-flex;align-items:center;justify-content:center;width:var(--_pfx-form-section-avatar-size);height:var(--_pfx-form-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-form-section-avatar-size);overflow:hidden}.section-title-avatar.size-sm{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-title-avatar.size-md{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-title-avatar.size-lg{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-title-avatar-image{object-fit:cover;border:1px solid color-mix(in srgb,var(--pfx-form-section-divider) 72%,transparent);background:var(--pfx-form-section-surface-flat)}.section-title-avatar-text,.section-title-avatar-placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent) 14%,var(--pfx-form-section-surface-flat));color:color-mix(in srgb,var(--pfx-editorial-form-accent) 82%,var(--pfx-form-label-strong) 18%);font-size:calc(var(--_pfx-form-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-title-avatar-placeholder mat-icon{font-size:calc(var(--_pfx-form-section-avatar-size) * .5625);width:calc(var(--_pfx-form-section-avatar-size) * .5625);height:calc(var(--_pfx-form-section-avatar-size) * .5625);line-height:calc(var(--_pfx-form-section-avatar-size) * .5625)}.section-title-avatar-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.form-context-empty-state{display:grid;min-height:var(--pdx-form-context-empty-min-height, 0);place-items:center;padding:var(--pdx-form-context-empty-padding, 0)}.form-context-empty-state praxis-empty-state-card{display:block;width:min(100%,var(--pdx-form-context-empty-max-width, 32rem))}.prx-form-tabs{display:block;margin-bottom:16px;max-width:100%}.prx-form-tabs__tablist{display:flex;flex-wrap:wrap;align-items:center;gap:8px;max-width:100%}.prx-form-tabs__tablist--scrollable{flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-webkit-overflow-scrolling:touch;padding:4px 2px}.prx-form-tabs__tablist--scrollable::-webkit-scrollbar{display:none}.prx-form-tabs__tab{display:inline-flex;align-items:center;gap:8px;min-width:0;padding:8px 14px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .12));background:color-mix(in srgb,var(--md-sys-color-surface, transparent) 40%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);font-family:inherit;font-size:.84rem;font-weight:500;cursor:pointer;white-space:nowrap;flex-shrink:0;-webkit-user-select:none;user-select:none;transition:all .2s cubic-bezier(.2,0,0,1)}.prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:var(--md-sys-color-surface-container-high, rgba(0, 0, 0, .05));border-color:var(--md-sys-color-outline, rgba(0, 0, 0, .24));color:var(--md-sys-color-on-surface)}.prx-form-tabs__tab:focus-visible{outline:2px solid var(--md-sys-color-primary, #005ac1);outline-offset:2px}.prx-form-tabs__tab:disabled{cursor:not-allowed;opacity:.45}.prx-form-tabs__tab--active{background:var(--md-sys-color-primary-container, color-mix(in srgb, var(--md-sys-color-primary, #005ac1) 16%, var(--md-sys-color-surface-container-high, #2b2930)));color:var(--md-sys-color-on-primary-container, var(--md-sys-color-primary, #005ac1));border-color:transparent;font-weight:600;box-shadow:0 1px 3px #00000014}.prx-form-tabs__tab-icon{font-size:18px;width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center}.prx-form-tabs__tab-badge{display:inline-flex;align-items:center;justify-content:center;padding:1px 7px;font-size:.72rem;font-weight:600;border-radius:999px;background:color-mix(in srgb,currentColor 14%,transparent)}.prx-form-tabs__tab-error-badge{display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;border-radius:999px;font-size:.7rem;font-weight:700;background:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-on-error, #ffffff);box-shadow:0 1px 2px #0003}.prx-form-tabs[data-appearance=underline]{border-bottom:1px solid var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tablist{gap:16px;padding-bottom:0}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab{border:none;border-radius:0;border-bottom:2px solid transparent;background:transparent;padding:8px 4px 10px;margin-bottom:-1px}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:transparent;border-bottom-color:var(--md-sys-color-outline-variant, #cac4d0)}.prx-form-tabs[data-appearance=underline] .prx-form-tabs__tab--active{background:transparent;box-shadow:none;border-bottom-color:var(--md-sys-color-primary, #005ac1);color:var(--md-sys-color-primary, #005ac1)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tablist{background:var(--md-sys-color-surface-container, rgba(0, 0, 0, .04));border-radius:12px;padding:4px;gap:4px;border:1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, .08))}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab{border:none;border-radius:8px;padding:6px 12px;background:transparent}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab:hover:not(:disabled):not(.prx-form-tabs__tab--active){background:color-mix(in srgb,currentColor 8%,transparent)}.prx-form-tabs[data-appearance=buttons] .prx-form-tabs__tab--active{background:var(--md-sys-color-surface, var(--mat-sys-surface));color:var(--md-sys-color-primary, #005ac1);box-shadow:0 1px 3px #0000001f}.section-drop-wrapper[hidden]{display:none!important}.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:var(--pdx-text-shimmer-base, var(--md-sys-color-on-surface-variant));font-weight:550;text-shadow:none}@supports (-webkit-background-clip: text) or (background-clip: text){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{background-image:var(--pdx-text-shimmer-gradient, linear-gradient(105deg, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 0%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 26%, color-mix(in oklab, var(--md-sys-color-tertiary, #6366f1) 66%, #a855f7 34%) 40%, var(--pdx-text-shimmer-peak, var(--md-sys-color-on-surface, #ffffff)) 50%, color-mix(in oklab, var(--md-sys-color-primary, #006a6a) 66%, #ec4899 34%) 60%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 74%, color-mix(in oklab, var(--md-sys-color-on-surface-variant, #64748b) 78%, var(--md-sys-color-on-surface, #0f172a) 22%) 100%));background-size:300% 100%;background-position:100% 50%;background-repeat:no-repeat;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent;animation:praxisFormTextShimmer var(--pdx-text-shimmer-duration, 2.6s) linear infinite;will-change:background-position}}@media(prefers-reduced-motion:reduce),(forced-colors:active),print{.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{animation:none!important;background-image:none!important;-webkit-text-fill-color:currentColor!important;color:var(--md-sys-color-primary)!important;will-change:auto}}@media(forced-colors:active){.form-loading-title,.entity-read-loading-text,.form-blocking-overlay p{color:CanvasText!important;-webkit-text-fill-color:CanvasText!important}}@keyframes praxisFormTextShimmer{0%{background-position:100% 50%}to{background-position:0% 50%}}\n"] }]
22188
22170
  }], ctorParameters: () => [{ type: i1.GenericCrudService }, { type: i2.HttpClient }, { type: i1$3.FormBuilder }, { type: i0.ChangeDetectorRef }, { type: FormLayoutService }, { type: FormContextService }, { type: FormRulesService }, { type: i7.SettingsPanelService }, { type: i2$1.MatDialog }, { type: undefined, decorators: [{
22189
22171
  type: Inject,
22190
22172
  args: [ASYNC_CONFIG_STORAGE]
@@ -30297,7 +30279,7 @@ class RulePropertiesPanelComponent {
30297
30279
  visualBlockNodes = {};
30298
30280
  rulesChange = new EventEmitter();
30299
30281
  i18n = this.resolveI18n();
30300
- jsonLogic = new PraxisJsonLogicService(null);
30282
+ jsonLogic = inject(PraxisJsonLogicService);
30301
30283
  selectedRuleId = null;
30302
30284
  selectedProperty = null;
30303
30285
  selectedVisualBlockNodeId = '';
@@ -30393,14 +30375,17 @@ class RulePropertiesPanelComponent {
30393
30375
  }
30394
30376
  get selectedRuleStatusLabel() {
30395
30377
  return this.canApply()
30396
- ? this.t('rules.property.panel.ready', 'Pronta para aplicar')
30397
- : this.t('rules.property.panel.incomplete', 'Incompleta');
30378
+ ? this.t('rules.property.panel.propertyEditable', 'Edição da propriedade disponível')
30379
+ : this.t('rules.property.panel.propertySelectionNeeded', 'Selecione regra e propriedade');
30398
30380
  }
30399
30381
  get selectedRuleConditionLabel() {
30400
30382
  const condition = this.selectedRule?.effect?.condition;
30401
30383
  if (condition === null || condition === undefined) {
30402
30384
  return this.t('rules.property.panel.conditionAlways', 'Sempre');
30403
30385
  }
30386
+ if (!this.isValidCondition(condition)) {
30387
+ return this.t('rules.property.panel.conditionInvalid', 'Condição inválida');
30388
+ }
30404
30389
  return this.t('rules.property.panel.conditionConfigured', 'Com condição');
30405
30390
  }
30406
30391
  get selectedRuleEffectLabel() {
@@ -30460,7 +30445,7 @@ class RulePropertiesPanelComponent {
30460
30445
  sampleData: parsed.data,
30461
30446
  };
30462
30447
  }
30463
- if (typeof condition === 'string' || typeof condition !== 'object') {
30448
+ if (!this.isValidCondition(condition)) {
30464
30449
  return {
30465
30450
  state: 'invalid',
30466
30451
  branchLabel: this.tx('config.ruleProperties.preview.branch.invalid', 'Condição inválida'),
@@ -30468,7 +30453,7 @@ class RulePropertiesPanelComponent {
30468
30453
  activeProperties: {},
30469
30454
  inactiveProperties: {},
30470
30455
  sampleData: parsed.data,
30471
- error: this.tx('config.ruleProperties.preview.errors.conditionObject', 'A condição precisa ser um objeto Json Logic canônico.'),
30456
+ error: this.tx('config.ruleProperties.preview.errors.conditionInvalid', 'A condição não é válida no runtime atual.'),
30472
30457
  };
30473
30458
  }
30474
30459
  try {
@@ -30499,17 +30484,29 @@ class RulePropertiesPanelComponent {
30499
30484
  };
30500
30485
  }
30501
30486
  }
30502
- ngOnChanges(_changes) {
30503
- if (this.rules.length && !this.selectedRuleId) {
30504
- this.selectedRuleId = this.rules[0].id;
30505
- this.onRuleChange();
30487
+ ngOnChanges(changes) {
30488
+ if (!changes['rules'])
30489
+ return;
30490
+ const previousRules = changes['rules'].previousValue;
30491
+ const previousRule = previousRules?.find((rule) => rule.id === this.selectedRuleId);
30492
+ const selectedStillExists = this.rules.some((rule) => rule.id === this.selectedRuleId);
30493
+ if (!selectedStillExists)
30494
+ this.selectedRuleId = this.rules[0]?.id ?? null;
30495
+ if (!selectedStillExists || JSON.stringify(previousRule?.effect?.condition) !==
30496
+ JSON.stringify(this.selectedRule?.effect?.condition)) {
30497
+ this.previewSampleDataJson = '{}';
30498
+ }
30499
+ if (!this.propertyOptions.some((property) => property.name === this.selectedProperty)) {
30500
+ this.selectedProperty = this.propertyOptions[0]?.name ?? null;
30506
30501
  }
30502
+ this.resetValues();
30507
30503
  }
30508
30504
  onRuleChange() {
30509
30505
  const rule = this.selectedRule;
30510
30506
  if (!rule)
30511
30507
  return;
30512
30508
  this.selectedProperty = this.propertyOptions[0]?.name || null;
30509
+ this.previewSampleDataJson = '{}';
30513
30510
  this.resetValues();
30514
30511
  }
30515
30512
  onPropertyChange() {
@@ -30544,6 +30541,20 @@ class RulePropertiesPanelComponent {
30544
30541
  canApply() {
30545
30542
  return !!this.selectedRule && !!this.selectedProperty && !!this.selectedRule?.targetType && !!this.selectedRule?.targets?.length;
30546
30543
  }
30544
+ isValidCondition(condition) {
30545
+ if (condition === null || condition === undefined)
30546
+ return true;
30547
+ try {
30548
+ this.jsonLogic.validate(condition, {
30549
+ availableRoots: ['form'], defaultRoot: 'form', allowImplicitRoot: true,
30550
+ requireExpressionObject: true,
30551
+ });
30552
+ return true;
30553
+ }
30554
+ catch {
30555
+ return false;
30556
+ }
30557
+ }
30547
30558
  t(key, fallback, params) {
30548
30559
  return this.tx(key, fallback, params);
30549
30560
  }
@@ -31068,17 +31079,15 @@ class RulePropertiesPanelComponent {
31068
31079
  }
31069
31080
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: RulePropertiesPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
31070
31081
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: RulePropertiesPanelComponent, isStandalone: true, selector: "praxis-rule-properties-panel", inputs: { rules: "rules", visualBlockNodes: "visualBlockNodes" }, outputs: { rulesChange: "rulesChange" }, providers: [providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG)], usesOnChanges: true, ngImport: i0, template: `
31071
- <mat-card class="rule-props-card">
31072
- <mat-card-header class="rule-props-header">
31073
- <div mat-card-avatar class="rule-props-avatar">
31074
- <mat-icon aria-hidden="true">tune</mat-icon>
31075
- </div>
31076
- <mat-card-title>{{ t('rules.property.panel.title', 'Efeito estruturado da regra') }}</mat-card-title>
31077
- <mat-card-subtitle>
31082
+ <section class="rule-props-panel">
31083
+ <header class="rule-props-header">
31084
+ <h3>{{ t('rules.property.panel.title', 'Efeito estruturado da regra') }}</h3>
31085
+ <p>
31078
31086
  {{ t('rules.property.panel.subtitle', 'Escolha uma regra, edite uma propriedade permitida e confira o patch antes de aplicar.') }}
31079
- </mat-card-subtitle>
31080
- </mat-card-header>
31081
- <mat-card-content>
31087
+ </p>
31088
+ <p class="property-scope-hint">{{ t('rules.property.panel.scopeHint', 'Este painel edita apenas os efeitos. A validade da regra e a aplicação no formulário são verificadas pelo editor do formulário.') }}</p>
31089
+ </header>
31090
+ <div class="rule-props-content">
31082
31091
  @if (selectedRule; as rule) {
31083
31092
  <div class="rule-context">
31084
31093
  <div class="rule-context__main">
@@ -31491,7 +31500,7 @@ class RulePropertiesPanelComponent {
31491
31500
  <div class="preview-header">
31492
31501
  <div>
31493
31502
  <h4>{{ t('config.ruleProperties.preview.title', 'Preview true/false') }}</h4>
31494
- <p>{{ t('config.ruleProperties.preview.subtitle', 'Edite dados de exemplo para ver qual efeito será aplicado sem persistir nada.') }}</p>
31503
+ <p>{{ t('config.ruleProperties.preview.scopeHint', 'Simule os dois ramos com dados de exemplo. O resultado não valida os alvos nem autoriza aplicar a regra.') }}</p>
31495
31504
  </div>
31496
31505
  <span class="preview-state" [class.preview-state--active]="rulePreview.state === 'true' || rulePreview.state === 'always'" [class.preview-state--false]="rulePreview.state === 'false'" [class.preview-state--invalid]="rulePreview.state === 'invalid'">
31497
31506
  {{ rulePreview.branchLabel }}
@@ -31551,9 +31560,9 @@ class RulePropertiesPanelComponent {
31551
31560
  </div>
31552
31561
  }
31553
31562
  </div>
31554
- </mat-card-content>
31555
- </mat-card>
31556
- `, isInline: true, styles: [":host{display:block;min-width:0}.rule-props-card{margin-top:16px;min-width:0;overflow:visible;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container-low);box-shadow:none}.rule-props-header{padding:16px 18px 10px}.rule-props-avatar{display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 42%,transparent)}.rule-props-card mat-card-content{display:grid;gap:14px;min-width:0;padding:0 18px 18px}.rule-context{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:14px;align-items:center;padding:12px 14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 16%,var(--md-sys-color-surface-container) 84%);min-width:0}.rule-context__main{display:grid;gap:3px;min-width:0}.rule-context__main strong{overflow:hidden;color:var(--md-sys-color-on-surface);font-size:15px;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}.rule-context__main span:last-child{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.rule-context__eyebrow{color:var(--md-sys-color-primary);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}.rule-context__meta{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px;min-width:0}.rule-context__chip{display:inline-flex;align-items:center;min-height:24px;max-width:180px;padding:3px 9px;overflow:hidden;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.rule-context__chip--warn{border-color:color-mix(in srgb,var(--md-sys-color-tertiary, var(--md-sys-color-primary)) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-tertiary, var(--md-sys-color-primary))}.rule-props-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-items:start;min-width:0}.rule-editor-section{display:grid;gap:8px;min-width:0}.rule-editor-section--selector{padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.rule-editor-section__title{display:inline-flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:700}.rule-editor-section__title span{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:999px;background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);font-size:11px}.property-workbench{grid-column:1 / -1;display:grid;gap:6px;min-width:0;padding-top:2px}.property-workbench__summary{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.value-row{grid-column:1 / -1;display:grid;grid-template-columns:minmax(min(210px,100%),.45fr) minmax(min(260px,100%),1fr);align-items:start;gap:12px;min-width:0;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.value-label{padding-top:16px;color:var(--md-sys-color-on-surface-variant);font-weight:600;line-height:1.35}.options-editor{grid-column:1 / -1;display:grid;gap:10px;width:100%;min-width:0;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.options-editor__title{color:var(--md-sys-color-on-surface-variant);font-size:13px;font-weight:600}.option-row{display:grid;grid-template-columns:minmax(min(160px,100%),1fr) minmax(min(160px,100%),1fr) auto auto;gap:10px;align-items:center;min-width:0}.validator-row{display:grid;grid-template-columns:minmax(min(150px,100%),1fr) minmax(min(120px,100%),.7fr) minmax(min(150px,100%),1fr) auto auto;gap:10px;align-items:center;min-width:0}.breakpoint-row{display:grid;grid-template-columns:56px minmax(min(160px,100%),1fr);gap:10px;align-items:center;min-width:0}.style-row{display:grid;grid-template-columns:minmax(min(220px,100%),1.1fr) minmax(min(120px,100%),.45fr) minmax(min(220px,100%),1fr) auto;gap:10px;align-items:start;min-width:0}.breakpoint-label{color:var(--md-sys-color-on-surface-variant);font-size:13px;font-weight:700;text-transform:uppercase}.visual-block-rule-note{grid-column:1 / -1;display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:start;padding:10px 12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 32%,var(--md-sys-color-outline-variant));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 28%,var(--md-sys-color-surface) 72%);color:var(--md-sys-color-on-surface);font-size:13px;line-height:1.45}.visual-block-rule-note mat-icon{width:18px;height:18px;font-size:18px;color:var(--md-sys-color-primary)}.visual-block-node-select{grid-column:1 / -1}.actions{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:10px;align-items:center}.actions__hint{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.preview{grid-column:1 / -1;background:var(--md-sys-color-surface-container, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);padding:12px;border-radius:8px}.preview-header{display:flex;justify-content:space-between;gap:16px;align-items:flex-start;margin-bottom:12px}.preview-header h4{margin:0 0 4px}.preview-header p{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.preview-state{flex:0 0 auto;min-width:96px;padding:6px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface);font-size:12px;font-weight:600;text-align:center}.preview-state--active{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 36%,var(--md-sys-color-surface) 64%)}.preview-state--false{border-color:color-mix(in srgb,var(--md-sys-color-tertiary, var(--md-sys-color-primary)) 34%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-tertiary, var(--md-sys-color-primary))}.preview-state--invalid{border-color:var(--md-sys-color-error);color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 36%,var(--md-sys-color-surface) 64%)}.preview-sample-field{width:100%}.preview-error{display:grid;grid-template-columns:auto 1fr;gap:8px;align-items:start;margin:4px 0 10px;color:var(--md-sys-color-error);font-size:13px}.preview-error mat-icon{width:18px;height:18px;font-size:18px}.preview-label{display:inline-flex;align-items:center;gap:8px;margin:4px 0;color:var(--md-sys-color-on-surface-variant);font-size:12px}.danger-action{color:var(--md-sys-color-error)}@media(max-width:720px){.rule-context{grid-template-columns:1fr}.rule-context__meta{justify-content:flex-start}.rule-props-grid,.value-row,.option-row,.validator-row,.breakpoint-row,.style-row{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.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$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$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: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.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: MatSlideToggleModule }, { kind: "component", type: i5$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "ngmodule", type: MatCardModule }, { kind: "component", type: i7$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i7$1.MatCardAvatar, selector: "[mat-card-avatar], [matCardAvatar]" }, { kind: "directive", type: i7$1.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i7$1.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i7$1.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i7$1.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "pipe", type: i1$2.JsonPipe, name: "json" }] });
31563
+ </div>
31564
+ </section>
31565
+ `, isInline: true, styles: [":host{display:block;min-width:0;container-type:inline-size}.rule-props-panel{margin-top:16px;min-width:0}.rule-props-header{padding-block:8px 14px}.rule-props-header h3{margin:0 0 4px}.rule-props-header p{margin:4px 0 0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.rule-props-content{display:grid;gap:14px;min-width:0}.rule-context{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:14px;align-items:center;padding:12px 14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 16%,var(--md-sys-color-surface-container) 84%);min-width:0}.rule-context__main{display:grid;gap:3px;min-width:0}.rule-context__main strong{color:var(--md-sys-color-on-surface);font-size:15px;line-height:1.25;overflow-wrap:anywhere}.rule-context__main span:last-child{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.rule-context__eyebrow{color:var(--md-sys-color-primary);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}.rule-context__meta{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px;min-width:0}.rule-context__chip{display:inline-flex;align-items:center;min-height:24px;max-width:100%;padding:3px 9px;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600;overflow-wrap:anywhere}.rule-context__chip--warn{border-color:color-mix(in srgb,var(--md-sys-color-tertiary, var(--md-sys-color-primary)) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-tertiary, var(--md-sys-color-primary))}.rule-props-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-items:start;min-width:0}.rule-editor-section{display:grid;gap:8px;min-width:0}.rule-editor-section--selector{padding-block:4px}.rule-editor-section__title{display:inline-flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:700}.rule-editor-section__title span{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:999px;background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);font-size:11px}.property-workbench{grid-column:1 / -1;display:grid;gap:6px;min-width:0;padding-top:2px}.property-workbench__summary{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.value-row{grid-column:1 / -1;display:grid;grid-template-columns:minmax(min(210px,100%),.45fr) minmax(min(260px,100%),1fr);align-items:start;gap:12px;min-width:0;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.value-label{padding-top:16px;color:var(--md-sys-color-on-surface-variant);font-weight:600;line-height:1.35}.options-editor{grid-column:1 / -1;display:grid;gap:10px;width:100%;min-width:0;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.options-editor__title{color:var(--md-sys-color-on-surface-variant);font-size:13px;font-weight:600}.option-row{display:grid;grid-template-columns:minmax(min(160px,100%),1fr) minmax(min(160px,100%),1fr) auto auto;gap:10px;align-items:center;min-width:0}.validator-row{display:grid;grid-template-columns:minmax(min(150px,100%),1fr) minmax(min(120px,100%),.7fr) minmax(min(150px,100%),1fr) auto auto;gap:10px;align-items:center;min-width:0}.breakpoint-row{display:grid;grid-template-columns:56px minmax(min(160px,100%),1fr);gap:10px;align-items:center;min-width:0}.style-row{display:grid;grid-template-columns:minmax(min(220px,100%),1.1fr) minmax(min(120px,100%),.45fr) minmax(min(220px,100%),1fr) auto;gap:10px;align-items:start;min-width:0}.breakpoint-label{color:var(--md-sys-color-on-surface-variant);font-size:13px;font-weight:700;text-transform:uppercase}.visual-block-rule-note{grid-column:1 / -1;display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:start;padding:10px 12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 32%,var(--md-sys-color-outline-variant));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 28%,var(--md-sys-color-surface) 72%);color:var(--md-sys-color-on-surface);font-size:13px;line-height:1.45}.visual-block-rule-note mat-icon{width:18px;height:18px;font-size:18px;color:var(--md-sys-color-primary)}.visual-block-node-select{grid-column:1 / -1}.actions{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:10px;align-items:center}.actions__hint{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.preview{grid-column:1 / -1;background:var(--md-sys-color-surface-container, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);padding:12px;border-radius:8px}.preview-header{display:flex;flex-wrap:wrap;justify-content:space-between;gap:16px;align-items:flex-start;margin-bottom:12px}.preview-header h4{margin:0 0 4px}.preview-header p{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.preview-state{flex:0 0 auto;min-width:96px;padding:6px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface);font-size:12px;font-weight:600;text-align:center}.preview-state--active{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 36%,var(--md-sys-color-surface) 64%)}.preview-state--false{border-color:color-mix(in srgb,var(--md-sys-color-tertiary, var(--md-sys-color-primary)) 34%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-tertiary, var(--md-sys-color-primary))}.preview-state--invalid{border-color:var(--md-sys-color-error);color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 36%,var(--md-sys-color-surface) 64%)}.preview-sample-field{width:100%}.preview-error{display:grid;grid-template-columns:auto 1fr;gap:8px;align-items:start;margin:4px 0 10px;color:var(--md-sys-color-error);font-size:13px}.preview-error mat-icon{width:18px;height:18px;font-size:18px}.preview-label{display:inline-flex;align-items:center;gap:8px;margin:4px 0;color:var(--md-sys-color-on-surface-variant);font-size:12px}pre{white-space:pre-wrap;overflow-wrap:anywhere}.danger-action{color:var(--md-sys-color-error)}@container (max-width: 720px){.rule-context{grid-template-columns:1fr}.rule-context__meta{justify-content:flex-start}.rule-props-grid,.value-row,.option-row,.validator-row,.breakpoint-row,.style-row{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.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$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$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: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.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: MatSlideToggleModule }, { kind: "component", type: i5$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "pipe", type: i1$2.JsonPipe, name: "json" }] });
31557
31566
  }
31558
31567
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: RulePropertiesPanelComponent, decorators: [{
31559
31568
  type: Component,
@@ -31565,23 +31574,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
31565
31574
  MatInputModule,
31566
31575
  MatSlideToggleModule,
31567
31576
  MatButtonModule,
31568
- MatCardModule,
31569
31577
  MatListModule,
31570
31578
  MatIconModule,
31571
31579
  MatTooltipModule,
31572
31580
  PraxisIconButtonComponent,
31573
31581
  ], template: `
31574
- <mat-card class="rule-props-card">
31575
- <mat-card-header class="rule-props-header">
31576
- <div mat-card-avatar class="rule-props-avatar">
31577
- <mat-icon aria-hidden="true">tune</mat-icon>
31578
- </div>
31579
- <mat-card-title>{{ t('rules.property.panel.title', 'Efeito estruturado da regra') }}</mat-card-title>
31580
- <mat-card-subtitle>
31582
+ <section class="rule-props-panel">
31583
+ <header class="rule-props-header">
31584
+ <h3>{{ t('rules.property.panel.title', 'Efeito estruturado da regra') }}</h3>
31585
+ <p>
31581
31586
  {{ t('rules.property.panel.subtitle', 'Escolha uma regra, edite uma propriedade permitida e confira o patch antes de aplicar.') }}
31582
- </mat-card-subtitle>
31583
- </mat-card-header>
31584
- <mat-card-content>
31587
+ </p>
31588
+ <p class="property-scope-hint">{{ t('rules.property.panel.scopeHint', 'Este painel edita apenas os efeitos. A validade da regra e a aplicação no formulário são verificadas pelo editor do formulário.') }}</p>
31589
+ </header>
31590
+ <div class="rule-props-content">
31585
31591
  @if (selectedRule; as rule) {
31586
31592
  <div class="rule-context">
31587
31593
  <div class="rule-context__main">
@@ -31994,7 +32000,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
31994
32000
  <div class="preview-header">
31995
32001
  <div>
31996
32002
  <h4>{{ t('config.ruleProperties.preview.title', 'Preview true/false') }}</h4>
31997
- <p>{{ t('config.ruleProperties.preview.subtitle', 'Edite dados de exemplo para ver qual efeito será aplicado sem persistir nada.') }}</p>
32003
+ <p>{{ t('config.ruleProperties.preview.scopeHint', 'Simule os dois ramos com dados de exemplo. O resultado não valida os alvos nem autoriza aplicar a regra.') }}</p>
31998
32004
  </div>
31999
32005
  <span class="preview-state" [class.preview-state--active]="rulePreview.state === 'true' || rulePreview.state === 'always'" [class.preview-state--false]="rulePreview.state === 'false'" [class.preview-state--invalid]="rulePreview.state === 'invalid'">
32000
32006
  {{ rulePreview.branchLabel }}
@@ -32054,9 +32060,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
32054
32060
  </div>
32055
32061
  }
32056
32062
  </div>
32057
- </mat-card-content>
32058
- </mat-card>
32059
- `, styles: [":host{display:block;min-width:0}.rule-props-card{margin-top:16px;min-width:0;overflow:visible;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface-container-low);box-shadow:none}.rule-props-header{padding:16px 18px 10px}.rule-props-avatar{display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 42%,transparent)}.rule-props-card mat-card-content{display:grid;gap:14px;min-width:0;padding:0 18px 18px}.rule-context{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:14px;align-items:center;padding:12px 14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 16%,var(--md-sys-color-surface-container) 84%);min-width:0}.rule-context__main{display:grid;gap:3px;min-width:0}.rule-context__main strong{overflow:hidden;color:var(--md-sys-color-on-surface);font-size:15px;line-height:1.25;text-overflow:ellipsis;white-space:nowrap}.rule-context__main span:last-child{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.rule-context__eyebrow{color:var(--md-sys-color-primary);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}.rule-context__meta{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px;min-width:0}.rule-context__chip{display:inline-flex;align-items:center;min-height:24px;max-width:180px;padding:3px 9px;overflow:hidden;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600;text-overflow:ellipsis;white-space:nowrap}.rule-context__chip--warn{border-color:color-mix(in srgb,var(--md-sys-color-tertiary, var(--md-sys-color-primary)) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-tertiary, var(--md-sys-color-primary))}.rule-props-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-items:start;min-width:0}.rule-editor-section{display:grid;gap:8px;min-width:0}.rule-editor-section--selector{padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.rule-editor-section__title{display:inline-flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:700}.rule-editor-section__title span{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:999px;background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);font-size:11px}.property-workbench{grid-column:1 / -1;display:grid;gap:6px;min-width:0;padding-top:2px}.property-workbench__summary{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.value-row{grid-column:1 / -1;display:grid;grid-template-columns:minmax(min(210px,100%),.45fr) minmax(min(260px,100%),1fr);align-items:start;gap:12px;min-width:0;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.value-label{padding-top:16px;color:var(--md-sys-color-on-surface-variant);font-weight:600;line-height:1.35}.options-editor{grid-column:1 / -1;display:grid;gap:10px;width:100%;min-width:0;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.options-editor__title{color:var(--md-sys-color-on-surface-variant);font-size:13px;font-weight:600}.option-row{display:grid;grid-template-columns:minmax(min(160px,100%),1fr) minmax(min(160px,100%),1fr) auto auto;gap:10px;align-items:center;min-width:0}.validator-row{display:grid;grid-template-columns:minmax(min(150px,100%),1fr) minmax(min(120px,100%),.7fr) minmax(min(150px,100%),1fr) auto auto;gap:10px;align-items:center;min-width:0}.breakpoint-row{display:grid;grid-template-columns:56px minmax(min(160px,100%),1fr);gap:10px;align-items:center;min-width:0}.style-row{display:grid;grid-template-columns:minmax(min(220px,100%),1.1fr) minmax(min(120px,100%),.45fr) minmax(min(220px,100%),1fr) auto;gap:10px;align-items:start;min-width:0}.breakpoint-label{color:var(--md-sys-color-on-surface-variant);font-size:13px;font-weight:700;text-transform:uppercase}.visual-block-rule-note{grid-column:1 / -1;display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:start;padding:10px 12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 32%,var(--md-sys-color-outline-variant));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 28%,var(--md-sys-color-surface) 72%);color:var(--md-sys-color-on-surface);font-size:13px;line-height:1.45}.visual-block-rule-note mat-icon{width:18px;height:18px;font-size:18px;color:var(--md-sys-color-primary)}.visual-block-node-select{grid-column:1 / -1}.actions{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:10px;align-items:center}.actions__hint{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.preview{grid-column:1 / -1;background:var(--md-sys-color-surface-container, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);padding:12px;border-radius:8px}.preview-header{display:flex;justify-content:space-between;gap:16px;align-items:flex-start;margin-bottom:12px}.preview-header h4{margin:0 0 4px}.preview-header p{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.preview-state{flex:0 0 auto;min-width:96px;padding:6px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface);font-size:12px;font-weight:600;text-align:center}.preview-state--active{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 36%,var(--md-sys-color-surface) 64%)}.preview-state--false{border-color:color-mix(in srgb,var(--md-sys-color-tertiary, var(--md-sys-color-primary)) 34%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-tertiary, var(--md-sys-color-primary))}.preview-state--invalid{border-color:var(--md-sys-color-error);color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 36%,var(--md-sys-color-surface) 64%)}.preview-sample-field{width:100%}.preview-error{display:grid;grid-template-columns:auto 1fr;gap:8px;align-items:start;margin:4px 0 10px;color:var(--md-sys-color-error);font-size:13px}.preview-error mat-icon{width:18px;height:18px;font-size:18px}.preview-label{display:inline-flex;align-items:center;gap:8px;margin:4px 0;color:var(--md-sys-color-on-surface-variant);font-size:12px}.danger-action{color:var(--md-sys-color-error)}@media(max-width:720px){.rule-context{grid-template-columns:1fr}.rule-context__meta{justify-content:flex-start}.rule-props-grid,.value-row,.option-row,.validator-row,.breakpoint-row,.style-row{grid-template-columns:1fr}}\n"] }]
32063
+ </div>
32064
+ </section>
32065
+ `, styles: [":host{display:block;min-width:0;container-type:inline-size}.rule-props-panel{margin-top:16px;min-width:0}.rule-props-header{padding-block:8px 14px}.rule-props-header h3{margin:0 0 4px}.rule-props-header p{margin:4px 0 0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.rule-props-content{display:grid;gap:14px;min-width:0}.rule-context{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:14px;align-items:center;padding:12px 14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 28%,var(--md-sys-color-outline-variant));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 16%,var(--md-sys-color-surface-container) 84%);min-width:0}.rule-context__main{display:grid;gap:3px;min-width:0}.rule-context__main strong{color:var(--md-sys-color-on-surface);font-size:15px;line-height:1.25;overflow-wrap:anywhere}.rule-context__main span:last-child{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.rule-context__eyebrow{color:var(--md-sys-color-primary);font-size:11px;font-weight:700;letter-spacing:0;text-transform:uppercase}.rule-context__meta{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:6px;min-width:0}.rule-context__chip{display:inline-flex;align-items:center;min-height:24px;max-width:100%;padding:3px 9px;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600;overflow-wrap:anywhere}.rule-context__chip--warn{border-color:color-mix(in srgb,var(--md-sys-color-tertiary, var(--md-sys-color-primary)) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-tertiary, var(--md-sys-color-primary))}.rule-props-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;align-items:start;min-width:0}.rule-editor-section{display:grid;gap:8px;min-width:0}.rule-editor-section--selector{padding-block:4px}.rule-editor-section__title{display:inline-flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:700}.rule-editor-section__title span{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:999px;background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary);font-size:11px}.property-workbench{grid-column:1 / -1;display:grid;gap:6px;min-width:0;padding-top:2px}.property-workbench__summary{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.value-row{grid-column:1 / -1;display:grid;grid-template-columns:minmax(min(210px,100%),.45fr) minmax(min(260px,100%),1fr);align-items:start;gap:12px;min-width:0;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.value-label{padding-top:16px;color:var(--md-sys-color-on-surface-variant);font-weight:600;line-height:1.35}.options-editor{grid-column:1 / -1;display:grid;gap:10px;width:100%;min-width:0;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.options-editor__title{color:var(--md-sys-color-on-surface-variant);font-size:13px;font-weight:600}.option-row{display:grid;grid-template-columns:minmax(min(160px,100%),1fr) minmax(min(160px,100%),1fr) auto auto;gap:10px;align-items:center;min-width:0}.validator-row{display:grid;grid-template-columns:minmax(min(150px,100%),1fr) minmax(min(120px,100%),.7fr) minmax(min(150px,100%),1fr) auto auto;gap:10px;align-items:center;min-width:0}.breakpoint-row{display:grid;grid-template-columns:56px minmax(min(160px,100%),1fr);gap:10px;align-items:center;min-width:0}.style-row{display:grid;grid-template-columns:minmax(min(220px,100%),1.1fr) minmax(min(120px,100%),.45fr) minmax(min(220px,100%),1fr) auto;gap:10px;align-items:start;min-width:0}.breakpoint-label{color:var(--md-sys-color-on-surface-variant);font-size:13px;font-weight:700;text-transform:uppercase}.visual-block-rule-note{grid-column:1 / -1;display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:start;padding:10px 12px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 32%,var(--md-sys-color-outline-variant));border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 28%,var(--md-sys-color-surface) 72%);color:var(--md-sys-color-on-surface);font-size:13px;line-height:1.45}.visual-block-rule-note mat-icon{width:18px;height:18px;font-size:18px;color:var(--md-sys-color-primary)}.visual-block-node-select{grid-column:1 / -1}.actions{grid-column:1 / -1;display:flex;flex-wrap:wrap;gap:10px;align-items:center}.actions__hint{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.35}.preview{grid-column:1 / -1;background:var(--md-sys-color-surface-container, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);padding:12px;border-radius:8px}.preview-header{display:flex;flex-wrap:wrap;justify-content:space-between;gap:16px;align-items:flex-start;margin-bottom:12px}.preview-header h4{margin:0 0 4px}.preview-header p{margin:0;color:var(--md-sys-color-on-surface-variant);font-size:13px;line-height:1.4}.preview-state{flex:0 0 auto;min-width:96px;padding:6px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface);font-size:12px;font-weight:600;text-align:center}.preview-state--active{border-color:color-mix(in srgb,var(--md-sys-color-primary) 42%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary-container) 36%,var(--md-sys-color-surface) 64%)}.preview-state--false{border-color:color-mix(in srgb,var(--md-sys-color-tertiary, var(--md-sys-color-primary)) 34%,var(--md-sys-color-outline-variant));color:var(--md-sys-color-tertiary, var(--md-sys-color-primary))}.preview-state--invalid{border-color:var(--md-sys-color-error);color:var(--md-sys-color-error);background:color-mix(in srgb,var(--md-sys-color-error-container) 36%,var(--md-sys-color-surface) 64%)}.preview-sample-field{width:100%}.preview-error{display:grid;grid-template-columns:auto 1fr;gap:8px;align-items:start;margin:4px 0 10px;color:var(--md-sys-color-error);font-size:13px}.preview-error mat-icon{width:18px;height:18px;font-size:18px}.preview-label{display:inline-flex;align-items:center;gap:8px;margin:4px 0;color:var(--md-sys-color-on-surface-variant);font-size:12px}pre{white-space:pre-wrap;overflow-wrap:anywhere}.danger-action{color:var(--md-sys-color-error)}@container (max-width: 720px){.rule-context{grid-template-columns:1fr}.rule-context__meta{justify-content:flex-start}.rule-props-grid,.value-row,.option-row,.validator-row,.breakpoint-row,.style-row{grid-template-columns:1fr}}\n"] }]
32060
32066
  }], propDecorators: { rules: [{
32061
32067
  type: Input
32062
32068
  }], visualBlockNodes: [{
@@ -32272,7 +32278,9 @@ class PraxisDynamicFormConfigEditor {
32272
32278
  hasProcessedInitialRuleState = false;
32273
32279
  ruleConversionFailed = false;
32274
32280
  jsonLogic = inject(PraxisJsonLogicService);
32281
+ cascadeRulesService = inject(CascadeRulesService);
32275
32282
  jsonEditorIsValid = true;
32283
+ cascadeDraftIsValid = true;
32276
32284
  globalActionValidationIssues = [];
32277
32285
  i18n = this.resolveI18n();
32278
32286
  globalActionCatalog;
@@ -32290,7 +32298,7 @@ class PraxisDynamicFormConfigEditor {
32290
32298
  isValid$ = new BehaviorSubject(true);
32291
32299
  isBusy$ = new BehaviorSubject(false);
32292
32300
  lastRulesSignature = null;
32293
- pendingRulePropertiesStateSignature = null;
32301
+ supersededRuleStateSignature = null;
32294
32302
  DEBUG = typeof window !== 'undefined' &&
32295
32303
  Boolean(window['__PRAXIS_DEBUG__']);
32296
32304
  debugLog(message, ...args) {
@@ -32392,10 +32400,7 @@ class PraxisDynamicFormConfigEditor {
32392
32400
  ngOnInit() {
32393
32401
  this.ruleBuilderConfig = this.createRuleBuilderConfig(this.editedConfig.fieldMetadata || [], this.editedConfig.sections || [], this.editedConfig.actions);
32394
32402
  this.refreshVisualBlockNodeOptions();
32395
- this.ruleBuilderState =
32396
- this.editedConfig.formRulesState ||
32397
- formLayoutRulesToBuilderState(this.editedConfig.formRules || []);
32398
- this.currentRules = this.projectBuilderRules(this.ruleBuilderState) ?? this.editedConfig.formRules ?? [];
32403
+ this.hydrateRuleDraft();
32399
32404
  this.initializeCommandRuleEditor();
32400
32405
  this.refreshRuleDiagnostics();
32401
32406
  this.lastRulesSignature = this.computeRulesSignature(this.ruleBuilderState);
@@ -32425,11 +32430,10 @@ class PraxisDynamicFormConfigEditor {
32425
32430
  this.debugLog('[FormConfigEditor] reset()');
32426
32431
  }
32427
32432
  catch { }
32433
+ this.cascadeDraftIsValid = true;
32434
+ this.syncCascadeManagerFields();
32428
32435
  this.jsonEditor?.updateJsonFromDocument(this.buildAuthoringDocument());
32429
- this.ruleBuilderState =
32430
- this.editedConfig.formRulesState ||
32431
- formLayoutRulesToBuilderState(this.editedConfig.formRules || []);
32432
- this.currentRules = this.projectBuilderRules(this.ruleBuilderState) ?? this.editedConfig.formRules ?? [];
32436
+ this.hydrateRuleDraft();
32433
32437
  this.initializeCommandRuleEditor();
32434
32438
  this.refreshVisualBlockNodeOptions();
32435
32439
  this.refreshRuleDiagnostics();
@@ -32449,9 +32453,11 @@ class PraxisDynamicFormConfigEditor {
32449
32453
  updateDirtyState(reason = 'unknown') {
32450
32454
  const a = serializeDynamicFormAuthoringDocument(this.appliedDocument ?? this.initialDocument);
32451
32455
  const b = serializeDynamicFormAuthoringDocument(this.buildAuthoringDocument());
32452
- const hasChanges = this.hasInvalidSurfaceDraft || stableStringify(a) !== stableStringify(b);
32456
+ const hasChanges = this.hasInvalidSurfaceDraft ||
32457
+ !this.cascadeDraftIsValid ||
32458
+ stableStringify(a) !== stableStringify(b);
32453
32459
  this.isDirty$.next(hasChanges);
32454
- if (!reason.startsWith('json-') && reason !== 'surface-validation' && this.jsonEditorIsValid) {
32460
+ if (!reason.startsWith('json-') && reason !== 'surface-validation' && reason !== 'cascade-validation' && this.jsonEditorIsValid) {
32455
32461
  this.jsonEditor?.updateJsonFromDocument(this.buildAuthoringDocument());
32456
32462
  }
32457
32463
  try {
@@ -32469,8 +32475,9 @@ class PraxisDynamicFormConfigEditor {
32469
32475
  // Para outras validações futuras, verificar se não há validação JSON em andamento
32470
32476
  }
32471
32477
  getSettingsValue() {
32472
- if (this.hasInvalidSurfaceDraft)
32478
+ if (this.hasInvalidSurfaceDraft || !this.isCascadeGraphValid()) {
32473
32479
  throw new Error(this.i18n?.t('editor.validation.invalidJson', undefined, 'Invalid JSON.', SURFACE_OPEN_I18N_NAMESPACE) ?? 'Invalid JSON.');
32480
+ }
32474
32481
  const document = this.buildAuthoringDocument();
32475
32482
  try {
32476
32483
  this.debugLog('[FormConfigEditor] getSettingsValue()', { sections: document.config.sections?.length || 0 });
@@ -32504,6 +32511,11 @@ class PraxisDynamicFormConfigEditor {
32504
32511
  ? newValue
32505
32512
  : parseLegacyOrDynamicFormDocument(newValue);
32506
32513
  this.editedConfig = this.stripLegacy(document.config);
32514
+ // JSON replaces the canonical rule list; removing it must not resurrect a
32515
+ // leftover visual projection from the same document.
32516
+ if (!document.config.formRules?.length) {
32517
+ delete this.editedConfig.formRulesState;
32518
+ }
32507
32519
  this.includeBackConfigBlock = isCanonicalDocument
32508
32520
  ? Object.prototype.hasOwnProperty.call(document.contextSnapshot || {}, 'backConfig')
32509
32521
  : this.includeBackConfigBlock || !!document.contextSnapshot?.backConfig;
@@ -32536,10 +32548,7 @@ class PraxisDynamicFormConfigEditor {
32536
32548
  catch { }
32537
32549
  this.ruleBuilderConfig = this.createRuleBuilderConfig(this.editedConfig.fieldMetadata || [], this.editedConfig.sections || [], this.editedConfig.actions);
32538
32550
  this.refreshVisualBlockNodeOptions();
32539
- this.ruleBuilderState =
32540
- document.config.formRulesState ||
32541
- formLayoutRulesToBuilderState(document.config.formRules || []);
32542
- this.currentRules = this.projectBuilderRules(this.ruleBuilderState) ?? this.editedConfig.formRules ?? [];
32551
+ this.hydrateRuleDraft();
32543
32552
  this.initializeCommandRuleEditor();
32544
32553
  this.refreshRuleDiagnostics();
32545
32554
  this.lastRulesSignature = this.computeRulesSignature(this.ruleBuilderState);
@@ -32567,18 +32576,29 @@ class PraxisDynamicFormConfigEditor {
32567
32576
  catch { }
32568
32577
  this.ruleBuilderConfig = this.createRuleBuilderConfig(newConfig.fieldMetadata || [], newConfig.sections || [], newConfig.actions);
32569
32578
  this.refreshVisualBlockNodeOptions();
32570
- this.ruleBuilderState =
32571
- newConfig.formRulesState ||
32572
- formLayoutRulesToBuilderState(newConfig.formRules || []);
32573
- this.currentRules = this.projectBuilderRules(this.ruleBuilderState) ?? this.editedConfig.formRules ?? [];
32579
+ this.hydrateRuleDraft();
32574
32580
  this.initializeCommandRuleEditor();
32575
32581
  this.refreshRuleDiagnostics();
32576
32582
  this.lastRulesSignature = this.computeRulesSignature(this.ruleBuilderState);
32577
32583
  this.updateDirtyState('layout-change');
32578
32584
  }
32585
+ onCascadeValidChange(valid) {
32586
+ if (this.cascadeDraftIsValid === valid)
32587
+ return;
32588
+ this.cascadeDraftIsValid = valid;
32589
+ this.updateDirtyState('cascade-validation');
32590
+ }
32591
+ isCascadeGraphValid() {
32592
+ if (!this.cascadeDraftIsValid)
32593
+ return false;
32594
+ return this.cascadeRulesService.validateFieldsCascadeGraph(this.editedConfig?.fieldMetadata || []).valid;
32595
+ }
32579
32596
  updateValidityState() {
32580
32597
  this.globalActionValidationIssues = this.collectGlobalActionValidationIssues(this.editedConfig);
32581
- this.isValid$.next(this.jsonEditorIsValid && !this.hasInvalidSurfaceDraft && !this.ruleConversionFailed &&
32598
+ this.isValid$.next(this.jsonEditorIsValid &&
32599
+ !this.hasInvalidSurfaceDraft &&
32600
+ this.isCascadeGraphValid() &&
32601
+ !this.ruleConversionFailed &&
32582
32602
  !this.ruleDiagnostics.some((rule) => rule.status.includes('invalid-condition')) &&
32583
32603
  this.globalActionValidationIssues.length === 0);
32584
32604
  }
@@ -32630,16 +32650,10 @@ class PraxisDynamicFormConfigEditor {
32630
32650
  this.hasProcessedInitialRuleState = true;
32631
32651
  }
32632
32652
  const signature = this.computeRulesSignature(state);
32633
- if (this.pendingRulePropertiesStateSignature) {
32634
- const expectedSignature = this.pendingRulePropertiesStateSignature;
32635
- if (signature !== expectedSignature) {
32636
- try {
32637
- this.debugLog('[FormConfigEditor] Ignoring stale rulesChanged echo after property panel apply');
32638
- }
32639
- catch { }
32640
- return;
32641
- }
32642
- this.pendingRulePropertiesStateSignature = null;
32653
+ const supersededSignature = this.supersededRuleStateSignature;
32654
+ this.supersededRuleStateSignature = null;
32655
+ if (signature === supersededSignature) {
32656
+ return;
32643
32657
  }
32644
32658
  if (signature === this.lastRulesSignature) {
32645
32659
  return;
@@ -32683,7 +32697,7 @@ class PraxisDynamicFormConfigEditor {
32683
32697
  const state = formLayoutRulesToBuilderState(rules);
32684
32698
  this.projectBuilderRules(state);
32685
32699
  const signature = this.computeRulesSignature(state);
32686
- this.pendingRulePropertiesStateSignature = signature;
32700
+ this.supersededRuleStateSignature = this.computeRulesSignature(this.ruleBuilderState);
32687
32701
  this.lastRulesSignature = signature;
32688
32702
  this.editedConfig = {
32689
32703
  ...this.editedConfig,
@@ -33144,7 +33158,7 @@ class PraxisDynamicFormConfigEditor {
33144
33158
  }
33145
33159
  getRuleStatusLabel(diagnostic) {
33146
33160
  if (diagnostic.status.includes('invalid-target'))
33147
- return this.tx('config.rules.status.invalidTarget', 'Alvo inválido');
33161
+ return this.tx('config.rules.status.invalidTarget', 'Alvo indisponível');
33148
33162
  if (diagnostic.status.includes('invalid-condition'))
33149
33163
  return this.tx('config.rules.status.invalidCondition', 'Condição inválida');
33150
33164
  if (diagnostic.status.includes('unsupported-property'))
@@ -33244,7 +33258,7 @@ class PraxisDynamicFormConfigEditor {
33244
33258
  .filter((target) => !target.exists)
33245
33259
  .map((target) => `${target.type}:${target.id}`);
33246
33260
  if (missingTargets.length) {
33247
- details.push(this.tx('config.rules.details.missingTargets', 'Alvos ausentes: {{targets}}', { targets: missingTargets.join(', ') }));
33261
+ details.push(this.tx('config.rules.details.missingTargets', 'Alvos indisponíveis nesta operação (ausentes ou ocultos por metadados/acesso): {{targets}}', { targets: missingTargets.join(', ') }));
33248
33262
  }
33249
33263
  if (diagnostic.conditionRefs.length) {
33250
33264
  details.push(this.tx('config.rules.details.usedFields', 'Campos usados: {{fields}}', { fields: diagnostic.conditionRefs.join(', ') }));
@@ -33790,13 +33804,32 @@ class PraxisDynamicFormConfigEditor {
33790
33804
  }
33791
33805
  return copy;
33792
33806
  }
33807
+ hydrateRuleDraft() {
33808
+ this.supersededRuleStateSignature = null;
33809
+ const rules = this.editedConfig.formRules;
33810
+ let state = this.editedConfig.formRulesState
33811
+ ?? formLayoutRulesToBuilderState(rules ?? []);
33812
+ let projected = this.projectBuilderRules(state);
33813
+ // A valid graph is a projection of the canonical document. Keep invalid drafts
33814
+ // for repair, but never let stale derived state overwrite a JSON rule edit.
33815
+ if (projected !== null && rules !== undefined && stableStringify(projected) !== stableStringify(rules)) {
33816
+ state = formLayoutRulesToBuilderState(rules);
33817
+ projected = this.projectBuilderRules(state);
33818
+ this.editedConfig = { ...this.editedConfig, formRulesState: state };
33819
+ }
33820
+ this.ruleBuilderState = state;
33821
+ this.currentRules = projected ?? rules ?? [];
33822
+ this.lastRulesSignature = this.computeRulesSignature(state);
33823
+ }
33793
33824
  computeRulesSignature(state) {
33794
33825
  if (!state)
33795
33826
  return null;
33796
33827
  return JSON.stringify({
33797
- nodes: state.nodes,
33828
+ nodes: Object.fromEntries(Object.entries(state.nodes).map(([id, node]) => {
33829
+ const { selected, ...document } = node;
33830
+ return [id, document];
33831
+ })),
33798
33832
  rootNodes: state.rootNodes,
33799
- currentJSON: state.currentJSON,
33800
33833
  validationErrors: state.validationErrors,
33801
33834
  mode: state.mode,
33802
33835
  });
@@ -34015,7 +34048,7 @@ class PraxisDynamicFormConfigEditor {
34015
34048
  return Object.entries(params).reduce((text, [key, value]) => text.split(`{{${key}}}`).join(String(value)), fallback);
34016
34049
  }
34017
34050
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDynamicFormConfigEditor, deps: [{ token: ASYNC_CONFIG_STORAGE }, { token: FormConfigService }, { token: i7.SettingsPanelService }, { token: i0.ChangeDetectorRef }, { token: GLOBAL_ACTION_CATALOG, optional: true }, { token: SETTINGS_PANEL_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Component });
34018
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisDynamicFormConfigEditor, isStandalone: true, selector: "praxis-dynamic-form-config-editor", providers: [FormConfigService, providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG)], viewQueries: [{ propertyName: "jsonEditor", first: true, predicate: JsonConfigEditorComponent, descendants: true }, { propertyName: "cascadeManager", first: true, predicate: CascadeManagerTabComponent, descendants: true }], ngImport: i0, template: "<div class=\"mobile-tab-selector\">\n <mat-form-field appearance=\"outline\" class=\"mobile-tab-selector__field\">\n <mat-label>{{ tx('config.tabs.mobileLabel', 'Se\u00E7\u00E3o do editor') }}</mat-label>\n <mat-select [(ngModel)]=\"selectedConfigTabIndex\" data-testid=\"dynamic-form-config-editor-mobile-tabs\">\n @for (tab of configTabOptions; track tab.key) {\n <mat-option [value]=\"tab.index\">{{ tab.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n\n<mat-tab-group [preserveContent]=\"true\" class=\"config-tabs\" data-testid=\"dynamic-form-config-editor-tabs\" [(selectedIndex)]=\"selectedConfigTabIndex\">\n <mat-tab [label]=\"configTabLabel('general')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-geral\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.general.title', 'Dados do formul\u00E1rio') }}</h3>\n <p class=\"text-caption\">{{ tx('config.general.subtitle', 'Defina o modo de dados e o contexto de edi\u00E7\u00E3o.') }}</p>\n </div>\n </div>\n <div class=\"form-modes\">\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.inputMode.label') }}</label>\n <mat-button-toggle-group [ngModel]=\"inputMode\" (ngModelChange)=\"inputMode = $event; onInputModeChange()\" [attr.aria-label]=\"tx('config.general.inputMode.label')\">\n <mat-button-toggle value=\"create\">{{ tx('config.general.inputMode.create') }}</mat-button-toggle>\n <mat-button-toggle value=\"edit\">{{ tx('config.general.inputMode.edit') }}</mat-button-toggle>\n <mat-button-toggle value=\"view\">{{ tx('config.general.inputMode.view') }}</mat-button-toggle>\n </mat-button-toggle-group>\n @if (inputMode === 'presentation' || inputMode === 'dossier') {\n <p class=\"control__hint\" data-testid=\"dynamic-form-native-mode-hint\" role=\"status\">\n {{ tx('config.general.inputMode.nativeMode', undefined, { mode: inputMode }) }}\n </p>\n }\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.layoutScope.label', 'Escopo de persist\u00EAncia do layout') }}</label>\n <mat-button-toggle-group\n data-testid=\"dynamic-form-layout-scope-toggle\"\n [ngModel]=\"inputLayoutScope\"\n (ngModelChange)=\"onLayoutScopeChange($event)\"\n [attr.aria-label]=\"tx('config.general.layoutScope.label', 'Escopo de persist\u00EAncia do layout')\">\n <mat-button-toggle value=\"shared\" data-testid=\"dynamic-form-layout-scope-shared\">\n {{ tx('config.general.layoutScope.shared', 'Todos os modos (Criar / Editar / Visualizar)') }}\n </mat-button-toggle>\n <mat-button-toggle value=\"mode-only\" data-testid=\"dynamic-form-layout-scope-mode-only\">\n {{ tx('config.general.layoutScope.modeOnly', 'Somente este modo ({{mode}})', { mode: tx('config.general.inputMode.' + inputMode, inputMode) }) }}\n </mat-button-toggle>\n </mat-button-toggle-group>\n <p class=\"control__hint\" data-testid=\"dynamic-form-layout-scope-hint\" role=\"status\">\n {{ inputLayoutScope === 'mode-only'\n ? tx('config.general.layoutScope.modeOnlyHint', 'Ao salvar, aplica este layout exclusivamente ao modo atual, sem alterar os demais modos.')\n : tx('config.general.layoutScope.sharedHint', 'Ao salvar, replica se\u00E7\u00F5es e grade nos demais modos que ainda compartilham layout.') }}\n </p>\n </div>\n @if (supportsPresentationSettings) {\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.displayMode.label') }}</label>\n <mat-button-toggle-group [ngModel]=\"displayMode\" (ngModelChange)=\"onDisplayModeChange($event)\" [attr.aria-label]=\"tx('config.general.displayMode.label')\">\n <mat-button-toggle value=\"automatic\">{{ tx('config.general.displayMode.automatic') }}</mat-button-toggle>\n <mat-button-toggle value=\"fields\">{{ tx('config.general.displayMode.fields') }}</mat-button-toggle>\n <mat-button-toggle value=\"presentation\">{{ tx('config.general.displayMode.presentation') }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <p class=\"display-result\" role=\"status\">{{ tx(displayModeHint) }}</p>\n @if (inputMode !== 'view' && inputMode !== 'presentation' && inputMode !== 'dossier' && inputPresentationMode === true) {\n <button mat-stroked-button type=\"button\" (click)=\"useViewMode()\">{{ tx('config.general.displayMode.useView') }}</button>\n }\n <button mat-button type=\"button\" (click)=\"openPresentationStyle()\">{{ tx('config.general.displayMode.openStyle') }}</button>\n }\n </div>\n </mat-card-content>\n </mat-card>\n\n @if (supportsPresentationSettings) {\n <mat-card class=\"section-card\" data-testid=\"form-empty-state-settings\">\n <mat-card-content>\n <h3>{{ tx('config.emptyState.heading') }}</h3>\n <p class=\"text-caption\">{{ tx('config.emptyState.help') }}</p>\n <mat-slide-toggle [ngModel]=\"!!inputEmptyState\" (ngModelChange)=\"setEmptyStateEnabled($event)\">{{ tx('config.emptyState.enabled') }}</mat-slide-toggle>\n @if (inputMode !== 'view' && inputMode !== 'presentation' && inputMode !== 'dossier') { <p class=\"text-caption\">{{ tx('config.emptyState.viewOnly') }}</p> }\n @if (inputEmptyState; as empty) {\n <div class=\"empty-state-fields empty-state-content\">\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.title') }}</mat-label><input matInput required [(ngModel)]=\"empty.title\" (ngModelChange)=\"onEmptyStateChange()\" /><mat-hint *ngIf=\"!empty.title?.trim()\">{{ tx('config.emptyState.titleRequired') }}</mat-hint></mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.emptyState.icon') }}</mat-label>\n @if (empty.icon) { <mat-icon matPrefix [praxisIcon]=\"empty.icon\" aria-hidden=\"true\"></mat-icon> }\n <input matInput [(ngModel)]=\"empty.icon\" (ngModelChange)=\"onEmptyStateChange()\" />\n <span matSuffix class=\"empty-state-icon-actions\">\n <button mat-icon-button type=\"button\" [attr.aria-label]=\"tx('config.emptyState.pickIcon')\" (click)=\"pickEmptyStateIcon()\"><mat-icon aria-hidden=\"true\">search</mat-icon></button>\n @if (empty.icon) { <button mat-icon-button type=\"button\" [attr.aria-label]=\"tx('config.emptyState.clearIcon')\" (click)=\"empty.icon = ''; onEmptyStateChange()\"><mat-icon aria-hidden=\"true\">close</mat-icon></button> }\n </span>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"empty-state-description\"><mat-label>{{ tx('config.emptyState.description') }}</mat-label><textarea matInput rows=\"2\" [(ngModel)]=\"empty.description\" (ngModelChange)=\"onEmptyStateChange()\"></textarea></mat-form-field>\n </div>\n <details class=\"empty-state-appearance\"><summary>{{ tx('config.emptyState.appearance') }}</summary><div class=\"empty-state-fields\">\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.tone') }}</mat-label><mat-select [(ngModel)]=\"empty.tone\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.tone; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.variant') }}</mat-label><mat-select [(ngModel)]=\"empty.variant\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.variant; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.alignment') }}</mat-label><mat-select [(ngModel)]=\"empty.alignment\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.alignment; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.density') }}</mat-label><mat-select [(ngModel)]=\"empty.density\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.density; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.iconContainer') }}</mat-label><mat-select [(ngModel)]=\"empty.iconContainer\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.iconContainer; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n </div></details>\n }\n </mat-card-content>\n </mat-card>\n }\n\n @if (hasResolvedRuntimeContract()) {\n <mat-card\n class=\"section-card\"\n data-testid=\"config-tab-runtime-contract\"\n >\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.general.runtimeContract.title', 'Contrato Runtime Resolvido') }}</h3>\n <p class=\"text-caption\">\n {{ tx('config.general.runtimeContract.subtitle', 'Visualiza\u00E7\u00E3o somente leitura do contrato backend resolvido pelo host atual.') }}\n </p>\n </div>\n </div>\n <div class=\"block-status block-status--readonly\">\n <strong>{{ tx('config.general.runtimeContract.runtimeLabel', 'Runtime') }}</strong>\n <span>\n {{ tx('config.general.runtimeContract.readonly', 'Esses valores v\u00EAm do host/runtime atual e n\u00E3o s\u00E3o persistidos em `bindings` nem em `contextSnapshot`.') }}\n </span>\n </div>\n <div class=\"runtime-contract-grid\">\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.schemaUrl', 'Schema URL') }}</span>\n <code class=\"runtime-contract-code\">{{ runtimeContract?.schemaUrl || '\u2014' }}</code>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.schemaSource', 'Origem do schema') }}</span>\n <strong>{{ describeRuntimeSource(runtimeContract?.schemaSource) }}</strong>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitMethod', 'Submit method') }}</span>\n <strong>{{ runtimeContract?.submitMethod || '\u2014' }}</strong>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitUrl', 'Submit URL') }}</span>\n <code class=\"runtime-contract-code\">{{ runtimeContract?.submitUrl || '\u2014' }}</code>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitSource', 'Origem do submit') }}</span>\n <strong>{{ describeRuntimeSource(runtimeContract?.submitSource) }}</strong>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n }\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('schema')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-schema\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.schema.title', 'Valida\u00E7\u00E3o de schema') }}</h3>\n <p class=\"text-caption\">{{ tx('config.schema.subtitle', 'Controle avisos quando o schema do servidor mudar.') }}</p>\n </div>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.schema.notify.label', 'Notificar quando desatualizado') }}</mat-label>\n <mat-select [(ngModel)]=\"schemaPrefs.notifyIfOutdated\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-notify')\">\n <mat-option value=\"both\">{{ tx('config.schema.notify.both', 'Banner + Snackbar') }}</mat-option>\n <mat-option value=\"inline\">{{ tx('config.schema.notify.inline', 'Somente Banner') }}</mat-option>\n <mat-option value=\"snackbar\">{{ tx('config.schema.notify.snackbar', 'Somente Snackbar') }}</mat-option>\n <mat-option value=\"none\">{{ tx('config.schema.notify.none', 'Nenhum') }}</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.schema.snooze.label', 'Intervalo de sil\u00EAncio (ms)') }}</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"schemaPrefs.snoozeMs\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-snooze')\" />\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-slide-toggle [(ngModel)]=\"schemaPrefs.autoOpenSettingsOnOutdated\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-auto-open')\">\n {{ tx('config.schema.autoOpenSettings', 'Abrir configura\u00E7\u00F5es automaticamente') }}\n </mat-slide-toggle>\n </div>\n @if (serverMeta) {\n <div class=\"form-row\">\n <div class=\"meta-card\">\n <div class=\"meta-row\">\n <span>{{ tx('config.schema.meta.serverHash', 'Server hash') }}</span>\n <strong>{{ serverMeta.serverHash || '\u2014' }}</strong>\n </div>\n <div class=\"meta-row\">\n <span>{{ tx('config.schema.meta.lastVerifiedAt', '\u00DAltima verifica\u00E7\u00E3o') }}</span>\n <strong>{{ serverMeta.lastVerifiedAt || '\u2014' }}</strong>\n </div>\n </div>\n </div>\n }\n <div class=\"block-status\" [class.block-status--implicit]=\"!isSchemaPrefsBlockPersisted()\">\n <strong>{{ tx('config.schema.prefs.label', 'Schema Prefs') }}</strong>\n @if (isSchemaPrefsBlockPersisted()) {\n <span>{{ tx('config.schema.prefs.persisted', '`contextSnapshot.schemaPrefs` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.schema.prefs.implicit', 'Bloco ausente no documento can\u00F4nico. Os controles exibem fallback visual e n\u00E3o ser\u00E3o salvos at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('layout')\">\n <div class=\"tab-content tab-content--full\" data-testid=\"config-tab-panel-layout\">\n <div class=\"section-body section-body--flex\">\n <praxis-layout-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"\n (select)=\"onLayoutSelect($event)\"></praxis-layout-editor>\n </div>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('hooks')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-hooks\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.hooks.title', 'Hooks de ciclo de vida') }}</h3>\n <p class=\"text-caption\">{{ tx('config.hooks.subtitle', 'Automatize a\u00E7\u00F5es nos eventos do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <praxis-hooks-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-hooks-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n @if (isPresentationMode) {\n <mat-tab [label]=\"configTabLabel('presentation')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-presentation\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.presentation.title', 'Modo Apresenta\u00E7\u00E3o') }}</h3>\n <p class=\"text-caption\">{{ tx('config.presentation.subtitle', 'Configura\u00E7\u00F5es de exibi\u00E7\u00E3o aplicadas somente ao modo apresenta\u00E7\u00E3o.') }}</p>\n </div>\n </div>\n <p class=\"display-result\" role=\"status\">{{ tx(displayModeHint) }}</p>\n <div class=\"presentation-layout\">\n <div class=\"presentation-controls\">\n <div class=\"block-status control-span\" [class.block-status--implicit]=\"!isPresentationBlockPersisted()\">\n <strong>{{ tx('config.presentation.block.label', 'Presentation') }}</strong>\n @if (isPresentationBlockPersisted()) {\n <span>{{ tx('config.presentation.block.persisted', '`contextSnapshot.presentation` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.presentation.block.implicit', 'Bloco ausente no documento can\u00F4nico. A pr\u00E9-visualiza\u00E7\u00E3o usa fallback local e n\u00E3o ser\u00E1 salva at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.labelPosition.label', 'Posi\u00E7\u00E3o do r\u00F3tulo') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.labelPosition\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-position')\" [attr.aria-label]=\"tx('config.presentation.labelPosition.ariaLabel', 'Posi\u00E7\u00E3o do r\u00F3tulo')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"above\">\n <mat-icon>view_stream</mat-icon>\n <span class=\"sr-only\">{{ tx('config.presentation.labelPosition.above', 'Acima') }}</span>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n <mat-icon>view_column</mat-icon>\n <span class=\"sr-only\">{{ tx('config.presentation.labelPosition.left', '\u00C0 esquerda') }}</span>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control control-span\">\n <label class=\"control__label\">{{ tx('config.presentation.density.label', 'Densidade') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.density\" (ngModelChange)=\"onPresentationPrefsChange('presentation-density')\" [attr.aria-label]=\"tx('config.presentation.density.ariaLabel', 'Densidade')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"comfortable\">{{ tx('config.presentation.density.comfortable', 'Confort\u00E1vel') }}</mat-button-toggle>\n <mat-button-toggle value=\"cozy\">{{ tx('config.presentation.density.cozy', 'Intermedi\u00E1ria') }}</mat-button-toggle>\n <mat-button-toggle value=\"compact\">{{ tx('config.presentation.density.compact', 'Compacta') }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.labelAlign.label', 'Alinhamento do r\u00F3tulo') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.labelAlign\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-align')\" [attr.aria-label]=\"tx('config.presentation.labelAlign.ariaLabel', 'Alinhamento do r\u00F3tulo')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"start\" [aria-label]=\"tx('config.presentation.align.start')\" [matTooltip]=\"tx('config.presentation.align.start')\"><mat-icon>format_align_left</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"center\" [aria-label]=\"tx('config.presentation.align.center')\" [matTooltip]=\"tx('config.presentation.align.center')\"><mat-icon>format_align_center</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"end\" [aria-label]=\"tx('config.presentation.align.end')\" [matTooltip]=\"tx('config.presentation.align.end')\"><mat-icon>format_align_right</mat-icon></mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.valueAlign.label', 'Alinhamento do valor') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.valueAlign\" (ngModelChange)=\"onPresentationPrefsChange('presentation-value-align')\" [attr.aria-label]=\"tx('config.presentation.valueAlign.ariaLabel', 'Alinhamento do valor')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"start\" [aria-label]=\"tx('config.presentation.align.start')\" [matTooltip]=\"tx('config.presentation.align.start')\"><mat-icon>format_align_left</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"center\" [aria-label]=\"tx('config.presentation.align.center')\" [matTooltip]=\"tx('config.presentation.align.center')\"><mat-icon>format_align_center</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"end\" [aria-label]=\"tx('config.presentation.align.end')\" [matTooltip]=\"tx('config.presentation.align.end')\"><mat-icon>format_align_right</mat-icon></mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.labelFontSize.label', 'Tamanho do r\u00F3tulo') }}</mat-label>\n <input matInput type=\"number\" min=\"10\" step=\"any\" [(ngModel)]=\"presentationPrefs.labelFontSize\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-font-size')\"\n [placeholder]=\"tx('config.presentation.labelFontSize.placeholder', 'ex.: 12')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.valueFontSize.label', 'Tamanho do valor') }}</mat-label>\n <input matInput type=\"number\" min=\"10\" step=\"any\" [(ngModel)]=\"presentationPrefs.valueFontSize\" (ngModelChange)=\"onPresentationPrefsChange('presentation-value-font-size')\"\n [placeholder]=\"tx('config.presentation.valueFontSize.placeholder', 'ex.: 16')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.labelWidth.label', 'Largura do r\u00F3tulo (label \u00E0 esquerda)') }}</mat-label>\n <input matInput type=\"number\" min=\"60\" [disabled]=\"presentationPrefs.labelPosition !== 'left'\" [(ngModel)]=\"presentationPrefs.labelWidth\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-width')\"\n [placeholder]=\"tx('config.presentation.labelWidth.placeholder', 'ex.: 140')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control control--inline\">\n <mat-slide-toggle [(ngModel)]=\"presentationPrefs.compact\" (ngModelChange)=\"onPresentationPrefsChange('presentation-compact')\">\n {{ tx('config.presentation.options.compactMode', 'Modo compacto') }}\n </mat-slide-toggle>\n <mat-checkbox [(ngModel)]=\"truncatePreview\">\n {{ tx('config.presentation.options.truncateValues', 'Truncar valores') }}\n </mat-checkbox>\n </div>\n </div>\n <div class=\"presentation-preview\">\n <h4>{{ tx('config.presentation.preview.title', 'Pr\u00E9-visualiza\u00E7\u00E3o') }}</h4>\n <p class=\"text-caption\">{{ tx('config.presentation.preview.sampleHint') }}</p>\n <div class=\"preview-card\">\n <div class=\"praxis-dynamic-form presentation-mode\" [ngClass]=\"{\n 'pres-compact': !!presentationPrefs.compact,\n 'pres-label-left': presentationPrefs.labelPosition === 'left',\n 'pres-label-above': presentationPrefs.labelPosition === 'above',\n 'pres-density-compact': presentationPrefs.density === 'compact',\n 'pres-density-cozy': presentationPrefs.density === 'cozy'\n }\" [style.--pfx-pres-label-size]=\"(presentationPrefs.labelFontSize || 12) + 'px'\"\n [style.--pfx-pres-value-size]=\"(presentationPrefs.valueFontSize || 16) + 'px'\"\n [style.--pfx-pres-label-width]=\"(presentationPrefs.labelWidth || 140) + 'px'\"\n [style.--pfx-pres-label-align]=\"presentationPrefs.labelAlign || 'start'\"\n [style.--pfx-pres-value-align]=\"presentationPrefs.valueAlign || 'start'\">\n @for (item of previewItems; track item) {\n <div class=\"preview-row\">\n <span class=\"praxis-presentation__label\">{{ item.label }}</span>\n <span class=\"praxis-presentation__value\" [attr.title]=\"truncatePreview ? item.value : null\"\n [style.maxWidth]=\"truncatePreview ? '280px' : null\"\n [style.overflow]=\"truncatePreview ? 'hidden' : null\"\n [style.textOverflow]=\"truncatePreview ? 'ellipsis' : null\"\n [style.whiteSpace]=\"truncatePreview ? 'nowrap' : 'normal'\">\n {{ item.value }}\n </span>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n }\n <mat-tab [label]=\"configTabLabel('behavior')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-comportamento\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.behavior.title', 'Comportamento') }}</h3>\n <p class=\"text-caption\">{{ tx('config.behavior.subtitle', 'Ajuste valida\u00E7\u00F5es e respostas do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <praxis-behavior-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-behavior-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('hints')\">\n <div class=\"tab-content tab-content--dense\" data-testid=\"config-tab-panel-hints\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.hints.title', 'Dicas dos modos') }}</h3>\n <p class=\"text-caption\">{{ tx('config.hints.subtitle', 'Personalize textos de apoio para modos de dados e estados de UI.') }}</p>\n </div>\n </div>\n <p class=\"text-caption\">{{ tx('config.hints.description', 'Personalize os textos usados como tooltip/hint para modos de dados e modos globais de UI.') }}</p>\n\n <div class=\"grid-2-cols grid-2-cols--compact\">\n <section>\n <h4>{{ tx('config.hints.dataModes.title', 'Modos de dados') }}</h4>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.create.label', 'Criar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.create\"\n (ngModelChange)=\"updateDirtyState('hints-data-create')\" [placeholder]=\"tx('config.hints.dataModes.create.placeholder', 'Ex.: Preencha os campos obrigat\u00F3rios.')\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.edit.label', 'Editar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.edit\"\n (ngModelChange)=\"updateDirtyState('hints-data-edit')\" [placeholder]=\"tx('config.hints.dataModes.edit.placeholder', 'Ex.: Revise os dados antes de salvar.')\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.view.label', 'Visualizar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.view\"\n (ngModelChange)=\"updateDirtyState('hints-data-view')\" [placeholder]=\"tx('config.hints.dataModes.view.placeholder', 'Ex.: Visualiza\u00E7\u00E3o somente leitura.')\" />\n </mat-form-field>\n </section>\n\n <section>\n <h4>{{ tx('config.hints.uiModes.title', 'Modos de UI') }}</h4>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.presentation.label', 'Apresenta\u00E7\u00E3o') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.presentation\"\n (ngModelChange)=\"updateDirtyState('hints-ui-presentation')\" [placeholder]=\"tx('config.hints.uiModes.presentation.placeholder', 'Ex.: Modo compacto para leitura r\u00E1pida.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.readonly.label', 'Leitura (readonly)') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.readonly\"\n (ngModelChange)=\"updateDirtyState('hints-ui-readonly')\" [placeholder]=\"tx('config.hints.uiModes.readonly.placeholder', 'Ex.: Campos bloqueados para edi\u00E7\u00E3o.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.disabled.label', 'Desabilitado') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.disabled\"\n (ngModelChange)=\"updateDirtyState('hints-ui-disabled')\" [placeholder]=\"tx('config.hints.uiModes.disabled.placeholder', 'Ex.: Fun\u00E7\u00E3o indispon\u00EDvel no momento.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.visible.label', 'Vis\u00EDvel') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.visible\"\n (ngModelChange)=\"updateDirtyState('hints-ui-visible')\" [placeholder]=\"tx('config.hints.uiModes.visible.placeholder', 'Ex.: Campo exibido conforme permiss\u00F5es.')\"></textarea>\n </mat-form-field>\n </section>\n </div>\n\n <section>\n <h4>{{ tx('config.helpPresentation.title', 'Apresenta\u00E7\u00E3o das ajudas dos campos') }}</h4>\n <p class=\"text-caption\">{{ tx('config.helpPresentation.description', 'Controle como hint/helpText dos campos aparece em formul\u00E1rios densos. Erros de valida\u00E7\u00E3o continuam inline.') }}</p>\n <div class=\"grid-3-cols\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.display.label', 'Exibi\u00E7\u00E3o') }}</mat-label>\n <mat-select [ngModel]=\"helpPresentationDraft.display\" (ngModelChange)=\"onHelpPresentationDisplayChange($event)\">\n <mat-option value=\"inline\">{{ tx('config.helpPresentation.display.inline', 'Inline') }}</mat-option>\n <mat-option value=\"popover\">{{ tx('config.helpPresentation.display.popover', '\u00CDcone de ajuda') }}</mat-option>\n <mat-option value=\"auto\">{{ tx('config.helpPresentation.display.auto', 'Autom\u00E1tica') }}</mat-option>\n <mat-option value=\"hidden\">{{ tx('config.helpPresentation.display.hidden', 'Oculta') }}</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.inlineMaxLength.label', 'Limite inline') }}</mat-label>\n <input matInput type=\"number\" min=\"0\" [ngModel]=\"helpPresentationDraft.inlineMaxLength\"\n (ngModelChange)=\"onHelpPresentationInlineMaxLengthChange($event)\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.preferPopoverForControls.label', 'Preferir \u00EDcone em') }}</mat-label>\n <input matInput [ngModel]=\"getHelpPreferPopoverControlsText()\"\n (ngModelChange)=\"onHelpPreferPopoverControlsChange($event)\"\n [placeholder]=\"tx('config.helpPresentation.preferPopoverForControls.placeholder', 'toggle, checkbox, select')\" />\n </mat-form-field>\n </div>\n </section>\n\n <div class=\"actions-row\">\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"restoreHintsDefaults()\">\n <mat-icon>restore</mat-icon>\n {{ tx('config.hints.actions.restoreDefaults', 'Restaurar padr\u00F5es') }}\n </button>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('actions')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-acoes\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.actions.title', 'A\u00E7\u00F5es do formul\u00E1rio') }}</h3>\n <p class=\"text-caption\">{{ tx('config.actions.subtitle', 'Configure bot\u00F5es padr\u00E3o e a\u00E7\u00F5es customizadas.') }}</p>\n </div>\n </div>\n <praxis-actions-editor #actionsDraft [config]=\"editedConfig\" (validationChange)=\"onSurfaceDraftValidity(actionsDraft, $event)\" (configChange)=\"onConfigChange($event)\"></praxis-actions-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('rules')\">\n <div class=\"tab-content visual-builder-content\" data-testid=\"config-tab-panel-regras\">\n <div class=\"builder-header\">\n <div>\n <h3>{{ tx('config.rules.title', 'Regras visuais') }}</h3>\n <p class=\"text-caption\">{{ tx('config.rules.subtitle', 'Defina visibilidade, estilos e rea\u00E7\u00F5es baseadas em condi\u00E7\u00F5es.') }}</p>\n </div>\n </div>\n @if (ruleConversionFailed) {\n <p role=\"alert\" data-testid=\"rules-conversion-error\">\n {{ tx('config.rules.conversionError', 'N\u00E3o foi poss\u00EDvel converter a condi\u00E7\u00E3o visual. Revise a regra; aplicar e salvar est\u00E3o bloqueados.') }}\n </p>\n }\n @if (ruleDiagnostics.length) {\n <div class=\"rules-diagnostics\" data-testid=\"rules-diagnostics-panel\">\n <div class=\"rules-diagnostics__summary\">\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--total\">\n {{ tx('config.rules.summary.total', '{{count}} regras', { count: ruleDiagnosticsSummary.total }) }}\n </span>\n @if (ruleDiagnosticsSummary.invalid) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--error\">\n {{ tx('config.rules.summary.invalid', '{{count}} inv\u00E1lidas', { count: ruleDiagnosticsSummary.invalid }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.unsupported) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.unsupported', '{{count}} com propriedades rejeitadas', { count: ruleDiagnosticsSummary.unsupported }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.runtimeOnly) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.runtimeOnly', '{{count}} runtime only', { count: ruleDiagnosticsSummary.runtimeOnly }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.pendingReview) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.pendingReview', '{{count}} pendentes de revis\u00E3o', { count: ruleDiagnosticsSummary.pendingReview }) }}\n </span>\n }\n </div>\n <div class=\"rules-diagnostics__list\" [attr.aria-label]=\"tx('config.rules.diagnostics.ariaLabel', 'Diagn\u00F3stico das regras')\">\n @for (diagnostic of ruleDiagnostics; track diagnostic) {\n <article class=\"rules-diagnostics__item\"\n [class.rules-diagnostics__item--error]=\"getRuleStatusTone(diagnostic) === 'error'\"\n [class.rules-diagnostics__item--warn]=\"getRuleStatusTone(diagnostic) === 'warn'\">\n <div>\n <strong>{{ diagnostic.ruleName || diagnostic.ruleId }}</strong>\n <span>\n {{ tx('config.rules.diagnostics.targetConditionSummary', '{{targets}} alvo(s) \u00B7 {{conditions}} campo(s) na condi\u00E7\u00E3o', { targets: diagnostic.targetRefs.length, conditions: diagnostic.conditionRefs.length }) }}\n </span>\n @if (getRuleDiagnosticDetails(diagnostic).length) {\n <ul class=\"rules-diagnostics__details\">\n @for (detail of getRuleDiagnosticDetails(diagnostic); track detail) {\n <li>{{ detail }}</li>\n }\n </ul>\n }\n </div>\n <div class=\"rules-diagnostics__actions\">\n <span class=\"rules-diagnostics__status\">{{ getRuleStatusLabel(diagnostic) }}</span>\n @if (canApplyRulePropertyFix(diagnostic)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [matTooltip]=\"tx('config.rules.actions.fix.tooltip', 'Aplicar whitelist e saneamento de propriedades nesta regra')\"\n (click)=\"applyRulePropertyFix(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">auto_fix_high</mat-icon>\n {{ tx('config.rules.actions.fix', 'Corrigir') }}\n </button>\n }\n @if (diagnostic.status.includes('llm-generated-pending-review')) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [disabled]=\"!canAcceptPendingLlmRule(diagnostic)\"\n [matTooltip]=\"canAcceptPendingLlmRule(diagnostic) ? tx('config.rules.actions.accept.tooltip.ready', 'Aceitar sugest\u00E3o e atualizar estado visual') : tx('config.rules.actions.accept.tooltip.blocked', 'Corrija alvo, condi\u00E7\u00E3o e propriedades antes de aceitar')\"\n (click)=\"acceptPendingLlmRule(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n {{ tx('config.rules.actions.accept', 'Aceitar') }}\n </button>\n }\n @if (canOpenRuleJsonReview(diagnostic)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [matTooltip]=\"tx('config.rules.actions.reviewJson.tooltip', 'Abrir a aba JSON para revisar esta regra sem convers\u00E3o visual')\"\n (click)=\"openRuleJsonReview(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">data_object</mat-icon>\n {{ tx('config.rules.actions.reviewJson', 'Ver JSON') }}\n </button>\n }\n </div>\n </article>\n }\n </div>\n </div>\n } @else {\n <div class=\"rules-diagnostics rules-diagnostics--empty\" data-testid=\"rules-diagnostics-empty\">\n {{ tx('config.rules.empty', 'Nenhuma regra definida ainda. Crie uma regra para ver alvos, condi\u00E7\u00E3o, propriedades e compatibilidade do builder.') }}\n </div>\n }\n <praxis-visual-builder [config]=\"ruleBuilderConfig\" [initialRules]=\"ruleBuilderState\"\n (rulesChanged)=\"onRulesChanged($event)\"></praxis-visual-builder>\n <praxis-rule-properties-panel\n [rules]=\"currentRules\"\n [visualBlockNodes]=\"visualBlockNodeOptions\"\n (rulesChange)=\"onRulePropertiesChanged($event)\"\n ></praxis-rule-properties-panel>\n <mat-card class=\"command-rules-card\" data-testid=\"form-command-rules-editor\">\n <mat-card-title>{{ tx('config.commandRules.title', 'Comandos condicionais') }}</mat-card-title>\n <mat-card-subtitle>{{ tx('config.commandRules.subtitle', 'Execute a\u00E7\u00F5es globais quando uma condi\u00E7\u00E3o do formul\u00E1rio for satisfeita.') }}</mat-card-subtitle>\n <mat-card-content>\n <div class=\"command-rules-grid\">\n <div class=\"command-rules-toolbar\">\n <mat-form-field appearance=\"outline\" class=\"command-rules-select\">\n <mat-label>{{ tx('config.commandRules.command.label', 'Comando') }}</mat-label>\n <mat-select [disabled]=\"hasInvalidSurfaceDraft\" [(ngModel)]=\"selectedCommandRuleId\" (selectionChange)=\"onCommandRuleSelectionChange()\">\n @for (rule of commandRules; track rule) {\n <mat-option [value]=\"rule.id\">\n {{ rule.id }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <button mat-stroked-button type=\"button\" [disabled]=\"hasInvalidSurfaceDraft\" (click)=\"addCommandRule()\">\n <mat-icon aria-hidden=\"true\">add</mat-icon>\n {{ tx('config.commandRules.actions.add', 'Adicionar') }}\n </button>\n <button mat-stroked-button color=\"warn\" type=\"button\" (click)=\"deleteCommandRule()\" [disabled]=\"hasInvalidSurfaceDraft || !selectedCommandRuleId\">\n <mat-icon aria-hidden=\"true\">delete</mat-icon>\n {{ tx('config.commandRules.actions.remove', 'Remover') }}\n </button>\n </div>\n\n @if (selectedCommandRuleId) {\n <div class=\"command-rule-condition-builder command-rules-full\">\n <praxis-visual-builder\n mode=\"condition\"\n [config]=\"ruleBuilderConfig\"\n [initialCondition]=\"commandRuleCondition\"\n (conditionChanged)=\"onCommandConditionChanged($event)\"\n ></praxis-visual-builder>\n </div>\n }\n\n <mat-form-field appearance=\"outline\" class=\"command-rules-full\">\n <mat-label>{{ tx('config.commandRules.conditionJson.label', 'Condi\u00E7\u00E3o JSON Logic') }}</mat-label>\n <textarea\n matInput\n rows=\"5\"\n [(ngModel)]=\"commandRuleConditionJson\"\n [attr.aria-label]=\"tx('config.commandRules.conditionJson.ariaLabel', 'Condi\u00E7\u00E3o JSON Logic do comando condicional')\"\n ></textarea>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.commandRules.globalAction.label', 'A\u00E7\u00E3o global') }}</mat-label>\n <mat-select [disabled]=\"hasInvalidSurfaceDraft\" [(ngModel)]=\"commandRuleActionId\" (selectionChange)=\"onCommandActionChange()\">\n @for (action of globalActionCatalog; track action) {\n <mat-option [value]=\"action.id\">\n {{ action.label || action.id }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.commandRules.distinctBy.label', 'distinctBy') }}</mat-label>\n <input matInput [(ngModel)]=\"commandRuleDistinctBy\" [placeholder]=\"tx('config.commandRules.distinctBy.placeholder', 'ex.: idade')\" />\n </mat-form-field>\n\n @if (commandRuleActionSchema; as actionSchema) {\n <div\n class=\"command-rules-payload-fields command-rules-full\"\n >\n <div class=\"command-rules-section-title\">{{ tx('config.commandRules.structuredPayload.title', 'Payload estruturado') }}</div>\n @if (actionSchema.editorMode !== 'surface-open') {\n @for (field of actionSchema.fields; track field) {\n @if (shouldShowCommandActionField(field)) {\n @if (field.type === 'toggle') {\n <mat-slide-toggle\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n {{ field.label }}\n </mat-slide-toggle>\n } @else {\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ field.label }}</mat-label>\n @if (field.type === 'textarea' || field.type === 'json') {\n <textarea\n matInput\n [rows]=\"field.rows || (field.type === 'json' ? 3 : 2)\"\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [placeholder]=\"field.placeholder || (field.type === 'json' ? '{ }' : '')\"\n [required]=\"isCommandActionFieldRequired(field)\"\n ></textarea>\n } @else {\n @if (field.type === 'select') {\n <mat-select\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [required]=\"isCommandActionFieldRequired(field)\"\n >\n @for (option of field.options || []; track option) {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n </mat-select>\n } @else {\n <input\n matInput\n [type]=\"field.type === 'number' ? 'number' : 'text'\"\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [placeholder]=\"field.placeholder || ''\"\n [required]=\"isCommandActionFieldRequired(field)\"\n />\n }\n }\n @if (field.hint) {\n <mat-hint>{{ field.hint }}</mat-hint>\n }\n @if (hasCommandActionFieldError(field.key)) {\n <mat-error>\n {{ getCommandActionFieldError(field.key) }}\n </mat-error>\n }\n @if (!hasCommandActionFieldError(field.key) && isCommandActionFieldMissing(field)) {\n <mat-error>\n {{ tx('config.commandRules.validation.requiredField', 'Campo obrigat\u00F3rio.') }}\n </mat-error>\n }\n </mat-form-field>\n }\n }\n }\n } @else {\n <praxis-surface-open-action-editor #commandSurfaceDraft\n class=\"command-rules-surface-editor\"\n data-testid=\"form-command-rule-surface-open-editor\"\n [value]=\"commandRuleSurfaceOpenPayload\"\n hostKind=\"dynamic-form\"\n (valueChange)=\"onCommandSurfaceOpenPayloadChange($event)\"\n (validationChange)=\"onSurfaceDraftValidity(commandSurfaceDraft, $event)\"\n ></praxis-surface-open-action-editor>\n }\n </div>\n }\n\n <mat-form-field appearance=\"outline\" class=\"command-rules-full\">\n <mat-label>{{ tx('config.commandRules.advancedPayload.label', 'Payload JSON avan\u00E7ado') }}</mat-label>\n <textarea\n matInput\n rows=\"4\"\n [(ngModel)]=\"commandRulePayloadJson\"\n [attr.aria-label]=\"tx('config.commandRules.advancedPayload.ariaLabel', 'Payload JSON da a\u00E7\u00E3o global')\"\n ></textarea>\n </mat-form-field>\n\n <div class=\"command-rules-options\">\n <mat-slide-toggle [(ngModel)]=\"commandRuleDistinct\">{{ tx('config.commandRules.options.distinct', 'Evitar repeti\u00E7\u00E3o enquanto a condi\u00E7\u00E3o permanecer verdadeira') }}</mat-slide-toggle>\n <mat-slide-toggle [(ngModel)]=\"commandRuleRunOnInitialEvaluation\">{{ tx('config.commandRules.options.runOnInitialEvaluation', 'Executar tamb\u00E9m na avalia\u00E7\u00E3o inicial') }}</mat-slide-toggle>\n </div>\n\n @if (commandRuleAuthoringError) {\n <div class=\"preview-error command-rules-full\">\n <mat-icon aria-hidden=\"true\">warning</mat-icon>\n <span>{{ commandRuleAuthoringError }}</span>\n </div>\n }\n\n <div\n class=\"command-rule-preview command-rules-full\"\n [class.command-rule-preview--invalid]=\"commandRulePreview.state === 'invalid'\"\n data-testid=\"command-rule-preview\"\n >\n <div class=\"command-rules-section-title\">{{ tx('config.commandRules.preview.title', 'Preview do comando') }}</div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.mode', 'Modo') }}</span>\n <strong>{{ commandRulePreview.executionMode }}</strong>\n </div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.action', 'A\u00E7\u00E3o') }}</span>\n <strong>{{ commandRulePreview.actionId || '\u2014' }}</strong>\n </div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.policy', 'Policy') }}</span>\n <code>{{ commandRulePreview.policy | json }}</code>\n </div>\n @if (commandRulePreview.diagnostics.length) {\n <div class=\"command-rule-preview__diagnostics\">\n <mat-icon aria-hidden=\"true\">{{ commandRulePreview.state === 'invalid' ? 'warning' : 'visibility' }}</mat-icon>\n <span>{{ commandRulePreview.diagnostics[0] }}</span>\n </div>\n }\n </div>\n\n <div class=\"command-rules-actions\">\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"applyCommandRule()\">\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n {{ tx('config.commandRules.actions.apply', 'Aplicar comando') }}\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('cascades')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-cascatas\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.cascades.title', 'Depend\u00EAncias entre campos') }}</h3>\n <p class=\"text-caption\">{{ tx('config.cascades.subtitle', 'Configure cascatas e carregamento entre campos.') }}</p>\n </div>\n </div>\n <praxis-cascade-manager-tab [fields]=\"editedConfig.fieldMetadata || []\"\n (apply)=\"onCascadeApply($event)\"></praxis-cascade-manager-tab>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('messages')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-mensagens\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.messages.title', 'Mensagens e feedback') }}</h3>\n <p class=\"text-caption\">{{ tx('config.messages.subtitle', 'Padronize textos de sucesso, erro e confirma\u00E7\u00F5es.') }}</p>\n </div>\n </div>\n <praxis-messages-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-messages-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('navigation')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-navegacao\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.navigation.title', 'Navega\u00E7\u00E3o de retorno') }}</h3>\n <p class=\"text-caption\">{{ tx('config.navigation.subtitle', 'Defina o comportamento do bot\u00E3o Voltar em fluxos CRUD.') }}</p>\n </div>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.navigation.returnTo.label', 'Rota de retorno') }}</mat-label>\n <input matInput id=\"returnTo\" [(ngModel)]=\"backConfig!.returnTo\" (ngModelChange)=\"onBackConfigChange()\" [placeholder]=\"tx('config.navigation.returnTo.placeholder', '/funcionarios')\" />\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-slide-toggle [(ngModel)]=\"backConfig!.confirmOnDirty\" (ngModelChange)=\"onBackConfigChange()\">\n {{ tx('config.navigation.confirmOnDirty.label', 'Confirmar ao sair com altera\u00E7\u00F5es') }}\n </mat-slide-toggle>\n </div>\n <div class=\"block-status\" [class.block-status--implicit]=\"!isBackConfigBlockPersisted()\">\n <strong>{{ tx('config.navigation.backConfig.label', 'Back Config') }}</strong>\n @if (isBackConfigBlockPersisted()) {\n <span>{{ tx('config.navigation.backConfig.persisted', '`contextSnapshot.backConfig` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.navigation.backConfig.implicit', 'Bloco ausente no documento can\u00F4nico. Os valores exibidos s\u00E3o fallback visual e n\u00E3o ser\u00E3o salvos at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n </div>\n <div class=\"section-help\">\n <span class=\"section-help__label\">{{ tx('config.navigation.note.label', 'Observa\u00E7\u00E3o:') }}</span>\n <button\n praxisIconButton=\"help_outline\"\n size=\"dense\"\n class=\"help-icon-button\"\n type=\"button\"\n [matTooltip]=\"tx('config.navigation.note.tooltip', 'Afeta o fluxo de navega\u00E7\u00E3o do CRUD e pode ser sobreposto por metadados do recurso.')\"\n matTooltipPosition=\"above\"\n >\n </button>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('json')\">\n <div class=\"tab-content json-tab-content\" data-testid=\"config-tab-panel-json\">\n <mat-card class=\"section-card section-card--json\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.json.title', 'Configura\u00E7\u00E3o JSON') }}</h3>\n <p class=\"text-caption\">{{ tx('config.json.subtitle', 'Edi\u00E7\u00E3o avan\u00E7ada do documento can\u00F4nico de autoria do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <form-json-config-editor [document]=\"jsonDocument\" (documentChange)=\"onJsonConfigChange($event)\"\n (validationChange)=\"onJsonValidationChange($event)\" (editorEvent)=\"onJsonEditorEvent($event)\">\n </form-json-config-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n</mat-tab-group>\n", styles: [":host{container:praxis-authoring-editor/inline-size;display:flex;flex-direction:column;height:100%;min-width:0}.mobile-tab-selector{display:none;flex:0 0 auto;padding:8px 16px 0;background:var(--md-sys-color-surface)}.mobile-tab-selector__field{width:100%}.config-tabs{flex:1 1 auto;min-height:0;min-width:0}::ng-deep .mat-mdc-tab-group.config-tabs{display:flex;flex-direction:column}::ng-deep .mat-mdc-tab-group.config-tabs .mat-mdc-tab-body-wrapper{flex:1;min-height:0;min-width:0}::ng-deep .mat-mdc-tab-group.config-tabs .mat-mdc-tab-body-content{height:100%;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;padding:0!important}.tab-content{padding:20px 24px 28px;flex:1;min-width:0;box-sizing:border-box;display:flex;flex-direction:column;gap:24px}.json-tab-content{min-width:0;padding:12px 16px 16px}.section-card.section-card--json{display:flex;flex:1;min-height:calc(100vh - 180px);border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-low)}.section-card.section-card--json>mat-card-content,.section-card.section-card--json>.mat-mdc-card-content{display:flex;flex:1;min-width:0;min-height:0;flex-direction:column;padding:16px!important}.section-card--json form-json-config-editor{display:block;flex:1;min-width:0;min-height:0}.form-row{display:block;margin-bottom:12px}.form-grid{display:grid;gap:12px}.section-help{display:inline-flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.section-help__label{font-weight:500}.grid-2-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px}.grid-2-cols--compact{gap:12px}.w-100{width:100%}.visual-builder-content{padding:0!important;height:100%;min-width:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;gap:16px}.visual-builder-content>praxis-visual-builder{flex:0 0 auto;min-width:0;min-height:clamp(360px,48vh,560px)}.visual-builder-content>praxis-rule-properties-panel{flex:0 0 auto;display:block;min-width:0;padding:0 16px 24px;box-sizing:border-box}.rules-diagnostics{flex:0 0 auto;display:grid;gap:10px;padding:12px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}.rules-diagnostics--empty{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.rules-diagnostics__summary,.rules-diagnostics__list{display:flex;flex-wrap:wrap;gap:8px}.rules-diagnostics__pill{display:inline-flex;align-items:center;min-height:24px;padding:3px 9px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:12px;font-weight:600}.rules-diagnostics__pill--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 72%,transparent);color:var(--md-sys-color-on-tertiary-container)}.rules-diagnostics__pill--error{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.rules-diagnostics__item{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;min-width:min(100%,280px);padding:8px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.rules-diagnostics__item>div{display:grid;gap:2px;min-width:0}.rules-diagnostics__item strong{color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rules-diagnostics__item span{color:var(--md-sys-color-on-surface-variant);font-size:11px}.rules-diagnostics__actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}.rules-diagnostics__details{display:grid;gap:2px;margin:4px 0 0;padding-left:16px;color:var(--md-sys-color-on-surface-variant);font-size:11px;line-height:1.35}.rules-diagnostics__details li{overflow-wrap:anywhere}.rules-diagnostics__item--warn{border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 52%,var(--md-sys-color-outline-variant))}.rules-diagnostics__item--error{border-color:var(--md-sys-color-error)}.rules-diagnostics__status{font-weight:600;margin-top:1px}.rules-diagnostics__action{min-width:0;height:28px;padding:0 10px;border-radius:999px;font-size:12px;line-height:1}.rules-diagnostics__action mat-icon{width:16px;height:16px;margin:0 4px 0 0;font-size:16px}.json-field{width:100%}.presentation-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:20px;align-items:start}.presentation-controls{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:14px 18px}.control{display:flex;flex-direction:column}.control-span{grid-column:1/-1}.block-status{grid-column:1/-1;display:flex;gap:8px;align-items:flex-start;padding:10px 12px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 35%,transparent);color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.45}.block-status strong{min-width:112px;font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.block-status--implicit{background:color-mix(in srgb,var(--md-sys-color-surface-variant) 42%,transparent);border:1px dashed var(--md-sys-color-outline)}.block-status--readonly{margin-bottom:12px}.block-status code{font-family:var(--md-ref-typeface-mono, \"Courier New\", monospace);font-size:11px}.control__label{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-bottom:6px}.toggle-group{max-width:100%;flex-wrap:wrap}.control--inline{grid-column:1/-1;display:flex;gap:16px;align-items:center}.presentation-preview{min-width:0;order:-1}.preview-card{border:1px solid var(--md-sys-color-outline);border-radius:12px;padding:14px;background:var(--md-sys-color-surface-container)}.preview-row{display:flex;gap:8px;padding:6px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.preview-row:last-child{border-bottom:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.presentation-preview .praxis-presentation__label{color:var(--md-sys-color-on-surface-variant);font-size:var(--pfx-pres-label-size, 12px)}.presentation-preview .praxis-presentation__value{min-width:0;overflow-wrap:anywhere;font-size:var(--pfx-pres-value-size, 16px);color:var(--md-sys-color-on-surface)}.presentation-preview .presentation-mode.pres-density-cozy .preview-row{padding:6px 0}.presentation-preview .presentation-mode.pres-density-compact .preview-row,.presentation-preview .presentation-mode.pres-compact .preview-row{padding:2px 0}.presentation-preview .presentation-mode.pres-label-left .preview-row{display:grid;grid-template-columns:var(--pfx-pres-label-width, 140px) 1fr;align-items:baseline;column-gap:10px}.presentation-preview .presentation-mode.pres-label-left .praxis-presentation__label{margin:0;text-align:var(--pfx-pres-label-align, start)}.presentation-preview .presentation-mode .praxis-presentation__value{text-align:var(--pfx-pres-value-align, start)}.presentation-preview h4{margin:0 0 8px;color:var(--md-sys-color-on-surface);font-size:1rem}.section-card:not(.section-card--json),.section-card:not(.section-card--json).mat-mdc-card,.section-card:not(.section-card--json).mat-mdc-card-outlined{border:none!important;border-width:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;margin:0!important;padding:0!important;--mdc-outlined-card-outline-width: 0px;--mdc-outlined-card-outline-color: transparent;--mdc-elevated-card-container-color: transparent;--mdc-outlined-card-container-color: transparent}.section-card:not(.section-card--json)>mat-card-content,.section-card:not(.section-card--json)>.mat-mdc-card-content{padding:0!important}.section-card:not(.section-card--json)+.section-card:not(.section-card--json),.section-card:not(.section-card--json).mat-mdc-card+.section-card:not(.section-card--json).mat-mdc-card{padding-top:24px!important;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 65%,transparent)!important}.section-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:16px}.tab-content--dense{padding:16px 20px 24px;gap:20px}.tab-content--dense .section-header{margin-bottom:10px}.tab-content--dense .form-row{margin-bottom:8px}.section-header h3{margin:0;font-size:1rem;font-weight:600;letter-spacing:-.01em;color:var(--md-sys-color-on-surface)}.text-caption{margin:4px 0 0;font-size:.85rem;line-height:1.45;color:var(--md-sys-color-on-surface-variant)}.section-header--compact{margin-bottom:10px}.section-body{display:block}.section-body--flex{flex:1;min-height:0;display:flex;flex-direction:column}.builder-header{padding:12px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.builder-header h3{margin:0;font-size:1rem;color:var(--md-sys-color-on-surface)}.hint{margin:8px 0 0;padding:10px 12px;border-radius:8px;border:1px dashed color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 75%,transparent);color:var(--md-sys-color-on-surface-variant)}.meta-card{display:grid;gap:8px;padding:12px 14px;border-radius:8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);color:var(--md-sys-color-on-surface)}.meta-row{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.meta-row strong{color:var(--md-sys-color-on-surface);font-weight:600}.runtime-contract-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px 14px}.runtime-contract-field{display:grid;gap:4px;padding:10px 12px;border-radius:8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 65%,transparent)}.runtime-contract-label{font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--md-sys-color-on-surface-variant)}.runtime-contract-code{display:block;font-family:var(--md-ref-typeface-mono, \"Courier New\", monospace);font-size:12px;line-height:1.45;color:var(--md-sys-color-on-surface);word-break:break-word;white-space:normal}.command-rules-card,.command-rules-card.mat-mdc-card,.command-rules-card.mat-mdc-card-outlined{margin:0!important;padding:20px 16px 24px!important;min-width:0;border:none!important;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 65%,transparent)!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;--mdc-outlined-card-outline-width: 0px;--mdc-outlined-card-outline-color: transparent;--mdc-elevated-card-container-color: transparent;--mdc-outlined-card-container-color: transparent}.command-rules-card>mat-card-content,.command-rules-card>.mat-mdc-card-content{padding:12px 0 0!important}.command-rules-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr));gap:12px;align-items:start;min-width:0}.command-rules-toolbar,.command-rules-options,.command-rules-actions{grid-column:1/-1;display:flex;align-items:center;gap:12px;flex-wrap:wrap}.command-rules-select{min-width:min(320px,100%)}.command-rules-full{grid-column:1/-1}.command-rule-condition-builder{min-height:420px;overflow:hidden;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.command-rules-payload-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px;min-width:0;padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.command-rules-section-title{grid-column:1/-1;font-size:12px;font-weight:600;color:var(--md-sys-color-on-surface-variant);text-transform:uppercase}.command-rules-surface-editor{grid-column:1/-1}.command-rule-preview{display:grid;gap:8px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}.command-rule-preview--invalid{border-color:var(--md-sys-color-error)}.command-rule-preview__row{display:grid;grid-template-columns:minmax(96px,.35fr) minmax(0,1fr);gap:8px;align-items:start;min-width:0}.command-rule-preview__row span{color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600}.command-rule-preview__row strong,.command-rule-preview__row code{min-width:0;overflow-wrap:anywhere}.command-rule-preview__diagnostics{display:flex;gap:8px;align-items:flex-start;color:var(--md-sys-color-on-surface-variant)}@container praxis-authoring-editor (max-width: 768px){.mobile-tab-selector{display:block}::ng-deep .mat-mdc-tab-group.config-tabs>.mat-mdc-tab-header{display:none}.tab-content{padding:12px}.json-tab-content{padding:8px}.section-card--json{min-height:auto}}.form-modes{display:flex;flex-direction:column;align-items:flex-start;gap:16px}.form-modes mat-button-toggle-group{max-width:100%;flex-wrap:wrap}.display-result{margin:0;padding-block:12px;color:var(--md-sys-color-on-surface);font:var(--md-sys-typescale-body-medium)}.presentation-preview .presentation-mode.pres-label-above .preview-row{flex-direction:column;gap:4px}.presentation-controls,.control{min-width:0}.control__hint{margin:6px 0 0;color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-body-small, 400 12px/1.45 sans-serif)}.block-status{flex-wrap:wrap}:host{container-type:inline-size}@container (min-width: 900px){.presentation-layout{grid-template-columns:minmax(0,1fr) minmax(280px,.8fr)}.presentation-preview{order:1;position:sticky;top:16px}}.empty-state-fields{display:grid;align-items:start;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:var(--p-space-3, 12px);margin-block-start:var(--p-space-4, 16px)}.empty-state-appearance summary{cursor:pointer;padding-block:var(--p-space-3, 12px);color:var(--md-sys-color-on-surface)}.empty-state-content{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}.empty-state-description{grid-column:1/-1}.empty-state-content mat-form-field{min-width:0}.empty-state-icon-actions{display:inline-flex;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.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$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i6$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i6$2.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"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i7$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i7$1.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i7$1.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i7$1.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$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: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.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: MatCheckboxModule }, { kind: "component", type: i12.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i5$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i7$2.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i7$2.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.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: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "component", type: JsonConfigEditorComponent, selector: "form-json-config-editor", inputs: ["config", "document"], outputs: ["configChange", "documentChange", "validationChange", "editorEvent"] }, { kind: "component", type: LayoutEditorComponent, selector: "praxis-layout-editor", inputs: ["config"], outputs: ["configChange", "select"] }, { kind: "component", type: BehaviorEditorComponent, selector: "praxis-behavior-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: ActionsEditorComponent$1, selector: "praxis-actions-editor", inputs: ["config"], outputs: ["configChange", "validationChange"] }, { kind: "component", type: MessagesEditorComponent, selector: "praxis-messages-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: HooksEditorComponent, selector: "praxis-hooks-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: RulePropertiesPanelComponent, selector: "praxis-rule-properties-panel", inputs: ["rules", "visualBlockNodes"], outputs: ["rulesChange"] }, { kind: "component", type: PraxisVisualBuilder, selector: "praxis-visual-builder", inputs: ["mode", "config", "initialRules", "initialCondition"], outputs: ["rulesChanged", "conditionChanged", "exportRequested", "importRequested"] }, { kind: "component", type: CascadeManagerTabComponent, selector: "praxis-cascade-manager-tab", inputs: ["fields", "connections"], outputs: ["apply", "cancel"] }, { kind: "component", type: SurfaceOpenActionEditorComponent, selector: "praxis-surface-open-action-editor", inputs: ["value", "hostKind"], outputs: ["valueChange", "validationChange"] }, { kind: "pipe", type: i1$2.JsonPipe, name: "json" }] });
34051
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisDynamicFormConfigEditor, isStandalone: true, selector: "praxis-dynamic-form-config-editor", providers: [FormConfigService, providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG)], viewQueries: [{ propertyName: "jsonEditor", first: true, predicate: JsonConfigEditorComponent, descendants: true }, { propertyName: "cascadeManager", first: true, predicate: CascadeManagerTabComponent, descendants: true }], ngImport: i0, template: "<div class=\"mobile-tab-selector\">\n <mat-form-field appearance=\"outline\" class=\"mobile-tab-selector__field\">\n <mat-label>{{ tx('config.tabs.mobileLabel', 'Se\u00E7\u00E3o do editor') }}</mat-label>\n <mat-select [(ngModel)]=\"selectedConfigTabIndex\" data-testid=\"dynamic-form-config-editor-mobile-tabs\">\n @for (tab of configTabOptions; track tab.key) {\n <mat-option [value]=\"tab.index\">{{ tab.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n\n<mat-tab-group [preserveContent]=\"true\" class=\"config-tabs\" data-testid=\"dynamic-form-config-editor-tabs\" [(selectedIndex)]=\"selectedConfigTabIndex\">\n <mat-tab [label]=\"configTabLabel('general')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-geral\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.general.title', 'Dados do formul\u00E1rio') }}</h3>\n <p class=\"text-caption\">{{ tx('config.general.subtitle', 'Defina o modo de dados e o contexto de edi\u00E7\u00E3o.') }}</p>\n </div>\n </div>\n <div class=\"form-modes\">\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.inputMode.label') }}</label>\n <mat-button-toggle-group [ngModel]=\"inputMode\" (ngModelChange)=\"inputMode = $event; onInputModeChange()\" [attr.aria-label]=\"tx('config.general.inputMode.label')\">\n <mat-button-toggle value=\"create\">{{ tx('config.general.inputMode.create') }}</mat-button-toggle>\n <mat-button-toggle value=\"edit\">{{ tx('config.general.inputMode.edit') }}</mat-button-toggle>\n <mat-button-toggle value=\"view\">{{ tx('config.general.inputMode.view') }}</mat-button-toggle>\n </mat-button-toggle-group>\n @if (inputMode === 'presentation' || inputMode === 'dossier') {\n <p class=\"control__hint\" data-testid=\"dynamic-form-native-mode-hint\" role=\"status\">\n {{ tx('config.general.inputMode.nativeMode', undefined, { mode: inputMode }) }}\n </p>\n }\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.layoutScope.label', 'Escopo de persist\u00EAncia do layout') }}</label>\n <mat-button-toggle-group\n data-testid=\"dynamic-form-layout-scope-toggle\"\n [ngModel]=\"inputLayoutScope\"\n (ngModelChange)=\"onLayoutScopeChange($event)\"\n [attr.aria-label]=\"tx('config.general.layoutScope.label', 'Escopo de persist\u00EAncia do layout')\">\n <mat-button-toggle value=\"shared\" data-testid=\"dynamic-form-layout-scope-shared\">\n {{ tx('config.general.layoutScope.shared', 'Todos os modos (Criar / Editar / Visualizar)') }}\n </mat-button-toggle>\n <mat-button-toggle value=\"mode-only\" data-testid=\"dynamic-form-layout-scope-mode-only\">\n {{ tx('config.general.layoutScope.modeOnly', 'Somente este modo ({{mode}})', { mode: tx('config.general.inputMode.' + inputMode, inputMode) }) }}\n </mat-button-toggle>\n </mat-button-toggle-group>\n <p class=\"control__hint\" data-testid=\"dynamic-form-layout-scope-hint\" role=\"status\">\n {{ inputLayoutScope === 'mode-only'\n ? tx('config.general.layoutScope.modeOnlyHint', 'Ao salvar, aplica este layout exclusivamente ao modo atual, sem alterar os demais modos.')\n : tx('config.general.layoutScope.sharedHint', 'Ao salvar, replica se\u00E7\u00F5es e grade nos demais modos que ainda compartilham layout.') }}\n </p>\n </div>\n @if (supportsPresentationSettings) {\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.displayMode.label') }}</label>\n <mat-button-toggle-group [ngModel]=\"displayMode\" (ngModelChange)=\"onDisplayModeChange($event)\" [attr.aria-label]=\"tx('config.general.displayMode.label')\">\n <mat-button-toggle value=\"automatic\">{{ tx('config.general.displayMode.automatic') }}</mat-button-toggle>\n <mat-button-toggle value=\"fields\">{{ tx('config.general.displayMode.fields') }}</mat-button-toggle>\n <mat-button-toggle value=\"presentation\">{{ tx('config.general.displayMode.presentation') }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <p class=\"display-result\" role=\"status\">{{ tx(displayModeHint) }}</p>\n @if (inputMode !== 'view' && inputMode !== 'presentation' && inputMode !== 'dossier' && inputPresentationMode === true) {\n <button mat-stroked-button type=\"button\" (click)=\"useViewMode()\">{{ tx('config.general.displayMode.useView') }}</button>\n }\n <button mat-button type=\"button\" (click)=\"openPresentationStyle()\">{{ tx('config.general.displayMode.openStyle') }}</button>\n }\n </div>\n </mat-card-content>\n </mat-card>\n\n @if (supportsPresentationSettings) {\n <mat-card class=\"section-card\" data-testid=\"form-empty-state-settings\">\n <mat-card-content>\n <h3>{{ tx('config.emptyState.heading') }}</h3>\n <p class=\"text-caption\">{{ tx('config.emptyState.help') }}</p>\n <mat-slide-toggle [ngModel]=\"!!inputEmptyState\" (ngModelChange)=\"setEmptyStateEnabled($event)\">{{ tx('config.emptyState.enabled') }}</mat-slide-toggle>\n @if (inputMode !== 'view' && inputMode !== 'presentation' && inputMode !== 'dossier') { <p class=\"text-caption\">{{ tx('config.emptyState.viewOnly') }}</p> }\n @if (inputEmptyState; as empty) {\n <div class=\"empty-state-fields empty-state-content\">\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.title') }}</mat-label><input matInput required [(ngModel)]=\"empty.title\" (ngModelChange)=\"onEmptyStateChange()\" /><mat-hint *ngIf=\"!empty.title?.trim()\">{{ tx('config.emptyState.titleRequired') }}</mat-hint></mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.emptyState.icon') }}</mat-label>\n @if (empty.icon) { <mat-icon matPrefix [praxisIcon]=\"empty.icon\" aria-hidden=\"true\"></mat-icon> }\n <input matInput [(ngModel)]=\"empty.icon\" (ngModelChange)=\"onEmptyStateChange()\" />\n <span matSuffix class=\"empty-state-icon-actions\">\n <button mat-icon-button type=\"button\" [attr.aria-label]=\"tx('config.emptyState.pickIcon')\" (click)=\"pickEmptyStateIcon()\"><mat-icon aria-hidden=\"true\">search</mat-icon></button>\n @if (empty.icon) { <button mat-icon-button type=\"button\" [attr.aria-label]=\"tx('config.emptyState.clearIcon')\" (click)=\"empty.icon = ''; onEmptyStateChange()\"><mat-icon aria-hidden=\"true\">close</mat-icon></button> }\n </span>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"empty-state-description\"><mat-label>{{ tx('config.emptyState.description') }}</mat-label><textarea matInput rows=\"2\" [(ngModel)]=\"empty.description\" (ngModelChange)=\"onEmptyStateChange()\"></textarea></mat-form-field>\n </div>\n <details class=\"empty-state-appearance\"><summary>{{ tx('config.emptyState.appearance') }}</summary><div class=\"empty-state-fields\">\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.tone') }}</mat-label><mat-select [(ngModel)]=\"empty.tone\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.tone; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.variant') }}</mat-label><mat-select [(ngModel)]=\"empty.variant\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.variant; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.alignment') }}</mat-label><mat-select [(ngModel)]=\"empty.alignment\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.alignment; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.density') }}</mat-label><mat-select [(ngModel)]=\"empty.density\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.density; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.iconContainer') }}</mat-label><mat-select [(ngModel)]=\"empty.iconContainer\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.iconContainer; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n </div></details>\n }\n </mat-card-content>\n </mat-card>\n }\n\n @if (hasResolvedRuntimeContract()) {\n <mat-card\n class=\"section-card\"\n data-testid=\"config-tab-runtime-contract\"\n >\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.general.runtimeContract.title', 'Contrato Runtime Resolvido') }}</h3>\n <p class=\"text-caption\">\n {{ tx('config.general.runtimeContract.subtitle', 'Visualiza\u00E7\u00E3o somente leitura do contrato backend resolvido pelo host atual.') }}\n </p>\n </div>\n </div>\n <div class=\"block-status block-status--readonly\">\n <strong>{{ tx('config.general.runtimeContract.runtimeLabel', 'Runtime') }}</strong>\n <span>\n {{ tx('config.general.runtimeContract.readonly', 'Esses valores v\u00EAm do host/runtime atual e n\u00E3o s\u00E3o persistidos em `bindings` nem em `contextSnapshot`.') }}\n </span>\n </div>\n <div class=\"runtime-contract-grid\">\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.schemaUrl', 'Schema URL') }}</span>\n <code class=\"runtime-contract-code\">{{ runtimeContract?.schemaUrl || '\u2014' }}</code>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.schemaSource', 'Origem do schema') }}</span>\n <strong>{{ describeRuntimeSource(runtimeContract?.schemaSource) }}</strong>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitMethod', 'Submit method') }}</span>\n <strong>{{ runtimeContract?.submitMethod || '\u2014' }}</strong>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitUrl', 'Submit URL') }}</span>\n <code class=\"runtime-contract-code\">{{ runtimeContract?.submitUrl || '\u2014' }}</code>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitSource', 'Origem do submit') }}</span>\n <strong>{{ describeRuntimeSource(runtimeContract?.submitSource) }}</strong>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n }\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('schema')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-schema\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.schema.title', 'Valida\u00E7\u00E3o de schema') }}</h3>\n <p class=\"text-caption\">{{ tx('config.schema.subtitle', 'Controle avisos quando o schema do servidor mudar.') }}</p>\n </div>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.schema.notify.label', 'Notificar quando desatualizado') }}</mat-label>\n <mat-select [(ngModel)]=\"schemaPrefs.notifyIfOutdated\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-notify')\">\n <mat-option value=\"both\">{{ tx('config.schema.notify.both', 'Banner + Snackbar') }}</mat-option>\n <mat-option value=\"inline\">{{ tx('config.schema.notify.inline', 'Somente Banner') }}</mat-option>\n <mat-option value=\"snackbar\">{{ tx('config.schema.notify.snackbar', 'Somente Snackbar') }}</mat-option>\n <mat-option value=\"none\">{{ tx('config.schema.notify.none', 'Nenhum') }}</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.schema.snooze.label', 'Intervalo de sil\u00EAncio (ms)') }}</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"schemaPrefs.snoozeMs\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-snooze')\" />\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-slide-toggle [(ngModel)]=\"schemaPrefs.autoOpenSettingsOnOutdated\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-auto-open')\">\n {{ tx('config.schema.autoOpenSettings', 'Abrir configura\u00E7\u00F5es automaticamente') }}\n </mat-slide-toggle>\n </div>\n @if (serverMeta) {\n <div class=\"form-row\">\n <div class=\"meta-card\">\n <div class=\"meta-row\">\n <span>{{ tx('config.schema.meta.serverHash', 'Server hash') }}</span>\n <strong>{{ serverMeta.serverHash || '\u2014' }}</strong>\n </div>\n <div class=\"meta-row\">\n <span>{{ tx('config.schema.meta.lastVerifiedAt', '\u00DAltima verifica\u00E7\u00E3o') }}</span>\n <strong>{{ serverMeta.lastVerifiedAt || '\u2014' }}</strong>\n </div>\n </div>\n </div>\n }\n <div class=\"block-status\" [class.block-status--implicit]=\"!isSchemaPrefsBlockPersisted()\">\n <strong>{{ tx('config.schema.prefs.label', 'Schema Prefs') }}</strong>\n @if (isSchemaPrefsBlockPersisted()) {\n <span>{{ tx('config.schema.prefs.persisted', '`contextSnapshot.schemaPrefs` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.schema.prefs.implicit', 'Bloco ausente no documento can\u00F4nico. Os controles exibem fallback visual e n\u00E3o ser\u00E3o salvos at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('layout')\">\n <div class=\"tab-content tab-content--full\" data-testid=\"config-tab-panel-layout\">\n <div class=\"section-body section-body--flex\">\n <praxis-layout-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"\n (select)=\"onLayoutSelect($event)\"></praxis-layout-editor>\n </div>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('hooks')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-hooks\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.hooks.title', 'Hooks de ciclo de vida') }}</h3>\n <p class=\"text-caption\">{{ tx('config.hooks.subtitle', 'Automatize a\u00E7\u00F5es nos eventos do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <praxis-hooks-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-hooks-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n @if (isPresentationMode) {\n <mat-tab [label]=\"configTabLabel('presentation')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-presentation\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.presentation.title', 'Modo Apresenta\u00E7\u00E3o') }}</h3>\n <p class=\"text-caption\">{{ tx('config.presentation.subtitle', 'Configura\u00E7\u00F5es de exibi\u00E7\u00E3o aplicadas somente ao modo apresenta\u00E7\u00E3o.') }}</p>\n </div>\n </div>\n <p class=\"display-result\" role=\"status\">{{ tx(displayModeHint) }}</p>\n <div class=\"presentation-layout\">\n <div class=\"presentation-controls\">\n <div class=\"block-status control-span\" [class.block-status--implicit]=\"!isPresentationBlockPersisted()\">\n <strong>{{ tx('config.presentation.block.label', 'Presentation') }}</strong>\n @if (isPresentationBlockPersisted()) {\n <span>{{ tx('config.presentation.block.persisted', '`contextSnapshot.presentation` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.presentation.block.implicit', 'Bloco ausente no documento can\u00F4nico. A pr\u00E9-visualiza\u00E7\u00E3o usa fallback local e n\u00E3o ser\u00E1 salva at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.labelPosition.label', 'Posi\u00E7\u00E3o do r\u00F3tulo') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.labelPosition\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-position')\" [attr.aria-label]=\"tx('config.presentation.labelPosition.ariaLabel', 'Posi\u00E7\u00E3o do r\u00F3tulo')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"above\">\n <mat-icon>view_stream</mat-icon>\n <span class=\"sr-only\">{{ tx('config.presentation.labelPosition.above', 'Acima') }}</span>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n <mat-icon>view_column</mat-icon>\n <span class=\"sr-only\">{{ tx('config.presentation.labelPosition.left', '\u00C0 esquerda') }}</span>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control control-span\">\n <label class=\"control__label\">{{ tx('config.presentation.density.label', 'Densidade') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.density\" (ngModelChange)=\"onPresentationPrefsChange('presentation-density')\" [attr.aria-label]=\"tx('config.presentation.density.ariaLabel', 'Densidade')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"comfortable\">{{ tx('config.presentation.density.comfortable', 'Confort\u00E1vel') }}</mat-button-toggle>\n <mat-button-toggle value=\"cozy\">{{ tx('config.presentation.density.cozy', 'Intermedi\u00E1ria') }}</mat-button-toggle>\n <mat-button-toggle value=\"compact\">{{ tx('config.presentation.density.compact', 'Compacta') }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.labelAlign.label', 'Alinhamento do r\u00F3tulo') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.labelAlign\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-align')\" [attr.aria-label]=\"tx('config.presentation.labelAlign.ariaLabel', 'Alinhamento do r\u00F3tulo')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"start\" [aria-label]=\"tx('config.presentation.align.start')\" [matTooltip]=\"tx('config.presentation.align.start')\"><mat-icon>format_align_left</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"center\" [aria-label]=\"tx('config.presentation.align.center')\" [matTooltip]=\"tx('config.presentation.align.center')\"><mat-icon>format_align_center</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"end\" [aria-label]=\"tx('config.presentation.align.end')\" [matTooltip]=\"tx('config.presentation.align.end')\"><mat-icon>format_align_right</mat-icon></mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.valueAlign.label', 'Alinhamento do valor') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.valueAlign\" (ngModelChange)=\"onPresentationPrefsChange('presentation-value-align')\" [attr.aria-label]=\"tx('config.presentation.valueAlign.ariaLabel', 'Alinhamento do valor')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"start\" [aria-label]=\"tx('config.presentation.align.start')\" [matTooltip]=\"tx('config.presentation.align.start')\"><mat-icon>format_align_left</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"center\" [aria-label]=\"tx('config.presentation.align.center')\" [matTooltip]=\"tx('config.presentation.align.center')\"><mat-icon>format_align_center</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"end\" [aria-label]=\"tx('config.presentation.align.end')\" [matTooltip]=\"tx('config.presentation.align.end')\"><mat-icon>format_align_right</mat-icon></mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.labelFontSize.label', 'Tamanho do r\u00F3tulo') }}</mat-label>\n <input matInput type=\"number\" min=\"10\" step=\"any\" [(ngModel)]=\"presentationPrefs.labelFontSize\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-font-size')\"\n [placeholder]=\"tx('config.presentation.labelFontSize.placeholder', 'ex.: 12')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.valueFontSize.label', 'Tamanho do valor') }}</mat-label>\n <input matInput type=\"number\" min=\"10\" step=\"any\" [(ngModel)]=\"presentationPrefs.valueFontSize\" (ngModelChange)=\"onPresentationPrefsChange('presentation-value-font-size')\"\n [placeholder]=\"tx('config.presentation.valueFontSize.placeholder', 'ex.: 16')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.labelWidth.label', 'Largura do r\u00F3tulo (label \u00E0 esquerda)') }}</mat-label>\n <input matInput type=\"number\" min=\"60\" [disabled]=\"presentationPrefs.labelPosition !== 'left'\" [(ngModel)]=\"presentationPrefs.labelWidth\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-width')\"\n [placeholder]=\"tx('config.presentation.labelWidth.placeholder', 'ex.: 140')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control control--inline\">\n <mat-slide-toggle [(ngModel)]=\"presentationPrefs.compact\" (ngModelChange)=\"onPresentationPrefsChange('presentation-compact')\">\n {{ tx('config.presentation.options.compactMode', 'Modo compacto') }}\n </mat-slide-toggle>\n <mat-checkbox [(ngModel)]=\"truncatePreview\">\n {{ tx('config.presentation.options.truncateValues', 'Truncar valores') }}\n </mat-checkbox>\n </div>\n </div>\n <div class=\"presentation-preview\">\n <h4>{{ tx('config.presentation.preview.title', 'Pr\u00E9-visualiza\u00E7\u00E3o') }}</h4>\n <p class=\"text-caption\">{{ tx('config.presentation.preview.sampleHint') }}</p>\n <div class=\"preview-card\">\n <div class=\"praxis-dynamic-form presentation-mode\" [ngClass]=\"{\n 'pres-compact': !!presentationPrefs.compact,\n 'pres-label-left': presentationPrefs.labelPosition === 'left',\n 'pres-label-above': presentationPrefs.labelPosition === 'above',\n 'pres-density-compact': presentationPrefs.density === 'compact',\n 'pres-density-cozy': presentationPrefs.density === 'cozy'\n }\" [style.--pfx-pres-label-size]=\"(presentationPrefs.labelFontSize || 12) + 'px'\"\n [style.--pfx-pres-value-size]=\"(presentationPrefs.valueFontSize || 16) + 'px'\"\n [style.--pfx-pres-label-width]=\"(presentationPrefs.labelWidth || 140) + 'px'\"\n [style.--pfx-pres-label-align]=\"presentationPrefs.labelAlign || 'start'\"\n [style.--pfx-pres-value-align]=\"presentationPrefs.valueAlign || 'start'\">\n @for (item of previewItems; track item) {\n <div class=\"preview-row\">\n <span class=\"praxis-presentation__label\">{{ item.label }}</span>\n <span class=\"praxis-presentation__value\" [attr.title]=\"truncatePreview ? item.value : null\"\n [style.maxWidth]=\"truncatePreview ? '280px' : null\"\n [style.overflow]=\"truncatePreview ? 'hidden' : null\"\n [style.textOverflow]=\"truncatePreview ? 'ellipsis' : null\"\n [style.whiteSpace]=\"truncatePreview ? 'nowrap' : 'normal'\">\n {{ item.value }}\n </span>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n }\n <mat-tab [label]=\"configTabLabel('behavior')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-comportamento\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.behavior.title', 'Comportamento') }}</h3>\n <p class=\"text-caption\">{{ tx('config.behavior.subtitle', 'Ajuste valida\u00E7\u00F5es e respostas do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <praxis-behavior-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-behavior-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('hints')\">\n <div class=\"tab-content tab-content--dense\" data-testid=\"config-tab-panel-hints\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.hints.title', 'Dicas dos modos') }}</h3>\n <p class=\"text-caption\">{{ tx('config.hints.subtitle', 'Personalize textos de apoio para modos de dados e estados de UI.') }}</p>\n </div>\n </div>\n <p class=\"text-caption\">{{ tx('config.hints.description', 'Personalize os textos usados como tooltip/hint para modos de dados e modos globais de UI.') }}</p>\n\n <div class=\"grid-2-cols grid-2-cols--compact\">\n <section>\n <h4>{{ tx('config.hints.dataModes.title', 'Modos de dados') }}</h4>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.create.label', 'Criar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.create\"\n (ngModelChange)=\"updateDirtyState('hints-data-create')\" [placeholder]=\"tx('config.hints.dataModes.create.placeholder', 'Ex.: Preencha os campos obrigat\u00F3rios.')\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.edit.label', 'Editar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.edit\"\n (ngModelChange)=\"updateDirtyState('hints-data-edit')\" [placeholder]=\"tx('config.hints.dataModes.edit.placeholder', 'Ex.: Revise os dados antes de salvar.')\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.view.label', 'Visualizar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.view\"\n (ngModelChange)=\"updateDirtyState('hints-data-view')\" [placeholder]=\"tx('config.hints.dataModes.view.placeholder', 'Ex.: Visualiza\u00E7\u00E3o somente leitura.')\" />\n </mat-form-field>\n </section>\n\n <section>\n <h4>{{ tx('config.hints.uiModes.title', 'Modos de UI') }}</h4>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.presentation.label', 'Apresenta\u00E7\u00E3o') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.presentation\"\n (ngModelChange)=\"updateDirtyState('hints-ui-presentation')\" [placeholder]=\"tx('config.hints.uiModes.presentation.placeholder', 'Ex.: Modo compacto para leitura r\u00E1pida.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.readonly.label', 'Leitura (readonly)') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.readonly\"\n (ngModelChange)=\"updateDirtyState('hints-ui-readonly')\" [placeholder]=\"tx('config.hints.uiModes.readonly.placeholder', 'Ex.: Campos bloqueados para edi\u00E7\u00E3o.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.disabled.label', 'Desabilitado') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.disabled\"\n (ngModelChange)=\"updateDirtyState('hints-ui-disabled')\" [placeholder]=\"tx('config.hints.uiModes.disabled.placeholder', 'Ex.: Fun\u00E7\u00E3o indispon\u00EDvel no momento.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.visible.label', 'Vis\u00EDvel') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.visible\"\n (ngModelChange)=\"updateDirtyState('hints-ui-visible')\" [placeholder]=\"tx('config.hints.uiModes.visible.placeholder', 'Ex.: Campo exibido conforme permiss\u00F5es.')\"></textarea>\n </mat-form-field>\n </section>\n </div>\n\n <section>\n <h4>{{ tx('config.helpPresentation.title', 'Apresenta\u00E7\u00E3o das ajudas dos campos') }}</h4>\n <p class=\"text-caption\">{{ tx('config.helpPresentation.description', 'Controle como hint/helpText dos campos aparece em formul\u00E1rios densos. Erros de valida\u00E7\u00E3o continuam inline.') }}</p>\n <div class=\"grid-3-cols\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.display.label', 'Exibi\u00E7\u00E3o') }}</mat-label>\n <mat-select [ngModel]=\"helpPresentationDraft.display\" (ngModelChange)=\"onHelpPresentationDisplayChange($event)\">\n <mat-option value=\"inline\">{{ tx('config.helpPresentation.display.inline', 'Inline') }}</mat-option>\n <mat-option value=\"popover\">{{ tx('config.helpPresentation.display.popover', '\u00CDcone de ajuda') }}</mat-option>\n <mat-option value=\"auto\">{{ tx('config.helpPresentation.display.auto', 'Autom\u00E1tica') }}</mat-option>\n <mat-option value=\"hidden\">{{ tx('config.helpPresentation.display.hidden', 'Oculta') }}</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.inlineMaxLength.label', 'Limite inline') }}</mat-label>\n <input matInput type=\"number\" min=\"0\" [ngModel]=\"helpPresentationDraft.inlineMaxLength\"\n (ngModelChange)=\"onHelpPresentationInlineMaxLengthChange($event)\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.preferPopoverForControls.label', 'Preferir \u00EDcone em') }}</mat-label>\n <input matInput [ngModel]=\"getHelpPreferPopoverControlsText()\"\n (ngModelChange)=\"onHelpPreferPopoverControlsChange($event)\"\n [placeholder]=\"tx('config.helpPresentation.preferPopoverForControls.placeholder', 'toggle, checkbox, select')\" />\n </mat-form-field>\n </div>\n </section>\n\n <div class=\"actions-row\">\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"restoreHintsDefaults()\">\n <mat-icon>restore</mat-icon>\n {{ tx('config.hints.actions.restoreDefaults', 'Restaurar padr\u00F5es') }}\n </button>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('actions')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-acoes\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.actions.title', 'A\u00E7\u00F5es do formul\u00E1rio') }}</h3>\n <p class=\"text-caption\">{{ tx('config.actions.subtitle', 'Configure bot\u00F5es padr\u00E3o e a\u00E7\u00F5es customizadas.') }}</p>\n </div>\n </div>\n <praxis-actions-editor #actionsDraft [config]=\"editedConfig\" (validationChange)=\"onSurfaceDraftValidity(actionsDraft, $event)\" (configChange)=\"onConfigChange($event)\"></praxis-actions-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('rules')\">\n <div class=\"tab-content visual-builder-content\" data-testid=\"config-tab-panel-regras\">\n <div class=\"builder-header\">\n <div>\n <h3>{{ tx('config.rules.title', 'Regras visuais') }}</h3>\n <p class=\"text-caption\">{{ tx('config.rules.subtitle', 'Controle a apresenta\u00E7\u00E3o dos campos. Estas regras n\u00E3o executam comandos nem substituem decis\u00F5es de neg\u00F3cio governadas.') }}</p>\n </div>\n </div>\n @if (ruleConversionFailed) {\n <p role=\"alert\" data-testid=\"rules-conversion-error\">\n {{ tx('config.rules.conversionError', 'N\u00E3o foi poss\u00EDvel converter a condi\u00E7\u00E3o visual. Revise a regra; aplicar e salvar est\u00E3o bloqueados.') }}\n </p>\n }\n @if (!ruleConversionFailed && ruleDiagnostics.length) {\n <div class=\"rules-diagnostics\" data-testid=\"rules-diagnostics-panel\">\n <div class=\"rules-diagnostics__summary\">\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--total\">\n {{ tx('config.rules.summary.total', '{{count}} regras', { count: ruleDiagnosticsSummary.total }) }}\n </span>\n @if (ruleDiagnosticsSummary.invalid) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--error\">\n {{ tx('config.rules.summary.invalid', '{{count}} inv\u00E1lidas', { count: ruleDiagnosticsSummary.invalid }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.unsupported) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.unsupported', '{{count}} com propriedades rejeitadas', { count: ruleDiagnosticsSummary.unsupported }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.runtimeOnly) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.runtimeOnly', '{{count}} runtime only', { count: ruleDiagnosticsSummary.runtimeOnly }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.pendingReview) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.pendingReview', '{{count}} pendentes de revis\u00E3o', { count: ruleDiagnosticsSummary.pendingReview }) }}\n </span>\n }\n </div>\n <div class=\"rules-diagnostics__list\" [attr.aria-label]=\"tx('config.rules.diagnostics.ariaLabel', 'Diagn\u00F3stico das regras')\">\n @for (diagnostic of ruleDiagnostics; track diagnostic) {\n <article class=\"rules-diagnostics__item\"\n [class.rules-diagnostics__item--error]=\"getRuleStatusTone(diagnostic) === 'error'\"\n [class.rules-diagnostics__item--warn]=\"getRuleStatusTone(diagnostic) === 'warn'\">\n <div>\n <strong>{{ diagnostic.ruleName || diagnostic.ruleId }}</strong>\n <span>\n {{ tx('config.rules.diagnostics.targetConditionSummary', '{{targets}} alvo(s) \u00B7 {{conditions}} campo(s) na condi\u00E7\u00E3o', { targets: diagnostic.targetRefs.length, conditions: diagnostic.conditionRefs.length }) }}\n </span>\n @if (getRuleDiagnosticDetails(diagnostic).length) {\n <ul class=\"rules-diagnostics__details\">\n @for (detail of getRuleDiagnosticDetails(diagnostic); track detail) {\n <li>{{ detail }}</li>\n }\n </ul>\n }\n </div>\n <div class=\"rules-diagnostics__actions\">\n <span class=\"rules-diagnostics__status\">{{ getRuleStatusLabel(diagnostic) }}</span>\n @if (canApplyRulePropertyFix(diagnostic)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [matTooltip]=\"tx('config.rules.actions.fix.tooltip', 'Aplicar whitelist e saneamento de propriedades nesta regra')\"\n (click)=\"applyRulePropertyFix(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">auto_fix_high</mat-icon>\n {{ tx('config.rules.actions.fix', 'Corrigir') }}\n </button>\n }\n @if (diagnostic.status.includes('llm-generated-pending-review')) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [disabled]=\"!canAcceptPendingLlmRule(diagnostic)\"\n [matTooltip]=\"canAcceptPendingLlmRule(diagnostic) ? tx('config.rules.actions.accept.tooltip.ready', 'Aceitar sugest\u00E3o e atualizar estado visual') : tx('config.rules.actions.accept.tooltip.blocked', 'Corrija alvo, condi\u00E7\u00E3o e propriedades antes de aceitar')\"\n (click)=\"acceptPendingLlmRule(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n {{ tx('config.rules.actions.accept', 'Aceitar') }}\n </button>\n }\n @if (canOpenRuleJsonReview(diagnostic)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [matTooltip]=\"tx('config.rules.actions.reviewJson.tooltip', 'Abrir a aba JSON para revisar esta regra sem convers\u00E3o visual')\"\n (click)=\"openRuleJsonReview(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">data_object</mat-icon>\n {{ tx('config.rules.actions.reviewJson', 'Ver JSON') }}\n </button>\n }\n </div>\n </article>\n }\n </div>\n </div>\n } @else if (!ruleConversionFailed) {\n <div class=\"rules-diagnostics rules-diagnostics--empty\" data-testid=\"rules-diagnostics-empty\">\n {{ tx('config.rules.empty', 'Nenhuma regra definida ainda. Crie uma regra para ver alvos, condi\u00E7\u00E3o, propriedades e compatibilidade do builder.') }}\n </div>\n }\n <praxis-visual-builder [config]=\"ruleBuilderConfig\" [initialRules]=\"ruleBuilderState\"\n (rulesChanged)=\"onRulesChanged($event)\"></praxis-visual-builder>\n @if (ruleConversionFailed) {\n <p role=\"status\" data-testid=\"rule-properties-draft-pending\">\n {{ tx('config.rules.effectsDraftPending', 'Conclua ou repare o rascunho no editor visual ou no JSON para editar seus efeitos. A \u00FAltima configura\u00E7\u00E3o aceita foi preservada e n\u00E3o representa este rascunho.') }}\n </p>\n } @else {\n <praxis-rule-properties-panel\n [rules]=\"currentRules\"\n [visualBlockNodes]=\"visualBlockNodeOptions\"\n (rulesChange)=\"onRulePropertiesChanged($event)\"\n ></praxis-rule-properties-panel>\n }\n <mat-card class=\"command-rules-card\" data-testid=\"form-command-rules-editor\">\n <mat-card-title>{{ tx('config.commandRules.title', 'Comandos condicionais') }}</mat-card-title>\n <mat-card-subtitle>{{ tx('config.commandRules.subtitle', 'Canal de comandos: execute a\u00E7\u00F5es globais quando uma condi\u00E7\u00E3o for satisfeita, respeitando as pol\u00EDticas da a\u00E7\u00E3o.') }}</mat-card-subtitle>\n <mat-card-content>\n <div class=\"command-rules-grid\">\n <div class=\"command-rules-toolbar\">\n <mat-form-field appearance=\"outline\" class=\"command-rules-select\">\n <mat-label>{{ tx('config.commandRules.command.label', 'Comando') }}</mat-label>\n <mat-select [disabled]=\"hasInvalidSurfaceDraft\" [(ngModel)]=\"selectedCommandRuleId\" (selectionChange)=\"onCommandRuleSelectionChange()\">\n @for (rule of commandRules; track rule) {\n <mat-option [value]=\"rule.id\">\n {{ rule.id }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <button mat-stroked-button type=\"button\" [disabled]=\"hasInvalidSurfaceDraft\" (click)=\"addCommandRule()\">\n <mat-icon aria-hidden=\"true\">add</mat-icon>\n {{ tx('config.commandRules.actions.add', 'Adicionar') }}\n </button>\n <button mat-stroked-button color=\"warn\" type=\"button\" (click)=\"deleteCommandRule()\" [disabled]=\"hasInvalidSurfaceDraft || !selectedCommandRuleId\">\n <mat-icon aria-hidden=\"true\">delete</mat-icon>\n {{ tx('config.commandRules.actions.remove', 'Remover') }}\n </button>\n </div>\n\n @if (selectedCommandRuleId) {\n <div class=\"command-rule-condition-builder command-rules-full\">\n <praxis-visual-builder\n mode=\"condition\"\n [config]=\"ruleBuilderConfig\"\n [initialCondition]=\"commandRuleCondition\"\n (conditionChanged)=\"onCommandConditionChanged($event)\"\n ></praxis-visual-builder>\n </div>\n }\n\n <mat-form-field appearance=\"outline\" class=\"command-rules-full\">\n <mat-label>{{ tx('config.commandRules.conditionJson.label', 'Condi\u00E7\u00E3o JSON Logic') }}</mat-label>\n <textarea\n matInput\n rows=\"5\"\n [(ngModel)]=\"commandRuleConditionJson\"\n [attr.aria-label]=\"tx('config.commandRules.conditionJson.ariaLabel', 'Condi\u00E7\u00E3o JSON Logic do comando condicional')\"\n ></textarea>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.commandRules.globalAction.label', 'A\u00E7\u00E3o global') }}</mat-label>\n <mat-select [disabled]=\"hasInvalidSurfaceDraft\" [(ngModel)]=\"commandRuleActionId\" (selectionChange)=\"onCommandActionChange()\">\n @for (action of globalActionCatalog; track action) {\n <mat-option [value]=\"action.id\">\n {{ action.label || action.id }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.commandRules.distinctBy.label', 'distinctBy') }}</mat-label>\n <input matInput [(ngModel)]=\"commandRuleDistinctBy\" [placeholder]=\"tx('config.commandRules.distinctBy.placeholder', 'ex.: idade')\" />\n </mat-form-field>\n\n @if (commandRuleActionSchema; as actionSchema) {\n <div\n class=\"command-rules-payload-fields command-rules-full\"\n >\n <div class=\"command-rules-section-title\">{{ tx('config.commandRules.structuredPayload.title', 'Payload estruturado') }}</div>\n @if (actionSchema.editorMode !== 'surface-open') {\n @for (field of actionSchema.fields; track field) {\n @if (shouldShowCommandActionField(field)) {\n @if (field.type === 'toggle') {\n <mat-slide-toggle\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n {{ field.label }}\n </mat-slide-toggle>\n } @else {\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ field.label }}</mat-label>\n @if (field.type === 'textarea' || field.type === 'json') {\n <textarea\n matInput\n [rows]=\"field.rows || (field.type === 'json' ? 3 : 2)\"\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [placeholder]=\"field.placeholder || (field.type === 'json' ? '{ }' : '')\"\n [required]=\"isCommandActionFieldRequired(field)\"\n ></textarea>\n } @else {\n @if (field.type === 'select') {\n <mat-select\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [required]=\"isCommandActionFieldRequired(field)\"\n >\n @for (option of field.options || []; track option) {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n </mat-select>\n } @else {\n <input\n matInput\n [type]=\"field.type === 'number' ? 'number' : 'text'\"\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [placeholder]=\"field.placeholder || ''\"\n [required]=\"isCommandActionFieldRequired(field)\"\n />\n }\n }\n @if (field.hint) {\n <mat-hint>{{ field.hint }}</mat-hint>\n }\n @if (hasCommandActionFieldError(field.key)) {\n <mat-error>\n {{ getCommandActionFieldError(field.key) }}\n </mat-error>\n }\n @if (!hasCommandActionFieldError(field.key) && isCommandActionFieldMissing(field)) {\n <mat-error>\n {{ tx('config.commandRules.validation.requiredField', 'Campo obrigat\u00F3rio.') }}\n </mat-error>\n }\n </mat-form-field>\n }\n }\n }\n } @else {\n <praxis-surface-open-action-editor #commandSurfaceDraft\n class=\"command-rules-surface-editor\"\n data-testid=\"form-command-rule-surface-open-editor\"\n [value]=\"commandRuleSurfaceOpenPayload\"\n hostKind=\"dynamic-form\"\n (valueChange)=\"onCommandSurfaceOpenPayloadChange($event)\"\n (validationChange)=\"onSurfaceDraftValidity(commandSurfaceDraft, $event)\"\n ></praxis-surface-open-action-editor>\n }\n </div>\n }\n\n <mat-form-field appearance=\"outline\" class=\"command-rules-full\">\n <mat-label>{{ tx('config.commandRules.advancedPayload.label', 'Payload JSON avan\u00E7ado') }}</mat-label>\n <textarea\n matInput\n rows=\"4\"\n [(ngModel)]=\"commandRulePayloadJson\"\n [attr.aria-label]=\"tx('config.commandRules.advancedPayload.ariaLabel', 'Payload JSON da a\u00E7\u00E3o global')\"\n ></textarea>\n </mat-form-field>\n\n <div class=\"command-rules-options\">\n <mat-slide-toggle [(ngModel)]=\"commandRuleDistinct\">{{ tx('config.commandRules.options.distinct', 'Evitar repeti\u00E7\u00E3o enquanto a condi\u00E7\u00E3o permanecer verdadeira') }}</mat-slide-toggle>\n <mat-slide-toggle [(ngModel)]=\"commandRuleRunOnInitialEvaluation\">{{ tx('config.commandRules.options.runOnInitialEvaluation', 'Executar tamb\u00E9m na avalia\u00E7\u00E3o inicial') }}</mat-slide-toggle>\n </div>\n\n @if (commandRuleAuthoringError) {\n <div class=\"preview-error command-rules-full\">\n <mat-icon aria-hidden=\"true\">warning</mat-icon>\n <span>{{ commandRuleAuthoringError }}</span>\n </div>\n }\n\n <div\n class=\"command-rule-preview command-rules-full\"\n [class.command-rule-preview--invalid]=\"commandRulePreview.state === 'invalid'\"\n data-testid=\"command-rule-preview\"\n >\n <div class=\"command-rules-section-title\">{{ tx('config.commandRules.preview.title', 'Preview do comando') }}</div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.mode', 'Modo') }}</span>\n <strong>{{ commandRulePreview.executionMode }}</strong>\n </div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.action', 'A\u00E7\u00E3o') }}</span>\n <strong>{{ commandRulePreview.actionId || '\u2014' }}</strong>\n </div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.policy', 'Policy') }}</span>\n <code>{{ commandRulePreview.policy | json }}</code>\n </div>\n @if (commandRulePreview.diagnostics.length) {\n <div class=\"command-rule-preview__diagnostics\">\n <mat-icon aria-hidden=\"true\">{{ commandRulePreview.state === 'invalid' ? 'warning' : 'visibility' }}</mat-icon>\n <span>{{ commandRulePreview.diagnostics[0] }}</span>\n </div>\n }\n </div>\n\n <div class=\"command-rules-actions\">\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"applyCommandRule()\">\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n {{ tx('config.commandRules.actions.apply', 'Aplicar comando') }}\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('cascades')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-cascatas\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.cascades.title', 'Depend\u00EAncias entre campos') }}</h3>\n <p class=\"text-caption\">{{ tx('config.cascades.subtitle', 'Configure cascatas e carregamento entre campos.') }}</p>\n </div>\n </div>\n <praxis-cascade-manager-tab [fields]=\"editedConfig.fieldMetadata || []\"\n (apply)=\"onCascadeApply($event)\"\n (validChange)=\"onCascadeValidChange($event)\"></praxis-cascade-manager-tab>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('messages')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-mensagens\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.messages.title', 'Mensagens e feedback') }}</h3>\n <p class=\"text-caption\">{{ tx('config.messages.subtitle', 'Padronize textos de sucesso, erro e confirma\u00E7\u00F5es.') }}</p>\n </div>\n </div>\n <praxis-messages-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-messages-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('navigation')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-navegacao\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.navigation.title', 'Navega\u00E7\u00E3o de retorno') }}</h3>\n <p class=\"text-caption\">{{ tx('config.navigation.subtitle', 'Defina o comportamento do bot\u00E3o Voltar em fluxos CRUD.') }}</p>\n </div>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.navigation.returnTo.label', 'Rota de retorno') }}</mat-label>\n <input matInput id=\"returnTo\" [(ngModel)]=\"backConfig!.returnTo\" (ngModelChange)=\"onBackConfigChange()\" [placeholder]=\"tx('config.navigation.returnTo.placeholder', '/funcionarios')\" />\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-slide-toggle [(ngModel)]=\"backConfig!.confirmOnDirty\" (ngModelChange)=\"onBackConfigChange()\">\n {{ tx('config.navigation.confirmOnDirty.label', 'Confirmar ao sair com altera\u00E7\u00F5es') }}\n </mat-slide-toggle>\n </div>\n <div class=\"block-status\" [class.block-status--implicit]=\"!isBackConfigBlockPersisted()\">\n <strong>{{ tx('config.navigation.backConfig.label', 'Back Config') }}</strong>\n @if (isBackConfigBlockPersisted()) {\n <span>{{ tx('config.navigation.backConfig.persisted', '`contextSnapshot.backConfig` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.navigation.backConfig.implicit', 'Bloco ausente no documento can\u00F4nico. Os valores exibidos s\u00E3o fallback visual e n\u00E3o ser\u00E3o salvos at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n </div>\n <div class=\"section-help\">\n <span class=\"section-help__label\">{{ tx('config.navigation.note.label', 'Observa\u00E7\u00E3o:') }}</span>\n <button\n praxisIconButton=\"help_outline\"\n size=\"dense\"\n class=\"help-icon-button\"\n type=\"button\"\n [matTooltip]=\"tx('config.navigation.note.tooltip', 'Afeta o fluxo de navega\u00E7\u00E3o do CRUD e pode ser sobreposto por metadados do recurso.')\"\n matTooltipPosition=\"above\"\n >\n </button>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('json')\">\n <div class=\"tab-content json-tab-content\" data-testid=\"config-tab-panel-json\">\n <mat-card class=\"section-card section-card--json\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.json.title', 'Configura\u00E7\u00E3o JSON') }}</h3>\n <p class=\"text-caption\">{{ tx('config.json.subtitle', 'Edi\u00E7\u00E3o avan\u00E7ada do documento can\u00F4nico de autoria do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <form-json-config-editor [document]=\"jsonDocument\" (documentChange)=\"onJsonConfigChange($event)\"\n (validationChange)=\"onJsonValidationChange($event)\" (editorEvent)=\"onJsonEditorEvent($event)\">\n </form-json-config-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n</mat-tab-group>\n", styles: [":host{container:praxis-authoring-editor/inline-size;display:flex;flex-direction:column;height:100%;min-width:0}.mobile-tab-selector{display:none;flex:0 0 auto;padding:8px 16px 0;background:var(--md-sys-color-surface)}.mobile-tab-selector__field{width:100%}.config-tabs{flex:1 1 auto;min-height:0;min-width:0}::ng-deep .mat-mdc-tab-group.config-tabs{display:flex;flex-direction:column}::ng-deep .mat-mdc-tab-group.config-tabs .mat-mdc-tab-body-wrapper{flex:1;min-height:0;min-width:0}::ng-deep .mat-mdc-tab-group.config-tabs .mat-mdc-tab-body-content{height:100%;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;padding:0!important}.tab-content{padding:20px 24px 28px;flex:1;min-width:0;box-sizing:border-box;display:flex;flex-direction:column;gap:24px}.json-tab-content{min-width:0;padding:12px 16px 16px}.section-card.section-card--json{display:flex;flex:1;min-height:calc(100vh - 180px);border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-low)}.section-card.section-card--json>mat-card-content,.section-card.section-card--json>.mat-mdc-card-content{display:flex;flex:1;min-width:0;min-height:0;flex-direction:column;padding:16px!important}.section-card--json form-json-config-editor{display:block;flex:1;min-width:0;min-height:0}.form-row{display:block;margin-bottom:12px}.form-grid{display:grid;gap:12px}.section-help{display:inline-flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.section-help__label{font-weight:500}.grid-2-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px}.grid-2-cols--compact{gap:12px}.w-100{width:100%}.visual-builder-content{padding:0!important;height:100%;min-width:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;gap:16px}.visual-builder-content>praxis-visual-builder{flex:0 0 auto;min-width:0;min-height:clamp(360px,48vh,560px)}.visual-builder-content>praxis-rule-properties-panel{flex:0 0 auto;display:block;min-width:0;padding:0 16px 24px;box-sizing:border-box}.rules-diagnostics{flex:0 0 auto;display:grid;gap:10px;padding:12px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}.rules-diagnostics--empty{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.rules-diagnostics__summary,.rules-diagnostics__list{display:flex;flex-wrap:wrap;gap:8px}.rules-diagnostics__pill{display:inline-flex;align-items:center;min-height:24px;padding:3px 9px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:12px;font-weight:600}.rules-diagnostics__pill--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 72%,transparent);color:var(--md-sys-color-on-tertiary-container)}.rules-diagnostics__pill--error{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.rules-diagnostics__item{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;min-width:min(100%,280px);padding:8px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.rules-diagnostics__item>div{display:grid;gap:2px;min-width:0}.rules-diagnostics__item strong{color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rules-diagnostics__item span{color:var(--md-sys-color-on-surface-variant);font-size:11px}.rules-diagnostics__actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}.rules-diagnostics__details{display:grid;gap:2px;margin:4px 0 0;padding-left:16px;color:var(--md-sys-color-on-surface-variant);font-size:11px;line-height:1.35}.rules-diagnostics__details li{overflow-wrap:anywhere}.rules-diagnostics__item--warn{border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 52%,var(--md-sys-color-outline-variant))}.rules-diagnostics__item--error{border-color:var(--md-sys-color-error)}.rules-diagnostics__status{font-weight:600;margin-top:1px}.rules-diagnostics__action{min-width:0;height:28px;padding:0 10px;border-radius:999px;font-size:12px;line-height:1}.rules-diagnostics__action mat-icon{width:16px;height:16px;margin:0 4px 0 0;font-size:16px}.json-field{width:100%}.presentation-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:20px;align-items:start}.presentation-controls{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:14px 18px}.control{display:flex;flex-direction:column}.control-span{grid-column:1/-1}.block-status{grid-column:1/-1;display:flex;gap:8px;align-items:flex-start;padding:10px 12px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 35%,transparent);color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.45}.block-status strong{min-width:112px;font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.block-status--implicit{background:color-mix(in srgb,var(--md-sys-color-surface-variant) 42%,transparent);border:1px dashed var(--md-sys-color-outline)}.block-status--readonly{margin-bottom:12px}.block-status code{font-family:var(--md-ref-typeface-mono, \"Courier New\", monospace);font-size:11px}.control__label{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-bottom:6px}.toggle-group{max-width:100%;flex-wrap:wrap}.control--inline{grid-column:1/-1;display:flex;gap:16px;align-items:center}.presentation-preview{min-width:0;order:-1}.preview-card{border:1px solid var(--md-sys-color-outline);border-radius:12px;padding:14px;background:var(--md-sys-color-surface-container)}.preview-row{display:flex;gap:8px;padding:6px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.preview-row:last-child{border-bottom:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.presentation-preview .praxis-presentation__label{color:var(--md-sys-color-on-surface-variant);font-size:var(--pfx-pres-label-size, 12px)}.presentation-preview .praxis-presentation__value{min-width:0;overflow-wrap:anywhere;font-size:var(--pfx-pres-value-size, 16px);color:var(--md-sys-color-on-surface)}.presentation-preview .presentation-mode.pres-density-cozy .preview-row{padding:6px 0}.presentation-preview .presentation-mode.pres-density-compact .preview-row,.presentation-preview .presentation-mode.pres-compact .preview-row{padding:2px 0}.presentation-preview .presentation-mode.pres-label-left .preview-row{display:grid;grid-template-columns:var(--pfx-pres-label-width, 140px) 1fr;align-items:baseline;column-gap:10px}.presentation-preview .presentation-mode.pres-label-left .praxis-presentation__label{margin:0;text-align:var(--pfx-pres-label-align, start)}.presentation-preview .presentation-mode .praxis-presentation__value{text-align:var(--pfx-pres-value-align, start)}.presentation-preview h4{margin:0 0 8px;color:var(--md-sys-color-on-surface);font-size:1rem}.section-card:not(.section-card--json),.section-card:not(.section-card--json).mat-mdc-card,.section-card:not(.section-card--json).mat-mdc-card-outlined{border:none!important;border-width:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;margin:0!important;padding:0!important;--mdc-outlined-card-outline-width: 0px;--mdc-outlined-card-outline-color: transparent;--mdc-elevated-card-container-color: transparent;--mdc-outlined-card-container-color: transparent}.section-card:not(.section-card--json)>mat-card-content,.section-card:not(.section-card--json)>.mat-mdc-card-content{padding:0!important}.section-card:not(.section-card--json)+.section-card:not(.section-card--json),.section-card:not(.section-card--json).mat-mdc-card+.section-card:not(.section-card--json).mat-mdc-card{padding-top:24px!important;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 65%,transparent)!important}.section-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:16px}.tab-content--dense{padding:16px 20px 24px;gap:20px}.tab-content--dense .section-header{margin-bottom:10px}.tab-content--dense .form-row{margin-bottom:8px}.section-header h3{margin:0;font-size:1rem;font-weight:600;letter-spacing:-.01em;color:var(--md-sys-color-on-surface)}.text-caption{margin:4px 0 0;font-size:.85rem;line-height:1.45;color:var(--md-sys-color-on-surface-variant)}.section-header--compact{margin-bottom:10px}.section-body{display:block}.section-body--flex{flex:1;min-height:0;display:flex;flex-direction:column}.builder-header{padding:12px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.builder-header h3{margin:0;font-size:1rem;color:var(--md-sys-color-on-surface)}.hint{margin:8px 0 0;padding:10px 12px;border-radius:8px;border:1px dashed color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 75%,transparent);color:var(--md-sys-color-on-surface-variant)}.meta-card{display:grid;gap:8px;padding:12px 14px;border-radius:8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);color:var(--md-sys-color-on-surface)}.meta-row{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.meta-row strong{color:var(--md-sys-color-on-surface);font-weight:600}.runtime-contract-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px 14px}.runtime-contract-field{display:grid;gap:4px;padding:10px 12px;border-radius:8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 65%,transparent)}.runtime-contract-label{font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--md-sys-color-on-surface-variant)}.runtime-contract-code{display:block;font-family:var(--md-ref-typeface-mono, \"Courier New\", monospace);font-size:12px;line-height:1.45;color:var(--md-sys-color-on-surface);word-break:break-word;white-space:normal}.command-rules-card,.command-rules-card.mat-mdc-card,.command-rules-card.mat-mdc-card-outlined{margin:0!important;padding:20px 16px 24px!important;min-width:0;border:none!important;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 65%,transparent)!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;--mdc-outlined-card-outline-width: 0px;--mdc-outlined-card-outline-color: transparent;--mdc-elevated-card-container-color: transparent;--mdc-outlined-card-container-color: transparent}.command-rules-card>mat-card-content,.command-rules-card>.mat-mdc-card-content{padding:12px 0 0!important}.command-rules-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr));gap:12px;align-items:start;min-width:0}.command-rules-toolbar,.command-rules-options,.command-rules-actions{grid-column:1/-1;display:flex;align-items:center;gap:12px;flex-wrap:wrap}.command-rules-select{min-width:min(320px,100%)}.command-rules-full{grid-column:1/-1}.command-rule-condition-builder{min-height:420px;overflow:hidden;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.command-rules-payload-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px;min-width:0;padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.command-rules-section-title{grid-column:1/-1;font-size:12px;font-weight:600;color:var(--md-sys-color-on-surface-variant);text-transform:uppercase}.command-rules-surface-editor{grid-column:1/-1}.command-rule-preview{display:grid;gap:8px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}.command-rule-preview--invalid{border-color:var(--md-sys-color-error)}.command-rule-preview__row{display:grid;grid-template-columns:minmax(96px,.35fr) minmax(0,1fr);gap:8px;align-items:start;min-width:0}.command-rule-preview__row span{color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600}.command-rule-preview__row strong,.command-rule-preview__row code{min-width:0;overflow-wrap:anywhere}.command-rule-preview__diagnostics{display:flex;gap:8px;align-items:flex-start;color:var(--md-sys-color-on-surface-variant)}@container praxis-authoring-editor (max-width: 768px){.mobile-tab-selector{display:block}::ng-deep .mat-mdc-tab-group.config-tabs>.mat-mdc-tab-header{display:none}.tab-content{padding:12px}.json-tab-content{padding:8px}.section-card--json{min-height:auto}}.form-modes{display:flex;flex-direction:column;align-items:flex-start;gap:16px}.form-modes mat-button-toggle-group{max-width:100%;flex-wrap:wrap}.display-result{margin:0;padding-block:12px;color:var(--md-sys-color-on-surface);font:var(--md-sys-typescale-body-medium)}.presentation-preview .presentation-mode.pres-label-above .preview-row{flex-direction:column;gap:4px}.presentation-controls,.control{min-width:0}.control__hint{margin:6px 0 0;color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-body-small, 400 12px/1.45 sans-serif)}.block-status{flex-wrap:wrap}:host{container-type:inline-size}@container (min-width: 900px){.presentation-layout{grid-template-columns:minmax(0,1fr) minmax(280px,.8fr)}.presentation-preview{order:1;position:sticky;top:16px}}.empty-state-fields{display:grid;align-items:start;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:var(--p-space-3, 12px);margin-block-start:var(--p-space-4, 16px)}.empty-state-appearance summary{cursor:pointer;padding-block:var(--p-space-3, 12px);color:var(--md-sys-color-on-surface)}.empty-state-content{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}.empty-state-description{grid-column:1/-1}.empty-state-content mat-form-field{min-width:0}.empty-state-icon-actions{display:inline-flex;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.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$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i6$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i6$2.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"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i7$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i7$1.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i7$1.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i7$1.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.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: i3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i2$2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2$2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2$2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i3$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: i3$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4$1.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: MatCheckboxModule }, { kind: "component", type: i12.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i5$1.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i7$2.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i7$2.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.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: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "component", type: JsonConfigEditorComponent, selector: "form-json-config-editor", inputs: ["config", "document"], outputs: ["configChange", "documentChange", "validationChange", "editorEvent"] }, { kind: "component", type: LayoutEditorComponent, selector: "praxis-layout-editor", inputs: ["config"], outputs: ["configChange", "select"] }, { kind: "component", type: BehaviorEditorComponent, selector: "praxis-behavior-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: ActionsEditorComponent$1, selector: "praxis-actions-editor", inputs: ["config"], outputs: ["configChange", "validationChange"] }, { kind: "component", type: MessagesEditorComponent, selector: "praxis-messages-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: HooksEditorComponent, selector: "praxis-hooks-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: RulePropertiesPanelComponent, selector: "praxis-rule-properties-panel", inputs: ["rules", "visualBlockNodes"], outputs: ["rulesChange"] }, { kind: "component", type: PraxisVisualBuilder, selector: "praxis-visual-builder", inputs: ["mode", "config", "initialRules", "initialCondition"], outputs: ["rulesChanged", "conditionChanged", "exportRequested", "importRequested"] }, { kind: "component", type: CascadeManagerTabComponent, selector: "praxis-cascade-manager-tab", inputs: ["fields", "connections"], outputs: ["apply", "cancel", "validChange"] }, { kind: "component", type: SurfaceOpenActionEditorComponent, selector: "praxis-surface-open-action-editor", inputs: ["value", "hostKind"], outputs: ["valueChange", "validationChange"] }, { kind: "pipe", type: i1$2.JsonPipe, name: "json" }] });
34019
34052
  }
34020
34053
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisDynamicFormConfigEditor, decorators: [{
34021
34054
  type: Component,
@@ -34045,7 +34078,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
34045
34078
  PraxisVisualBuilder,
34046
34079
  CascadeManagerTabComponent,
34047
34080
  SurfaceOpenActionEditorComponent,
34048
- ], providers: [FormConfigService, providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG)], template: "<div class=\"mobile-tab-selector\">\n <mat-form-field appearance=\"outline\" class=\"mobile-tab-selector__field\">\n <mat-label>{{ tx('config.tabs.mobileLabel', 'Se\u00E7\u00E3o do editor') }}</mat-label>\n <mat-select [(ngModel)]=\"selectedConfigTabIndex\" data-testid=\"dynamic-form-config-editor-mobile-tabs\">\n @for (tab of configTabOptions; track tab.key) {\n <mat-option [value]=\"tab.index\">{{ tab.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n\n<mat-tab-group [preserveContent]=\"true\" class=\"config-tabs\" data-testid=\"dynamic-form-config-editor-tabs\" [(selectedIndex)]=\"selectedConfigTabIndex\">\n <mat-tab [label]=\"configTabLabel('general')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-geral\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.general.title', 'Dados do formul\u00E1rio') }}</h3>\n <p class=\"text-caption\">{{ tx('config.general.subtitle', 'Defina o modo de dados e o contexto de edi\u00E7\u00E3o.') }}</p>\n </div>\n </div>\n <div class=\"form-modes\">\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.inputMode.label') }}</label>\n <mat-button-toggle-group [ngModel]=\"inputMode\" (ngModelChange)=\"inputMode = $event; onInputModeChange()\" [attr.aria-label]=\"tx('config.general.inputMode.label')\">\n <mat-button-toggle value=\"create\">{{ tx('config.general.inputMode.create') }}</mat-button-toggle>\n <mat-button-toggle value=\"edit\">{{ tx('config.general.inputMode.edit') }}</mat-button-toggle>\n <mat-button-toggle value=\"view\">{{ tx('config.general.inputMode.view') }}</mat-button-toggle>\n </mat-button-toggle-group>\n @if (inputMode === 'presentation' || inputMode === 'dossier') {\n <p class=\"control__hint\" data-testid=\"dynamic-form-native-mode-hint\" role=\"status\">\n {{ tx('config.general.inputMode.nativeMode', undefined, { mode: inputMode }) }}\n </p>\n }\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.layoutScope.label', 'Escopo de persist\u00EAncia do layout') }}</label>\n <mat-button-toggle-group\n data-testid=\"dynamic-form-layout-scope-toggle\"\n [ngModel]=\"inputLayoutScope\"\n (ngModelChange)=\"onLayoutScopeChange($event)\"\n [attr.aria-label]=\"tx('config.general.layoutScope.label', 'Escopo de persist\u00EAncia do layout')\">\n <mat-button-toggle value=\"shared\" data-testid=\"dynamic-form-layout-scope-shared\">\n {{ tx('config.general.layoutScope.shared', 'Todos os modos (Criar / Editar / Visualizar)') }}\n </mat-button-toggle>\n <mat-button-toggle value=\"mode-only\" data-testid=\"dynamic-form-layout-scope-mode-only\">\n {{ tx('config.general.layoutScope.modeOnly', 'Somente este modo ({{mode}})', { mode: tx('config.general.inputMode.' + inputMode, inputMode) }) }}\n </mat-button-toggle>\n </mat-button-toggle-group>\n <p class=\"control__hint\" data-testid=\"dynamic-form-layout-scope-hint\" role=\"status\">\n {{ inputLayoutScope === 'mode-only'\n ? tx('config.general.layoutScope.modeOnlyHint', 'Ao salvar, aplica este layout exclusivamente ao modo atual, sem alterar os demais modos.')\n : tx('config.general.layoutScope.sharedHint', 'Ao salvar, replica se\u00E7\u00F5es e grade nos demais modos que ainda compartilham layout.') }}\n </p>\n </div>\n @if (supportsPresentationSettings) {\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.displayMode.label') }}</label>\n <mat-button-toggle-group [ngModel]=\"displayMode\" (ngModelChange)=\"onDisplayModeChange($event)\" [attr.aria-label]=\"tx('config.general.displayMode.label')\">\n <mat-button-toggle value=\"automatic\">{{ tx('config.general.displayMode.automatic') }}</mat-button-toggle>\n <mat-button-toggle value=\"fields\">{{ tx('config.general.displayMode.fields') }}</mat-button-toggle>\n <mat-button-toggle value=\"presentation\">{{ tx('config.general.displayMode.presentation') }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <p class=\"display-result\" role=\"status\">{{ tx(displayModeHint) }}</p>\n @if (inputMode !== 'view' && inputMode !== 'presentation' && inputMode !== 'dossier' && inputPresentationMode === true) {\n <button mat-stroked-button type=\"button\" (click)=\"useViewMode()\">{{ tx('config.general.displayMode.useView') }}</button>\n }\n <button mat-button type=\"button\" (click)=\"openPresentationStyle()\">{{ tx('config.general.displayMode.openStyle') }}</button>\n }\n </div>\n </mat-card-content>\n </mat-card>\n\n @if (supportsPresentationSettings) {\n <mat-card class=\"section-card\" data-testid=\"form-empty-state-settings\">\n <mat-card-content>\n <h3>{{ tx('config.emptyState.heading') }}</h3>\n <p class=\"text-caption\">{{ tx('config.emptyState.help') }}</p>\n <mat-slide-toggle [ngModel]=\"!!inputEmptyState\" (ngModelChange)=\"setEmptyStateEnabled($event)\">{{ tx('config.emptyState.enabled') }}</mat-slide-toggle>\n @if (inputMode !== 'view' && inputMode !== 'presentation' && inputMode !== 'dossier') { <p class=\"text-caption\">{{ tx('config.emptyState.viewOnly') }}</p> }\n @if (inputEmptyState; as empty) {\n <div class=\"empty-state-fields empty-state-content\">\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.title') }}</mat-label><input matInput required [(ngModel)]=\"empty.title\" (ngModelChange)=\"onEmptyStateChange()\" /><mat-hint *ngIf=\"!empty.title?.trim()\">{{ tx('config.emptyState.titleRequired') }}</mat-hint></mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.emptyState.icon') }}</mat-label>\n @if (empty.icon) { <mat-icon matPrefix [praxisIcon]=\"empty.icon\" aria-hidden=\"true\"></mat-icon> }\n <input matInput [(ngModel)]=\"empty.icon\" (ngModelChange)=\"onEmptyStateChange()\" />\n <span matSuffix class=\"empty-state-icon-actions\">\n <button mat-icon-button type=\"button\" [attr.aria-label]=\"tx('config.emptyState.pickIcon')\" (click)=\"pickEmptyStateIcon()\"><mat-icon aria-hidden=\"true\">search</mat-icon></button>\n @if (empty.icon) { <button mat-icon-button type=\"button\" [attr.aria-label]=\"tx('config.emptyState.clearIcon')\" (click)=\"empty.icon = ''; onEmptyStateChange()\"><mat-icon aria-hidden=\"true\">close</mat-icon></button> }\n </span>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"empty-state-description\"><mat-label>{{ tx('config.emptyState.description') }}</mat-label><textarea matInput rows=\"2\" [(ngModel)]=\"empty.description\" (ngModelChange)=\"onEmptyStateChange()\"></textarea></mat-form-field>\n </div>\n <details class=\"empty-state-appearance\"><summary>{{ tx('config.emptyState.appearance') }}</summary><div class=\"empty-state-fields\">\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.tone') }}</mat-label><mat-select [(ngModel)]=\"empty.tone\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.tone; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.variant') }}</mat-label><mat-select [(ngModel)]=\"empty.variant\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.variant; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.alignment') }}</mat-label><mat-select [(ngModel)]=\"empty.alignment\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.alignment; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.density') }}</mat-label><mat-select [(ngModel)]=\"empty.density\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.density; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.iconContainer') }}</mat-label><mat-select [(ngModel)]=\"empty.iconContainer\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.iconContainer; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n </div></details>\n }\n </mat-card-content>\n </mat-card>\n }\n\n @if (hasResolvedRuntimeContract()) {\n <mat-card\n class=\"section-card\"\n data-testid=\"config-tab-runtime-contract\"\n >\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.general.runtimeContract.title', 'Contrato Runtime Resolvido') }}</h3>\n <p class=\"text-caption\">\n {{ tx('config.general.runtimeContract.subtitle', 'Visualiza\u00E7\u00E3o somente leitura do contrato backend resolvido pelo host atual.') }}\n </p>\n </div>\n </div>\n <div class=\"block-status block-status--readonly\">\n <strong>{{ tx('config.general.runtimeContract.runtimeLabel', 'Runtime') }}</strong>\n <span>\n {{ tx('config.general.runtimeContract.readonly', 'Esses valores v\u00EAm do host/runtime atual e n\u00E3o s\u00E3o persistidos em `bindings` nem em `contextSnapshot`.') }}\n </span>\n </div>\n <div class=\"runtime-contract-grid\">\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.schemaUrl', 'Schema URL') }}</span>\n <code class=\"runtime-contract-code\">{{ runtimeContract?.schemaUrl || '\u2014' }}</code>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.schemaSource', 'Origem do schema') }}</span>\n <strong>{{ describeRuntimeSource(runtimeContract?.schemaSource) }}</strong>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitMethod', 'Submit method') }}</span>\n <strong>{{ runtimeContract?.submitMethod || '\u2014' }}</strong>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitUrl', 'Submit URL') }}</span>\n <code class=\"runtime-contract-code\">{{ runtimeContract?.submitUrl || '\u2014' }}</code>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitSource', 'Origem do submit') }}</span>\n <strong>{{ describeRuntimeSource(runtimeContract?.submitSource) }}</strong>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n }\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('schema')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-schema\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.schema.title', 'Valida\u00E7\u00E3o de schema') }}</h3>\n <p class=\"text-caption\">{{ tx('config.schema.subtitle', 'Controle avisos quando o schema do servidor mudar.') }}</p>\n </div>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.schema.notify.label', 'Notificar quando desatualizado') }}</mat-label>\n <mat-select [(ngModel)]=\"schemaPrefs.notifyIfOutdated\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-notify')\">\n <mat-option value=\"both\">{{ tx('config.schema.notify.both', 'Banner + Snackbar') }}</mat-option>\n <mat-option value=\"inline\">{{ tx('config.schema.notify.inline', 'Somente Banner') }}</mat-option>\n <mat-option value=\"snackbar\">{{ tx('config.schema.notify.snackbar', 'Somente Snackbar') }}</mat-option>\n <mat-option value=\"none\">{{ tx('config.schema.notify.none', 'Nenhum') }}</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.schema.snooze.label', 'Intervalo de sil\u00EAncio (ms)') }}</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"schemaPrefs.snoozeMs\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-snooze')\" />\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-slide-toggle [(ngModel)]=\"schemaPrefs.autoOpenSettingsOnOutdated\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-auto-open')\">\n {{ tx('config.schema.autoOpenSettings', 'Abrir configura\u00E7\u00F5es automaticamente') }}\n </mat-slide-toggle>\n </div>\n @if (serverMeta) {\n <div class=\"form-row\">\n <div class=\"meta-card\">\n <div class=\"meta-row\">\n <span>{{ tx('config.schema.meta.serverHash', 'Server hash') }}</span>\n <strong>{{ serverMeta.serverHash || '\u2014' }}</strong>\n </div>\n <div class=\"meta-row\">\n <span>{{ tx('config.schema.meta.lastVerifiedAt', '\u00DAltima verifica\u00E7\u00E3o') }}</span>\n <strong>{{ serverMeta.lastVerifiedAt || '\u2014' }}</strong>\n </div>\n </div>\n </div>\n }\n <div class=\"block-status\" [class.block-status--implicit]=\"!isSchemaPrefsBlockPersisted()\">\n <strong>{{ tx('config.schema.prefs.label', 'Schema Prefs') }}</strong>\n @if (isSchemaPrefsBlockPersisted()) {\n <span>{{ tx('config.schema.prefs.persisted', '`contextSnapshot.schemaPrefs` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.schema.prefs.implicit', 'Bloco ausente no documento can\u00F4nico. Os controles exibem fallback visual e n\u00E3o ser\u00E3o salvos at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('layout')\">\n <div class=\"tab-content tab-content--full\" data-testid=\"config-tab-panel-layout\">\n <div class=\"section-body section-body--flex\">\n <praxis-layout-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"\n (select)=\"onLayoutSelect($event)\"></praxis-layout-editor>\n </div>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('hooks')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-hooks\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.hooks.title', 'Hooks de ciclo de vida') }}</h3>\n <p class=\"text-caption\">{{ tx('config.hooks.subtitle', 'Automatize a\u00E7\u00F5es nos eventos do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <praxis-hooks-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-hooks-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n @if (isPresentationMode) {\n <mat-tab [label]=\"configTabLabel('presentation')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-presentation\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.presentation.title', 'Modo Apresenta\u00E7\u00E3o') }}</h3>\n <p class=\"text-caption\">{{ tx('config.presentation.subtitle', 'Configura\u00E7\u00F5es de exibi\u00E7\u00E3o aplicadas somente ao modo apresenta\u00E7\u00E3o.') }}</p>\n </div>\n </div>\n <p class=\"display-result\" role=\"status\">{{ tx(displayModeHint) }}</p>\n <div class=\"presentation-layout\">\n <div class=\"presentation-controls\">\n <div class=\"block-status control-span\" [class.block-status--implicit]=\"!isPresentationBlockPersisted()\">\n <strong>{{ tx('config.presentation.block.label', 'Presentation') }}</strong>\n @if (isPresentationBlockPersisted()) {\n <span>{{ tx('config.presentation.block.persisted', '`contextSnapshot.presentation` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.presentation.block.implicit', 'Bloco ausente no documento can\u00F4nico. A pr\u00E9-visualiza\u00E7\u00E3o usa fallback local e n\u00E3o ser\u00E1 salva at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.labelPosition.label', 'Posi\u00E7\u00E3o do r\u00F3tulo') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.labelPosition\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-position')\" [attr.aria-label]=\"tx('config.presentation.labelPosition.ariaLabel', 'Posi\u00E7\u00E3o do r\u00F3tulo')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"above\">\n <mat-icon>view_stream</mat-icon>\n <span class=\"sr-only\">{{ tx('config.presentation.labelPosition.above', 'Acima') }}</span>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n <mat-icon>view_column</mat-icon>\n <span class=\"sr-only\">{{ tx('config.presentation.labelPosition.left', '\u00C0 esquerda') }}</span>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control control-span\">\n <label class=\"control__label\">{{ tx('config.presentation.density.label', 'Densidade') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.density\" (ngModelChange)=\"onPresentationPrefsChange('presentation-density')\" [attr.aria-label]=\"tx('config.presentation.density.ariaLabel', 'Densidade')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"comfortable\">{{ tx('config.presentation.density.comfortable', 'Confort\u00E1vel') }}</mat-button-toggle>\n <mat-button-toggle value=\"cozy\">{{ tx('config.presentation.density.cozy', 'Intermedi\u00E1ria') }}</mat-button-toggle>\n <mat-button-toggle value=\"compact\">{{ tx('config.presentation.density.compact', 'Compacta') }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.labelAlign.label', 'Alinhamento do r\u00F3tulo') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.labelAlign\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-align')\" [attr.aria-label]=\"tx('config.presentation.labelAlign.ariaLabel', 'Alinhamento do r\u00F3tulo')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"start\" [aria-label]=\"tx('config.presentation.align.start')\" [matTooltip]=\"tx('config.presentation.align.start')\"><mat-icon>format_align_left</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"center\" [aria-label]=\"tx('config.presentation.align.center')\" [matTooltip]=\"tx('config.presentation.align.center')\"><mat-icon>format_align_center</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"end\" [aria-label]=\"tx('config.presentation.align.end')\" [matTooltip]=\"tx('config.presentation.align.end')\"><mat-icon>format_align_right</mat-icon></mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.valueAlign.label', 'Alinhamento do valor') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.valueAlign\" (ngModelChange)=\"onPresentationPrefsChange('presentation-value-align')\" [attr.aria-label]=\"tx('config.presentation.valueAlign.ariaLabel', 'Alinhamento do valor')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"start\" [aria-label]=\"tx('config.presentation.align.start')\" [matTooltip]=\"tx('config.presentation.align.start')\"><mat-icon>format_align_left</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"center\" [aria-label]=\"tx('config.presentation.align.center')\" [matTooltip]=\"tx('config.presentation.align.center')\"><mat-icon>format_align_center</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"end\" [aria-label]=\"tx('config.presentation.align.end')\" [matTooltip]=\"tx('config.presentation.align.end')\"><mat-icon>format_align_right</mat-icon></mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.labelFontSize.label', 'Tamanho do r\u00F3tulo') }}</mat-label>\n <input matInput type=\"number\" min=\"10\" step=\"any\" [(ngModel)]=\"presentationPrefs.labelFontSize\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-font-size')\"\n [placeholder]=\"tx('config.presentation.labelFontSize.placeholder', 'ex.: 12')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.valueFontSize.label', 'Tamanho do valor') }}</mat-label>\n <input matInput type=\"number\" min=\"10\" step=\"any\" [(ngModel)]=\"presentationPrefs.valueFontSize\" (ngModelChange)=\"onPresentationPrefsChange('presentation-value-font-size')\"\n [placeholder]=\"tx('config.presentation.valueFontSize.placeholder', 'ex.: 16')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.labelWidth.label', 'Largura do r\u00F3tulo (label \u00E0 esquerda)') }}</mat-label>\n <input matInput type=\"number\" min=\"60\" [disabled]=\"presentationPrefs.labelPosition !== 'left'\" [(ngModel)]=\"presentationPrefs.labelWidth\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-width')\"\n [placeholder]=\"tx('config.presentation.labelWidth.placeholder', 'ex.: 140')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control control--inline\">\n <mat-slide-toggle [(ngModel)]=\"presentationPrefs.compact\" (ngModelChange)=\"onPresentationPrefsChange('presentation-compact')\">\n {{ tx('config.presentation.options.compactMode', 'Modo compacto') }}\n </mat-slide-toggle>\n <mat-checkbox [(ngModel)]=\"truncatePreview\">\n {{ tx('config.presentation.options.truncateValues', 'Truncar valores') }}\n </mat-checkbox>\n </div>\n </div>\n <div class=\"presentation-preview\">\n <h4>{{ tx('config.presentation.preview.title', 'Pr\u00E9-visualiza\u00E7\u00E3o') }}</h4>\n <p class=\"text-caption\">{{ tx('config.presentation.preview.sampleHint') }}</p>\n <div class=\"preview-card\">\n <div class=\"praxis-dynamic-form presentation-mode\" [ngClass]=\"{\n 'pres-compact': !!presentationPrefs.compact,\n 'pres-label-left': presentationPrefs.labelPosition === 'left',\n 'pres-label-above': presentationPrefs.labelPosition === 'above',\n 'pres-density-compact': presentationPrefs.density === 'compact',\n 'pres-density-cozy': presentationPrefs.density === 'cozy'\n }\" [style.--pfx-pres-label-size]=\"(presentationPrefs.labelFontSize || 12) + 'px'\"\n [style.--pfx-pres-value-size]=\"(presentationPrefs.valueFontSize || 16) + 'px'\"\n [style.--pfx-pres-label-width]=\"(presentationPrefs.labelWidth || 140) + 'px'\"\n [style.--pfx-pres-label-align]=\"presentationPrefs.labelAlign || 'start'\"\n [style.--pfx-pres-value-align]=\"presentationPrefs.valueAlign || 'start'\">\n @for (item of previewItems; track item) {\n <div class=\"preview-row\">\n <span class=\"praxis-presentation__label\">{{ item.label }}</span>\n <span class=\"praxis-presentation__value\" [attr.title]=\"truncatePreview ? item.value : null\"\n [style.maxWidth]=\"truncatePreview ? '280px' : null\"\n [style.overflow]=\"truncatePreview ? 'hidden' : null\"\n [style.textOverflow]=\"truncatePreview ? 'ellipsis' : null\"\n [style.whiteSpace]=\"truncatePreview ? 'nowrap' : 'normal'\">\n {{ item.value }}\n </span>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n }\n <mat-tab [label]=\"configTabLabel('behavior')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-comportamento\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.behavior.title', 'Comportamento') }}</h3>\n <p class=\"text-caption\">{{ tx('config.behavior.subtitle', 'Ajuste valida\u00E7\u00F5es e respostas do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <praxis-behavior-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-behavior-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('hints')\">\n <div class=\"tab-content tab-content--dense\" data-testid=\"config-tab-panel-hints\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.hints.title', 'Dicas dos modos') }}</h3>\n <p class=\"text-caption\">{{ tx('config.hints.subtitle', 'Personalize textos de apoio para modos de dados e estados de UI.') }}</p>\n </div>\n </div>\n <p class=\"text-caption\">{{ tx('config.hints.description', 'Personalize os textos usados como tooltip/hint para modos de dados e modos globais de UI.') }}</p>\n\n <div class=\"grid-2-cols grid-2-cols--compact\">\n <section>\n <h4>{{ tx('config.hints.dataModes.title', 'Modos de dados') }}</h4>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.create.label', 'Criar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.create\"\n (ngModelChange)=\"updateDirtyState('hints-data-create')\" [placeholder]=\"tx('config.hints.dataModes.create.placeholder', 'Ex.: Preencha os campos obrigat\u00F3rios.')\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.edit.label', 'Editar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.edit\"\n (ngModelChange)=\"updateDirtyState('hints-data-edit')\" [placeholder]=\"tx('config.hints.dataModes.edit.placeholder', 'Ex.: Revise os dados antes de salvar.')\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.view.label', 'Visualizar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.view\"\n (ngModelChange)=\"updateDirtyState('hints-data-view')\" [placeholder]=\"tx('config.hints.dataModes.view.placeholder', 'Ex.: Visualiza\u00E7\u00E3o somente leitura.')\" />\n </mat-form-field>\n </section>\n\n <section>\n <h4>{{ tx('config.hints.uiModes.title', 'Modos de UI') }}</h4>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.presentation.label', 'Apresenta\u00E7\u00E3o') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.presentation\"\n (ngModelChange)=\"updateDirtyState('hints-ui-presentation')\" [placeholder]=\"tx('config.hints.uiModes.presentation.placeholder', 'Ex.: Modo compacto para leitura r\u00E1pida.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.readonly.label', 'Leitura (readonly)') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.readonly\"\n (ngModelChange)=\"updateDirtyState('hints-ui-readonly')\" [placeholder]=\"tx('config.hints.uiModes.readonly.placeholder', 'Ex.: Campos bloqueados para edi\u00E7\u00E3o.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.disabled.label', 'Desabilitado') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.disabled\"\n (ngModelChange)=\"updateDirtyState('hints-ui-disabled')\" [placeholder]=\"tx('config.hints.uiModes.disabled.placeholder', 'Ex.: Fun\u00E7\u00E3o indispon\u00EDvel no momento.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.visible.label', 'Vis\u00EDvel') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.visible\"\n (ngModelChange)=\"updateDirtyState('hints-ui-visible')\" [placeholder]=\"tx('config.hints.uiModes.visible.placeholder', 'Ex.: Campo exibido conforme permiss\u00F5es.')\"></textarea>\n </mat-form-field>\n </section>\n </div>\n\n <section>\n <h4>{{ tx('config.helpPresentation.title', 'Apresenta\u00E7\u00E3o das ajudas dos campos') }}</h4>\n <p class=\"text-caption\">{{ tx('config.helpPresentation.description', 'Controle como hint/helpText dos campos aparece em formul\u00E1rios densos. Erros de valida\u00E7\u00E3o continuam inline.') }}</p>\n <div class=\"grid-3-cols\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.display.label', 'Exibi\u00E7\u00E3o') }}</mat-label>\n <mat-select [ngModel]=\"helpPresentationDraft.display\" (ngModelChange)=\"onHelpPresentationDisplayChange($event)\">\n <mat-option value=\"inline\">{{ tx('config.helpPresentation.display.inline', 'Inline') }}</mat-option>\n <mat-option value=\"popover\">{{ tx('config.helpPresentation.display.popover', '\u00CDcone de ajuda') }}</mat-option>\n <mat-option value=\"auto\">{{ tx('config.helpPresentation.display.auto', 'Autom\u00E1tica') }}</mat-option>\n <mat-option value=\"hidden\">{{ tx('config.helpPresentation.display.hidden', 'Oculta') }}</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.inlineMaxLength.label', 'Limite inline') }}</mat-label>\n <input matInput type=\"number\" min=\"0\" [ngModel]=\"helpPresentationDraft.inlineMaxLength\"\n (ngModelChange)=\"onHelpPresentationInlineMaxLengthChange($event)\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.preferPopoverForControls.label', 'Preferir \u00EDcone em') }}</mat-label>\n <input matInput [ngModel]=\"getHelpPreferPopoverControlsText()\"\n (ngModelChange)=\"onHelpPreferPopoverControlsChange($event)\"\n [placeholder]=\"tx('config.helpPresentation.preferPopoverForControls.placeholder', 'toggle, checkbox, select')\" />\n </mat-form-field>\n </div>\n </section>\n\n <div class=\"actions-row\">\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"restoreHintsDefaults()\">\n <mat-icon>restore</mat-icon>\n {{ tx('config.hints.actions.restoreDefaults', 'Restaurar padr\u00F5es') }}\n </button>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('actions')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-acoes\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.actions.title', 'A\u00E7\u00F5es do formul\u00E1rio') }}</h3>\n <p class=\"text-caption\">{{ tx('config.actions.subtitle', 'Configure bot\u00F5es padr\u00E3o e a\u00E7\u00F5es customizadas.') }}</p>\n </div>\n </div>\n <praxis-actions-editor #actionsDraft [config]=\"editedConfig\" (validationChange)=\"onSurfaceDraftValidity(actionsDraft, $event)\" (configChange)=\"onConfigChange($event)\"></praxis-actions-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('rules')\">\n <div class=\"tab-content visual-builder-content\" data-testid=\"config-tab-panel-regras\">\n <div class=\"builder-header\">\n <div>\n <h3>{{ tx('config.rules.title', 'Regras visuais') }}</h3>\n <p class=\"text-caption\">{{ tx('config.rules.subtitle', 'Defina visibilidade, estilos e rea\u00E7\u00F5es baseadas em condi\u00E7\u00F5es.') }}</p>\n </div>\n </div>\n @if (ruleConversionFailed) {\n <p role=\"alert\" data-testid=\"rules-conversion-error\">\n {{ tx('config.rules.conversionError', 'N\u00E3o foi poss\u00EDvel converter a condi\u00E7\u00E3o visual. Revise a regra; aplicar e salvar est\u00E3o bloqueados.') }}\n </p>\n }\n @if (ruleDiagnostics.length) {\n <div class=\"rules-diagnostics\" data-testid=\"rules-diagnostics-panel\">\n <div class=\"rules-diagnostics__summary\">\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--total\">\n {{ tx('config.rules.summary.total', '{{count}} regras', { count: ruleDiagnosticsSummary.total }) }}\n </span>\n @if (ruleDiagnosticsSummary.invalid) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--error\">\n {{ tx('config.rules.summary.invalid', '{{count}} inv\u00E1lidas', { count: ruleDiagnosticsSummary.invalid }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.unsupported) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.unsupported', '{{count}} com propriedades rejeitadas', { count: ruleDiagnosticsSummary.unsupported }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.runtimeOnly) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.runtimeOnly', '{{count}} runtime only', { count: ruleDiagnosticsSummary.runtimeOnly }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.pendingReview) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.pendingReview', '{{count}} pendentes de revis\u00E3o', { count: ruleDiagnosticsSummary.pendingReview }) }}\n </span>\n }\n </div>\n <div class=\"rules-diagnostics__list\" [attr.aria-label]=\"tx('config.rules.diagnostics.ariaLabel', 'Diagn\u00F3stico das regras')\">\n @for (diagnostic of ruleDiagnostics; track diagnostic) {\n <article class=\"rules-diagnostics__item\"\n [class.rules-diagnostics__item--error]=\"getRuleStatusTone(diagnostic) === 'error'\"\n [class.rules-diagnostics__item--warn]=\"getRuleStatusTone(diagnostic) === 'warn'\">\n <div>\n <strong>{{ diagnostic.ruleName || diagnostic.ruleId }}</strong>\n <span>\n {{ tx('config.rules.diagnostics.targetConditionSummary', '{{targets}} alvo(s) \u00B7 {{conditions}} campo(s) na condi\u00E7\u00E3o', { targets: diagnostic.targetRefs.length, conditions: diagnostic.conditionRefs.length }) }}\n </span>\n @if (getRuleDiagnosticDetails(diagnostic).length) {\n <ul class=\"rules-diagnostics__details\">\n @for (detail of getRuleDiagnosticDetails(diagnostic); track detail) {\n <li>{{ detail }}</li>\n }\n </ul>\n }\n </div>\n <div class=\"rules-diagnostics__actions\">\n <span class=\"rules-diagnostics__status\">{{ getRuleStatusLabel(diagnostic) }}</span>\n @if (canApplyRulePropertyFix(diagnostic)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [matTooltip]=\"tx('config.rules.actions.fix.tooltip', 'Aplicar whitelist e saneamento de propriedades nesta regra')\"\n (click)=\"applyRulePropertyFix(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">auto_fix_high</mat-icon>\n {{ tx('config.rules.actions.fix', 'Corrigir') }}\n </button>\n }\n @if (diagnostic.status.includes('llm-generated-pending-review')) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [disabled]=\"!canAcceptPendingLlmRule(diagnostic)\"\n [matTooltip]=\"canAcceptPendingLlmRule(diagnostic) ? tx('config.rules.actions.accept.tooltip.ready', 'Aceitar sugest\u00E3o e atualizar estado visual') : tx('config.rules.actions.accept.tooltip.blocked', 'Corrija alvo, condi\u00E7\u00E3o e propriedades antes de aceitar')\"\n (click)=\"acceptPendingLlmRule(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n {{ tx('config.rules.actions.accept', 'Aceitar') }}\n </button>\n }\n @if (canOpenRuleJsonReview(diagnostic)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [matTooltip]=\"tx('config.rules.actions.reviewJson.tooltip', 'Abrir a aba JSON para revisar esta regra sem convers\u00E3o visual')\"\n (click)=\"openRuleJsonReview(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">data_object</mat-icon>\n {{ tx('config.rules.actions.reviewJson', 'Ver JSON') }}\n </button>\n }\n </div>\n </article>\n }\n </div>\n </div>\n } @else {\n <div class=\"rules-diagnostics rules-diagnostics--empty\" data-testid=\"rules-diagnostics-empty\">\n {{ tx('config.rules.empty', 'Nenhuma regra definida ainda. Crie uma regra para ver alvos, condi\u00E7\u00E3o, propriedades e compatibilidade do builder.') }}\n </div>\n }\n <praxis-visual-builder [config]=\"ruleBuilderConfig\" [initialRules]=\"ruleBuilderState\"\n (rulesChanged)=\"onRulesChanged($event)\"></praxis-visual-builder>\n <praxis-rule-properties-panel\n [rules]=\"currentRules\"\n [visualBlockNodes]=\"visualBlockNodeOptions\"\n (rulesChange)=\"onRulePropertiesChanged($event)\"\n ></praxis-rule-properties-panel>\n <mat-card class=\"command-rules-card\" data-testid=\"form-command-rules-editor\">\n <mat-card-title>{{ tx('config.commandRules.title', 'Comandos condicionais') }}</mat-card-title>\n <mat-card-subtitle>{{ tx('config.commandRules.subtitle', 'Execute a\u00E7\u00F5es globais quando uma condi\u00E7\u00E3o do formul\u00E1rio for satisfeita.') }}</mat-card-subtitle>\n <mat-card-content>\n <div class=\"command-rules-grid\">\n <div class=\"command-rules-toolbar\">\n <mat-form-field appearance=\"outline\" class=\"command-rules-select\">\n <mat-label>{{ tx('config.commandRules.command.label', 'Comando') }}</mat-label>\n <mat-select [disabled]=\"hasInvalidSurfaceDraft\" [(ngModel)]=\"selectedCommandRuleId\" (selectionChange)=\"onCommandRuleSelectionChange()\">\n @for (rule of commandRules; track rule) {\n <mat-option [value]=\"rule.id\">\n {{ rule.id }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <button mat-stroked-button type=\"button\" [disabled]=\"hasInvalidSurfaceDraft\" (click)=\"addCommandRule()\">\n <mat-icon aria-hidden=\"true\">add</mat-icon>\n {{ tx('config.commandRules.actions.add', 'Adicionar') }}\n </button>\n <button mat-stroked-button color=\"warn\" type=\"button\" (click)=\"deleteCommandRule()\" [disabled]=\"hasInvalidSurfaceDraft || !selectedCommandRuleId\">\n <mat-icon aria-hidden=\"true\">delete</mat-icon>\n {{ tx('config.commandRules.actions.remove', 'Remover') }}\n </button>\n </div>\n\n @if (selectedCommandRuleId) {\n <div class=\"command-rule-condition-builder command-rules-full\">\n <praxis-visual-builder\n mode=\"condition\"\n [config]=\"ruleBuilderConfig\"\n [initialCondition]=\"commandRuleCondition\"\n (conditionChanged)=\"onCommandConditionChanged($event)\"\n ></praxis-visual-builder>\n </div>\n }\n\n <mat-form-field appearance=\"outline\" class=\"command-rules-full\">\n <mat-label>{{ tx('config.commandRules.conditionJson.label', 'Condi\u00E7\u00E3o JSON Logic') }}</mat-label>\n <textarea\n matInput\n rows=\"5\"\n [(ngModel)]=\"commandRuleConditionJson\"\n [attr.aria-label]=\"tx('config.commandRules.conditionJson.ariaLabel', 'Condi\u00E7\u00E3o JSON Logic do comando condicional')\"\n ></textarea>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.commandRules.globalAction.label', 'A\u00E7\u00E3o global') }}</mat-label>\n <mat-select [disabled]=\"hasInvalidSurfaceDraft\" [(ngModel)]=\"commandRuleActionId\" (selectionChange)=\"onCommandActionChange()\">\n @for (action of globalActionCatalog; track action) {\n <mat-option [value]=\"action.id\">\n {{ action.label || action.id }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.commandRules.distinctBy.label', 'distinctBy') }}</mat-label>\n <input matInput [(ngModel)]=\"commandRuleDistinctBy\" [placeholder]=\"tx('config.commandRules.distinctBy.placeholder', 'ex.: idade')\" />\n </mat-form-field>\n\n @if (commandRuleActionSchema; as actionSchema) {\n <div\n class=\"command-rules-payload-fields command-rules-full\"\n >\n <div class=\"command-rules-section-title\">{{ tx('config.commandRules.structuredPayload.title', 'Payload estruturado') }}</div>\n @if (actionSchema.editorMode !== 'surface-open') {\n @for (field of actionSchema.fields; track field) {\n @if (shouldShowCommandActionField(field)) {\n @if (field.type === 'toggle') {\n <mat-slide-toggle\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n {{ field.label }}\n </mat-slide-toggle>\n } @else {\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ field.label }}</mat-label>\n @if (field.type === 'textarea' || field.type === 'json') {\n <textarea\n matInput\n [rows]=\"field.rows || (field.type === 'json' ? 3 : 2)\"\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [placeholder]=\"field.placeholder || (field.type === 'json' ? '{ }' : '')\"\n [required]=\"isCommandActionFieldRequired(field)\"\n ></textarea>\n } @else {\n @if (field.type === 'select') {\n <mat-select\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [required]=\"isCommandActionFieldRequired(field)\"\n >\n @for (option of field.options || []; track option) {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n </mat-select>\n } @else {\n <input\n matInput\n [type]=\"field.type === 'number' ? 'number' : 'text'\"\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [placeholder]=\"field.placeholder || ''\"\n [required]=\"isCommandActionFieldRequired(field)\"\n />\n }\n }\n @if (field.hint) {\n <mat-hint>{{ field.hint }}</mat-hint>\n }\n @if (hasCommandActionFieldError(field.key)) {\n <mat-error>\n {{ getCommandActionFieldError(field.key) }}\n </mat-error>\n }\n @if (!hasCommandActionFieldError(field.key) && isCommandActionFieldMissing(field)) {\n <mat-error>\n {{ tx('config.commandRules.validation.requiredField', 'Campo obrigat\u00F3rio.') }}\n </mat-error>\n }\n </mat-form-field>\n }\n }\n }\n } @else {\n <praxis-surface-open-action-editor #commandSurfaceDraft\n class=\"command-rules-surface-editor\"\n data-testid=\"form-command-rule-surface-open-editor\"\n [value]=\"commandRuleSurfaceOpenPayload\"\n hostKind=\"dynamic-form\"\n (valueChange)=\"onCommandSurfaceOpenPayloadChange($event)\"\n (validationChange)=\"onSurfaceDraftValidity(commandSurfaceDraft, $event)\"\n ></praxis-surface-open-action-editor>\n }\n </div>\n }\n\n <mat-form-field appearance=\"outline\" class=\"command-rules-full\">\n <mat-label>{{ tx('config.commandRules.advancedPayload.label', 'Payload JSON avan\u00E7ado') }}</mat-label>\n <textarea\n matInput\n rows=\"4\"\n [(ngModel)]=\"commandRulePayloadJson\"\n [attr.aria-label]=\"tx('config.commandRules.advancedPayload.ariaLabel', 'Payload JSON da a\u00E7\u00E3o global')\"\n ></textarea>\n </mat-form-field>\n\n <div class=\"command-rules-options\">\n <mat-slide-toggle [(ngModel)]=\"commandRuleDistinct\">{{ tx('config.commandRules.options.distinct', 'Evitar repeti\u00E7\u00E3o enquanto a condi\u00E7\u00E3o permanecer verdadeira') }}</mat-slide-toggle>\n <mat-slide-toggle [(ngModel)]=\"commandRuleRunOnInitialEvaluation\">{{ tx('config.commandRules.options.runOnInitialEvaluation', 'Executar tamb\u00E9m na avalia\u00E7\u00E3o inicial') }}</mat-slide-toggle>\n </div>\n\n @if (commandRuleAuthoringError) {\n <div class=\"preview-error command-rules-full\">\n <mat-icon aria-hidden=\"true\">warning</mat-icon>\n <span>{{ commandRuleAuthoringError }}</span>\n </div>\n }\n\n <div\n class=\"command-rule-preview command-rules-full\"\n [class.command-rule-preview--invalid]=\"commandRulePreview.state === 'invalid'\"\n data-testid=\"command-rule-preview\"\n >\n <div class=\"command-rules-section-title\">{{ tx('config.commandRules.preview.title', 'Preview do comando') }}</div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.mode', 'Modo') }}</span>\n <strong>{{ commandRulePreview.executionMode }}</strong>\n </div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.action', 'A\u00E7\u00E3o') }}</span>\n <strong>{{ commandRulePreview.actionId || '\u2014' }}</strong>\n </div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.policy', 'Policy') }}</span>\n <code>{{ commandRulePreview.policy | json }}</code>\n </div>\n @if (commandRulePreview.diagnostics.length) {\n <div class=\"command-rule-preview__diagnostics\">\n <mat-icon aria-hidden=\"true\">{{ commandRulePreview.state === 'invalid' ? 'warning' : 'visibility' }}</mat-icon>\n <span>{{ commandRulePreview.diagnostics[0] }}</span>\n </div>\n }\n </div>\n\n <div class=\"command-rules-actions\">\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"applyCommandRule()\">\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n {{ tx('config.commandRules.actions.apply', 'Aplicar comando') }}\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('cascades')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-cascatas\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.cascades.title', 'Depend\u00EAncias entre campos') }}</h3>\n <p class=\"text-caption\">{{ tx('config.cascades.subtitle', 'Configure cascatas e carregamento entre campos.') }}</p>\n </div>\n </div>\n <praxis-cascade-manager-tab [fields]=\"editedConfig.fieldMetadata || []\"\n (apply)=\"onCascadeApply($event)\"></praxis-cascade-manager-tab>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('messages')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-mensagens\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.messages.title', 'Mensagens e feedback') }}</h3>\n <p class=\"text-caption\">{{ tx('config.messages.subtitle', 'Padronize textos de sucesso, erro e confirma\u00E7\u00F5es.') }}</p>\n </div>\n </div>\n <praxis-messages-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-messages-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('navigation')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-navegacao\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.navigation.title', 'Navega\u00E7\u00E3o de retorno') }}</h3>\n <p class=\"text-caption\">{{ tx('config.navigation.subtitle', 'Defina o comportamento do bot\u00E3o Voltar em fluxos CRUD.') }}</p>\n </div>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.navigation.returnTo.label', 'Rota de retorno') }}</mat-label>\n <input matInput id=\"returnTo\" [(ngModel)]=\"backConfig!.returnTo\" (ngModelChange)=\"onBackConfigChange()\" [placeholder]=\"tx('config.navigation.returnTo.placeholder', '/funcionarios')\" />\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-slide-toggle [(ngModel)]=\"backConfig!.confirmOnDirty\" (ngModelChange)=\"onBackConfigChange()\">\n {{ tx('config.navigation.confirmOnDirty.label', 'Confirmar ao sair com altera\u00E7\u00F5es') }}\n </mat-slide-toggle>\n </div>\n <div class=\"block-status\" [class.block-status--implicit]=\"!isBackConfigBlockPersisted()\">\n <strong>{{ tx('config.navigation.backConfig.label', 'Back Config') }}</strong>\n @if (isBackConfigBlockPersisted()) {\n <span>{{ tx('config.navigation.backConfig.persisted', '`contextSnapshot.backConfig` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.navigation.backConfig.implicit', 'Bloco ausente no documento can\u00F4nico. Os valores exibidos s\u00E3o fallback visual e n\u00E3o ser\u00E3o salvos at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n </div>\n <div class=\"section-help\">\n <span class=\"section-help__label\">{{ tx('config.navigation.note.label', 'Observa\u00E7\u00E3o:') }}</span>\n <button\n praxisIconButton=\"help_outline\"\n size=\"dense\"\n class=\"help-icon-button\"\n type=\"button\"\n [matTooltip]=\"tx('config.navigation.note.tooltip', 'Afeta o fluxo de navega\u00E7\u00E3o do CRUD e pode ser sobreposto por metadados do recurso.')\"\n matTooltipPosition=\"above\"\n >\n </button>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('json')\">\n <div class=\"tab-content json-tab-content\" data-testid=\"config-tab-panel-json\">\n <mat-card class=\"section-card section-card--json\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.json.title', 'Configura\u00E7\u00E3o JSON') }}</h3>\n <p class=\"text-caption\">{{ tx('config.json.subtitle', 'Edi\u00E7\u00E3o avan\u00E7ada do documento can\u00F4nico de autoria do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <form-json-config-editor [document]=\"jsonDocument\" (documentChange)=\"onJsonConfigChange($event)\"\n (validationChange)=\"onJsonValidationChange($event)\" (editorEvent)=\"onJsonEditorEvent($event)\">\n </form-json-config-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n</mat-tab-group>\n", styles: [":host{container:praxis-authoring-editor/inline-size;display:flex;flex-direction:column;height:100%;min-width:0}.mobile-tab-selector{display:none;flex:0 0 auto;padding:8px 16px 0;background:var(--md-sys-color-surface)}.mobile-tab-selector__field{width:100%}.config-tabs{flex:1 1 auto;min-height:0;min-width:0}::ng-deep .mat-mdc-tab-group.config-tabs{display:flex;flex-direction:column}::ng-deep .mat-mdc-tab-group.config-tabs .mat-mdc-tab-body-wrapper{flex:1;min-height:0;min-width:0}::ng-deep .mat-mdc-tab-group.config-tabs .mat-mdc-tab-body-content{height:100%;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;padding:0!important}.tab-content{padding:20px 24px 28px;flex:1;min-width:0;box-sizing:border-box;display:flex;flex-direction:column;gap:24px}.json-tab-content{min-width:0;padding:12px 16px 16px}.section-card.section-card--json{display:flex;flex:1;min-height:calc(100vh - 180px);border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-low)}.section-card.section-card--json>mat-card-content,.section-card.section-card--json>.mat-mdc-card-content{display:flex;flex:1;min-width:0;min-height:0;flex-direction:column;padding:16px!important}.section-card--json form-json-config-editor{display:block;flex:1;min-width:0;min-height:0}.form-row{display:block;margin-bottom:12px}.form-grid{display:grid;gap:12px}.section-help{display:inline-flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.section-help__label{font-weight:500}.grid-2-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px}.grid-2-cols--compact{gap:12px}.w-100{width:100%}.visual-builder-content{padding:0!important;height:100%;min-width:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;gap:16px}.visual-builder-content>praxis-visual-builder{flex:0 0 auto;min-width:0;min-height:clamp(360px,48vh,560px)}.visual-builder-content>praxis-rule-properties-panel{flex:0 0 auto;display:block;min-width:0;padding:0 16px 24px;box-sizing:border-box}.rules-diagnostics{flex:0 0 auto;display:grid;gap:10px;padding:12px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}.rules-diagnostics--empty{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.rules-diagnostics__summary,.rules-diagnostics__list{display:flex;flex-wrap:wrap;gap:8px}.rules-diagnostics__pill{display:inline-flex;align-items:center;min-height:24px;padding:3px 9px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:12px;font-weight:600}.rules-diagnostics__pill--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 72%,transparent);color:var(--md-sys-color-on-tertiary-container)}.rules-diagnostics__pill--error{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.rules-diagnostics__item{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;min-width:min(100%,280px);padding:8px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.rules-diagnostics__item>div{display:grid;gap:2px;min-width:0}.rules-diagnostics__item strong{color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rules-diagnostics__item span{color:var(--md-sys-color-on-surface-variant);font-size:11px}.rules-diagnostics__actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}.rules-diagnostics__details{display:grid;gap:2px;margin:4px 0 0;padding-left:16px;color:var(--md-sys-color-on-surface-variant);font-size:11px;line-height:1.35}.rules-diagnostics__details li{overflow-wrap:anywhere}.rules-diagnostics__item--warn{border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 52%,var(--md-sys-color-outline-variant))}.rules-diagnostics__item--error{border-color:var(--md-sys-color-error)}.rules-diagnostics__status{font-weight:600;margin-top:1px}.rules-diagnostics__action{min-width:0;height:28px;padding:0 10px;border-radius:999px;font-size:12px;line-height:1}.rules-diagnostics__action mat-icon{width:16px;height:16px;margin:0 4px 0 0;font-size:16px}.json-field{width:100%}.presentation-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:20px;align-items:start}.presentation-controls{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:14px 18px}.control{display:flex;flex-direction:column}.control-span{grid-column:1/-1}.block-status{grid-column:1/-1;display:flex;gap:8px;align-items:flex-start;padding:10px 12px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 35%,transparent);color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.45}.block-status strong{min-width:112px;font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.block-status--implicit{background:color-mix(in srgb,var(--md-sys-color-surface-variant) 42%,transparent);border:1px dashed var(--md-sys-color-outline)}.block-status--readonly{margin-bottom:12px}.block-status code{font-family:var(--md-ref-typeface-mono, \"Courier New\", monospace);font-size:11px}.control__label{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-bottom:6px}.toggle-group{max-width:100%;flex-wrap:wrap}.control--inline{grid-column:1/-1;display:flex;gap:16px;align-items:center}.presentation-preview{min-width:0;order:-1}.preview-card{border:1px solid var(--md-sys-color-outline);border-radius:12px;padding:14px;background:var(--md-sys-color-surface-container)}.preview-row{display:flex;gap:8px;padding:6px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.preview-row:last-child{border-bottom:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.presentation-preview .praxis-presentation__label{color:var(--md-sys-color-on-surface-variant);font-size:var(--pfx-pres-label-size, 12px)}.presentation-preview .praxis-presentation__value{min-width:0;overflow-wrap:anywhere;font-size:var(--pfx-pres-value-size, 16px);color:var(--md-sys-color-on-surface)}.presentation-preview .presentation-mode.pres-density-cozy .preview-row{padding:6px 0}.presentation-preview .presentation-mode.pres-density-compact .preview-row,.presentation-preview .presentation-mode.pres-compact .preview-row{padding:2px 0}.presentation-preview .presentation-mode.pres-label-left .preview-row{display:grid;grid-template-columns:var(--pfx-pres-label-width, 140px) 1fr;align-items:baseline;column-gap:10px}.presentation-preview .presentation-mode.pres-label-left .praxis-presentation__label{margin:0;text-align:var(--pfx-pres-label-align, start)}.presentation-preview .presentation-mode .praxis-presentation__value{text-align:var(--pfx-pres-value-align, start)}.presentation-preview h4{margin:0 0 8px;color:var(--md-sys-color-on-surface);font-size:1rem}.section-card:not(.section-card--json),.section-card:not(.section-card--json).mat-mdc-card,.section-card:not(.section-card--json).mat-mdc-card-outlined{border:none!important;border-width:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;margin:0!important;padding:0!important;--mdc-outlined-card-outline-width: 0px;--mdc-outlined-card-outline-color: transparent;--mdc-elevated-card-container-color: transparent;--mdc-outlined-card-container-color: transparent}.section-card:not(.section-card--json)>mat-card-content,.section-card:not(.section-card--json)>.mat-mdc-card-content{padding:0!important}.section-card:not(.section-card--json)+.section-card:not(.section-card--json),.section-card:not(.section-card--json).mat-mdc-card+.section-card:not(.section-card--json).mat-mdc-card{padding-top:24px!important;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 65%,transparent)!important}.section-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:16px}.tab-content--dense{padding:16px 20px 24px;gap:20px}.tab-content--dense .section-header{margin-bottom:10px}.tab-content--dense .form-row{margin-bottom:8px}.section-header h3{margin:0;font-size:1rem;font-weight:600;letter-spacing:-.01em;color:var(--md-sys-color-on-surface)}.text-caption{margin:4px 0 0;font-size:.85rem;line-height:1.45;color:var(--md-sys-color-on-surface-variant)}.section-header--compact{margin-bottom:10px}.section-body{display:block}.section-body--flex{flex:1;min-height:0;display:flex;flex-direction:column}.builder-header{padding:12px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.builder-header h3{margin:0;font-size:1rem;color:var(--md-sys-color-on-surface)}.hint{margin:8px 0 0;padding:10px 12px;border-radius:8px;border:1px dashed color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 75%,transparent);color:var(--md-sys-color-on-surface-variant)}.meta-card{display:grid;gap:8px;padding:12px 14px;border-radius:8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);color:var(--md-sys-color-on-surface)}.meta-row{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.meta-row strong{color:var(--md-sys-color-on-surface);font-weight:600}.runtime-contract-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px 14px}.runtime-contract-field{display:grid;gap:4px;padding:10px 12px;border-radius:8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 65%,transparent)}.runtime-contract-label{font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--md-sys-color-on-surface-variant)}.runtime-contract-code{display:block;font-family:var(--md-ref-typeface-mono, \"Courier New\", monospace);font-size:12px;line-height:1.45;color:var(--md-sys-color-on-surface);word-break:break-word;white-space:normal}.command-rules-card,.command-rules-card.mat-mdc-card,.command-rules-card.mat-mdc-card-outlined{margin:0!important;padding:20px 16px 24px!important;min-width:0;border:none!important;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 65%,transparent)!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;--mdc-outlined-card-outline-width: 0px;--mdc-outlined-card-outline-color: transparent;--mdc-elevated-card-container-color: transparent;--mdc-outlined-card-container-color: transparent}.command-rules-card>mat-card-content,.command-rules-card>.mat-mdc-card-content{padding:12px 0 0!important}.command-rules-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr));gap:12px;align-items:start;min-width:0}.command-rules-toolbar,.command-rules-options,.command-rules-actions{grid-column:1/-1;display:flex;align-items:center;gap:12px;flex-wrap:wrap}.command-rules-select{min-width:min(320px,100%)}.command-rules-full{grid-column:1/-1}.command-rule-condition-builder{min-height:420px;overflow:hidden;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.command-rules-payload-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px;min-width:0;padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.command-rules-section-title{grid-column:1/-1;font-size:12px;font-weight:600;color:var(--md-sys-color-on-surface-variant);text-transform:uppercase}.command-rules-surface-editor{grid-column:1/-1}.command-rule-preview{display:grid;gap:8px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}.command-rule-preview--invalid{border-color:var(--md-sys-color-error)}.command-rule-preview__row{display:grid;grid-template-columns:minmax(96px,.35fr) minmax(0,1fr);gap:8px;align-items:start;min-width:0}.command-rule-preview__row span{color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600}.command-rule-preview__row strong,.command-rule-preview__row code{min-width:0;overflow-wrap:anywhere}.command-rule-preview__diagnostics{display:flex;gap:8px;align-items:flex-start;color:var(--md-sys-color-on-surface-variant)}@container praxis-authoring-editor (max-width: 768px){.mobile-tab-selector{display:block}::ng-deep .mat-mdc-tab-group.config-tabs>.mat-mdc-tab-header{display:none}.tab-content{padding:12px}.json-tab-content{padding:8px}.section-card--json{min-height:auto}}.form-modes{display:flex;flex-direction:column;align-items:flex-start;gap:16px}.form-modes mat-button-toggle-group{max-width:100%;flex-wrap:wrap}.display-result{margin:0;padding-block:12px;color:var(--md-sys-color-on-surface);font:var(--md-sys-typescale-body-medium)}.presentation-preview .presentation-mode.pres-label-above .preview-row{flex-direction:column;gap:4px}.presentation-controls,.control{min-width:0}.control__hint{margin:6px 0 0;color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-body-small, 400 12px/1.45 sans-serif)}.block-status{flex-wrap:wrap}:host{container-type:inline-size}@container (min-width: 900px){.presentation-layout{grid-template-columns:minmax(0,1fr) minmax(280px,.8fr)}.presentation-preview{order:1;position:sticky;top:16px}}.empty-state-fields{display:grid;align-items:start;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:var(--p-space-3, 12px);margin-block-start:var(--p-space-4, 16px)}.empty-state-appearance summary{cursor:pointer;padding-block:var(--p-space-3, 12px);color:var(--md-sys-color-on-surface)}.empty-state-content{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}.empty-state-description{grid-column:1/-1}.empty-state-content mat-form-field{min-width:0}.empty-state-icon-actions{display:inline-flex;align-items:center}\n"] }]
34081
+ ], providers: [FormConfigService, providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG)], template: "<div class=\"mobile-tab-selector\">\n <mat-form-field appearance=\"outline\" class=\"mobile-tab-selector__field\">\n <mat-label>{{ tx('config.tabs.mobileLabel', 'Se\u00E7\u00E3o do editor') }}</mat-label>\n <mat-select [(ngModel)]=\"selectedConfigTabIndex\" data-testid=\"dynamic-form-config-editor-mobile-tabs\">\n @for (tab of configTabOptions; track tab.key) {\n <mat-option [value]=\"tab.index\">{{ tab.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n\n<mat-tab-group [preserveContent]=\"true\" class=\"config-tabs\" data-testid=\"dynamic-form-config-editor-tabs\" [(selectedIndex)]=\"selectedConfigTabIndex\">\n <mat-tab [label]=\"configTabLabel('general')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-geral\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.general.title', 'Dados do formul\u00E1rio') }}</h3>\n <p class=\"text-caption\">{{ tx('config.general.subtitle', 'Defina o modo de dados e o contexto de edi\u00E7\u00E3o.') }}</p>\n </div>\n </div>\n <div class=\"form-modes\">\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.inputMode.label') }}</label>\n <mat-button-toggle-group [ngModel]=\"inputMode\" (ngModelChange)=\"inputMode = $event; onInputModeChange()\" [attr.aria-label]=\"tx('config.general.inputMode.label')\">\n <mat-button-toggle value=\"create\">{{ tx('config.general.inputMode.create') }}</mat-button-toggle>\n <mat-button-toggle value=\"edit\">{{ tx('config.general.inputMode.edit') }}</mat-button-toggle>\n <mat-button-toggle value=\"view\">{{ tx('config.general.inputMode.view') }}</mat-button-toggle>\n </mat-button-toggle-group>\n @if (inputMode === 'presentation' || inputMode === 'dossier') {\n <p class=\"control__hint\" data-testid=\"dynamic-form-native-mode-hint\" role=\"status\">\n {{ tx('config.general.inputMode.nativeMode', undefined, { mode: inputMode }) }}\n </p>\n }\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.layoutScope.label', 'Escopo de persist\u00EAncia do layout') }}</label>\n <mat-button-toggle-group\n data-testid=\"dynamic-form-layout-scope-toggle\"\n [ngModel]=\"inputLayoutScope\"\n (ngModelChange)=\"onLayoutScopeChange($event)\"\n [attr.aria-label]=\"tx('config.general.layoutScope.label', 'Escopo de persist\u00EAncia do layout')\">\n <mat-button-toggle value=\"shared\" data-testid=\"dynamic-form-layout-scope-shared\">\n {{ tx('config.general.layoutScope.shared', 'Todos os modos (Criar / Editar / Visualizar)') }}\n </mat-button-toggle>\n <mat-button-toggle value=\"mode-only\" data-testid=\"dynamic-form-layout-scope-mode-only\">\n {{ tx('config.general.layoutScope.modeOnly', 'Somente este modo ({{mode}})', { mode: tx('config.general.inputMode.' + inputMode, inputMode) }) }}\n </mat-button-toggle>\n </mat-button-toggle-group>\n <p class=\"control__hint\" data-testid=\"dynamic-form-layout-scope-hint\" role=\"status\">\n {{ inputLayoutScope === 'mode-only'\n ? tx('config.general.layoutScope.modeOnlyHint', 'Ao salvar, aplica este layout exclusivamente ao modo atual, sem alterar os demais modos.')\n : tx('config.general.layoutScope.sharedHint', 'Ao salvar, replica se\u00E7\u00F5es e grade nos demais modos que ainda compartilham layout.') }}\n </p>\n </div>\n @if (supportsPresentationSettings) {\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.general.displayMode.label') }}</label>\n <mat-button-toggle-group [ngModel]=\"displayMode\" (ngModelChange)=\"onDisplayModeChange($event)\" [attr.aria-label]=\"tx('config.general.displayMode.label')\">\n <mat-button-toggle value=\"automatic\">{{ tx('config.general.displayMode.automatic') }}</mat-button-toggle>\n <mat-button-toggle value=\"fields\">{{ tx('config.general.displayMode.fields') }}</mat-button-toggle>\n <mat-button-toggle value=\"presentation\">{{ tx('config.general.displayMode.presentation') }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <p class=\"display-result\" role=\"status\">{{ tx(displayModeHint) }}</p>\n @if (inputMode !== 'view' && inputMode !== 'presentation' && inputMode !== 'dossier' && inputPresentationMode === true) {\n <button mat-stroked-button type=\"button\" (click)=\"useViewMode()\">{{ tx('config.general.displayMode.useView') }}</button>\n }\n <button mat-button type=\"button\" (click)=\"openPresentationStyle()\">{{ tx('config.general.displayMode.openStyle') }}</button>\n }\n </div>\n </mat-card-content>\n </mat-card>\n\n @if (supportsPresentationSettings) {\n <mat-card class=\"section-card\" data-testid=\"form-empty-state-settings\">\n <mat-card-content>\n <h3>{{ tx('config.emptyState.heading') }}</h3>\n <p class=\"text-caption\">{{ tx('config.emptyState.help') }}</p>\n <mat-slide-toggle [ngModel]=\"!!inputEmptyState\" (ngModelChange)=\"setEmptyStateEnabled($event)\">{{ tx('config.emptyState.enabled') }}</mat-slide-toggle>\n @if (inputMode !== 'view' && inputMode !== 'presentation' && inputMode !== 'dossier') { <p class=\"text-caption\">{{ tx('config.emptyState.viewOnly') }}</p> }\n @if (inputEmptyState; as empty) {\n <div class=\"empty-state-fields empty-state-content\">\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.title') }}</mat-label><input matInput required [(ngModel)]=\"empty.title\" (ngModelChange)=\"onEmptyStateChange()\" /><mat-hint *ngIf=\"!empty.title?.trim()\">{{ tx('config.emptyState.titleRequired') }}</mat-hint></mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.emptyState.icon') }}</mat-label>\n @if (empty.icon) { <mat-icon matPrefix [praxisIcon]=\"empty.icon\" aria-hidden=\"true\"></mat-icon> }\n <input matInput [(ngModel)]=\"empty.icon\" (ngModelChange)=\"onEmptyStateChange()\" />\n <span matSuffix class=\"empty-state-icon-actions\">\n <button mat-icon-button type=\"button\" [attr.aria-label]=\"tx('config.emptyState.pickIcon')\" (click)=\"pickEmptyStateIcon()\"><mat-icon aria-hidden=\"true\">search</mat-icon></button>\n @if (empty.icon) { <button mat-icon-button type=\"button\" [attr.aria-label]=\"tx('config.emptyState.clearIcon')\" (click)=\"empty.icon = ''; onEmptyStateChange()\"><mat-icon aria-hidden=\"true\">close</mat-icon></button> }\n </span>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"empty-state-description\"><mat-label>{{ tx('config.emptyState.description') }}</mat-label><textarea matInput rows=\"2\" [(ngModel)]=\"empty.description\" (ngModelChange)=\"onEmptyStateChange()\"></textarea></mat-form-field>\n </div>\n <details class=\"empty-state-appearance\"><summary>{{ tx('config.emptyState.appearance') }}</summary><div class=\"empty-state-fields\">\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.tone') }}</mat-label><mat-select [(ngModel)]=\"empty.tone\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.tone; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.variant') }}</mat-label><mat-select [(ngModel)]=\"empty.variant\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.variant; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.alignment') }}</mat-label><mat-select [(ngModel)]=\"empty.alignment\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.alignment; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.density') }}</mat-label><mat-select [(ngModel)]=\"empty.density\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.density; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n <mat-form-field appearance=\"outline\"><mat-label>{{ tx('config.emptyState.iconContainer') }}</mat-label><mat-select [(ngModel)]=\"empty.iconContainer\" (ngModelChange)=\"onEmptyStateChange()\"><mat-option [value]=\"undefined\">{{ tx('config.emptyState.inherit') }}</mat-option>@for (value of emptyStateOptions.iconContainer; track value) { <mat-option [value]=\"value\">{{ tx('config.emptyState.option.' + value) }}</mat-option> }</mat-select></mat-form-field>\n </div></details>\n }\n </mat-card-content>\n </mat-card>\n }\n\n @if (hasResolvedRuntimeContract()) {\n <mat-card\n class=\"section-card\"\n data-testid=\"config-tab-runtime-contract\"\n >\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.general.runtimeContract.title', 'Contrato Runtime Resolvido') }}</h3>\n <p class=\"text-caption\">\n {{ tx('config.general.runtimeContract.subtitle', 'Visualiza\u00E7\u00E3o somente leitura do contrato backend resolvido pelo host atual.') }}\n </p>\n </div>\n </div>\n <div class=\"block-status block-status--readonly\">\n <strong>{{ tx('config.general.runtimeContract.runtimeLabel', 'Runtime') }}</strong>\n <span>\n {{ tx('config.general.runtimeContract.readonly', 'Esses valores v\u00EAm do host/runtime atual e n\u00E3o s\u00E3o persistidos em `bindings` nem em `contextSnapshot`.') }}\n </span>\n </div>\n <div class=\"runtime-contract-grid\">\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.schemaUrl', 'Schema URL') }}</span>\n <code class=\"runtime-contract-code\">{{ runtimeContract?.schemaUrl || '\u2014' }}</code>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.schemaSource', 'Origem do schema') }}</span>\n <strong>{{ describeRuntimeSource(runtimeContract?.schemaSource) }}</strong>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitMethod', 'Submit method') }}</span>\n <strong>{{ runtimeContract?.submitMethod || '\u2014' }}</strong>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitUrl', 'Submit URL') }}</span>\n <code class=\"runtime-contract-code\">{{ runtimeContract?.submitUrl || '\u2014' }}</code>\n </div>\n <div class=\"runtime-contract-field\">\n <span class=\"runtime-contract-label\">{{ tx('config.general.runtimeContract.submitSource', 'Origem do submit') }}</span>\n <strong>{{ describeRuntimeSource(runtimeContract?.submitSource) }}</strong>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n }\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('schema')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-schema\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.schema.title', 'Valida\u00E7\u00E3o de schema') }}</h3>\n <p class=\"text-caption\">{{ tx('config.schema.subtitle', 'Controle avisos quando o schema do servidor mudar.') }}</p>\n </div>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.schema.notify.label', 'Notificar quando desatualizado') }}</mat-label>\n <mat-select [(ngModel)]=\"schemaPrefs.notifyIfOutdated\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-notify')\">\n <mat-option value=\"both\">{{ tx('config.schema.notify.both', 'Banner + Snackbar') }}</mat-option>\n <mat-option value=\"inline\">{{ tx('config.schema.notify.inline', 'Somente Banner') }}</mat-option>\n <mat-option value=\"snackbar\">{{ tx('config.schema.notify.snackbar', 'Somente Snackbar') }}</mat-option>\n <mat-option value=\"none\">{{ tx('config.schema.notify.none', 'Nenhum') }}</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.schema.snooze.label', 'Intervalo de sil\u00EAncio (ms)') }}</mat-label>\n <input matInput type=\"number\" [(ngModel)]=\"schemaPrefs.snoozeMs\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-snooze')\" />\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-slide-toggle [(ngModel)]=\"schemaPrefs.autoOpenSettingsOnOutdated\" (ngModelChange)=\"onSchemaPrefsChange('schema-prefs-auto-open')\">\n {{ tx('config.schema.autoOpenSettings', 'Abrir configura\u00E7\u00F5es automaticamente') }}\n </mat-slide-toggle>\n </div>\n @if (serverMeta) {\n <div class=\"form-row\">\n <div class=\"meta-card\">\n <div class=\"meta-row\">\n <span>{{ tx('config.schema.meta.serverHash', 'Server hash') }}</span>\n <strong>{{ serverMeta.serverHash || '\u2014' }}</strong>\n </div>\n <div class=\"meta-row\">\n <span>{{ tx('config.schema.meta.lastVerifiedAt', '\u00DAltima verifica\u00E7\u00E3o') }}</span>\n <strong>{{ serverMeta.lastVerifiedAt || '\u2014' }}</strong>\n </div>\n </div>\n </div>\n }\n <div class=\"block-status\" [class.block-status--implicit]=\"!isSchemaPrefsBlockPersisted()\">\n <strong>{{ tx('config.schema.prefs.label', 'Schema Prefs') }}</strong>\n @if (isSchemaPrefsBlockPersisted()) {\n <span>{{ tx('config.schema.prefs.persisted', '`contextSnapshot.schemaPrefs` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.schema.prefs.implicit', 'Bloco ausente no documento can\u00F4nico. Os controles exibem fallback visual e n\u00E3o ser\u00E3o salvos at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('layout')\">\n <div class=\"tab-content tab-content--full\" data-testid=\"config-tab-panel-layout\">\n <div class=\"section-body section-body--flex\">\n <praxis-layout-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"\n (select)=\"onLayoutSelect($event)\"></praxis-layout-editor>\n </div>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('hooks')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-hooks\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.hooks.title', 'Hooks de ciclo de vida') }}</h3>\n <p class=\"text-caption\">{{ tx('config.hooks.subtitle', 'Automatize a\u00E7\u00F5es nos eventos do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <praxis-hooks-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-hooks-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n @if (isPresentationMode) {\n <mat-tab [label]=\"configTabLabel('presentation')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-presentation\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.presentation.title', 'Modo Apresenta\u00E7\u00E3o') }}</h3>\n <p class=\"text-caption\">{{ tx('config.presentation.subtitle', 'Configura\u00E7\u00F5es de exibi\u00E7\u00E3o aplicadas somente ao modo apresenta\u00E7\u00E3o.') }}</p>\n </div>\n </div>\n <p class=\"display-result\" role=\"status\">{{ tx(displayModeHint) }}</p>\n <div class=\"presentation-layout\">\n <div class=\"presentation-controls\">\n <div class=\"block-status control-span\" [class.block-status--implicit]=\"!isPresentationBlockPersisted()\">\n <strong>{{ tx('config.presentation.block.label', 'Presentation') }}</strong>\n @if (isPresentationBlockPersisted()) {\n <span>{{ tx('config.presentation.block.persisted', '`contextSnapshot.presentation` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.presentation.block.implicit', 'Bloco ausente no documento can\u00F4nico. A pr\u00E9-visualiza\u00E7\u00E3o usa fallback local e n\u00E3o ser\u00E1 salva at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.labelPosition.label', 'Posi\u00E7\u00E3o do r\u00F3tulo') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.labelPosition\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-position')\" [attr.aria-label]=\"tx('config.presentation.labelPosition.ariaLabel', 'Posi\u00E7\u00E3o do r\u00F3tulo')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"above\">\n <mat-icon>view_stream</mat-icon>\n <span class=\"sr-only\">{{ tx('config.presentation.labelPosition.above', 'Acima') }}</span>\n </mat-button-toggle>\n <mat-button-toggle value=\"left\">\n <mat-icon>view_column</mat-icon>\n <span class=\"sr-only\">{{ tx('config.presentation.labelPosition.left', '\u00C0 esquerda') }}</span>\n </mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control control-span\">\n <label class=\"control__label\">{{ tx('config.presentation.density.label', 'Densidade') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.density\" (ngModelChange)=\"onPresentationPrefsChange('presentation-density')\" [attr.aria-label]=\"tx('config.presentation.density.ariaLabel', 'Densidade')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"comfortable\">{{ tx('config.presentation.density.comfortable', 'Confort\u00E1vel') }}</mat-button-toggle>\n <mat-button-toggle value=\"cozy\">{{ tx('config.presentation.density.cozy', 'Intermedi\u00E1ria') }}</mat-button-toggle>\n <mat-button-toggle value=\"compact\">{{ tx('config.presentation.density.compact', 'Compacta') }}</mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.labelAlign.label', 'Alinhamento do r\u00F3tulo') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.labelAlign\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-align')\" [attr.aria-label]=\"tx('config.presentation.labelAlign.ariaLabel', 'Alinhamento do r\u00F3tulo')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"start\" [aria-label]=\"tx('config.presentation.align.start')\" [matTooltip]=\"tx('config.presentation.align.start')\"><mat-icon>format_align_left</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"center\" [aria-label]=\"tx('config.presentation.align.center')\" [matTooltip]=\"tx('config.presentation.align.center')\"><mat-icon>format_align_center</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"end\" [aria-label]=\"tx('config.presentation.align.end')\" [matTooltip]=\"tx('config.presentation.align.end')\"><mat-icon>format_align_right</mat-icon></mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <label class=\"control__label\">{{ tx('config.presentation.valueAlign.label', 'Alinhamento do valor') }}</label>\n <mat-button-toggle-group [(ngModel)]=\"presentationPrefs.valueAlign\" (ngModelChange)=\"onPresentationPrefsChange('presentation-value-align')\" [attr.aria-label]=\"tx('config.presentation.valueAlign.ariaLabel', 'Alinhamento do valor')\"\n class=\"toggle-group\">\n <mat-button-toggle value=\"start\" [aria-label]=\"tx('config.presentation.align.start')\" [matTooltip]=\"tx('config.presentation.align.start')\"><mat-icon>format_align_left</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"center\" [aria-label]=\"tx('config.presentation.align.center')\" [matTooltip]=\"tx('config.presentation.align.center')\"><mat-icon>format_align_center</mat-icon></mat-button-toggle>\n <mat-button-toggle value=\"end\" [aria-label]=\"tx('config.presentation.align.end')\" [matTooltip]=\"tx('config.presentation.align.end')\"><mat-icon>format_align_right</mat-icon></mat-button-toggle>\n </mat-button-toggle-group>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.labelFontSize.label', 'Tamanho do r\u00F3tulo') }}</mat-label>\n <input matInput type=\"number\" min=\"10\" step=\"any\" [(ngModel)]=\"presentationPrefs.labelFontSize\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-font-size')\"\n [placeholder]=\"tx('config.presentation.labelFontSize.placeholder', 'ex.: 12')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.valueFontSize.label', 'Tamanho do valor') }}</mat-label>\n <input matInput type=\"number\" min=\"10\" step=\"any\" [(ngModel)]=\"presentationPrefs.valueFontSize\" (ngModelChange)=\"onPresentationPrefsChange('presentation-value-font-size')\"\n [placeholder]=\"tx('config.presentation.valueFontSize.placeholder', 'ex.: 16')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.presentation.labelWidth.label', 'Largura do r\u00F3tulo (label \u00E0 esquerda)') }}</mat-label>\n <input matInput type=\"number\" min=\"60\" [disabled]=\"presentationPrefs.labelPosition !== 'left'\" [(ngModel)]=\"presentationPrefs.labelWidth\" (ngModelChange)=\"onPresentationPrefsChange('presentation-label-width')\"\n [placeholder]=\"tx('config.presentation.labelWidth.placeholder', 'ex.: 140')\" />\n <span matSuffix>px</span>\n </mat-form-field>\n </div>\n <div class=\"control control--inline\">\n <mat-slide-toggle [(ngModel)]=\"presentationPrefs.compact\" (ngModelChange)=\"onPresentationPrefsChange('presentation-compact')\">\n {{ tx('config.presentation.options.compactMode', 'Modo compacto') }}\n </mat-slide-toggle>\n <mat-checkbox [(ngModel)]=\"truncatePreview\">\n {{ tx('config.presentation.options.truncateValues', 'Truncar valores') }}\n </mat-checkbox>\n </div>\n </div>\n <div class=\"presentation-preview\">\n <h4>{{ tx('config.presentation.preview.title', 'Pr\u00E9-visualiza\u00E7\u00E3o') }}</h4>\n <p class=\"text-caption\">{{ tx('config.presentation.preview.sampleHint') }}</p>\n <div class=\"preview-card\">\n <div class=\"praxis-dynamic-form presentation-mode\" [ngClass]=\"{\n 'pres-compact': !!presentationPrefs.compact,\n 'pres-label-left': presentationPrefs.labelPosition === 'left',\n 'pres-label-above': presentationPrefs.labelPosition === 'above',\n 'pres-density-compact': presentationPrefs.density === 'compact',\n 'pres-density-cozy': presentationPrefs.density === 'cozy'\n }\" [style.--pfx-pres-label-size]=\"(presentationPrefs.labelFontSize || 12) + 'px'\"\n [style.--pfx-pres-value-size]=\"(presentationPrefs.valueFontSize || 16) + 'px'\"\n [style.--pfx-pres-label-width]=\"(presentationPrefs.labelWidth || 140) + 'px'\"\n [style.--pfx-pres-label-align]=\"presentationPrefs.labelAlign || 'start'\"\n [style.--pfx-pres-value-align]=\"presentationPrefs.valueAlign || 'start'\">\n @for (item of previewItems; track item) {\n <div class=\"preview-row\">\n <span class=\"praxis-presentation__label\">{{ item.label }}</span>\n <span class=\"praxis-presentation__value\" [attr.title]=\"truncatePreview ? item.value : null\"\n [style.maxWidth]=\"truncatePreview ? '280px' : null\"\n [style.overflow]=\"truncatePreview ? 'hidden' : null\"\n [style.textOverflow]=\"truncatePreview ? 'ellipsis' : null\"\n [style.whiteSpace]=\"truncatePreview ? 'nowrap' : 'normal'\">\n {{ item.value }}\n </span>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n }\n <mat-tab [label]=\"configTabLabel('behavior')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-comportamento\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.behavior.title', 'Comportamento') }}</h3>\n <p class=\"text-caption\">{{ tx('config.behavior.subtitle', 'Ajuste valida\u00E7\u00F5es e respostas do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <praxis-behavior-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-behavior-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('hints')\">\n <div class=\"tab-content tab-content--dense\" data-testid=\"config-tab-panel-hints\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.hints.title', 'Dicas dos modos') }}</h3>\n <p class=\"text-caption\">{{ tx('config.hints.subtitle', 'Personalize textos de apoio para modos de dados e estados de UI.') }}</p>\n </div>\n </div>\n <p class=\"text-caption\">{{ tx('config.hints.description', 'Personalize os textos usados como tooltip/hint para modos de dados e modos globais de UI.') }}</p>\n\n <div class=\"grid-2-cols grid-2-cols--compact\">\n <section>\n <h4>{{ tx('config.hints.dataModes.title', 'Modos de dados') }}</h4>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.create.label', 'Criar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.create\"\n (ngModelChange)=\"updateDirtyState('hints-data-create')\" [placeholder]=\"tx('config.hints.dataModes.create.placeholder', 'Ex.: Preencha os campos obrigat\u00F3rios.')\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.edit.label', 'Editar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.edit\"\n (ngModelChange)=\"updateDirtyState('hints-data-edit')\" [placeholder]=\"tx('config.hints.dataModes.edit.placeholder', 'Ex.: Revise os dados antes de salvar.')\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.dataModes.view.label', 'Visualizar') }}</mat-label>\n <input matInput [(ngModel)]=\"editedConfig.hints!.dataModes.view\"\n (ngModelChange)=\"updateDirtyState('hints-data-view')\" [placeholder]=\"tx('config.hints.dataModes.view.placeholder', 'Ex.: Visualiza\u00E7\u00E3o somente leitura.')\" />\n </mat-form-field>\n </section>\n\n <section>\n <h4>{{ tx('config.hints.uiModes.title', 'Modos de UI') }}</h4>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.presentation.label', 'Apresenta\u00E7\u00E3o') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.presentation\"\n (ngModelChange)=\"updateDirtyState('hints-ui-presentation')\" [placeholder]=\"tx('config.hints.uiModes.presentation.placeholder', 'Ex.: Modo compacto para leitura r\u00E1pida.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.readonly.label', 'Leitura (readonly)') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.readonly\"\n (ngModelChange)=\"updateDirtyState('hints-ui-readonly')\" [placeholder]=\"tx('config.hints.uiModes.readonly.placeholder', 'Ex.: Campos bloqueados para edi\u00E7\u00E3o.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.disabled.label', 'Desabilitado') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.disabled\"\n (ngModelChange)=\"updateDirtyState('hints-ui-disabled')\" [placeholder]=\"tx('config.hints.uiModes.disabled.placeholder', 'Ex.: Fun\u00E7\u00E3o indispon\u00EDvel no momento.')\"></textarea>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.hints.uiModes.visible.label', 'Vis\u00EDvel') }}</mat-label>\n <textarea matInput rows=\"2\" [(ngModel)]=\"editedConfig.hints!.uiModes.visible\"\n (ngModelChange)=\"updateDirtyState('hints-ui-visible')\" [placeholder]=\"tx('config.hints.uiModes.visible.placeholder', 'Ex.: Campo exibido conforme permiss\u00F5es.')\"></textarea>\n </mat-form-field>\n </section>\n </div>\n\n <section>\n <h4>{{ tx('config.helpPresentation.title', 'Apresenta\u00E7\u00E3o das ajudas dos campos') }}</h4>\n <p class=\"text-caption\">{{ tx('config.helpPresentation.description', 'Controle como hint/helpText dos campos aparece em formul\u00E1rios densos. Erros de valida\u00E7\u00E3o continuam inline.') }}</p>\n <div class=\"grid-3-cols\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.display.label', 'Exibi\u00E7\u00E3o') }}</mat-label>\n <mat-select [ngModel]=\"helpPresentationDraft.display\" (ngModelChange)=\"onHelpPresentationDisplayChange($event)\">\n <mat-option value=\"inline\">{{ tx('config.helpPresentation.display.inline', 'Inline') }}</mat-option>\n <mat-option value=\"popover\">{{ tx('config.helpPresentation.display.popover', '\u00CDcone de ajuda') }}</mat-option>\n <mat-option value=\"auto\">{{ tx('config.helpPresentation.display.auto', 'Autom\u00E1tica') }}</mat-option>\n <mat-option value=\"hidden\">{{ tx('config.helpPresentation.display.hidden', 'Oculta') }}</mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.inlineMaxLength.label', 'Limite inline') }}</mat-label>\n <input matInput type=\"number\" min=\"0\" [ngModel]=\"helpPresentationDraft.inlineMaxLength\"\n (ngModelChange)=\"onHelpPresentationInlineMaxLengthChange($event)\" />\n </mat-form-field>\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.helpPresentation.preferPopoverForControls.label', 'Preferir \u00EDcone em') }}</mat-label>\n <input matInput [ngModel]=\"getHelpPreferPopoverControlsText()\"\n (ngModelChange)=\"onHelpPreferPopoverControlsChange($event)\"\n [placeholder]=\"tx('config.helpPresentation.preferPopoverForControls.placeholder', 'toggle, checkbox, select')\" />\n </mat-form-field>\n </div>\n </section>\n\n <div class=\"actions-row\">\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"restoreHintsDefaults()\">\n <mat-icon>restore</mat-icon>\n {{ tx('config.hints.actions.restoreDefaults', 'Restaurar padr\u00F5es') }}\n </button>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('actions')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-acoes\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.actions.title', 'A\u00E7\u00F5es do formul\u00E1rio') }}</h3>\n <p class=\"text-caption\">{{ tx('config.actions.subtitle', 'Configure bot\u00F5es padr\u00E3o e a\u00E7\u00F5es customizadas.') }}</p>\n </div>\n </div>\n <praxis-actions-editor #actionsDraft [config]=\"editedConfig\" (validationChange)=\"onSurfaceDraftValidity(actionsDraft, $event)\" (configChange)=\"onConfigChange($event)\"></praxis-actions-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('rules')\">\n <div class=\"tab-content visual-builder-content\" data-testid=\"config-tab-panel-regras\">\n <div class=\"builder-header\">\n <div>\n <h3>{{ tx('config.rules.title', 'Regras visuais') }}</h3>\n <p class=\"text-caption\">{{ tx('config.rules.subtitle', 'Controle a apresenta\u00E7\u00E3o dos campos. Estas regras n\u00E3o executam comandos nem substituem decis\u00F5es de neg\u00F3cio governadas.') }}</p>\n </div>\n </div>\n @if (ruleConversionFailed) {\n <p role=\"alert\" data-testid=\"rules-conversion-error\">\n {{ tx('config.rules.conversionError', 'N\u00E3o foi poss\u00EDvel converter a condi\u00E7\u00E3o visual. Revise a regra; aplicar e salvar est\u00E3o bloqueados.') }}\n </p>\n }\n @if (!ruleConversionFailed && ruleDiagnostics.length) {\n <div class=\"rules-diagnostics\" data-testid=\"rules-diagnostics-panel\">\n <div class=\"rules-diagnostics__summary\">\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--total\">\n {{ tx('config.rules.summary.total', '{{count}} regras', { count: ruleDiagnosticsSummary.total }) }}\n </span>\n @if (ruleDiagnosticsSummary.invalid) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--error\">\n {{ tx('config.rules.summary.invalid', '{{count}} inv\u00E1lidas', { count: ruleDiagnosticsSummary.invalid }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.unsupported) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.unsupported', '{{count}} com propriedades rejeitadas', { count: ruleDiagnosticsSummary.unsupported }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.runtimeOnly) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.runtimeOnly', '{{count}} runtime only', { count: ruleDiagnosticsSummary.runtimeOnly }) }}\n </span>\n }\n @if (ruleDiagnosticsSummary.pendingReview) {\n <span class=\"rules-diagnostics__pill rules-diagnostics__pill--warn\">\n {{ tx('config.rules.summary.pendingReview', '{{count}} pendentes de revis\u00E3o', { count: ruleDiagnosticsSummary.pendingReview }) }}\n </span>\n }\n </div>\n <div class=\"rules-diagnostics__list\" [attr.aria-label]=\"tx('config.rules.diagnostics.ariaLabel', 'Diagn\u00F3stico das regras')\">\n @for (diagnostic of ruleDiagnostics; track diagnostic) {\n <article class=\"rules-diagnostics__item\"\n [class.rules-diagnostics__item--error]=\"getRuleStatusTone(diagnostic) === 'error'\"\n [class.rules-diagnostics__item--warn]=\"getRuleStatusTone(diagnostic) === 'warn'\">\n <div>\n <strong>{{ diagnostic.ruleName || diagnostic.ruleId }}</strong>\n <span>\n {{ tx('config.rules.diagnostics.targetConditionSummary', '{{targets}} alvo(s) \u00B7 {{conditions}} campo(s) na condi\u00E7\u00E3o', { targets: diagnostic.targetRefs.length, conditions: diagnostic.conditionRefs.length }) }}\n </span>\n @if (getRuleDiagnosticDetails(diagnostic).length) {\n <ul class=\"rules-diagnostics__details\">\n @for (detail of getRuleDiagnosticDetails(diagnostic); track detail) {\n <li>{{ detail }}</li>\n }\n </ul>\n }\n </div>\n <div class=\"rules-diagnostics__actions\">\n <span class=\"rules-diagnostics__status\">{{ getRuleStatusLabel(diagnostic) }}</span>\n @if (canApplyRulePropertyFix(diagnostic)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [matTooltip]=\"tx('config.rules.actions.fix.tooltip', 'Aplicar whitelist e saneamento de propriedades nesta regra')\"\n (click)=\"applyRulePropertyFix(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">auto_fix_high</mat-icon>\n {{ tx('config.rules.actions.fix', 'Corrigir') }}\n </button>\n }\n @if (diagnostic.status.includes('llm-generated-pending-review')) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [disabled]=\"!canAcceptPendingLlmRule(diagnostic)\"\n [matTooltip]=\"canAcceptPendingLlmRule(diagnostic) ? tx('config.rules.actions.accept.tooltip.ready', 'Aceitar sugest\u00E3o e atualizar estado visual') : tx('config.rules.actions.accept.tooltip.blocked', 'Corrija alvo, condi\u00E7\u00E3o e propriedades antes de aceitar')\"\n (click)=\"acceptPendingLlmRule(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n {{ tx('config.rules.actions.accept', 'Aceitar') }}\n </button>\n }\n @if (canOpenRuleJsonReview(diagnostic)) {\n <button\n mat-stroked-button\n type=\"button\"\n class=\"rules-diagnostics__action\"\n [matTooltip]=\"tx('config.rules.actions.reviewJson.tooltip', 'Abrir a aba JSON para revisar esta regra sem convers\u00E3o visual')\"\n (click)=\"openRuleJsonReview(diagnostic.ruleId)\">\n <mat-icon aria-hidden=\"true\">data_object</mat-icon>\n {{ tx('config.rules.actions.reviewJson', 'Ver JSON') }}\n </button>\n }\n </div>\n </article>\n }\n </div>\n </div>\n } @else if (!ruleConversionFailed) {\n <div class=\"rules-diagnostics rules-diagnostics--empty\" data-testid=\"rules-diagnostics-empty\">\n {{ tx('config.rules.empty', 'Nenhuma regra definida ainda. Crie uma regra para ver alvos, condi\u00E7\u00E3o, propriedades e compatibilidade do builder.') }}\n </div>\n }\n <praxis-visual-builder [config]=\"ruleBuilderConfig\" [initialRules]=\"ruleBuilderState\"\n (rulesChanged)=\"onRulesChanged($event)\"></praxis-visual-builder>\n @if (ruleConversionFailed) {\n <p role=\"status\" data-testid=\"rule-properties-draft-pending\">\n {{ tx('config.rules.effectsDraftPending', 'Conclua ou repare o rascunho no editor visual ou no JSON para editar seus efeitos. A \u00FAltima configura\u00E7\u00E3o aceita foi preservada e n\u00E3o representa este rascunho.') }}\n </p>\n } @else {\n <praxis-rule-properties-panel\n [rules]=\"currentRules\"\n [visualBlockNodes]=\"visualBlockNodeOptions\"\n (rulesChange)=\"onRulePropertiesChanged($event)\"\n ></praxis-rule-properties-panel>\n }\n <mat-card class=\"command-rules-card\" data-testid=\"form-command-rules-editor\">\n <mat-card-title>{{ tx('config.commandRules.title', 'Comandos condicionais') }}</mat-card-title>\n <mat-card-subtitle>{{ tx('config.commandRules.subtitle', 'Canal de comandos: execute a\u00E7\u00F5es globais quando uma condi\u00E7\u00E3o for satisfeita, respeitando as pol\u00EDticas da a\u00E7\u00E3o.') }}</mat-card-subtitle>\n <mat-card-content>\n <div class=\"command-rules-grid\">\n <div class=\"command-rules-toolbar\">\n <mat-form-field appearance=\"outline\" class=\"command-rules-select\">\n <mat-label>{{ tx('config.commandRules.command.label', 'Comando') }}</mat-label>\n <mat-select [disabled]=\"hasInvalidSurfaceDraft\" [(ngModel)]=\"selectedCommandRuleId\" (selectionChange)=\"onCommandRuleSelectionChange()\">\n @for (rule of commandRules; track rule) {\n <mat-option [value]=\"rule.id\">\n {{ rule.id }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n <button mat-stroked-button type=\"button\" [disabled]=\"hasInvalidSurfaceDraft\" (click)=\"addCommandRule()\">\n <mat-icon aria-hidden=\"true\">add</mat-icon>\n {{ tx('config.commandRules.actions.add', 'Adicionar') }}\n </button>\n <button mat-stroked-button color=\"warn\" type=\"button\" (click)=\"deleteCommandRule()\" [disabled]=\"hasInvalidSurfaceDraft || !selectedCommandRuleId\">\n <mat-icon aria-hidden=\"true\">delete</mat-icon>\n {{ tx('config.commandRules.actions.remove', 'Remover') }}\n </button>\n </div>\n\n @if (selectedCommandRuleId) {\n <div class=\"command-rule-condition-builder command-rules-full\">\n <praxis-visual-builder\n mode=\"condition\"\n [config]=\"ruleBuilderConfig\"\n [initialCondition]=\"commandRuleCondition\"\n (conditionChanged)=\"onCommandConditionChanged($event)\"\n ></praxis-visual-builder>\n </div>\n }\n\n <mat-form-field appearance=\"outline\" class=\"command-rules-full\">\n <mat-label>{{ tx('config.commandRules.conditionJson.label', 'Condi\u00E7\u00E3o JSON Logic') }}</mat-label>\n <textarea\n matInput\n rows=\"5\"\n [(ngModel)]=\"commandRuleConditionJson\"\n [attr.aria-label]=\"tx('config.commandRules.conditionJson.ariaLabel', 'Condi\u00E7\u00E3o JSON Logic do comando condicional')\"\n ></textarea>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.commandRules.globalAction.label', 'A\u00E7\u00E3o global') }}</mat-label>\n <mat-select [disabled]=\"hasInvalidSurfaceDraft\" [(ngModel)]=\"commandRuleActionId\" (selectionChange)=\"onCommandActionChange()\">\n @for (action of globalActionCatalog; track action) {\n <mat-option [value]=\"action.id\">\n {{ action.label || action.id }}\n </mat-option>\n }\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('config.commandRules.distinctBy.label', 'distinctBy') }}</mat-label>\n <input matInput [(ngModel)]=\"commandRuleDistinctBy\" [placeholder]=\"tx('config.commandRules.distinctBy.placeholder', 'ex.: idade')\" />\n </mat-form-field>\n\n @if (commandRuleActionSchema; as actionSchema) {\n <div\n class=\"command-rules-payload-fields command-rules-full\"\n >\n <div class=\"command-rules-section-title\">{{ tx('config.commandRules.structuredPayload.title', 'Payload estruturado') }}</div>\n @if (actionSchema.editorMode !== 'surface-open') {\n @for (field of actionSchema.fields; track field) {\n @if (shouldShowCommandActionField(field)) {\n @if (field.type === 'toggle') {\n <mat-slide-toggle\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n >\n {{ field.label }}\n </mat-slide-toggle>\n } @else {\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ field.label }}</mat-label>\n @if (field.type === 'textarea' || field.type === 'json') {\n <textarea\n matInput\n [rows]=\"field.rows || (field.type === 'json' ? 3 : 2)\"\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [placeholder]=\"field.placeholder || (field.type === 'json' ? '{ }' : '')\"\n [required]=\"isCommandActionFieldRequired(field)\"\n ></textarea>\n } @else {\n @if (field.type === 'select') {\n <mat-select\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [required]=\"isCommandActionFieldRequired(field)\"\n >\n @for (option of field.options || []; track option) {\n <mat-option [value]=\"option.value\">\n {{ option.label }}\n </mat-option>\n }\n </mat-select>\n } @else {\n <input\n matInput\n [type]=\"field.type === 'number' ? 'number' : 'text'\"\n [ngModel]=\"getCommandActionFieldValue(field)\"\n (ngModelChange)=\"onCommandActionFieldChange(field, $event)\"\n [ngModelOptions]=\"{ standalone: true }\"\n [placeholder]=\"field.placeholder || ''\"\n [required]=\"isCommandActionFieldRequired(field)\"\n />\n }\n }\n @if (field.hint) {\n <mat-hint>{{ field.hint }}</mat-hint>\n }\n @if (hasCommandActionFieldError(field.key)) {\n <mat-error>\n {{ getCommandActionFieldError(field.key) }}\n </mat-error>\n }\n @if (!hasCommandActionFieldError(field.key) && isCommandActionFieldMissing(field)) {\n <mat-error>\n {{ tx('config.commandRules.validation.requiredField', 'Campo obrigat\u00F3rio.') }}\n </mat-error>\n }\n </mat-form-field>\n }\n }\n }\n } @else {\n <praxis-surface-open-action-editor #commandSurfaceDraft\n class=\"command-rules-surface-editor\"\n data-testid=\"form-command-rule-surface-open-editor\"\n [value]=\"commandRuleSurfaceOpenPayload\"\n hostKind=\"dynamic-form\"\n (valueChange)=\"onCommandSurfaceOpenPayloadChange($event)\"\n (validationChange)=\"onSurfaceDraftValidity(commandSurfaceDraft, $event)\"\n ></praxis-surface-open-action-editor>\n }\n </div>\n }\n\n <mat-form-field appearance=\"outline\" class=\"command-rules-full\">\n <mat-label>{{ tx('config.commandRules.advancedPayload.label', 'Payload JSON avan\u00E7ado') }}</mat-label>\n <textarea\n matInput\n rows=\"4\"\n [(ngModel)]=\"commandRulePayloadJson\"\n [attr.aria-label]=\"tx('config.commandRules.advancedPayload.ariaLabel', 'Payload JSON da a\u00E7\u00E3o global')\"\n ></textarea>\n </mat-form-field>\n\n <div class=\"command-rules-options\">\n <mat-slide-toggle [(ngModel)]=\"commandRuleDistinct\">{{ tx('config.commandRules.options.distinct', 'Evitar repeti\u00E7\u00E3o enquanto a condi\u00E7\u00E3o permanecer verdadeira') }}</mat-slide-toggle>\n <mat-slide-toggle [(ngModel)]=\"commandRuleRunOnInitialEvaluation\">{{ tx('config.commandRules.options.runOnInitialEvaluation', 'Executar tamb\u00E9m na avalia\u00E7\u00E3o inicial') }}</mat-slide-toggle>\n </div>\n\n @if (commandRuleAuthoringError) {\n <div class=\"preview-error command-rules-full\">\n <mat-icon aria-hidden=\"true\">warning</mat-icon>\n <span>{{ commandRuleAuthoringError }}</span>\n </div>\n }\n\n <div\n class=\"command-rule-preview command-rules-full\"\n [class.command-rule-preview--invalid]=\"commandRulePreview.state === 'invalid'\"\n data-testid=\"command-rule-preview\"\n >\n <div class=\"command-rules-section-title\">{{ tx('config.commandRules.preview.title', 'Preview do comando') }}</div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.mode', 'Modo') }}</span>\n <strong>{{ commandRulePreview.executionMode }}</strong>\n </div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.action', 'A\u00E7\u00E3o') }}</span>\n <strong>{{ commandRulePreview.actionId || '\u2014' }}</strong>\n </div>\n <div class=\"command-rule-preview__row\">\n <span>{{ tx('config.commandRules.preview.policy', 'Policy') }}</span>\n <code>{{ commandRulePreview.policy | json }}</code>\n </div>\n @if (commandRulePreview.diagnostics.length) {\n <div class=\"command-rule-preview__diagnostics\">\n <mat-icon aria-hidden=\"true\">{{ commandRulePreview.state === 'invalid' ? 'warning' : 'visibility' }}</mat-icon>\n <span>{{ commandRulePreview.diagnostics[0] }}</span>\n </div>\n }\n </div>\n\n <div class=\"command-rules-actions\">\n <button mat-flat-button color=\"primary\" type=\"button\" (click)=\"applyCommandRule()\">\n <mat-icon aria-hidden=\"true\">check</mat-icon>\n {{ tx('config.commandRules.actions.apply', 'Aplicar comando') }}\n </button>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('cascades')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-cascatas\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.cascades.title', 'Depend\u00EAncias entre campos') }}</h3>\n <p class=\"text-caption\">{{ tx('config.cascades.subtitle', 'Configure cascatas e carregamento entre campos.') }}</p>\n </div>\n </div>\n <praxis-cascade-manager-tab [fields]=\"editedConfig.fieldMetadata || []\"\n (apply)=\"onCascadeApply($event)\"\n (validChange)=\"onCascadeValidChange($event)\"></praxis-cascade-manager-tab>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('messages')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-mensagens\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.messages.title', 'Mensagens e feedback') }}</h3>\n <p class=\"text-caption\">{{ tx('config.messages.subtitle', 'Padronize textos de sucesso, erro e confirma\u00E7\u00F5es.') }}</p>\n </div>\n </div>\n <praxis-messages-editor [config]=\"editedConfig\" (configChange)=\"onConfigChange($event)\"></praxis-messages-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('navigation')\">\n <div class=\"tab-content\" data-testid=\"config-tab-panel-navegacao\">\n <mat-card class=\"section-card\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.navigation.title', 'Navega\u00E7\u00E3o de retorno') }}</h3>\n <p class=\"text-caption\">{{ tx('config.navigation.subtitle', 'Defina o comportamento do bot\u00E3o Voltar em fluxos CRUD.') }}</p>\n </div>\n </div>\n <div class=\"form-grid\">\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"w-100\">\n <mat-label>{{ tx('config.navigation.returnTo.label', 'Rota de retorno') }}</mat-label>\n <input matInput id=\"returnTo\" [(ngModel)]=\"backConfig!.returnTo\" (ngModelChange)=\"onBackConfigChange()\" [placeholder]=\"tx('config.navigation.returnTo.placeholder', '/funcionarios')\" />\n </mat-form-field>\n </div>\n <div class=\"form-row\">\n <mat-slide-toggle [(ngModel)]=\"backConfig!.confirmOnDirty\" (ngModelChange)=\"onBackConfigChange()\">\n {{ tx('config.navigation.confirmOnDirty.label', 'Confirmar ao sair com altera\u00E7\u00F5es') }}\n </mat-slide-toggle>\n </div>\n <div class=\"block-status\" [class.block-status--implicit]=\"!isBackConfigBlockPersisted()\">\n <strong>{{ tx('config.navigation.backConfig.label', 'Back Config') }}</strong>\n @if (isBackConfigBlockPersisted()) {\n <span>{{ tx('config.navigation.backConfig.persisted', '`contextSnapshot.backConfig` ser\u00E1 persistido no documento can\u00F4nico.') }}</span>\n } @else {\n {{ tx('config.navigation.backConfig.implicit', 'Bloco ausente no documento can\u00F4nico. Os valores exibidos s\u00E3o fallback visual e n\u00E3o ser\u00E3o salvos at\u00E9 voc\u00EA editar.') }}\n }\n </div>\n </div>\n <div class=\"section-help\">\n <span class=\"section-help__label\">{{ tx('config.navigation.note.label', 'Observa\u00E7\u00E3o:') }}</span>\n <button\n praxisIconButton=\"help_outline\"\n size=\"dense\"\n class=\"help-icon-button\"\n type=\"button\"\n [matTooltip]=\"tx('config.navigation.note.tooltip', 'Afeta o fluxo de navega\u00E7\u00E3o do CRUD e pode ser sobreposto por metadados do recurso.')\"\n matTooltipPosition=\"above\"\n >\n </button>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n <mat-tab [label]=\"configTabLabel('json')\">\n <div class=\"tab-content json-tab-content\" data-testid=\"config-tab-panel-json\">\n <mat-card class=\"section-card section-card--json\">\n <mat-card-content>\n <div class=\"section-header\">\n <div>\n <h3>{{ tx('config.json.title', 'Configura\u00E7\u00E3o JSON') }}</h3>\n <p class=\"text-caption\">{{ tx('config.json.subtitle', 'Edi\u00E7\u00E3o avan\u00E7ada do documento can\u00F4nico de autoria do formul\u00E1rio.') }}</p>\n </div>\n </div>\n <form-json-config-editor [document]=\"jsonDocument\" (documentChange)=\"onJsonConfigChange($event)\"\n (validationChange)=\"onJsonValidationChange($event)\" (editorEvent)=\"onJsonEditorEvent($event)\">\n </form-json-config-editor>\n </mat-card-content>\n </mat-card>\n </div>\n </mat-tab>\n</mat-tab-group>\n", styles: [":host{container:praxis-authoring-editor/inline-size;display:flex;flex-direction:column;height:100%;min-width:0}.mobile-tab-selector{display:none;flex:0 0 auto;padding:8px 16px 0;background:var(--md-sys-color-surface)}.mobile-tab-selector__field{width:100%}.config-tabs{flex:1 1 auto;min-height:0;min-width:0}::ng-deep .mat-mdc-tab-group.config-tabs{display:flex;flex-direction:column}::ng-deep .mat-mdc-tab-group.config-tabs .mat-mdc-tab-body-wrapper{flex:1;min-height:0;min-width:0}::ng-deep .mat-mdc-tab-group.config-tabs .mat-mdc-tab-body-content{height:100%;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;padding:0!important}.tab-content{padding:20px 24px 28px;flex:1;min-width:0;box-sizing:border-box;display:flex;flex-direction:column;gap:24px}.json-tab-content{min-width:0;padding:12px 16px 16px}.section-card.section-card--json{display:flex;flex:1;min-height:calc(100vh - 180px);border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-low)}.section-card.section-card--json>mat-card-content,.section-card.section-card--json>.mat-mdc-card-content{display:flex;flex:1;min-width:0;min-height:0;flex-direction:column;padding:16px!important}.section-card--json form-json-config-editor{display:block;flex:1;min-width:0;min-height:0}.form-row{display:block;margin-bottom:12px}.form-grid{display:grid;gap:12px}.section-help{display:inline-flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.section-help__label{font-weight:500}.grid-2-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:16px}.grid-2-cols--compact{gap:12px}.w-100{width:100%}.visual-builder-content{padding:0!important;height:100%;min-width:0;overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;gap:16px}.visual-builder-content>praxis-visual-builder{flex:0 0 auto;min-width:0;min-height:clamp(360px,48vh,560px)}.visual-builder-content>praxis-rule-properties-panel{flex:0 0 auto;display:block;min-width:0;padding:0 16px 24px;box-sizing:border-box}.rules-diagnostics{flex:0 0 auto;display:grid;gap:10px;padding:12px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low)}.rules-diagnostics--empty{color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.rules-diagnostics__summary,.rules-diagnostics__list{display:flex;flex-wrap:wrap;gap:8px}.rules-diagnostics__pill{display:inline-flex;align-items:center;min-height:24px;padding:3px 9px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface);font-size:12px;font-weight:600}.rules-diagnostics__pill--warn{background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 72%,transparent);color:var(--md-sys-color-on-tertiary-container)}.rules-diagnostics__pill--error{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container)}.rules-diagnostics__item{display:flex;align-items:flex-start;justify-content:space-between;gap:14px;min-width:min(100%,280px);padding:8px 10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container)}.rules-diagnostics__item>div{display:grid;gap:2px;min-width:0}.rules-diagnostics__item strong{color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rules-diagnostics__item span{color:var(--md-sys-color-on-surface-variant);font-size:11px}.rules-diagnostics__actions{flex:0 0 auto;display:flex;align-items:center;gap:8px}.rules-diagnostics__details{display:grid;gap:2px;margin:4px 0 0;padding-left:16px;color:var(--md-sys-color-on-surface-variant);font-size:11px;line-height:1.35}.rules-diagnostics__details li{overflow-wrap:anywhere}.rules-diagnostics__item--warn{border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 52%,var(--md-sys-color-outline-variant))}.rules-diagnostics__item--error{border-color:var(--md-sys-color-error)}.rules-diagnostics__status{font-weight:600;margin-top:1px}.rules-diagnostics__action{min-width:0;height:28px;padding:0 10px;border-radius:999px;font-size:12px;line-height:1}.rules-diagnostics__action mat-icon{width:16px;height:16px;margin:0 4px 0 0;font-size:16px}.json-field{width:100%}.presentation-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:20px;align-items:start}.presentation-controls{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:14px 18px}.control{display:flex;flex-direction:column}.control-span{grid-column:1/-1}.block-status{grid-column:1/-1;display:flex;gap:8px;align-items:flex-start;padding:10px 12px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-primary-container) 35%,transparent);color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.45}.block-status strong{min-width:112px;font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.block-status--implicit{background:color-mix(in srgb,var(--md-sys-color-surface-variant) 42%,transparent);border:1px dashed var(--md-sys-color-outline)}.block-status--readonly{margin-bottom:12px}.block-status code{font-family:var(--md-ref-typeface-mono, \"Courier New\", monospace);font-size:11px}.control__label{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-bottom:6px}.toggle-group{max-width:100%;flex-wrap:wrap}.control--inline{grid-column:1/-1;display:flex;gap:16px;align-items:center}.presentation-preview{min-width:0;order:-1}.preview-card{border:1px solid var(--md-sys-color-outline);border-radius:12px;padding:14px;background:var(--md-sys-color-surface-container)}.preview-row{display:flex;gap:8px;padding:6px 0;border-bottom:1px dashed var(--md-sys-color-outline-variant)}.preview-row:last-child{border-bottom:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.presentation-preview .praxis-presentation__label{color:var(--md-sys-color-on-surface-variant);font-size:var(--pfx-pres-label-size, 12px)}.presentation-preview .praxis-presentation__value{min-width:0;overflow-wrap:anywhere;font-size:var(--pfx-pres-value-size, 16px);color:var(--md-sys-color-on-surface)}.presentation-preview .presentation-mode.pres-density-cozy .preview-row{padding:6px 0}.presentation-preview .presentation-mode.pres-density-compact .preview-row,.presentation-preview .presentation-mode.pres-compact .preview-row{padding:2px 0}.presentation-preview .presentation-mode.pres-label-left .preview-row{display:grid;grid-template-columns:var(--pfx-pres-label-width, 140px) 1fr;align-items:baseline;column-gap:10px}.presentation-preview .presentation-mode.pres-label-left .praxis-presentation__label{margin:0;text-align:var(--pfx-pres-label-align, start)}.presentation-preview .presentation-mode .praxis-presentation__value{text-align:var(--pfx-pres-value-align, start)}.presentation-preview h4{margin:0 0 8px;color:var(--md-sys-color-on-surface);font-size:1rem}.section-card:not(.section-card--json),.section-card:not(.section-card--json).mat-mdc-card,.section-card:not(.section-card--json).mat-mdc-card-outlined{border:none!important;border-width:0!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;margin:0!important;padding:0!important;--mdc-outlined-card-outline-width: 0px;--mdc-outlined-card-outline-color: transparent;--mdc-elevated-card-container-color: transparent;--mdc-outlined-card-container-color: transparent}.section-card:not(.section-card--json)>mat-card-content,.section-card:not(.section-card--json)>.mat-mdc-card-content{padding:0!important}.section-card:not(.section-card--json)+.section-card:not(.section-card--json),.section-card:not(.section-card--json).mat-mdc-card+.section-card:not(.section-card--json).mat-mdc-card{padding-top:24px!important;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 65%,transparent)!important}.section-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:16px}.tab-content--dense{padding:16px 20px 24px;gap:20px}.tab-content--dense .section-header{margin-bottom:10px}.tab-content--dense .form-row{margin-bottom:8px}.section-header h3{margin:0;font-size:1rem;font-weight:600;letter-spacing:-.01em;color:var(--md-sys-color-on-surface)}.text-caption{margin:4px 0 0;font-size:.85rem;line-height:1.45;color:var(--md-sys-color-on-surface-variant)}.section-header--compact{margin-bottom:10px}.section-body{display:block}.section-body--flex{flex:1;min-height:0;display:flex;flex-direction:column}.builder-header{padding:12px 16px;border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.builder-header h3{margin:0;font-size:1rem;color:var(--md-sys-color-on-surface)}.hint{margin:8px 0 0;padding:10px 12px;border-radius:8px;border:1px dashed color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 75%,transparent);color:var(--md-sys-color-on-surface-variant)}.meta-card{display:grid;gap:8px;padding:12px 14px;border-radius:8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 70%,transparent);color:var(--md-sys-color-on-surface)}.meta-row{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.meta-row strong{color:var(--md-sys-color-on-surface);font-weight:600}.runtime-contract-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px 14px}.runtime-contract-field{display:grid;gap:4px;padding:10px 12px;border-radius:8px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 65%,transparent)}.runtime-contract-label{font-size:11px;font-weight:600;letter-spacing:.02em;color:var(--md-sys-color-on-surface-variant)}.runtime-contract-code{display:block;font-family:var(--md-ref-typeface-mono, \"Courier New\", monospace);font-size:12px;line-height:1.45;color:var(--md-sys-color-on-surface);word-break:break-word;white-space:normal}.command-rules-card,.command-rules-card.mat-mdc-card,.command-rules-card.mat-mdc-card-outlined{margin:0!important;padding:20px 16px 24px!important;min-width:0;border:none!important;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 65%,transparent)!important;border-radius:0!important;background:transparent!important;box-shadow:none!important;--mdc-outlined-card-outline-width: 0px;--mdc-outlined-card-outline-color: transparent;--mdc-elevated-card-container-color: transparent;--mdc-outlined-card-container-color: transparent}.command-rules-card>mat-card-content,.command-rules-card>.mat-mdc-card-content{padding:12px 0 0!important}.command-rules-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(260px,100%),1fr));gap:12px;align-items:start;min-width:0}.command-rules-toolbar,.command-rules-options,.command-rules-actions{grid-column:1/-1;display:flex;align-items:center;gap:12px;flex-wrap:wrap}.command-rules-select{min-width:min(320px,100%)}.command-rules-full{grid-column:1/-1}.command-rule-condition-builder{min-height:420px;overflow:hidden;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.command-rules-payload-fields{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr));gap:12px;min-width:0;padding:12px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface-container-low)}.command-rules-section-title{grid-column:1/-1;font-size:12px;font-weight:600;color:var(--md-sys-color-on-surface-variant);text-transform:uppercase}.command-rules-surface-editor{grid-column:1/-1}.command-rule-preview{display:grid;gap:8px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}.command-rule-preview--invalid{border-color:var(--md-sys-color-error)}.command-rule-preview__row{display:grid;grid-template-columns:minmax(96px,.35fr) minmax(0,1fr);gap:8px;align-items:start;min-width:0}.command-rule-preview__row span{color:var(--md-sys-color-on-surface-variant);font-size:12px;font-weight:600}.command-rule-preview__row strong,.command-rule-preview__row code{min-width:0;overflow-wrap:anywhere}.command-rule-preview__diagnostics{display:flex;gap:8px;align-items:flex-start;color:var(--md-sys-color-on-surface-variant)}@container praxis-authoring-editor (max-width: 768px){.mobile-tab-selector{display:block}::ng-deep .mat-mdc-tab-group.config-tabs>.mat-mdc-tab-header{display:none}.tab-content{padding:12px}.json-tab-content{padding:8px}.section-card--json{min-height:auto}}.form-modes{display:flex;flex-direction:column;align-items:flex-start;gap:16px}.form-modes mat-button-toggle-group{max-width:100%;flex-wrap:wrap}.display-result{margin:0;padding-block:12px;color:var(--md-sys-color-on-surface);font:var(--md-sys-typescale-body-medium)}.presentation-preview .presentation-mode.pres-label-above .preview-row{flex-direction:column;gap:4px}.presentation-controls,.control{min-width:0}.control__hint{margin:6px 0 0;color:var(--md-sys-color-on-surface-variant);font:var(--md-sys-typescale-body-small, 400 12px/1.45 sans-serif)}.block-status{flex-wrap:wrap}:host{container-type:inline-size}@container (min-width: 900px){.presentation-layout{grid-template-columns:minmax(0,1fr) minmax(280px,.8fr)}.presentation-preview{order:1;position:sticky;top:16px}}.empty-state-fields{display:grid;align-items:start;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:var(--p-space-3, 12px);margin-block-start:var(--p-space-4, 16px)}.empty-state-appearance summary{cursor:pointer;padding-block:var(--p-space-3, 12px);color:var(--md-sys-color-on-surface)}.empty-state-content{grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr))}.empty-state-description{grid-column:1/-1}.empty-state-content mat-form-field{min-width:0}.empty-state-icon-actions{display:inline-flex;align-items:center}\n"] }]
34049
34082
  }], ctorParameters: () => [{ type: undefined, decorators: [{
34050
34083
  type: Inject,
34051
34084
  args: [ASYNC_CONFIG_STORAGE]
@@ -41036,7 +41069,7 @@ function objectNulls(value, path, diagnostics) {
41036
41069
  function record(value) { return value !== null && typeof value === 'object' && !Array.isArray(value); }
41037
41070
  function problem(code, path) { return { level: 'error', code, path, message: code }; }
41038
41071
  /** Derive execution-only identity and disable independent preferences. Never persist this projection. */
41039
- function materializeDynamicFormPageRuntimeInputs(value, pageId, widgetKey) {
41072
+ function materializeDynamicFormPageRuntimeInputs(value, pageId, widgetKey, options) {
41040
41073
  const decoded = decodeDynamicFormPageInputs(value);
41041
41074
  if (!decoded.document)
41042
41075
  return { inputs: null, diagnostics: decoded.diagnostics };
@@ -41047,12 +41080,48 @@ function materializeDynamicFormPageRuntimeInputs(value, pageId, widgetKey) {
41047
41080
  catch {
41048
41081
  return { inputs: null, diagnostics: [problem('dynamicForm.page.identity.invalid', '/key')] };
41049
41082
  }
41083
+ const cloned = cloneBoundedUiLayoutJsonDocument(value);
41084
+ if (options?.preview && record(cloned['config'])) {
41085
+ const previewConfig = { ...cloned['config'] };
41086
+ const existingActions = record(previewConfig['actions']) ? previewConfig['actions'] : {};
41087
+ previewConfig['actions'] = {
41088
+ ...existingActions,
41089
+ showSaveButton: false,
41090
+ showDeleteButton: false,
41091
+ showSubmitButton: false,
41092
+ custom: [],
41093
+ };
41094
+ delete previewConfig['hooks'];
41095
+ delete previewConfig['beforeSubmit'];
41096
+ delete previewConfig['afterSubmit'];
41097
+ delete previewConfig['onSubmit'];
41098
+ delete previewConfig['submitUrl'];
41099
+ cloned['config'] = previewConfig;
41100
+ }
41050
41101
  return {
41051
- inputs: { ...cloneBoundedUiLayoutJsonDocument(value), formId: id, componentInstanceId: id,
41052
- configPersistenceStrategy: 'volatile', enableCustomization: false, showAiAssistant: false },
41102
+ inputs: {
41103
+ ...cloned,
41104
+ formId: id,
41105
+ componentInstanceId: id,
41106
+ configPersistenceStrategy: 'volatile',
41107
+ enableCustomization: false,
41108
+ showAiAssistant: false,
41109
+ },
41053
41110
  diagnostics: [],
41054
41111
  };
41055
41112
  }
41113
+ const DYNAMIC_FORM_GOVERNED_PAGE_PREVIEW_ADAPTER = {
41114
+ widgetDefinitionId: 'praxis-dynamic-form',
41115
+ certifiedForInteractivePreview: true,
41116
+ validate: validateDynamicFormPageWidget,
41117
+ materializePreviewInputs: (widget, pageId) => {
41118
+ const materialized = materializeDynamicFormPageRuntimeInputs(widget.definition.inputs, pageId, widget.key, { preview: true });
41119
+ if (!materialized.inputs) {
41120
+ throw new Error(materialized.diagnostics[0]?.code ?? 'dynamicForm.page.preview.invalid');
41121
+ }
41122
+ return materialized.inputs;
41123
+ },
41124
+ };
41056
41125
  function nativePath(value) {
41057
41126
  const parts = (value ?? 'config').replace(/\[(\d+)\]/g, '.$1').split('.');
41058
41127
  const scope = parts.shift();
@@ -41073,4 +41142,4 @@ function nativePath(value) {
41073
41142
  * Generated bundle index. Do not edit.
41074
41143
  */
41075
41144
 
41076
- export { ActionsEditorComponent, CORPORATE_PRESENTATION_FORMAT_GALLERY, CanvasStateService, CanvasToolbarComponent, ColumnEditorComponent, DomainRuleFormRulesService, DynamicFormLayoutService, DynamicFormSchemaCacheService, ERGADM00034_COMPACT_PRESENTATION_EXAMPLE, Ergadm00034CompactPresentationExampleComponent, FORM_AI_CAPABILITIES, FORM_COMPONENT_AI_CAPABILITIES, FieldConfiguratorComponent, FieldEditorComponent, FormConfigService, FormContextService, FormLayoutService, FormRulesService, JsonConfigEditorComponent, LayoutColorToken, LayoutEditorComponent, LayoutPrefsService, PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST, PRAXIS_DYNAMIC_FORM_COMPONENT_METADATA, PRAXIS_FILTER_FORM_AUTHORING_MANIFEST, PRAXIS_FILTER_FORM_AUTHORING_PROJECTION, PRAXIS_FILTER_FORM_COMPONENT_METADATA, PraxisDynamicForm, PraxisDynamicFormConfigEditor, PraxisDynamicFormWidgetConfigEditor, PraxisFilterForm, PraxisFilterFormWidgetConfigEditor, PraxisFormActionsComponent, RowConfiguratorComponent, RowEditorComponent, SETTINGS_PANEL_DYNAMIC_FORM_PROVIDER, SectionEditorComponent, TASK_PRESETS, applyVisibilityRules, buildCorporatePresentationFormatGalleryConfig, buildDynamicFormApplyPlan, buildDynamicFormRuleAuthoringContext, buildErgadm00034CompactPresentationConfig, createDynamicFormAuthoringDocument, decodeDynamicFormPageInputs, encodeDynamicFormPageInputs, formLayoutRulesToBuilderState, getFormAiCatalog, getFormCapabilities, getFormEnum, isRuleSatisfied, materializeDynamicFormPageRuntimeInputs, normalizeDateArrays, normalizeDynamicFormAuthoringDocument, parseLegacyOrDynamicFormDocument, projectDynamicFormPageEditorChanges, providePraxisDynamicFormMetadata, providePraxisFilterFormMetadata, provideSettingsPanelDynamicForm, ruleBuilderStateToFormLayoutRules, serializeDynamicFormAuthoringDocument, stripLegacyFieldMetadata, toCanonicalDynamicFormConfig, validateDynamicFormAuthoringDocument, validateDynamicFormAuthoringInput, validateDynamicFormPageWidget };
41145
+ export { ActionsEditorComponent, CORPORATE_PRESENTATION_FORMAT_GALLERY, CanvasStateService, CanvasToolbarComponent, ColumnEditorComponent, DYNAMIC_FORM_GOVERNED_PAGE_PREVIEW_ADAPTER, DomainRuleFormRulesService, DynamicFormLayoutService, DynamicFormSchemaCacheService, ERGADM00034_COMPACT_PRESENTATION_EXAMPLE, Ergadm00034CompactPresentationExampleComponent, FORM_AI_CAPABILITIES, FORM_COMPONENT_AI_CAPABILITIES, FieldConfiguratorComponent, FieldEditorComponent, FormConfigService, FormContextService, FormLayoutService, FormRulesService, JsonConfigEditorComponent, LayoutColorToken, LayoutEditorComponent, LayoutPrefsService, PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST, PRAXIS_DYNAMIC_FORM_COMPONENT_METADATA, PRAXIS_FILTER_FORM_AUTHORING_MANIFEST, PRAXIS_FILTER_FORM_AUTHORING_PROJECTION, PRAXIS_FILTER_FORM_COMPONENT_METADATA, PraxisDynamicForm, PraxisDynamicFormConfigEditor, PraxisDynamicFormWidgetConfigEditor, PraxisFilterForm, PraxisFilterFormWidgetConfigEditor, PraxisFormActionsComponent, RowConfiguratorComponent, RowEditorComponent, SETTINGS_PANEL_DYNAMIC_FORM_PROVIDER, SectionEditorComponent, TASK_PRESETS, applyVisibilityRules, buildCorporatePresentationFormatGalleryConfig, buildDynamicFormApplyPlan, buildDynamicFormRuleAuthoringContext, buildErgadm00034CompactPresentationConfig, createDynamicFormAuthoringDocument, decodeDynamicFormPageInputs, encodeDynamicFormPageInputs, formLayoutRulesToBuilderState, getFormAiCatalog, getFormCapabilities, getFormEnum, isRuleSatisfied, materializeDynamicFormPageRuntimeInputs, normalizeDateArrays, normalizeDynamicFormAuthoringDocument, parseLegacyOrDynamicFormDocument, projectDynamicFormPageEditorChanges, providePraxisDynamicFormMetadata, providePraxisFilterFormMetadata, provideSettingsPanelDynamicForm, ruleBuilderStateToFormLayoutRules, serializeDynamicFormAuthoringDocument, stripLegacyFieldMetadata, toCanonicalDynamicFormConfig, validateDynamicFormAuthoringDocument, validateDynamicFormAuthoringInput, validateDynamicFormPageWidget };