Files
chatc2/.impeccable/design.json
T
AyronSantos 12d419de7c feat: comprehensive design system overhaul
Applied impeccable design critique, audit, harden, layout, distill, and polish across all pages.

DESIGN SYSTEM:
- Created PRODUCT.md (5 design principles, WCAG 2.1 AA target)
- Created DESIGN.md (34 color tokens, 6 radius scale, full component spec)
- Created .impeccable/design.json (sidecar with tonal ramps, shadows, motion)

ACCESSIBILITY:
- 33 aria-labels across 7 pages (was ~13)
- 63 <label> elements (was ~30)
- 6 <main> landmarks + role=navigation on all sidebars
- Esc to close modals on 4 pages
- Keyboard shortcuts (Ctrl+J/K, Ctrl+F) on chat

THEMING:
- 216 hardcoded colors replaced with var() references
- 449 !important removed from dark-mode.css
- Dark mode script unified (was duplicated 9x inline)
- All modals converted to .modal-overlay + .modal design system classes

CHAT:
- Error states for messages (.msg.erro, .msg.enviando)
- Connection status indicator
- Confirmation modal before finalizar
- Input bar reorganized (3 visible actions, + menu)
- Right panel accordions
- Send button disabled when empty
- Touch targets 44px on mobile

CLIENT DETAIL:
- Tabs/badges/sub-tabs use CSS classes instead of inline styles
- 'Iniciar Conversa' button now primary action
- alert() replaced with inline feedback
- Modal converted to design system classes

CLIENT LIST:
- Modal moved inside <body> (was HTML-invalid)
- alert() replaced with inline feedback
- Modal uses .show pattern

SETTINGS:
- 4 modals converted to design system classes
- 14 alert() calls replaced with inline feedback
- fecharModal() uses classList instead of style.display

ROUTES:
- border-radius normalized, hardcoded colors fixed

Score progression:
  Chat:        23 → 32/40
  Client List: 32 → 35/40
  Client Detail: 26 → 30/40
  Settings:     29 → 35/40
  Routes:       37 → 38/40
  Audit (project): 14/20 → 17/20
2026-06-23 16:58:12 +00:00

