feat(ui): standardize 24px icon system with dynamic theme recoloring

This commit is contained in:
Claudecio Martins
2026-10-20 20:04:52 -03:00
parent b13129b7d8
commit 5d8c5d487d
34 changed files with 509 additions and 253 deletions
+106
View File
@@ -0,0 +1,106 @@
# Sistema de Ícones — CyberCore Signer
Este documento estabelece as especificações de design, gramática visual, convenções de código e diretrizes de renderização do sistema de ícones do **CyberCore Signer**.
---
## 1. Gramática Visual e Grid Base
O sistema de ícones do CyberCore Signer foi projetado para oferecer clareza, consistência corporativa e alta fidelidade tanto no **Modo Claro** quanto no **Modo Escuro**, além de suporte a telas com alta densidade de pixels (HiDPI / Retina).
| Parâmetro | Especificação | Descrição |
| :--- | :--- | :--- |
| **ViewBox Canônico** | `0 0 24 24` | Todos os ícones são desenhados em um canvas quadrado padronizado de 24×24 pixels. |
| **Safe Area** | `2px` em todas as bordas | Os grafismos principais ficam contidos na área útil de `20×20px` (coordenadas de `2` a `22`). |
| **Stroke (Espessura)** | `1.75px` a `2.0px` | Traços consistentes entre todos os glifos vetoriais, proporcionando peso uniforme. |
| **Cantos e Terminações** | `round` | `stroke-linecap="round"` e `stroke-linejoin="round"` para um visual moderno e suave. |
| **Texto Embutido** | **Nenhum** (`Proibido`) | Ícones não devem incorporar elementos `<text>`. Toda semântica é transmitida por formas puras e labels da interface. |
---
## 2. Paleta de Cores e Tintas Semânticas
Os ícones utilizam `currentColor` como tinta principal, permitindo repintura dinâmica e herança das cores dos tokens do tema ativo:
| Papel | Token / Cor Modo Claro | Token / Cor Modo Escuro | Uso |
| :--- | :--- | :--- | :--- |
| **Tinta Principal (`currentColor`)** | `#1E293B` (`-fx-color-text`) | `#F1F5F9` (`-fx-color-text`) | Linhas de contorno, silhuetas e glifos primários. |
| **Acento Primário** | `#0288D1` (`-fx-color-primary`) | `#38BDF8` (`-fx-color-primary`) | Elementos de destaque, dobras de documentos, escudos. |
| **Sucesso** | `#10B981` (`-fx-color-success`) | `#34D399` (`-fx-color-success`) | Confirmações, validações concluídas (`check`, `validate`). |
| **Alerta / Atenção** | `#F59E0B` (`-fx-color-warning`) | `#FBBF24` (`-fx-color-warning`) | Avisos de validade próxima, selos e certificações (`seal`). |
| **Erro / Perigo** | `#EF4444` (`-fx-color-error`) | `#F87171` (`-fx-color-error`) | Ações destrutivas, falhas de assinatura (`error`, `exit`). |
| **Atenuado / Muted** | `#64748B` (`-fx-color-text-muted`) | `#94A3B8` (`-fx-color-text-muted`) | Guias internas, linhas secundárias, fechar (`close`). |
---
## 3. Escala de Tamanhos Padronizados
Para manter a consistência da interface, os ícones devem ser consumidos exclusivamente através dos 5 tamanhos canônicos definidos na fachada `Icons`:
```
16px 20px 24px 32px 40px
[ Micro ] [ Pequeno ] [ Padrão ] [ Médio ] [ Grande ]
```
- **`SIZE_16` (16×16 px):** Badges de status de certificado, botões auxiliares pequenos de janelas de diálogo (ex.: fechar, atualizar).
- **`SIZE_20` (20×20 px):** Menus secundários, botões de ação secundária, itens compactos em listas.
- **`SIZE_24` (24×24 px):** Tamanho padrão de componentes, botões de barra lateral do Hub, campos com ícone prefixado.
- **`SIZE_32` (32×32 px):** Cabeçalhos de diálogos de aprovação CCSP, títulos de assistentes.
- **`SIZE_40` (40×40 px):** Cartões e botões do painel principal (Hub de Ações Rápidas).
---
## 4. Catálogo dos Ícones Vetoriais
| Arquivo SVG | Glifo / Nome | Propósito e Uso na Aplicação |
| :--- | :--- | :--- |
| `pdf.svg` | `Icons.pdf()` | Assinatura de documentos PDF e fluxos PAdES. |
| `xml.svg` | `Icons.xml()` | Assinatura de documentos XML e notas fiscais (XMLDSig). |
| `file.svg` | `Icons.file()` | Assinatura de arquivos e digests genéricos. |
| `attached.svg` | `Icons.attached()` | Assinatura atachada / envelopada (CAdES Attached). |
| `batch.svg` | `Icons.batch()` | Assinatura de múltiplos documentos em lote. |
| `co-sign.svg` | `Icons.coSign()` | Adição de co-assinatura em documento já assinado. |
| `timestamp.svg` | `Icons.timestamp()` | Aplicação de carimbo do tempo (TSA). |
| `ltv.svg` | `Icons.ltv()` | Assinatura com validação de longo prazo (LTV). |
| `validate.svg` | `Icons.validate()` | Validador de integridade e assinaturas digitais. |
| `validate-timestamp.svg` | `Icons.validateTimestamp()` | Validador específico de carimbos de tempo. |
| `seal.svg` | `Icons.seal()` | Gerenciamento e aplicação de selos visuais. |
| `seal-icp-brasil.svg` | `Icons.sealIcpBrasil()` | Selo vetorial oficial padrão ICP-Brasil. |
| `cert.svg` | `Icons.certificates()` | Gerenciamento e seleção de certificados A1 e A3. |
| `shield.svg` | `Icons.shield()` | Segurança, proteção e integridade do agente. |
| `settings.svg` | `Icons.settings()` | Painel de configurações e preferências locais. |
| `logs.svg` | `Icons.logs()` | Visualizador de registros de auditoria e logs locais. |
| `tutorial.svg` | `Icons.tutorial()` | Guia interativo e tutorial de primeiros passos. |
| `about.svg` | `Icons.about()` | Diálogo sobre o CyberCore Signer, versão e licença. |
| `exit.svg` | `Icons.exit()` | Confirmação e encerramento do agente desktop. |
| `refresh.svg` | `Icons.refresh()` | Atualizar lista de certificados e recarregar dados. |
| `sun.svg` | `Icons.sun()` | Alternador para Modo Claro. |
| `moon.svg` | `Icons.moon()` | Alternador para Modo Escuro. |
| `arrow-right.svg` | `Icons.arrowRight()` | Navegação para próximo passo ou expansão. |
| `close.svg` | `Icons.close()` | Fechar diálogo, dispensar notificação ou cancelar. |
| `check.svg` | `Icons.check()` | Operação concluída com sucesso ou item selecionado. |
| `error.svg` | `Icons.error()` | Alerta de falha, cancelamento ou erro de hardware. |
| `star.svg` | `Icons.star()` | Certificado padrão ou favorito selecionado. |
| `zoom-in.svg` | `Icons.zoomIn()` | Aumentar zoom na visualização de documento ou selo. |
| `zoom-out.svg` | `Icons.zoomOut()` | Reduzir zoom na visualização de documento ou selo. |
| `zoom-fit.svg` | `Icons.zoomFit()` | Ajustar visualização à tela ou página inteira. |
---
## 5. Implementação Técnica
### Fachada `Icons`
A classe `br.com.cybercore.signer.ui.components.Icons` centraliza a instanciação:
```java
// Tamanho padrão (24px) com cor do tema ativo:
Node icon = Icons.settings();
// Tamanho específico:
Node refresh = Icons.refresh(Icons.SIZE_16);
// Tinta customizada:
Node custom = Icons.of("pdf", Icons.SIZE_40, Color.web("#0288D1"));
```
### Repintura Dinâmica
Ao registrar alteração de tema em `ThemeManager`, os nós de ícone baseados em `currentColor` recebem automaticamente o listener e atualizam suas cores em tempo real sem necessidade de recriar a janela.
@@ -39,6 +39,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import br.com.cybercore.signer.ui.theme.ThemeManager;
import java.util.Optional;
import java.util.function.Supplier;
@@ -130,18 +131,25 @@ public final class AssetManager {
* Retorna um Node de ícone customizado (prioritariamente SVG, com fallback para PNG ou supplier vetorial).
*/
public static Node getIconOrDefault(String iconName, double size, Supplier<Node> fallbackSupplier) {
return getIconOrDefault(iconName, size, null, fallbackSupplier);
}
/**
* Retorna um Node de ícone customizado com suporte a repintura ou tinta explícita.
*/
public static Node getIconOrDefault(String iconName, double size, Color tint, Supplier<Node> fallbackSupplier) {
if (iconName != null && !iconName.isBlank()) {
String cleanName = cleanBaseName(iconName);
// 1. Prioridade para SVG em ./assets/icons/
Optional<Node> localSvg = loadSvgIconFromPath(Path.of("assets", "icons", cleanName + ".svg"), size);
Optional<Node> localSvg = loadSvgIconFromPath(Path.of("assets", "icons", cleanName + ".svg"), size, tint);
if (localSvg.isPresent()) {
return localSvg.get();
}
// 2. Procura SVG em ~/.cybercore/assets/icons/
String userHome = System.getProperty("user.home", ".");
Optional<Node> userSvg = loadSvgIconFromPath(Path.of(userHome, ".cybercore", "assets", "icons", cleanName + ".svg"), size);
Optional<Node> userSvg = loadSvgIconFromPath(Path.of(userHome, ".cybercore", "assets", "icons", cleanName + ".svg"), size, tint);
if (userSvg.isPresent()) {
return userSvg.get();
}
@@ -151,7 +159,7 @@ public final class AssetManager {
InputStream resStream = AssetManager.class.getResourceAsStream(resSvgPath);
if (resStream != null) {
try (resStream) {
Node node = parseSvgToNode(resStream, size, size);
Node node = parseSvgToNode(resStream, size, size, tint);
if (node != null) {
return node;
}
@@ -184,7 +192,7 @@ public final class AssetManager {
Path localSvg = Path.of("assets", "images", cleanName + ".svg");
if (Files.isRegularFile(localSvg)) {
try (InputStream in = new FileInputStream(localSvg.toFile())) {
Node node = parseSvgToNode(in, width, height);
Node node = parseSvgToNode(in, width, height, null);
if (node != null) {
logger.debug("Carregada imagem SVG local: {}", localSvg);
return node;
@@ -199,7 +207,7 @@ public final class AssetManager {
Path userSvg = Path.of(userHome, ".cybercore", "assets", "images", cleanName + ".svg");
if (Files.isRegularFile(userSvg)) {
try (InputStream in = new FileInputStream(userSvg.toFile())) {
Node node = parseSvgToNode(in, width, height);
Node node = parseSvgToNode(in, width, height, null);
if (node != null) {
logger.debug("Carregada imagem SVG do usuário: {}", userSvg);
return node;
@@ -214,7 +222,7 @@ public final class AssetManager {
InputStream resStream = AssetManager.class.getResourceAsStream(resPath);
if (resStream != null) {
try (resStream) {
Node node = parseSvgToNode(resStream, width, height);
Node node = parseSvgToNode(resStream, width, height, null);
if (node != null) {
return node;
}
@@ -253,10 +261,10 @@ public final class AssetManager {
return clean;
}
private static Optional<Node> loadSvgIconFromPath(Path path, double size) {
private static Optional<Node> loadSvgIconFromPath(Path path, double size, Color tint) {
if (Files.isRegularFile(path)) {
try (InputStream in = new FileInputStream(path.toFile())) {
Node node = parseSvgToNode(in, size, size);
Node node = parseSvgToNode(in, size, size, tint);
if (node != null) {
logger.debug("Carregado ícone SVG customizado de: {}", path);
return Optional.of(node);
@@ -272,13 +280,18 @@ public final class AssetManager {
* Parser analítico de SVG para nós gráficos JavaFX com suporte a dimensões quadradas.
*/
public static Node parseSvgToNode(InputStream in, double targetSize) {
return parseSvgToNode(in, targetSize, targetSize);
return parseSvgToNode(in, targetSize, targetSize, null);
}
public static Node parseSvgToNode(InputStream in, double targetSize, Color tint) {
return parseSvgToNode(in, targetSize, targetSize, tint);
}
/**
* Parser analítico completo de SVG para nós gráficos JavaFX com dimensões proporcionais e suporte a defs/gradientes.
*/
public static Node parseSvgToNode(InputStream in, double targetWidth, double targetHeight) {
return parseSvgToNode(in, targetWidth, targetHeight, null);
}
public static Node parseSvgToNode(InputStream in, double targetWidth, double targetHeight, Color tint) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(false);
@@ -326,8 +339,14 @@ public final class AssetManager {
Map<String, Paint> defsMap = new HashMap<>();
parseDefs(svg, defsMap);
Color effectiveCurrentColor = (tint != null) ? tint :
(ThemeManager.isDark() ? Color.web("#F1F5F9") : Color.web("#1E293B"));
List<Shape> dynamicStrokeShapes = new ArrayList<>();
List<Shape> dynamicFillShapes = new ArrayList<>();
RenderContext ctx = new RenderContext(defsMap, effectiveCurrentColor, dynamicStrokeShapes, dynamicFillShapes);
Group contentGroup = new Group();
renderChildren(svg, contentGroup, defsMap);
renderChildren(svg, contentGroup, ctx);
double scaleX = targetWidth / vbWidth;
double scaleY = targetHeight / vbHeight;
@@ -348,9 +367,24 @@ public final class AssetManager {
);
Pane container = new Pane(contentGroup);
container.getStyleClass().add("cyber-icon");
container.setPrefSize(targetWidth, targetHeight);
container.setMaxSize(targetWidth, targetHeight);
container.setMinSize(targetWidth, targetHeight);
// Se for dinâmico (sem tint fixo) e contiver elementos currentColor, atualiza com a mudança de tema
if (tint == null && (!dynamicStrokeShapes.isEmpty() || !dynamicFillShapes.isEmpty())) {
ThemeManager.addListener(theme -> {
Color c = (theme == ThemeManager.AppTheme.DARK) ? Color.web("#F1F5F9") : Color.web("#1E293B");
for (Shape s : dynamicStrokeShapes) {
s.setStroke(c);
}
for (Shape s : dynamicFillShapes) {
s.setFill(c);
}
});
}
return container;
} catch (Exception e) {
@@ -444,7 +478,14 @@ public final class AssetManager {
}
}
private static void renderChildren(Element parent, Group targetGroup, Map<String, Paint> defsMap) {
private record RenderContext(
Map<String, Paint> defsMap,
Color currentColor,
List<Shape> dynamicStrokeShapes,
List<Shape> dynamicFillShapes
) {}
private static void renderChildren(Element parent, Group targetGroup, RenderContext ctx) {
NodeList children = parent.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
org.w3c.dom.Node n = children.item(i);
@@ -452,7 +493,7 @@ public final class AssetManager {
if ("defs".equalsIgnoreCase(el.getTagName())) {
continue;
}
Node jfxNode = createElementNode(el, defsMap);
Node jfxNode = createElementNode(el, ctx);
if (jfxNode != null) {
targetGroup.getChildren().add(jfxNode);
}
@@ -460,7 +501,7 @@ public final class AssetManager {
}
}
private static Node createElementNode(Element el, Map<String, Paint> defsMap) {
private static Node createElementNode(Element el, RenderContext ctx) {
String tagName = el.getTagName().toLowerCase();
Shape shape = null;
@@ -527,7 +568,7 @@ public final class AssetManager {
Map<String, String> inlineStyle = el.hasAttribute("style") ? parseStyleAttribute(el.getAttribute("style")) : Map.of();
String fillVal = inlineStyle.getOrDefault("fill", el.hasAttribute("fill") ? el.getAttribute("fill") : null);
if (fillVal != null) {
t.setFill(parsePaint(fillVal, defsMap, Color.BLACK));
t.setFill(parsePaint(fillVal, ctx, Color.BLACK));
}
String anchor = inlineStyle.getOrDefault("text-anchor", el.getAttribute("text-anchor"));
@@ -555,9 +596,9 @@ public final class AssetManager {
}
case "g" -> {
Group g = new Group();
renderChildren(el, g, defsMap);
renderChildren(el, g, ctx);
if (el.hasAttribute("stroke")) {
Paint strokePaint = parsePaint(el.getAttribute("stroke"), defsMap, null);
Paint strokePaint = parsePaint(el.getAttribute("stroke"), ctx, null);
double sw = parseDouble(el.getAttribute("stroke-width"), 1.0);
for (Node child : g.getChildren()) {
if (child instanceof Shape s) {
@@ -572,7 +613,8 @@ public final class AssetManager {
}
if (shape != null) {
applyShapeStyles(el, shape, defsMap);
shape.getStyleClass().add("cyber-icon-glyph");
applyShapeStyles(el, shape, ctx);
applyElementTransform(el, shape);
return shape;
}
@@ -597,19 +639,25 @@ public final class AssetManager {
return styleMap;
}
private static void applyShapeStyles(Element el, Shape shape, Map<String, Paint> defsMap) {
private static void applyShapeStyles(Element el, Shape shape, RenderContext ctx) {
Map<String, String> inlineStyle = el.hasAttribute("style") ? parseStyleAttribute(el.getAttribute("style")) : Map.of();
String fillVal = inlineStyle.getOrDefault("fill", el.hasAttribute("fill") ? el.getAttribute("fill") : null);
if (fillVal != null) {
shape.setFill(parsePaint(fillVal, defsMap, Color.TRANSPARENT));
if ("currentColor".equalsIgnoreCase(fillVal.trim()) && ctx != null) {
ctx.dynamicFillShapes().add(shape);
}
shape.setFill(parsePaint(fillVal, ctx, Color.TRANSPARENT));
} else if (shape instanceof Line) {
shape.setFill(Color.TRANSPARENT);
}
String strokeVal = inlineStyle.getOrDefault("stroke", el.hasAttribute("stroke") ? el.getAttribute("stroke") : null);
if (strokeVal != null) {
shape.setStroke(parsePaint(strokeVal, defsMap, Color.TRANSPARENT));
if ("currentColor".equalsIgnoreCase(strokeVal.trim()) && ctx != null) {
ctx.dynamicStrokeShapes().add(shape);
}
shape.setStroke(parsePaint(strokeVal, ctx, Color.TRANSPARENT));
}
String strokeWidthVal = inlineStyle.getOrDefault("stroke-width", el.hasAttribute("stroke-width") ? el.getAttribute("stroke-width") : null);
@@ -629,20 +677,20 @@ public final class AssetManager {
}
}
private static Paint parsePaint(String str, Map<String, Paint> defsMap, Paint fallback) {
private static Paint parsePaint(String str, RenderContext ctx, Paint fallback) {
if (str == null || str.isBlank() || "none".equalsIgnoreCase(str)) {
return Color.TRANSPARENT;
}
String trimmed = str.trim();
if (trimmed.startsWith("url(#") && trimmed.endsWith(")")) {
String id = trimmed.substring(5, trimmed.length() - 1).trim();
Paint defPaint = defsMap.get(id);
Paint defPaint = ctx != null && ctx.defsMap() != null ? ctx.defsMap().get(id) : null;
if (defPaint != null) {
return defPaint;
}
return Color.web("#0288d1");
}
return parseColor(trimmed, fallback instanceof Color ? (Color) fallback : Color.BLACK);
return parseColor(trimmed, fallback instanceof Color ? (Color) fallback : Color.BLACK, ctx);
}
private static void parsePoints(String ptsStr, java.util.List<Double> pointsList) {
@@ -658,12 +706,19 @@ public final class AssetManager {
}
private static Color parseColor(String str, Color fallback) {
return parseColor(str, fallback, null);
}
private static Color parseColor(String str, Color fallback, RenderContext ctx) {
if (str == null || str.isBlank() || "none".equalsIgnoreCase(str)) {
return Color.TRANSPARENT;
}
String trimmed = str.trim();
if ("currentColor".equalsIgnoreCase(trimmed)) {
return Color.web("#0288d1");
if (ctx != null && ctx.currentColor() != null) {
return ctx.currentColor();
}
return ThemeManager.isDark() ? Color.web("#F1F5F9") : Color.web("#1E293B");
}
try {
return Color.web(trimmed);
@@ -0,0 +1,165 @@
package br.com.cybercore.signer.ui.components;
import br.com.cybercore.signer.ui.assets.AssetManager;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import java.util.function.Supplier;
/**
* Fachada centralizada e moderna para obtenção de ícones vetoriais padronizados no CyberCore Signer.
* <p>
* Segue a gramática visual estipulada em {@code docs/icon-system.md}:
* grid canônico de 24x24 px, safe area de 2px, stroke 1.75-2.0px, sem textos embutidos
* e repintura dinâmica orientada a temas (currentColor).
*/
public final class Icons {
/** Tamanho micro (16x16 px) para badges, tags e botões compactos. */
public static final int SIZE_16 = 16;
/** Tamanho pequeno (20x20 px) para botões auxiliares e itens compactos. */
public static final int SIZE_20 = 20;
/** Tamanho padrão canônico (24x24 px) para botões de diálogo e barra lateral. */
public static final int SIZE_24 = 24;
/** Tamanho médio (32x32 px) para cabeçalhos e diálogos de aprovação CCSP. */
public static final int SIZE_32 = 32;
/** Tamanho grande (40x40 px) para cards e botões do painel principal (Hub). */
public static final int SIZE_40 = 40;
private Icons() {
}
/**
* Retorna um ícone vetorial pelo nome no tamanho especificado, com repintura dinâmica de tema.
*/
public static Node of(String name, int size) {
return of(name, size, null, null);
}
/**
* Retorna um ícone vetorial pelo nome no tamanho especificado, aplicando uma tinta (tint) fixa.
*/
public static Node of(String name, int size, Color tint) {
return of(name, size, tint, null);
}
/**
* Retorna um ícone vetorial com fallback customizado.
*/
public static Node of(String name, int size, Color tint, Supplier<Node> fallbackSupplier) {
return AssetManager.getIconOrDefault(name, size, tint, fallbackSupplier);
}
// ==========================================
// MÉTODOS DE CONVENIÊNCIA POR SEMÂNTICA VISUAL
// ==========================================
public static Node pdf() { return pdf(SIZE_24); }
public static Node pdf(int size) { return of("pdf", size); }
public static Node pdf(int size, Color tint) { return of("pdf", size, tint); }
public static Node xml() { return xml(SIZE_24); }
public static Node xml(int size) { return of("xml", size); }
public static Node file() { return file(SIZE_24); }
public static Node file(int size) { return of("file", size); }
public static Node attached() { return attached(SIZE_24); }
public static Node attached(int size) { return of("attached", size); }
public static Node batch() { return batch(SIZE_24); }
public static Node batch(int size) { return of("batch", size); }
public static Node coSign() { return coSign(SIZE_24); }
public static Node coSign(int size) { return of("co-sign", size); }
public static Node timestamp() { return timestamp(SIZE_24); }
public static Node timestamp(int size) { return of("timestamp", size); }
public static Node ltv() { return ltv(SIZE_24); }
public static Node ltv(int size) { return of("ltv", size); }
public static Node validate() { return validate(SIZE_24); }
public static Node validate(int size) { return of("validate", size); }
public static Node validateTimestamp() { return validateTimestamp(SIZE_24); }
public static Node validateTimestamp(int size) { return of("validate-timestamp", size); }
public static Node seal() { return seal(SIZE_24); }
public static Node seal(int size) { return of("seal", size); }
public static Node sealIcpBrasil() { return sealIcpBrasil(SIZE_24); }
public static Node sealIcpBrasil(int size) { return of("seal-icp-brasil", size); }
public static Node certificates() { return certificates(SIZE_24); }
public static Node certificates(int size) { return of("cert", size); }
public static Node shield() { return shield(SIZE_24); }
public static Node shield(int size) { return of("shield", size); }
public static Node settings() { return settings(SIZE_24); }
public static Node settings(int size) { return of("settings", size); }
public static Node logs() { return logs(SIZE_24); }
public static Node logs(int size) { return of("logs", size); }
public static Node tutorial() { return tutorial(SIZE_24); }
public static Node tutorial(int size) { return of("tutorial", size); }
public static Node about() { return about(SIZE_24); }
public static Node about(int size) { return of("about", size); }
public static Node exit() { return exit(SIZE_24); }
public static Node exit(int size) { return of("exit", size); }
public static Node refresh() { return refresh(SIZE_16); }
public static Node refresh(int size) { return of("refresh", size); }
public static Node sun() { return sun(SIZE_16); }
public static Node sun(int size) { return of("sun", size); }
public static Node moon() { return moon(SIZE_16); }
public static Node moon(int size) { return of("moon", size); }
public static Node arrowRight() { return arrowRight(SIZE_16); }
public static Node arrowRight(int size) { return of("arrow-right", size); }
public static Node close() { return close(SIZE_16); }
public static Node close(int size) { return of("close", size); }
public static Node check() { return check(SIZE_16); }
public static Node check(int size) { return of("check", size); }
public static Node error() { return error(SIZE_16); }
public static Node error(int size) { return of("error", size); }
public static Node star() { return star(SIZE_16); }
public static Node star(int size) { return of("star", size); }
public static Node zoomIn() { return zoomIn(SIZE_16); }
public static Node zoomIn(int size) { return of("zoom-in", size); }
public static Node zoomOut() { return zoomOut(SIZE_16); }
public static Node zoomOut(int size) { return of("zoom-out", size); }
public static Node zoomFit() { return zoomFit(SIZE_16); }
public static Node zoomFit(int size) { return of("zoom-fit", size); }
/**
* Logotipo institucional principal do CyberCore Signer.
*/
public static Node appLogo(double width, double height) {
return AssetManager.getLogoOrDefault(width, height, () -> SvgIcons.buildAppCrystalLogo(Math.min(width, height)));
}
/**
* Logotipo de cristal CyberCore.
*/
public static Node appCrystal(double size) {
return SvgIcons.createAppCrystalLogo(size);
}
}
@@ -1,6 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Círculo azul e letra 'i' informativa centrada em (24, 24) -->
<circle cx="24" cy="24" r="18" fill="#0288d1"/>
<circle cx="24" cy="15" r="2.5" fill="#ffffff"/>
<line x1="24" y1="21" x2="24" y2="33" stroke="#ffffff" stroke-width="4.5" stroke-linecap="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/>
<circle cx="12" cy="7.5" r="1.2" fill="currentColor"/>
<line x1="12" y1="11" x2="12" y2="16.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 362 B

After

Width:  |  Height:  |  Size: 338 B

@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 8 5 L 15 12 L 8 19" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 9 5 L 16 12 L 9 19" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 221 B

After

Width:  |  Height:  |  Size: 224 B

@@ -1,12 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Folha de documento com dobra -->
<path d="M 10 4 L 34 4 L 42 12 L 42 44 L 10 44 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
<path d="M 34 4 L 34 12 L 42 12 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2"/>
<!-- Linhas de texto representativas -->
<line x1="16" y1="20" x2="36" y2="20" stroke="#90caf9" stroke-width="2" stroke-linecap="round"/>
<line x1="16" y1="26" x2="36" y2="26" stroke="#90caf9" stroke-width="2" stroke-linecap="round"/>
<line x1="16" y1="32" x2="30" y2="32" stroke="#90caf9" stroke-width="2" stroke-linecap="round"/>
<!-- Clipe de papel metálico prendendo a folha -->
<path d="M 12 2 C 8 2 6 5 6 9 L 6 25 C 6 29 9 32 14 32 C 18 32 21 29 21 25 L 21 11 C 21 8 19 6 16 6 C 13 6 12 8 12 11 L 12 24"
fill="none" stroke="#455a64" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 16.5 6.5 L 9.5 13.5 C 8.1 14.9 8.1 17.1 9.5 18.5 C 10.9 19.9 13.1 19.9 14.5 18.5 L 20 13 C 22.2 10.8 22.2 7.2 20 5 C 17.8 2.8 14.2 2.8 12 5 L 6.5 10.5 C 3.7 13.3 3.7 17.7 6.5 20.5 C 9.3 23.3 13.7 23.3 16.5 20.5 L 20 17"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 976 B

After

Width:  |  Height:  |  Size: 433 B

@@ -1,13 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Folha traseira (3) -->
<path d="M 16 4 L 38 4 L 44 10 L 44 32 L 16 32 Z" fill="#e1f5fe" stroke="#4fc3f7" stroke-width="2" stroke-linejoin="round"/>
<!-- Folha do meio (2) -->
<path d="M 10 10 L 32 10 L 38 16 L 38 38 L 10 38 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2" stroke-linejoin="round"/>
<!-- Folha frontal (1) -->
<path d="M 4 16 L 26 16 L 32 22 L 32 44 L 4 44 Z" fill="#ffffff" stroke="#01579b" stroke-width="2.2" stroke-linejoin="round"/>
<!-- Dobra folha frontal -->
<path d="M 26 16 L 26 22 L 32 22 Z" fill="#e1f5fe" stroke="#01579b" stroke-width="1.8"/>
<!-- Checkmark de execução/lote concluído -->
<circle cx="34" cy="34" r="10" fill="#00c853"/>
<path d="M 29 34 L 33 38 L 39 30" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 3.5 7.5 H 16.5 V 20.5 H 3.5 Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<path d="M 7.5 4.5 H 20.5 V 17.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<line x1="7" y1="11.5" x2="13" y2="11.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<line x1="7" y1="15.5" x2="11" y2="15.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 920 B

After

Width:  |  Height:  |  Size: 543 B

@@ -1,11 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Pasta de arquivos de certificados -->
<path d="M 4 10 L 16 10 L 20 14 L 44 14 L 44 40 L 4 40 Z" fill="#e1f5fe" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
<!-- Aba superior da pasta -->
<path d="M 4 18 L 44 18" stroke="#0288d1" stroke-width="2"/>
<!-- Cadeado de segurança dourado/azul -->
<rect x="26" y="24" width="14" height="12" rx="3" fill="#0288d1"/>
<!-- Arco do cadeado -->
<path d="M 29 24 L 29 20 C 29 17 31 15 33 15 C 35 15 37 17 37 20 L 37 24" fill="none" stroke="#01579b" stroke-width="2.5"/>
<circle cx="33" cy="30" r="1.8" fill="#ffffff"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<rect x="3" y="4" width="18" height="16" rx="2.5" fill="none" stroke="currentColor" stroke-width="2"/>
<circle cx="12" cy="10" r="2.5" fill="none" stroke="#0288d1" stroke-width="1.8"/>
<path d="M 10.5 12.2 L 9.5 17 L 12 15.5 L 14.5 17 L 13.5 12.2" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linejoin="round"/>
<line x1="6" y1="7" x2="8" y2="7" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<line x1="16" y1="7" x2="18" y2="7" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 688 B

After

Width:  |  Height:  |  Size: 625 B

@@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<circle cx="24" cy="24" r="20" fill="#10b981"/>
<path d="M 14 24 L 21 31 L 34 17" fill="none" stroke="#ffffff" stroke-width="4.5" stroke-linecap="round" stroke-linejoin="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="12" cy="12" r="9" fill="#10b981"/>
<path d="M 8 12 L 11 15 L 16 9" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 274 B

After

Width:  |  Height:  |  Size: 269 B

@@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 6 6 L 18 18 M 18 6 L 6 18" fill="none" stroke="#64748b" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 6 6 L 18 18 M 18 6 L 6 18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 228 B

After

Width:  |  Height:  |  Size: 231 B

@@ -1,12 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Folha secundária -->
<path d="M 6 10 L 26 10 L 32 16 L 32 40 L 6 40 Z" fill="#ffffff" stroke="#1976d2" stroke-width="2.2" stroke-linejoin="round"/>
<!-- Folha primária -->
<path d="M 16 4 L 36 4 L 42 10 L 42 34 L 16 34 Z" fill="#e3f2fd" stroke="#0288d1" stroke-width="2.2" stroke-linejoin="round"/>
<path d="M 36 4 L 36 10 L 42 10 Z" fill="#bbdefb" stroke="#0288d1" stroke-width="1.8"/>
<!-- Ícone de dois usuários / parceiros de assinatura -->
<circle cx="16" cy="24" r="4" fill="#0d47a1"/>
<path d="M 10 36 C 10 31 13 30 16 30 C 19 30 22 31 22 36 Z" fill="#0d47a1"/>
<circle cx="26" cy="22" r="3.5" fill="#0288d1"/>
<path d="M 21 34 C 21 30 24 29 26 29 C 29 29 32 30 32 34 Z" fill="#0288d1"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 13 3.5 H 5 C 4.4 3.5 4 3.9 4 4.5 V 20.5 C 4 21.1 4.4 21.5 5 21.5 H 17 C 17.6 21.5 18 21.1 18 20.5 V 13"
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<path d="M 12 18 C 14 18 16 17 18 15" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<path d="M 18.5 3.5 L 21 6 L 14 13 L 11.5 13.5 L 12 11 Z" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 815 B

After

Width:  |  Height:  |  Size: 546 B

@@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<circle cx="24" cy="24" r="20" fill="#ef4444"/>
<line x1="16" y1="16" x2="32" y2="32" stroke="#ffffff" stroke-width="4.5" stroke-linecap="round"/>
<line x1="32" y1="16" x2="16" y2="32" stroke="#ffffff" stroke-width="4.5" stroke-linecap="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="12" cy="12" r="9" fill="#ef4444"/>
<line x1="8.5" y1="8.5" x2="15.5" y2="15.5" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
<line x1="15.5" y1="8.5" x2="8.5" y2="15.5" stroke="#ffffff" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 343 B

After

Width:  |  Height:  |  Size: 350 B

@@ -1,8 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Porta de saída / batente -->
<path d="M 24 8 L 12 8 C 9.8 8 8 9.8 8 12 L 8 36 C 8 38.2 9.8 40 12 40 L 24 40"
fill="none" stroke="#546e7a" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<!-- Seta vermelha apontando para fora -->
<line x1="18" y1="24" x2="40" y2="24" stroke="#d32f2f" stroke-width="3.2" stroke-linecap="round"/>
<polyline points="32 16, 40 24, 32 32" fill="none" stroke="#d32f2f" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 10 3.5 H 5.5 C 4.4 3.5 3.5 4.4 3.5 5.5 V 18.5 C 3.5 19.6 4.4 20.5 5.5 20.5 H 10"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="8.5" y1="12" x2="20.5" y2="12" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/>
<polyline points="16.5 8, 20.5 12, 16.5 16" fill="none" stroke="#ef4444" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 537 B

@@ -1,13 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Folha de documento com dobra -->
<path d="M 8 4 L 32 4 L 42 14 L 42 44 L 8 44 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
<!-- Dobra de canto -->
<path d="M 32 4 L 32 14 L 42 14 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2" stroke-linejoin="round"/>
<!-- Linhas de texto representativas -->
<line x1="14" y1="20" x2="34" y2="20" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
<line x1="14" y1="26" x2="34" y2="26" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
<!-- Caneta / Pena de assinatura eletrônica -->
<path d="M 16 38 L 30 24 L 35 29 L 21 43 L 14 44 Z" fill="#0288d1"/>
<path d="M 30 24 L 34 20 L 39 25 L 35 29 Z" fill="#01579b"/>
<circle cx="16" cy="42" r="1.5" fill="#ffffff"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 5 3.5 H 14 L 19 8.5 V 20.5 C 19 21.1 18.5 21.5 17.9 21.5 H 5 C 4.4 21.5 4 21.1 4 20.5 V 4.5 C 4 3.9 4.4 3.5 5 3.5 Z"
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<path d="M 14 3.5 V 8.5 H 19" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<line x1="8" y1="13" x2="15" y2="13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<line x1="8" y1="17" x2="13" y2="17" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 873 B

After

Width:  |  Height:  |  Size: 626 B

@@ -1,13 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Janela de terminal / console -->
<rect x="4" y="6" width="40" height="36" rx="6" fill="#1e293b" stroke="#334155" stroke-width="2"/>
<!-- Barra de título do terminal com botões -->
<circle cx="10" cy="12" r="2" fill="#ef4444"/>
<circle cx="16" cy="12" r="2" fill="#f59e0b"/>
<circle cx="22" cy="12" r="2" fill="#10b981"/>
<!-- Linha divisória -->
<line x1="4" y1="18" x2="44" y2="18" stroke="#334155" stroke-width="1.5"/>
<!-- Texto e prompt de código </> -->
<path d="M 12 24 L 18 29 L 12 34" fill="none" stroke="#38bdf8" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="22" y1="34" x2="32" y2="34" stroke="#94a3b8" stroke-width="2.5" stroke-linecap="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<rect x="2.5" y="3.5" width="19" height="17" rx="3" fill="none" stroke="currentColor" stroke-width="2"/>
<path d="M 6.5 8.5 L 9.5 11 L 6.5 13.5" fill="none" stroke="#0288d1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="11.5" y1="13.5" x2="16.5" y2="13.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="6.5" y1="16.5" x2="14" y2="16.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" opacity="0.6"/>
</svg>

Before

Width:  |  Height:  |  Size: 811 B

After

Width:  |  Height:  |  Size: 572 B

@@ -1,11 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Folha de documento com dobra -->
<path d="M 8 4 L 30 4 L 38 12 L 38 34 L 8 34 Z" fill="#ffffff" stroke="#00838f" stroke-width="2.5" stroke-linejoin="round"/>
<path d="M 30 4 L 30 12 L 38 12 Z" fill="#b2dfdb" stroke="#00838f" stroke-width="2"/>
<!-- Linhas no documento -->
<line x1="14" y1="18" x2="30" y2="18" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
<line x1="14" y1="24" x2="24" y2="24" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
<!-- Selo LTV com fita de proteção permanente -->
<circle cx="32" cy="32" r="12" fill="#e0f2f1" stroke="#00897b" stroke-width="2.5"/>
<text x="32" y="36.5" font-family="Segoe UI, Arial, sans-serif" font-size="9" font-weight="bold" fill="#00695c" text-anchor="middle">LTV</text>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 5 3.5 H 14 L 19 8.5 V 20.5 C 19 21.1 18.5 21.5 17.9 21.5 H 5 C 4.4 21.5 4 21.1 4 20.5 V 4.5 C 4 3.9 4.4 3.5 5 3.5 Z"
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<circle cx="14" cy="15" r="4.5" fill="none" stroke="#0288d1" stroke-width="1.8"/>
<polyline points="14 12.5, 14 15, 16 15" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 861 B

After

Width:  |  Height:  |  Size: 507 B

@@ -1,6 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Lua crescente ciano/índigo perfeitamente centrada em (24, 24) -->
<path d="M 24 8 A 16 16 0 1 0 40 24 A 14 14 0 0 1 24 8 Z" fill="#38bdf8"/>
<circle cx="34" cy="14" r="1.8" fill="#818cf8"/>
<circle cx="38" cy="22" r="1.2" fill="#818cf8"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 12 3 A 9 9 0 1 0 21 12 A 7.5 7.5 0 0 1 12 3 Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 344 B

After

Width:  |  Height:  |  Size: 251 B

@@ -1,13 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Folha de documento com dobra -->
<path d="M 8 4 L 32 4 L 42 14 L 42 44 L 8 44 Z" fill="#ffffff" stroke="#d32f2f" stroke-width="2.5" stroke-linejoin="round"/>
<!-- Dobra de canto -->
<path d="M 32 4 L 32 14 L 42 14 Z" fill="#ffcdd2" stroke="#d32f2f" stroke-width="2" stroke-linejoin="round"/>
<!-- Linhas de texto representativas -->
<line x1="13" y1="18" x2="27" y2="18" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
<line x1="13" y1="22" x2="35" y2="22" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
<line x1="13" y1="26" x2="35" y2="26" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
<!-- Etiqueta vermelha com sigla PDF perfeitamente centralizada -->
<rect x="11" y="31" width="28" height="11" rx="3" fill="#d32f2f"/>
<text x="25" y="36.5" font-family="'Segoe UI', Arial, sans-serif" font-size="8.5px" font-weight="bold" fill="#ffffff" text-anchor="middle" dominant-baseline="central">PDF</text>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 5 3.5 H 14 L 19 8.5 V 20.5 C 19 21.1 18.5 21.5 17.9 21.5 H 5 C 4.4 21.5 4 21.1 4 20.5 V 4.5 C 4 3.9 4.4 3.5 5 3.5 Z"
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<path d="M 14 3.5 V 8.5 H 19" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<rect x="7" y="12" width="10" height="6" rx="1.5" fill="#ef4444"/>
<path d="M 9 14 H 10.5 C 11 14 11.5 14.3 11.5 14.8 C 11.5 15.3 11 15.6 10.5 15.6 H 9 V 17 M 9 15.6 H 10.5" stroke="#ffffff" stroke-width="1" stroke-linecap="round" fill="none"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 665 B

@@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 20 4 L 20 9 L 15 9" fill="none" stroke="#0284c7" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 4 20 L 4 15 L 9 15" fill="none" stroke="#0284c7" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 5.8 9 A 7 7 0 0 1 18.5 7.5 L 20 9 M 4 15 L 5.5 16.5 A 7 7 0 0 0 18.2 15" fill="none" stroke="#0284c7" stroke-width="2.2" stroke-linecap="round"/>
<path d="M 19 4 L 19 9 L 14 9" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 5 20 L 5 15 L 10 15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 6.3 8.7 A 8 8 0 0 1 18.5 7.5 L 19 9 M 5 15 L 5.5 16.5 A 8 8 0 0 0 17.7 15.3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 510 B

After

Width:  |  Height:  |  Size: 524 B

@@ -1,15 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 54" width="36" height="54">
<!-- Escudo Criptográfico Vetorial ICP-Brasil -->
<path d="M18 4 L32 9 V24 C32 37 25 46 18 50 C11 46 4 37 4 24 V9 Z" fill="#0d47a1" opacity="0.14"/>
<path d="M18 4 L32 9 V24 C32 37 25 46 18 50 C11 46 4 37 4 24 V9 Z" fill="none" stroke="#0d47a1" stroke-width="2.2" stroke-linejoin="round"/>
<!-- Corpo do Cadeado de Segurança -->
<rect x="11" y="24" width="14" height="12" rx="2.5" fill="#0284c7"/>
<!-- Arco Superior do Cadeado -->
<path d="M13.5 24 V19 C13.5 16.5 15.5 14.5 18 14.5 C20.5 14.5 22.5 16.5 22.5 19 V24" fill="none" stroke="#0284c7" stroke-width="2.2" stroke-linecap="round"/>
<!-- Orifício da Chave -->
<circle cx="18" cy="29" r="1.6" fill="#ffffff"/>
<path d="M17.3 29.5 L18.7 29.5 L19.2 33 L16.8 33 Z" fill="#ffffff"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 12 2.5 L 4.5 5.5 V 11 C 4.5 16 8 20 12 21.5 C 16 20 19.5 16 19.5 11 V 5.5 Z"
fill="none" stroke="#0288d1" stroke-width="2" stroke-linejoin="round"/>
<rect x="8.5" y="11" width="7" height="5.5" rx="1.2" fill="#0288d1"/>
<path d="M 10 11 V 8.5 C 10 7.4 10.9 6.5 12 6.5 C 13.1 6.5 14 7.4 14 8.5 V 11" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round"/>
<circle cx="12" cy="13.5" r="0.8" fill="#ffffff"/>
</svg>

Before

Width:  |  Height:  |  Size: 858 B

After

Width:  |  Height:  |  Size: 541 B

@@ -1,11 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Fita pendente do selo -->
<polygon points="18,30 24,44 30,30" fill="#f59e0b"/>
<polygon points="12,30 16,42 20,30" fill="#d97706"/>
<polygon points="28,30 32,42 36,30" fill="#d97706"/>
<!-- Medalha / Selo circular -->
<circle cx="24" cy="20" r="16" fill="#d97706" stroke="#fbbf24" stroke-width="2.5"/>
<circle cx="24" cy="20" r="13" fill="none" stroke="#fbbf24" stroke-width="1.2" stroke-dasharray="2,2"/>
<!-- Estrela de 5 pontas central -->
<polygon points="24,9 26.5,16.5 34,16.5 28,21 30.5,28.5 24,24 17.5,28.5 20,21 14,16.5 21.5,16.5" fill="#ffffff"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="12" cy="10" r="7.5" fill="none" stroke="#f59e0b" stroke-width="2"/>
<circle cx="12" cy="10" r="4.5" fill="none" stroke="#f59e0b" stroke-width="1.2" stroke-dasharray="2 1.5"/>
<path d="M 9.5 15.5 L 7 21.5 L 12 19 L 17 21.5 L 14.5 15.5" fill="none" stroke="#d97706" stroke-width="1.8" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 671 B

After

Width:  |  Height:  |  Size: 418 B

@@ -1,4 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Engrenagem corporativa simétrica centrada em (24, 24) -->
<path fill="#0288d1" fill-rule="evenodd" d="M 21.5 5 L 26.5 5 L 27.2 10.2 C 29 10.9 30.7 11.9 32.2 13.1 L 36.6 10.6 L 40.1 14.1 L 37.6 18.5 C 38.8 20 39.8 21.7 40.5 23.5 L 45.7 24.2 L 45.7 29.2 L 40.5 29.9 C 39.8 31.7 38.8 33.4 37.6 34.9 L 40.1 39.3 L 36.6 42.8 L 32.2 40.3 C 30.7 41.5 29 42.5 27.2 43.2 L 26.5 48.4 L 21.5 48.4 L 20.8 43.2 C 19 42.5 17.3 41.5 15.8 40.3 L 11.4 42.8 L 7.9 39.3 L 10.4 34.9 C 9.2 33.4 8.2 31.7 7.5 29.9 L 2.3 29.2 L 2.3 24.2 L 7.5 23.5 C 8.2 21.7 9.2 20 10.4 18.5 L 7.9 14.1 L 11.4 10.6 L 15.8 13.1 C 17.3 11.9 19 10.9 20.8 10.2 Z M 24 17.5 A 6.5 6.5 0 1 0 24 30.5 A 6.5 6.5 0 1 0 24 17.5 Z"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="12" cy="12" r="3" fill="none" stroke="currentColor" stroke-width="2"/>
<path d="M 10.7 2.5 L 13.3 2.5 L 13.7 4.8 C 14.4 5.1 15.1 5.5 15.8 6.1 L 17.9 5.2 L 19.8 7.1 L 18.9 9.2 C 19.4 9.9 19.8 10.6 20.1 11.3 L 22.5 11.7 L 22.5 14.3 L 20.1 14.7 C 19.8 15.4 19.4 16.1 18.9 16.8 L 19.8 18.9 L 17.9 20.8 L 15.8 19.9 C 15.1 20.5 14.4 20.9 13.7 21.2 L 13.3 23.5 L 10.7 23.5 L 10.3 21.2 C 9.6 20.9 8.9 20.5 8.2 19.9 L 6.1 20.8 L 4.2 18.9 L 5.1 16.8 C 4.6 16.1 4.2 15.4 3.9 14.7 L 1.5 14.3 L 1.5 11.7 L 3.9 11.3 C 4.2 10.6 4.6 9.9 5.1 9.2 L 4.2 7.1 L 6.1 5.2 L 8.2 6.1 C 8.9 5.5 9.6 5.1 10.3 4.8 Z"
fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 784 B

After

Width:  |  Height:  |  Size: 784 B

@@ -1,6 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Escudo CyberShield -->
<path d="M 24 4 L 8 11 L 8 24 C 8 34.5 15 42.5 24 45 C 33 42.5 40 34.5 40 24 L 40 11 Z" fill="#0284c7" stroke="#38bdf8" stroke-width="2.5" stroke-linejoin="round"/>
<!-- Chave de segurança criptográfica no centro -->
<path d="M 24 14 C 20.7 14 18 16.7 18 20 C 18 22.4 19.5 24.5 22 25.4 L 22 34 L 26 34 L 26 30 L 28 30 L 28 27 L 26 27 L 26 25.4 C 28.5 24.5 30 22.4 30 20 C 30 16.7 27.3 14 24 14 Z M 24 18 C 25.1 18 26 18.9 26 20 C 26 21.1 25.1 22 24 22 C 22.9 22 22 21.1 22 20 C 22 18.9 22.9 18 24 18 Z" fill="#ffffff"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 12 2.5 L 4 5.5 V 11.5 C 4 16.5 7.5 21 12 22.5 C 16.5 21 20 16.5 20 11.5 V 5.5 Z"
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<path d="M 8.5 11.5 L 11 14 L 15.5 9.5" fill="none" stroke="#0288d1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 649 B

After

Width:  |  Height:  |  Size: 408 B

@@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<polygon points="24,4 29.5,16.5 43,17.5 32.5,26.5 35.8,40 24,32.5 12.2,40 15.5,26.5 5,17.5 18.5,16.5"
fill="#f59e0b" stroke="#d97706" stroke-width="2" stroke-linejoin="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<polygon points="12,2.5 14.8,8.2 21.1,9.1 16.5,13.6 17.6,19.9 12,16.9 6.4,19.9 7.5,13.6 2.9,9.1 9.2,8.2"
fill="#f59e0b" stroke="#d97706" stroke-width="1.2" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 287 B

@@ -1,15 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Núcleo solar brilhante -->
<circle cx="24" cy="24" r="10" fill="#f59e0b"/>
<!-- Raios solares -->
<g stroke="#f59e0b" stroke-width="3" stroke-linecap="round">
<line x1="24" y1="4" x2="24" y2="9"/>
<line x1="24" y1="39" x2="24" y2="44"/>
<line x1="4" y1="24" x2="9" y2="24"/>
<line x1="39" y1="24" x2="44" y2="24"/>
<line x1="9.8" y1="9.8" x2="13.3" y2="13.3"/>
<line x1="34.7" y1="34.7" x2="38.2" y2="38.2"/>
<line x1="9.8" y1="38.2" x2="13.3" y2="34.7"/>
<line x1="34.7" y1="13.3" x2="38.2" y2="9.8"/>
</g>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="12" cy="12" r="4.5" fill="none" stroke="currentColor" stroke-width="2"/>
<line x1="12" y1="2" x2="12" y2="4.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="12" y1="19.5" x2="12" y2="22" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="2" y1="12" x2="4.5" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="19.5" y1="12" x2="22" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="4.9" y1="4.9" x2="6.7" y2="6.7" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="17.3" y1="17.3" x2="19.1" y2="19.1" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="4.9" y1="19.1" x2="6.7" y2="17.3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<line x1="17.3" y1="6.7" x2="19.1" y2="4.9" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 647 B

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -1,13 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Folha de documento com dobra -->
<path d="M 8 4 L 30 4 L 38 12 L 38 34 L 8 34 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
<path d="M 30 4 L 30 12 L 38 12 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2"/>
<!-- Linhas no documento -->
<line x1="14" y1="18" x2="30" y2="18" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
<line x1="14" y1="24" x2="24" y2="24" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
<!-- Relógio de precisão temporal TSA -->
<circle cx="32" cy="32" r="12" fill="#e1f5fe" stroke="#0288d1" stroke-width="2.5"/>
<circle cx="32" cy="32" r="2" fill="#01579b"/>
<line x1="32" y1="24" x2="32" y2="32" stroke="#01579b" stroke-width="2.5" stroke-linecap="round"/>
<line x1="32" y1="32" x2="38" y2="32" stroke="#01579b" stroke-width="2.5" stroke-linecap="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/>
<polyline points="12 7, 12 12, 16 14" fill="none" stroke="#0288d1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="12" y1="1" x2="12" y2="3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 958 B

After

Width:  |  Height:  |  Size: 413 B

@@ -1,8 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Monitor de computador -->
<rect x="4" y="6" width="40" height="28" rx="4" fill="#ffffff" stroke="#0288d1" stroke-width="2.5"/>
<!-- Base do monitor -->
<path d="M 16 34 L 12 42 L 36 42 L 32 34" fill="none" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
<!-- Ícone de play/vídeo tutorial central -->
<polygon points="20,14 32,20 20,26" fill="#0288d1"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 3 6.5 C 3 5 4.5 4 6 4 C 8.5 4 11 5.5 12 7 C 13 5.5 15.5 4 18 4 C 19.5 4 21 5 21 6.5 V 18 C 21 19 19.5 19.5 18 19.5 C 15.5 19.5 13 18 12 17 C 11 18 8.5 19.5 6 19.5 C 4.5 19.5 3 19 3 18 Z"
fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
<line x1="12" y1="7" x2="12" y2="17" stroke="currentColor" stroke-width="1.8"/>
</svg>

Before

Width:  |  Height:  |  Size: 477 B

After

Width:  |  Height:  |  Size: 461 B

@@ -1,10 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Círculo de relógio base -->
<circle cx="24" cy="24" r="20" fill="#f1f8e9" stroke="#558b2f" stroke-width="2.5"/>
<!-- Ponteiros do relógio -->
<line x1="24" y1="12" x2="24" y2="24" stroke="#33691e" stroke-width="2" stroke-linecap="round"/>
<line x1="24" y1="24" x2="32" y2="24" stroke="#33691e" stroke-width="2" stroke-linecap="round"/>
<!-- Checkmark verde de validação de tempo -->
<circle cx="34" cy="34" r="10" fill="#2e7d32"/>
<path d="M 29 34 L 33 38 L 39 30" fill="none" stroke="#ffffff" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="10" cy="10" r="7.5" fill="none" stroke="currentColor" stroke-width="2"/>
<polyline points="10 6, 10 10, 13 11" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
<circle cx="16.5" cy="16.5" r="5" fill="none" stroke="#10b981" stroke-width="2"/>
<polyline points="14.8 16.5, 16 17.7, 18.5 15.2" fill="none" stroke="#10b981" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 679 B

After

Width:  |  Height:  |  Size: 528 B

@@ -1,11 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Folha de documento com dobra -->
<path d="M 8 4 L 32 4 L 42 14 L 42 44 L 8 44 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
<path d="M 32 4 L 32 14 L 42 14 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2"/>
<!-- Linhas no documento -->
<line x1="14" y1="20" x2="34" y2="20" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
<line x1="14" y1="26" x2="28" y2="26" stroke="#cfd8dc" stroke-width="2" stroke-linecap="round"/>
<!-- Emblema de validação com Checkmark verde -->
<circle cx="30" cy="34" r="11" fill="#e8f5e9" stroke="#2e7d32" stroke-width="2.5"/>
<path d="M 24 34 L 28 38 L 36 29" fill="none" stroke="#2e7d32" stroke-width="3.2" stroke-linecap="round" stroke-linejoin="round"/>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 5 3.5 H 13 L 18 8.5 V 13" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<path d="M 5 3.5 V 20.5 H 10" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<circle cx="15.5" cy="16.5" r="5" fill="none" stroke="#10b981" stroke-width="2"/>
<polyline points="13.8 16.5, 15 17.7, 17.5 15.2" fill="none" stroke="#10b981" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 848 B

After

Width:  |  Height:  |  Size: 548 B

@@ -1,13 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<!-- Folha de documento com dobra -->
<path d="M 8 4 L 32 4 L 42 14 L 42 44 L 8 44 Z" fill="#ffffff" stroke="#0288d1" stroke-width="2.5" stroke-linejoin="round"/>
<!-- Dobra de canto -->
<path d="M 32 4 L 32 14 L 42 14 Z" fill="#b3e5fc" stroke="#0288d1" stroke-width="2" stroke-linejoin="round"/>
<!-- Linhas de texto representativas -->
<line x1="13" y1="18" x2="27" y2="18" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
<line x1="13" y1="22" x2="35" y2="22" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
<line x1="13" y1="26" x2="35" y2="26" stroke="#b0bec5" stroke-width="2" stroke-linecap="round"/>
<!-- Etiqueta azul com sigla XML perfeitamente centralizada -->
<rect x="11" y="31" width="28" height="11" rx="3" fill="#0288d1"/>
<text x="25" y="36.5" font-family="'Segoe UI', Arial, sans-serif" font-size="8px" font-weight="bold" fill="#ffffff" text-anchor="middle" dominant-baseline="central">&lt;XML&gt;</text>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 5 3.5 H 14 L 19 8.5 V 20.5 C 19 21.1 18.5 21.5 17.9 21.5 H 5 C 4.4 21.5 4 21.1 4 20.5 V 4.5 C 4 3.9 4.4 3.5 5 3.5 Z"
fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<path d="M 14 3.5 V 8.5 H 19" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
<path d="M 8.5 13 L 6.5 15 L 8.5 17" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 15.5 13 L 17.5 15 L 15.5 17" fill="none" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
<line x1="13" y1="12.5" x2="11" y2="17.5" stroke="#0288d1" stroke-width="1.8" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 796 B

@@ -1,3 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path d="M 4 9 L 4 4 L 9 4 M 15 4 L 20 4 L 20 9 M 20 15 L 20 20 L 15 20 M 9 20 L 4 20 L 4 15" fill="none" stroke="#0284c7" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 4 8 L 4 4 L 8 4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 16 4 L 20 4 L 20 8" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 4 16 L 4 20 L 8 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M 16 20 L 20 20 L 20 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 284 B

After

Width:  |  Height:  |  Size: 623 B

@@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="10" cy="10" r="7" fill="none" stroke="#0284c7" stroke-width="2.2"/>
<path d="M 15 15 L 21 21" fill="none" stroke="#0284c7" stroke-width="2.5" stroke-linecap="round"/>
<path d="M 10 7 L 10 13 M 7 10 L 13 10" fill="none" stroke="#0284c7" stroke-width="2" stroke-linecap="round"/>
<circle cx="10.5" cy="10.5" r="6.5" fill="none" stroke="currentColor" stroke-width="2"/>
<path d="M 15.5 15.5 L 20.5 20.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<path d="M 10.5 7.5 L 10.5 13.5 M 7.5 10.5 L 13.5 10.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 387 B

After

Width:  |  Height:  |  Size: 428 B

@@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<circle cx="10" cy="10" r="7" fill="none" stroke="#0284c7" stroke-width="2.2"/>
<path d="M 15 15 L 21 21" fill="none" stroke="#0284c7" stroke-width="2.5" stroke-linecap="round"/>
<path d="M 7 10 L 13 10" fill="none" stroke="#0284c7" stroke-width="2" stroke-linecap="round"/>
<circle cx="10.5" cy="10.5" r="6.5" fill="none" stroke="currentColor" stroke-width="2"/>
<path d="M 15.5 15.5 L 20.5 20.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
<path d="M 7.5 10.5 L 13.5 10.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 372 B

After

Width:  |  Height:  |  Size: 405 B

@@ -34,7 +34,7 @@ class AssetManagerTest {
"pdf", "xml", "file", "batch", "attached", "co-sign",
"timestamp", "ltv", "validate", "validate-timestamp", "exit",
"logs", "settings", "tutorial", "cert", "about", "sun", "moon",
"shield", "seal", "check", "error", "star", "close", "arrow-right",
"shield", "seal", "seal-icp-brasil", "check", "error", "star", "close", "arrow-right",
"zoom-in", "zoom-out", "zoom-fit", "refresh"
};
@@ -44,6 +44,31 @@ class AssetManagerTest {
}
}
@Test
@DisplayName("Deve instanciar ícones através da fachada Icons nos 5 tamanhos padronizados")
void shouldCreateIconsViaNewFacadeInAllStandardSizes() {
assertThat(br.com.cybercore.signer.ui.components.Icons.settings(br.com.cybercore.signer.ui.components.Icons.SIZE_16)).isNotNull();
assertThat(br.com.cybercore.signer.ui.components.Icons.pdf(br.com.cybercore.signer.ui.components.Icons.SIZE_20)).isNotNull();
assertThat(br.com.cybercore.signer.ui.components.Icons.certificates(br.com.cybercore.signer.ui.components.Icons.SIZE_24)).isNotNull();
assertThat(br.com.cybercore.signer.ui.components.Icons.shield(br.com.cybercore.signer.ui.components.Icons.SIZE_32)).isNotNull();
assertThat(br.com.cybercore.signer.ui.components.Icons.xml(br.com.cybercore.signer.ui.components.Icons.SIZE_40)).isNotNull();
assertThat(br.com.cybercore.signer.ui.components.Icons.sealIcpBrasil()).isNotNull();
}
@Test
@DisplayName("Deve repintar dinamicamente elementos currentColor ao mudar o tema")
void shouldRepaintCurrentColorDynamicallyOnThemeChange() {
Node iconNode = br.com.cybercore.signer.ui.components.Icons.settings(24);
assertThat(iconNode).isInstanceOf(javafx.scene.layout.Pane.class);
// Alterna o tema e garante que não lança erro
br.com.cybercore.signer.ui.theme.ThemeManager.setCurrentTheme(br.com.cybercore.signer.ui.theme.ThemeManager.AppTheme.DARK);
assertThat(br.com.cybercore.signer.ui.theme.ThemeManager.isDark()).isTrue();
br.com.cybercore.signer.ui.theme.ThemeManager.setCurrentTheme(br.com.cybercore.signer.ui.theme.ThemeManager.AppTheme.LIGHT);
assertThat(br.com.cybercore.signer.ui.theme.ThemeManager.isDark()).isFalse();
}
@Test
@DisplayName("Deve instanciar nós de ícones via fábrica SvgIcons com fallback")
void shouldCreateNodesViaSvgIcons() {