# UI Troubleshooting & Resolução de Estilos (JavaFX CSS) Este documento registra a investigação da causa raiz de problemas visuais na interface gráfica do CyberCore Signer, em especial a falha de renderização de textos com cor preta (`Color.BLACK`) via `setStyle()`, a eliminação definitiva de estilos inline de cor e a transição para o tema claro unificado. --- ## 1. O Problema: Texto Renderizado em Preto (`#000000`) via `setStyle` ### Sintoma Em diálogos modais como `ExitConfirmationDialog`, `PdfSignDialog` e `PdfCertificateSignDialog`, chamadas como: ```java subtitle.setStyle("-fx-text-fill: -fx-text-secondary;"); lblDocName.setStyle("-fx-text-fill: -fx-text-primary;"); dragTip.setStyle("-fx-text-fill: -fx-text-secondary;"); ``` resultavam em texto renderizado com a cor preta opaca (`#000000`), mesmo quando o token `-fx-text-secondary` já se encontrava definido no arquivo `theme.css`. --- ## 2. Investigação Técnica e Causa Raiz ### 2.1 Por que `setStyle("-fx-text-fill: -fx-text-secondary")` renderiza PRETO? No motor de estilização do JavaFX (`com.sun.javafx.css.StyleManager` / `CssStyleHelper`): 1. **Momento da Avaliação (Timing) de Nós Fora da Árvore da Scene:** Quando um nó (como um `Label` ou `Text`) é instanciado no código Java dentro do construtor de um diálogo e recebe `.setStyle("-fx-text-fill: -fx-text-secondary;")`, ele ainda **não foi anexado ao grafo de cena** (`Scene`). 2. **Escopo de Resolução de Lookups Ausente:** Como `-fx-text-secondary` é uma cor pesquisada (*looked-up color*) definida no seletor `.root` da folha de estilo da aplicação, a engine de CSS do JavaFX tenta resolver essa variável subindo a cadeia de nós pais (`parent chain`) até alcançar `.root`. Como o nó está solto na memória (sem parent e sem Scene vinculada no instante da chamada), o lookup não encontra nenhuma definição válida. 3. **Mecanismo de Fallback Silencioso do Modena (`Color.BLACK`):** O analisador do JavaFX não lança exceção ao falhar na resolução de uma cor de lookup em estilo inline. Em vez disso, seu conversor (`PaintConverter` / `ColorConverter`) assume o valor padrão de salvaguarda da especificação Modena: **`Color.BLACK` (`rgba(0, 0, 0, 1.0)`)**. 4. **Imutabilidade e Prioridade do Estilo Inline:** O estilo inline atribuído via `setStyle(...)` possui a especificidade mais alta na hierarquia CSS do JavaFX. O valor pré-resolvido como `Color.BLACK` fica gravado diretamente no cache de estilo do nó. Quando a Scene finalmente executa a passagem formal de CSS (`applyCss()` / `layout()`), a engine prioriza o estilo inline e não reavalia o lookup que falhou previamente. ### 2.2 Por que o problema não ocorre com Classes CSS? Quando utilizamos classes semânticas declaradas em folha de estilo (ex.: `lbl.getStyleClass().add("text-muted");`): ```css .text-muted { -fx-text-fill: -fx-text-secondary; } ``` A resolução da regra é postergada até que o nó pertença à hierarquia da Scene e a passagem de CSS do JavaFX seja executada. Nesse momento, o nó tem acesso direto às definições de `.root`, resolvendo perfeitamente o token para a cor correta da paleta (`#475569`). --- ## 3. Diretriz Arquitetural: Proibição de Cores em `setStyle()` Fica estabelecido como regra obrigatória de desenvolvimento no `cybercore-ui`: 1. **`setStyle()` restrito exclusivamente à Geometria:** - Permitido: dimensões dinâmicas, larguras mínimas, alturas, alinhamentos e paddings específicos de cálculo em tempo de execução (`-fx-min-width`, `-fx-pref-width`, `-fx-padding`, `-fx-alignment`). - **Terminantemente proibido em `setStyle()`:** - `-fx-text-fill` - `-fx-background-color` - `-fx-border-color` - `-fx-fill` / `-fx-stroke` - Códigos hexadecimais (`#...`) ou funções cromáticas (`rgb(...)`, `rgba(...)`) - Nomes de lookups de cor (`-fx-accent`, `-fx-color-*`, etc.) 2. **Uso Obrigatório de Classes CSS Semânticas:** | Classe CSS | Finalidade | Propriedade Aplicada | |---|---|---| | `.text-primary` | Texto principal | `-fx-text-fill: -fx-text-primary;` | | `.text-secondary`, `.text-muted` | Texto auxiliar / metadados | `-fx-text-fill: -fx-text-secondary;` | | `.text-accent` | Destaque primário | `-fx-text-fill: -fx-accent;` | | `.text-bold` | Tipografia em negrito | `-fx-font-weight: bold;` | | `.text-small` | Texto compacto | `-fx-font-size: 11px;` | | `.text-mono` | Fonte monoespaçada para hashes | `-fx-font-family: monospace;` | | `.surface-box` | Container de superfície branca com borda | `-fx-background-color: -fx-color-surface;` | | `.toolbar-box` | Barra de ferramentas compacta | `-fx-background-color: -fx-color-surface;` | | `.scroll-transparent` | ScrollPane sem fundo cinza | `-fx-background-color: transparent;` | | `.status-ok` / `.status-warn` / `.status-error` | Indicadores de status | Cores semânticas da paleta | --- ## 4. Salvaguardas Automatizadas O teste de arquitetura [`DesignTokenGuardrailTest.java`](file:///var/www/cybercore/cybercore-signer/modules/cybercore-ui/src/test/java/br/com/cybercore/signer/ui/theme/DesignTokenGuardrailTest.java) atua como barreira de compilação contínua: - Varre todos os arquivos `.java` no módulo `cybercore-ui` e reprova automaticamente o build se qualquer chamada `setStyle()` contiver propriedades ou valores de cor. - Valida matematicamente a relação de contraste WCAG AA (mínimo de 4.5:1 para texto normal) em todas as combinações de tokens de texto sobre superfície/fundo. - Assegura ausência de seletores ou classes residuais de temas escuros (`.theme-dark`, `AppTheme`, `isDark()`). --- ## 5. Comportamento da Barra de Título Nativa no Windows (DWM em Modo Escuro) ### Diagnóstico Operacional Quando o sistema operacional Windows 10/11 está configurado no "Modo Escuro do Sistema" (*Personalização > Cores > Escolher o modo: Escuro*), o gerenciador de janelas do sistema operacional (**Desktop Window Manager — DWM**) aplica automaticamente o atributo `DWMWA_USE_IMMERSIVE_DARK_MODE` na moldura não-cliente da janela nativa (`HWND`). Como o CyberCore Signer utiliza decoração nativa padrão (`StageStyle.DECORATED`) para preservar o comportamento esperado pelo usuário empresarial — incluindo cantos arredondados, atalhos de teclado nativos, suporte a múltiplos monitores com DPIs distintos e os *Snap Layouts* do Windows 11 — a barra de título nativa é desenhada pelo Windows em tom escuro, enquanto o conteúdo da janela exibe o tema claro unificado da aplicação. ### Diretriz de Arquitetura (Não Forçar) Em estrita conformidade com as diretrizes do projeto (Regras 2 e 23): 1. **Não forçar a barra de título:** Evita-se o uso de hacks de baixo nível via JNA/JNI para sobrescrever o DWM do Windows ou janelas não decoradas (`UNDECORATED`), o que causaria quebra de acessibilidade e perda de recursos nativos do sistema. 2. **Harmonia Visual:** A moldura do Windows atua como moldura de sistema e o conteúdo claro do CyberCore Signer permanece legível, íntegro e em total conformidade com a especificação de interface.