Container centralizado em --container-max (1280px), padding lateral responsivo via --container-pad e grade estruturada em base 8 — três breakpoints, um único sistema.
Princípio
A unidade mínima de espaçamento é 8px. Todo padding, margin e gap de layout é múltiplo direto dessa base — 8, 16, 24, 32, 48, 64, 96, 128. O container de conteúdo usa max-width: var(--container-max) (1280px) e margin: 0 auto para centralização. O padding lateral é sempre var(--container-pad): 48px em desktop, 32px em tablet, 24px em mobile — o tokens.css redefine o valor em cada breakpoint via @media, e quem usa o token herda o ajuste sem redeclarar as regras. No shell desktop, o shell.css define grid-template-columns: 280px 1fr, ancorando a sidebar fixa à esquerda e deixando a área de conteúdo fluida.
A escala completa de tokens de espaçamento — de --space-8 a --space-128 — está documentada na página Espaçamento. No contexto de grade e layout, a regra é direta: padding, margin e gap com valores que não são múltiplos de 8 (13px, 17px, 22px) são violação. A única exceção são ajustes ópticos de glifo tipográfico — alinhamentos finos que o olho exige e o grid de 8 não resolve — e nesses casos o valor permitido é múltiplo de 4, nunca arbitrário, nunca em posições de layout.
Tokens de layout
Três tokens cobrem todo o sistema de grade: largura máxima do conteúdo, padding lateral responsivo e altura da topbar mobile. O --container-pad merece atenção: não são três tokens com um por breakpoint — é um único token cujo valor é redefinido por @media no tokens.css. Os valores completos estão em design-system/tokens/tokens.css.
| Token | Valor | Contexto de uso | Papel |
|---|---|---|---|
--container-max | 1280px | Todos os breakpoints — desktop, tablet e mobile. | Largura máxima do conteúdo centralizado. Qualquer container de conteúdo usa max-width: var(--container-max) + margin: 0 auto. |
--container-pad | var(--space-48) → desktopvar(--space-32) → tabletvar(--space-24) → mobile | Ajustado via @media no tokens.css: 48px acima de 1024px, 32px entre 768px e 1024px, 24px abaixo de 768px. Um único token — não declarar os três valores diretamente nos componentes. | Padding lateral do container de conteúdo. Um único token — o tokens.css redefine seu valor em cada breakpoint via @media. Nunca usar valor fixo em px onde --container-pad cabe. |
--header-height | 64px | Mobile e tablet — topbar sticky. Em desktop, a topbar não é renderizada. | Altura da topbar mobile. Usada para calcular padding-top de conteúdo e posicionamento do drawer em viewports estreitas. Em desktop, a topbar não é renderizada — o shell usa sidebar fixa. |
Três breakpoints
O sistema opera em três faixas: desktop (≥ 1025px), tablet (768–1024px) e mobile (< 768px). Os pontos de quebra são definidos no tokens.css via @media e propagados pelo token --container-pad. O shell.css e os componentes consomem o token — nenhum componente redefine os breakpoints por conta própria.
Desktop — >= 1025px
A sidebar fica fixa à esquerda em 280px — o shell.css define o shell como grid-template-columns: 280px 1fr. A área de conteúdo ocupa o restante da largura disponível, limitada a --container-max (1280px) com margin: 0 auto. O padding lateral é var(--container-pad), que em desktop resolve para var(--space-48) (48px = 6×8). Tipografia nos tamanhos padrão do tokens.css — --type-size-display em 64px.
Tablet — 768–1024px
A sidebar sai do fluxo e vira drawer off-canvas, acionado pelo botão de hamburger na topbar sticky. A topbar ocupa --header-height (64px) no topo da viewport. A área de conteúdo ocupa 100% da largura disponível menos o padding lateral — o tokens.css redefine --container-pad para var(--space-32) (32px = 4×8) nessa faixa. A tipografia se ajusta: --type-size-display-lg cai de 80px para 64px, --type-size-display cai de 64px para 56px, --type-size-2xl cai de 48px para 40px, --type-size-xl cai de 40px para 32px.
Mobile — < 768px
Mesma estrutura de drawer do tablet. O --container-pad cai para var(--space-24) (24px = 3×8), preservando espaço respirável numa viewport estreita. A tipografia mantém os valores do tablet: --type-size-display em 56px, --type-size-xl em 32px, --type-size-display-lg em 64px, --type-size-2xl em 40px — sem redução adicional no mobile. O grid de cards colapsa para 1 coluna — nenhum card divide largura com outro na tela.
Card Grid responsivo
O Card Grid opera com 3 colunas em desktop, 2 em tablet e 1 em mobile. O gap entre cards é sempre múltiplo de 8 — --space-24 (24px) como valor padrão. O grid usa CSS Grid com grid-template-columns responsivo definido no grade-e-layout.css; os componentes não declaram media queries próprias. O contexto de breakpoint vem dos tokens, que propagam o ajuste de --container-pad de forma centralizada.
Compromisso vence hoje
Luz · R$ 127,30. Pago ou deixa pra mim?
Saldo projetado
R$ 2.140 em 15/mai · R$ 380 acima do mês anterior.
Gasto em delivery
R$ 230 este mês · R$ 80 abaixo da média.
Em desktop, os três cards ficam lado a lado em colunas iguais. Em tablet, o grid colapsa para 2 colunas — dois cards na primeira linha, um na segunda. Em mobile, os três ficam empilhados em coluna única.
Regras de uso
- Layout ancorado em tokens — nunca valores arbitrários. Todo espaçamento de layout — padding, gap, margin — usa
--space-*. Todo limite de largura usa--container-max. Valor em px avulso que não seja múltiplo de 8 é violação direta do anti-padrão #12. --container-max(1280px) em qualquer conteúdo centralizado. Todo wrapper de conteúdo usamax-width: var(--container-max)commargin: 0 auto. Conteúdo que ultrapasse 1280px sem justificativa documentada é violação — não é exceção de design, é revisão necessária.- Padding lateral sempre via
--container-pad. Os três valores de padding lateral (48 / 32 / 24px) vivem notokens.css. Componentes não devem redeclarar esses valores em media queries próprias. Quem usavar(--container-pad)herda o comportamento responsivo sem custo adicional. - Grid colapsa em múltiplos de 8: 3 → 2 → 1 colunas. A sequência de colapso do Card Grid por breakpoint é 3 → 2 → 1. O gap entre colunas é sempre múltiplo de 8. Não pular de 3 para 1 sem passar por 2 — exceto em grids que nascem com 2 colunas, que podem colapsar direto para 1.
- Sidebar vira drawer em < 1025px. Abaixo de 1025px, a sidebar some do fluxo de layout e vira drawer off-canvas acionado por hamburger na topbar. O
shell.csse ods-nav.jsjá implementam esse comportamento. Componentes novos não redeclaram a lógica de drawer — consomem o shell como está. - Scroll vertical é aceito; scroll horizontal é violação. Nenhuma superfície de produto produz overflow horizontal. A única exceção é tabela dentro de
.peppe-table-wrapcomoverflow-x: autoexplícito. Qualquer componente que rompa a largura do viewport sem esse wrapper é violação — não é decisão de layout, é correção obrigatória.
Anti-padrões referenciados
Anti-padrões com relação direta a decisões de grade e layout. O arquivo-fonte está em .claude/ui-design/anti-patterns.md. Links permanentes serão atualizados quando a seção de anti-padrões visuais for publicada.
- #12 — Espaçamento fora da escala estruturalPadding, margin ou gap com valores que não são múltiplos de 8 — 13px, 17px, 22px, 10px. A escala começa em
--space-8e sobe em múltiplos. Múltiplos de 4 são aceitos apenas para ajustes ópticos de glifo tipográfico, nunca em posições de layout. Um componente comgap: 10pxnuma tela onde tudo usa base-8 produz desalinhamento que se acumula silenciosamente — cada elemento ligeiramente fora do grid, sem que nenhum isoladamente explique o resultado. - Responsividade — overflow horizontal não declaradoQualquer elemento que produza scroll horizontal sem wrapper explícito é violação. Os casos mais comuns: imagens sem
max-width: 100%, textos comwhite-space: nowrapsem contenção, e tabelas sem.peppe-table-wrap. A página deve caber em qualquer largura de viewport de produto — se um componente força overflow, é o componente que muda, não a viewport que acomoda.
Consultar .claude/ui-design/anti-patterns.md na íntegra para demais anti-padrões visuais.