Koder Style — Design Decisions
Companion to `specs/themes/verge.kmd`. Documents every design decision made for the Koder visual identity: palette, radius, spacing, typography, and per-component decisions from form elements through surfaces. Also tracks which decisions are still deferred. This is the "rationale" document; `verge.kmd` is the normative token spec.
Spec — Koder Style: Design Decisions
*tatus* v0 — cobrindo décisions #008.1–#008.11. Atualizar a cada nova divergência editorial sobre o baseline Adwaita.
§1 — Position
Esta spec é o *og editorial*das decisões de design Koder. A spec normativa de tokens é specs/themes/verge.kmd; o CSS canônico vive em tools/design-gen/assets/css/presets.css (.preset.verge).
A relação:
KDS (Koder Design System)
└── Verge (design language — specs/themes/verge.kmd)
└── v0: Adwaita 1:1 baseline ← ponto de partida
└── v1: primeiro wave de divergência ← governado por ESTA SPEC
└── v2+: evolução subsequente"Koder style" não é um preset separado de verge: é o *aminho de divergência*que Verge percorre à medida que se afasta do baseline Adwaita e adopta decisões específicas da identidade Koder. Quando uma decisão está ratificada, ela entra em verge.kmd §R4.{N} como diff de tokens + bump de versão menor.
§2 — Decisões ratificadas
D1 — Forma dos botões em formulários
*ecisão (owner, 20260513):*Botões em formulários e ações primárias usam "formato quadrado, porém com cantos minimamente abaulados". Tradução em token:
| Token | v0 (Adwaita) | Decisão Koder |
|---|---|---|
--radius-btn |
6px | *px* |
--radius-sm (inputs) |
4px | *px*(mantido) |
--radius-md (cards) |
6px | *px*(mantido) |
--radius-lg (modals) |
8px | *px*(mantido) |
--radius-pill |
— | *99px*(toggles/segmented) |
*ationale:*5px cai entre "square 0" e Material's "rounded 8". Aparência profissional sem a redondeza genérica do Material 3. Pill (999px) é reservado exclusivamente para toggles e segmented controls, onde a forma circular tem significado funcional.
*mplementação:*tokens adicionados ao .preset.verge em presets.css (v0 ainda usa 6px de Adwaita para --radius-btn; flip para 5px é o primeiro commit de divergência v0→v0.1).
*ending (D1.flip):*Owner precisa confirmar que o flip
--radius-btn: 5pxpode ir pro CSS. Quando confirmar, editar a linha empresets.csse bump Verge para v0.1.
D2 — Paleta de cores da identidade Koder
*ecisão (20260514):*A paleta de identidade Koder (usada no brand mark e em hero/marketing surfaces) é *ndigo* derivada do gradiente visual da logomarca:
#c7d2fe (índigo 200) → #6366f1 (índigo 500) → #4338ca (índigo 700) → #1e1b4b (índigo 950) → #818cf8 (dark-mode accent)*sta paleta NÃO é o default de Verge v0.*O default de Verge v0 é Adwaita blue (#3584E4), escolhido por:
- Neutralidade cross-product (não "força" a marca Koder em apps sem
relação com a brand)
- Paridade com GNOME para apps desktop nativos
- a11y:
#3584E4em--accent-strong (#1c71d8)passa AA 4.77
A paleta índigo ENTRA no preset quando um produto explicitamente se identifica como produto Koder (landing pages, produtos horizontais da Stack — Kode, Koder Hub, Koder ID, etc.). O mecanismo de aplicação é via CSS var override no nível do produto:
:root {
--accent: #6366f1;
--accent-strong: #4338ca;
--accent-on: #ffffff;
--focus: 2px solid #818cf8;
}*ending (D2.when):*Definir quais produtos adoptam índigo vs ficam em Adwaita blue. Sugestão: produtos da Koder Stack core (Kode, Hub, ID, Pass, Drive) usam índigo; produtos sectoriais (Crescer, Vivver) usam sua própria paleta.
D3 — Tipografia
*ecisão (per specs/fonts/typography.kmd, ratificada no #008):*
| Role | v0 stack |
|---|---|
| Sans-serif (body + UI) | Inter, sistema fallback |
| Mono (code + terminal) | JetBrains Mono, monospace |
| Display (hero/marketing) | Koder Display custom (defer → #128) |
| Serif (longform) | Lora, Georgia, serif |
O fallback de Verge v0 ('Cabin', 'Cantarell', 'Inter', sans-serif) mantém compatibilidade com GNOME desktop. Em web apps Koder puros, Inter é servido como self-hosted .woff2 per specs/fonts/
typography.kmd.
*ending (D3.display):*Koder Display custom (tracking em projects/koder-stack#128). Em v0, Inter cobre display roles.
D4 — Espaçamento
*ecisão (#008.1):*Escala 4-base em doubling: 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 px
Equivale ao sistema Tailwind / Material default — muscle memory preservado. Tokens CSS:
| Token | Valor |
|---|---|
--pad-y (button vertical) |
8px |
--pad-x (button horizontal) |
12px |
--gap-field (entre campos de form) |
10px |
--pad-form (padding interno do form) |
18px |
--gap-title (título → primeiro campo) |
14px |
D5 — Sombras
*ecisão (#008.1):*Sombras Koder são *ndigo-tinted*(em vez de pure-black de Adwaita) para amarrar com a palette da identidade:
--shadow-form: 0 0 0 1px rgba(30,27,75,0.06);
--shadow-card: 0 1px 3px rgba(30,27,75,0.12), 0 1px 2px rgba(30,27,75,0.08);
--shadow-elevated: 0 4px 12px rgba(30,27,75,0.14), 0 2px 6px rgba(30,27,75,0.08);Em dark mode, sombras voltam ao neutro preto (rgba(0,0,0,...)) porque o contraste índigoondark é imperceptível.
*tatus:*tokens ratificados mas não aplicados ao preset Verge v0 ainda (Adwaita usa black-channel shadows). Entram na divergência v0.1.
§3 — Component decisions (#008.2–#008.8)
§3.1 — Form elements (#008.2)
Implementados em .preset.verge (+ dark overrides):
| Elemento | Estado | Token / comportamento |
|---|---|---|
btn-primary |
defaulthoverfocus/disabled | background: var(--accent), radius --radius-btn |
btn-secondary |
defaulthoverdisabled | border 1px solid var(--accent), fill on hover |
btn-tertiary |
text-style | cor var(--accent), underline hover |
btn-ghost |
text+border | borda rgba(0,0,0,0.12), sem fill |
btn-destructive |
vermelho | var(--error) |
input |
defaultfocuserror/disabled | --input-border, focus ring 2px solid var(--accent) |
input--error |
estado de erro | border-color: var(--error) |
checkbox / radio |
default/checked | custom styled via CSS |
toggle/switch |
on/off | --toggle-off: #c0c0c0, on = var(--accent) |
select |
default | nativo com appearance: none + chevron SVG |
| Disabled treatment | global | opacity: var(--disabled-opacity, 0.42) |
*otion:*todos os elementos usam transition: var(--motion, 150ms ease).
§3.2 — Containers (#008.3)
| Componente | Variante | Token chave |
|---|---|---|
| Card | outlined, elevated, interactive | --shadow-card, --card-border, border-radius: var(--radius-lg) |
| Alert/Banner | infosuccesswarning/error | --info-bg, --success-bg, --warning-bg, --error-bg |
| Tabs (static) | CSS-only via :checked |
--tab-border, --accent active indicator |
| Accordion | <details> nativo |
summary marker rotates |
| Badge/chip | primaryneutralsuccesswarningerror | --badge-radius: 100px (pill shape) |
§3.3 — Navegação (#008.4)
| Componente | Implementação |
|---|---|
| App bar | position: sticky; top: 0; z-index: 10 + --surface bg |
| Breadcrumb | lista <nav> com separador › |
| Pagination | botões com aria-current="page" |
| Nav rail | sidebar coluna com --rail-active-bg no item ativo |
§3.4 — Data (#008.5)
| Componente | Implementação |
|---|---|
| Table | --table-border, --table-header-bg, --table-row-hover |
| Progress bar | linear, cores primary/warning |
| Stat/KPI card | delta arrow ▲▼, --stat-label-color |
§3.5 — Feedback (#008.6)
| Componente | Implementação |
|---|---|
| Toast/Snackbar | --toast-bg: #2e3436 / dark: #424242, fixed bottom-right |
| Spinner | CSS keyframe border-radius: 50%, --spinner-track |
| Skeleton | pulsing --skeleton-bg rgba(0,0,0,0.08) |
| Empty state | ícone + heading + ação primary |
§3.6 — Tipografia aplicada (#008.7)
Escala T1–T7 alinhada com --kdr-font-size-* tokens implícitos:
| Classe | px | uso |
|---|---|---|
.t1 |
48 | Hero / display |
.t2 |
36 | H1 de página |
.t3 |
28 | H2 de seção |
.t4 |
22 | H3 / cards |
.t5 |
18 | Subtítulo |
.t6 |
14 | Body padrão |
.t7 |
12 | Caption / overline |
Tokens adicionados: --font-mono, --code-bg, --code-color.
§3.7 — Layout primitives (#008.8)
| Primitive | Classe CSS | Uso |
|---|---|---|
| Stack | .stack (flex-column) |
pilha vertical de componentes |
| Row | .row (flex-row) |
linha com gap |
| Divider | .divider, .divider-with-label |
separador |
| Surface levels | .surface-0/1/2 |
hierarquia de planos |
| Focus ring demo | .focus-demo |
visualização do token |
§3.8 — Surface-specific (#008.9)
Tabs Mobile / Desktop / Web / TV na detail page de cada preset. Density overrides por surface (via .preset.surface-<X>):
| Surface | Altura mínima btn/input | Font-size |
|---|---|---|
| Mobile | 44px | 15-16px |
| Desktop | 28px | 12px |
| Web | 36px | padrão |
| TV | 56px | 18px |
*V:*focus ring explícito 4px solid var(--accent) (D-pad nav). *eb:*progressive enhancement — sem hover states como requirement.
§4 — Form builder (#008.10-11)
O Preset builder em kds.koder.dev/<locale>/tools/style-builder/ implementa edição visual dos tokens Verge:
- *ba Colors* 11 tokens de cor (accent, bg, surface, on-surface,
label, error, success, warning)
- *ba Shape* 4 sliders de radius (smmdlg/btn)
- *ba Spacing* 4 sliders (pad
y/x, gapfield, pad-form) - *ba Type* dropdown de font-family
- *review* form de cadastro + strip de componentes ao vivo
- *xport* CSS preset block + JSON + URL compartilhável (hash base64)
- *mport* JSON ou CSS vars
- *ndo/Redo* stack de 50 passos (Ctrl+Z / Ctrl+Y)
- *iff* painel
<details>com alterações vs defaults Verge
§5 — Decisões pendentes
| ID | Tema | Decisão necessária |
|---|---|---|
| D1.flip | Radius btn 5px | Owner confirmar flip no CSS (atualmente 6px Adwaita) |
| D2.when | Paleta índigo | Quais produtos adoptam índigo vs Adwaita blue |
| D3.display | Koder Display | Aguardar #128 (custom font) |
| D5.shadows | Sombras índigo-tinted | Confirmar aplicação ao preset Verge v0 |
| #008.13 | Migration | Produtos Koder migrar de .preset.material3 → .preset.verge |
| #008.14 | Default preset | Confirmar .preset.verge como único default (atual: já é Default: true) |
§6 — Ferramentas e testes
| Ferramenta | Path | Propósito |
|---|---|---|
| Preset builder | kds.koder.dev/<locale>/tools/style-builder/ |
Edição visual interativa |
| Contrast audit | tools/design-gen/cmd/verge-contrast-audit/ |
WCAG AA check automatizado |
| Regression test | tests/regression/verge_contrast_baseline_test.go |
Trava score ≥ 11 pares passing |
| Audit script | specs/themes/ui-style-audit.sh |
Valida uso de preset nos apps |
§7 — Cross-links
specs/themes/verge.kmd— spec normativa de tokens + versioningspecs/themes/ui-style.kmd— registry de 43 presets + auditspecs/themes/light-dark.kmd— esquema light/dark cross-surfacespecs/fonts/typography.kmd— roles de tipografia + self-hosted.woff2specs/themes/motion/— easing + durations + transitionstools/design-gen/assets/css/presets.css— CSS canônico (.preset.verge)tools/design-gen/backlog/pending/008-koder-native-style-and-form-builder.md— épico de sub-tickets