378 lines
19 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"schemaVersion": 2,
"generatedAt": "2026-06-23T17:00:00.000Z",
"title": "Design System: Chatc2",
"extensions": {
"colorMeta": {
"indigo-funcional": {
"role": "primary",
"displayName": "Índigo Funcional",
"canonical": "#667eea",
"tonalRamp": [
"#1a1a5e", "#2a2a7e", "#3a3a9e", "#4a4abe",
"#667eea", "#8888f0", "#aaaaf6", "#ccccfa"
]
},
"indigo-profundo": {
"role": "primary",
"displayName": "Índigo Profundo",
"canonical": "#5a67d8",
"tonalRamp": [
"#151860", "#252878", "#353a90", "#454ca8",
"#5a67d8", "#7a84e6", "#9aa1f0", "#babff8"
]
},
"violeta-apoio": {
"role": "secondary",
"displayName": "Violeta de Apoio",
"canonical": "#764ba2",
"tonalRamp": [
"#1e0a3c", "#2e1658", "#3e226e", "#4e2e84",
"#764ba2", "#9678c0", "#b69ed8", "#d6c4ee"
]
},
"meia-noite-inicio": {
"role": "neutral",
"displayName": "Meia-Noite Início",
"canonical": "#1e1b4b",
"tonalRamp": [
"#0a0830", "#100e40", "#181450", "#1e1b4b",
"#2e2b68", "#3e3b82", "#4e4b9a", "#5e5bb0"
]
},
"meia-noite-fim": {
"role": "neutral",
"displayName": "Meia-Noite Fim",
"canonical": "#312e81",
"tonalRamp": [
"#101040", "#1a1858", "#242270", "#312e81",
"#4a4898", "#6462ae", "#7e7cc4", "#9896da"
]
},
"papel-limpo": {
"role": "neutral",
"displayName": "Papel Limpo",
"canonical": "#ffffff",
"tonalRamp": [
"#f0f0f0", "#f3f3f3", "#f6f6f6", "#f9f9f9",
"#ffffff", "#ffffff", "#ffffff", "#ffffff"
]
},
"papel-suave": {
"role": "neutral",
"displayName": "Papel Suave",
"canonical": "#f9fafb",
"tonalRamp": [
"#e8eaed", "#edeff2", "#f2f4f6", "#f6f7f9",
"#f9fafb", "#fbfcfc", "#fdfdfd", "#fefefe"
]
},
"papel-frio": {
"role": "neutral",
"displayName": "Papel Frio",
"canonical": "#f3f4f6",
"tonalRamp": [
"#e0e2e6", "#e5e7eb", "#eaecf0", "#eff0f3",
"#f3f4f6", "#f7f7f9", "#fafafb", "#fcfcfd"
]
},
"grafite": {
"role": "neutral",
"displayName": "Grafite",
"canonical": "#111827",
"tonalRamp": [
"#0a0e14", "#0d1118", "#0f141e", "#101724",
"#111827", "#1f2937", "#374151", "#4b5563"
]
},
"verde-confirma": {
"role": "semantic",
"displayName": "Verde Confirma",
"canonical": "#059669",
"tonalRamp": [
"#002a18", "#004228", "#005a34", "#007240",
"#059669", "#22b87a", "#40d492", "#60eaaa"
]
},
"vermelho-alerta": {
"role": "semantic",
"displayName": "Vermelho Alerta",
"canonical": "#ef4444",
"tonalRamp": [
"#3c0000", "#5c0000", "#7c0808", "#9c1414",
"#ef4444", "#f47070", "#f89898", "#fcc0c0"
]
},
"ambar-aviso": {
"role": "semantic",
"displayName": "Âmbar Aviso",
"canonical": "#f59e0b",
"tonalRamp": [
"#3c2400", "#5c3800", "#7c4c00", "#9c6000",
"#f59e0b", "#f7b840", "#f9ce70", "#fbe4a0"
]
},
"verde-whatsapp": {
"role": "semantic",
"displayName": "Verde WhatsApp",
"canonical": "#25d366",
"tonalRamp": [
"#003d10", "#005d1a", "#007d24", "#009d2e",
"#25d366", "#45e880", "#65f0a0", "#85f8c0"
]
},
"bolha-agente": {
"role": "semantic",
"displayName": "Bolha Agente",
"canonical": "#dcf8c6",
"tonalRamp": [
"#8cb870", "#a8d090", "#bce8a8", "#ccf0b6",
"#dcf8c6", "#e8fad6", "#f0fce6", "#f8fef0"
]
},
"bolha-privada-bg": {
"role": "semantic",
"displayName": "Bolha Privada Fundo",
"canonical": "#fef9c3",
"tonalRamp": [
"#b0a840", "#c8c060", "#d8d480", "#e8e8a0",
"#fef9c3", "#fefbd6", "#fefde8", "#fffef4"
]
},
"chat-wallpaper": {
"role": "neutral",
"displayName": "Chat Wallpaper",
"canonical": "#e5ddd5",
"tonalRamp": [
"#b0a898", "#c0b8a8", "#d0c8b8", "#d8d0c8",
"#e5ddd5", "#eae4de", "#f0ece8", "#f6f4f0"
]
},
"violeta-tab": {
"role": "primary",
"displayName": "Violeta Tab",
"canonical": "#a78bfa",
"tonalRamp": [
"#403060", "#604890", "#8060c0", "#9070e0",
"#a78bfa", "#b8a0fc", "#c8b8fe", "#d8d0ff"
]
},
"vermelho-hover": {
"role": "semantic",
"displayName": "Vermelho Hover",
"canonical": "#dc2626",
"tonalRamp": [
"#3c0000", "#5c0808", "#7c1010", "#9c1818",
"#dc2626", "#f05050", "#f88080", "#fcb0b0"
]
},
"cinza-borda-hover": {
"role": "neutral",
"displayName": "Cinza Borda Hover",
"canonical": "#d1d5db",
"tonalRamp": [
"#a0a4aa", "#b0b4ba", "#c0c4ca", "#c8ccd2",
"#d1d5db", "#dce0e6", "#e8ecf0", "#f4f6f8"
]
}
},
"typographyMeta": {
"display": {
"displayName": "Display",
"purpose": "Título da página de login. Uso exclusivo em momentos de entrada."
},
"title": {
"displayName": "Title",
"purpose": "Título da topbar e cabeçalhos de seção principal."
},
"body": {
"displayName": "Body",
"purpose": "Texto corrido, labels, conteúdo de mensagens, células de tabela."
},
"label": {
"displayName": "Label",
"purpose": "Rótulos de navegação, cabeçalhos de tabela, metadados. Sempre uppercase com tracking."
}
},
"shadows": [
{
"name": "ambient",
"value": "0 1px 3px rgba(0,0,0,0.08)",
"purpose": "Cards estáticos e topbar. Sombra padrão para separação sutil."
},
{
"name": "floating",
"value": "0 4px 16px rgba(0,0,0,0.10)",
"purpose": "Elementos com destaque moderado: dropdowns, previews."
},
{
"name": "modal",
"value": "0 20px 60px rgba(0,0,0,0.18)",
"purpose": "Exclusivo para overlays de modal, combinado com backdrop-filter blur."
}
],
"motion": [
{
"name": "ease-standard",
"value": "all 0.15s ease",
"purpose": "Transição padrão para todos os estados interativos: hover, focus, active."
},
{
"name": "modal-enter",
"value": "0.18s ease",
"purpose": "Animação de entrada de modais: fade + scale(0.96 → 1)."
}
],
"breakpoints": [
{ "name": "tablet", "value": "768px" },
{ "name": "desktop-sm", "value": "1024px" },
{ "name": "mobile-sm", "value": "480px" }
]
},
"components": [
{
"name": "Primary Button",
"kind": "button",
"refersTo": "button-primary",
"description": "Ação principal. Fundo índigo funcional, resposta imediata ao hover e active.",
"html": "<button class=\"ds-btn-primary\">ENVIAR</button>",
"css": ".ds-btn-primary { background: #667eea; color: #fff; border: 1px solid #667eea; padding: 9px 18px; border-radius: 10px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.15s ease; font-family: inherit; display: inline-flex; align-items: center; gap: 6px; } .ds-btn-primary:hover { background: #5a67d8; border-color: #5a67d8; } .ds-btn-primary:active { transform: scale(0.98); } .ds-btn-primary:focus-visible { outline: 2px solid #667eea; outline-offset: 2px; }"
},
{
"name": "Secondary Button",
"kind": "button",
"refersTo": "button-secondary",
"description": "Ação secundária. Fundo branco com borda cinza. Hover suave para papel-suave.",
"html": "<button class=\"ds-btn-secondary\">CANCELAR</button>",
"css": ".ds-btn-secondary { background: #ffffff; color: #374151; border: 1px solid #e5e7eb; padding: 9px 18px; border-radius: 10px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.15s ease; font-family: inherit; display: inline-flex; align-items: center; gap: 6px; } .ds-btn-secondary:hover { background: #f9fafb; } .ds-btn-secondary:active { transform: scale(0.98); } .ds-btn-secondary:focus-visible { outline: 2px solid #667eea; outline-offset: 2px; }"
},
{
"name": "Danger Button",
"kind": "button",
"refersTo": "button-danger",
"description": "Ação destrutiva. Exclusivo para excluir, finalizar, remover.",
"html": "<button class=\"ds-btn-danger\">EXCLUIR</button>",
"css": ".ds-btn-danger { background: #ef4444; color: #fff; border: 1px solid #ef4444; padding: 9px 18px; border-radius: 10px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.15s ease; font-family: inherit; display: inline-flex; align-items: center; gap: 6px; } .ds-btn-danger:hover { background: #dc2626; border-color: #dc2626; } .ds-btn-danger:active { transform: scale(0.98); } .ds-btn-danger:focus-visible { outline: 2px solid #ef4444; outline-offset: 2px; }"
},
{
"name": "Text Input",
"kind": "input",
"refersTo": "input-text",
"description": "Campo de texto padrão com ring de foco de 3px como assinatura de acessibilidade.",
"html": "<input class=\"ds-input-text\" type=\"text\" placeholder=\"Buscar...\" />",
"css": ".ds-input-text { width: 100%; padding: 10px 14px; border: 2px solid #e5e7eb; border-radius: 10px; font-size: 14px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #111827; background: #f9fafb; outline: none; transition: all 0.15s ease; } .ds-input-text:focus { border-color: #667eea; background: #ffffff; box-shadow: 0 0 0 3px rgba(102,126,234,0.12); } .ds-input-text::placeholder { color: #6b7280; } .ds-input-text.error { border-color: #ef4444; background: #fef2f2; }"
},
{
"name": "Card",
"kind": "card",
"refersTo": "card",
"description": "Container padrão para conteúdo. Fundo branco, borda sutil, sombra ambient.",
"html": "<div class=\"ds-card\"><h3>Título do Card</h3><p>Conteúdo do card com informações relevantes para o atendente.</p></div>",
"css": ".ds-card { background: #ffffff; border-radius: 16px; padding: 24px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); border: 1px solid #f3f4f6; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } .ds-card h3 { font-size: 15px; font-weight: 600; color: #374151; margin: 0 0 16px 0; } .ds-card p { font-size: 14px; color: #374151; margin: 0; line-height: 1.5; }"
},
{
"name": "Stat Card",
"kind": "card",
"refersTo": "stat-card",
"description": "Card de métrica do dashboard com faixa lateral colorida como identificador semântico.",
"html": "<div class=\"ds-stat-card ds-stat-abertas\"><div class=\"ds-stat-num\">42</div><div class=\"ds-stat-lbl\">Conversas Abertas</div></div>",
"css": ".ds-stat-card { background: #ffffff; border-radius: 12px; padding: 18px; box-shadow: 0 1px 3px rgba(0,0,0,0.08); border-left: 4px solid #9ca3af; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } .ds-stat-abertas { border-left-color: #059669; } .ds-stat-num { font-size: 32px; font-weight: 800; color: #111827; line-height: 1; } .ds-stat-lbl { font-size: 13px; color: #6b7280; margin-top: 6px; font-weight: 600; }"
},
{
"name": "Badge / Chip",
"kind": "chip",
"refersTo": "badge",
"description": "Indicador de status. Totalmente arredondado, trio semântico completo.",
"html": "<span class=\"ds-badge ds-badge-success\">ATIVO</span>",
"css": ".ds-badge { display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 20px; font-size: 12px; font-weight: 600; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } .ds-badge-success { background: #d1fae5; color: #065f46; } .ds-badge-danger { background: #fef2f2; color: #991b1b; } .ds-badge-warning { background: #fef3c7; color: #92400e; }"
},
{
"name": "Navigation Sidebar",
"kind": "nav",
"refersTo": "sidebar",
"description": "Barra lateral noturna fixa. Âncora de navegação em todas as páginas.",
"html": "<nav class=\"ds-sidebar\"><div class=\"ds-sidebar-brand\">Chatc2</div><a href=\"#\" class=\"ds-sidebar-link active\">📊 Dashboard</a><a href=\"#\" class=\"ds-sidebar-link\">👥 Clientes</a></nav>",
"css": ".ds-sidebar { width: 240px; background: linear-gradient(180deg, #1e1b4b 0%, #312e81 100%); display: flex; flex-direction: column; flex-shrink: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } .ds-sidebar-brand { padding: 20px 18px; border-bottom: 1px solid rgba(255,255,255,0.08); color: #fff; font-size: 16px; font-weight: 700; letter-spacing: -0.2px; } .ds-sidebar-link { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: 8px; color: rgba(255,255,255,0.72); text-decoration: none; font-size: 14px; margin: 1px 10px; transition: all 0.15s ease; } .ds-sidebar-link:hover { background: rgba(255,255,255,0.10); color: #fff; } .ds-sidebar-link.active { background: rgba(255,255,255,0.16); color: #fff; font-weight: 600; }"
},
{
"name": "Modal",
"kind": "custom",
"refersTo": "modal",
"description": "Overlay com blur. A caixa de diálogo definitiva do Chatc2.",
"html": "<div class=\"ds-modal-overlay show\"><div class=\"ds-modal-box\"><h3>Confirmação</h3><p>Tem certeza que deseja prosseguir?</p><div class=\"ds-modal-footer\"><button class=\"ds-btn-secondary\">Cancelar</button><button class=\"ds-btn-primary\">Confirmar</button></div></div></div>",
"css": ".ds-modal-overlay { background: rgba(0,0,0,0.48); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } .ds-modal-box { background: #ffffff; border-radius: 16px; padding: 28px; width: 90%; max-width: 440px; box-shadow: 0 20px 60px rgba(0,0,0,0.18); animation: ds-modalIn 0.18s ease; } @keyframes ds-modalIn { from { opacity: 0; transform: scale(0.96) translateY(-10px); } to { opacity: 1; transform: scale(1) translateY(0); } } .ds-modal-box h3 { margin: 0 0 18px 0; font-size: 17px; font-weight: 700; color: #111827; } .ds-modal-box p { margin: 0 0 20px 0; font-size: 14px; color: #374151; } .ds-modal-footer { display: flex; gap: 8px; justify-content: flex-end; }"
},
{
"name": "Chat Bubble - Cliente",
"kind": "custom",
"refersTo": "msg-cliente",
"description": "Bolha de mensagem do cliente. Alinhada à esquerda, fundo branco com borda sutil.",
"html": "<div class=\"ds-msg-cliente\">Olá, preciso de ajuda com meu boleto.</div>",
"css": ".ds-msg-cliente { align-self: flex-start; background: #ffffff; border: 1px solid #f3f4f6; padding: 10px 14px; border-radius: 16px; border-top-left-radius: 4px; max-width: 70%; font-size: 14px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #111827; word-wrap: break-word; }"
}
],
"narrative": {
"northStar": "O Terminal Humanizado",
"overview": "O Chatc2 é um terminal funcional — preciso, confiável, sem firulas — mas que não esquece que do outro lado da tela há uma pessoa. A interface respira. Curvas suaves (6px16px) substituem cantos duros de terminal. O espaço entre elementos é generoso o suficiente para não cansar, mas econômico o bastante para manter densidade de informação. Toques de índigo funcional guiam o olhar sem gritar. O sidebar noturno ancora a experiência com profundidade, como um painel de comando que nunca apaga. O sistema rejeita explicitamente a poluição visual e a ambiguidade. Cada estado tem feedback imediato. Cada cor tem um porquê. Cada pixel de sombra existe para hierarquia, não por decoração.",
"keyCharacteristics": [
"Paleta enxuta: um acento índigo + violeta de apoio + neutros limpos",
"Dark mode como cidadão de primeira classe",
"Sombras leves — destaque sem peso",
"Tipografia de sistema: nativa, zero latência",
"Componentes táteis que respondem ao toque com confiança"
],
"rules": [
{
"name": "The One Voice Rule",
"body": "O índigo funcional ocupa ≤10% de qualquer tela. Sua raridade é o ponto. Se tudo é índigo, nada é importante.",
"section": "colors"
},
{
"name": "The Semantic Triplet Rule",
"body": "Estados (sucesso, erro, aviso) sempre usam o trio completo: cor de destaque + fundo claro + texto escuro. Nunca usar a cor de destaque como fundo de texto corrido.",
"section": "colors"
},
{
"name": "The Native-First Rule",
"body": "Nunca importar webfonts. O sistema operacional já tem tipografia excelente.",
"section": "typography"
},
{
"name": "The Weight Discipline Rule",
"body": "Apenas três pesos convivem: 400 (corpo), 600 (labels), 700800 (títulos). Nunca usar 300, 500 ou 900.",
"section": "typography"
},
{
"name": "The Flat-by-Default Rule",
"body": "A superfície base é plana. Sombras aparecem apenas quando um elemento precisa de separação hierárquica — nunca por decoração.",
"section": "elevation"
},
{
"name": "The Dark Mode Elevation Rule",
"body": "No dark mode, sombras são abolidas. A diferenciação entre superfícies é 100% tonal.",
"section": "elevation"
}
],
"dos": [
"Usar o índigo funcional (#667eea) em ≤10% da superfície visível. Ele é um acento, não uma cor de fundo.",
"Garantir que todo estado interativo tenha feedback em ≤150ms.",
"Comunicar estado com ícone + cor. Nunca apenas cor.",
"Usar o trio semântico completo para qualquer indicador de estado.",
"Manter o dark mode com diferenciação tonal, nunca com sombras.",
"Usar border-left: 4px solid com cor semântica para stat cards no dashboard.",
"Usar padding mínimo de 24px em cards, 14px 24px na topbar.",
"Preservar a barra lateral noturna em todas as páginas."
],
"donts": [
"Criar interfaces abarrotadas onde o atendente precise adivinhar onde as coisas estão.",
"Usar mais de 3 pesos tipográficos na mesma tela.",
"Importar webfonts externas.",
"Usar sombras em dark mode.",
"Usar cores semânticas como cor de fundo para texto corrido.",
"Criar modais sem overlay escuro + blur.",
"Usar cantos vivos (border-radius: 0) em componentes interativos.",
"Omitir o ring de foco de 3px em inputs."
]
}
}