nexus-core-v3 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/agents/README.md +133 -0
  4. package/agents/_protocol.md +107 -0
  5. package/agents/analyst.md +138 -0
  6. package/agents/architect.md +146 -0
  7. package/agents/data-engineer.md +170 -0
  8. package/agents/dev.md +134 -0
  9. package/agents/devops.md +141 -0
  10. package/agents/nexus-master.md +147 -0
  11. package/agents/pm.md +133 -0
  12. package/agents/po.md +138 -0
  13. package/agents/qa.md +192 -0
  14. package/agents/sm.md +122 -0
  15. package/agents/squad-creator.md +121 -0
  16. package/agents/ux-design-expert.md +165 -0
  17. package/artifact-manifest.json +903 -0
  18. package/bin/nexus.mjs +37 -0
  19. package/checklists/README.md +49 -0
  20. package/checklists/architect-checklist.md +47 -0
  21. package/checklists/change-checklist.md +61 -0
  22. package/checklists/db-predeploy-checklist.md +57 -0
  23. package/checklists/design-quality-checklist.md +57 -0
  24. package/checklists/discovery-checklist.md +36 -0
  25. package/checklists/foundation-checklist.md +39 -0
  26. package/checklists/launch-checklist.md +39 -0
  27. package/checklists/pm-checklist.md +48 -0
  28. package/checklists/po-master-checklist.md +64 -0
  29. package/checklists/reality-check-checklist.md +49 -0
  30. package/checklists/story-dod-checklist.md +52 -0
  31. package/checklists/story-draft-checklist.md +36 -0
  32. package/dist/bin/dashboard.html +279 -0
  33. package/dist/bin/nexus.mjs +20008 -0
  34. package/dist/constitution.yaml +76 -0
  35. package/knowledge/README.md +57 -0
  36. package/knowledge/architecture/architectural-styles-map.md +182 -0
  37. package/knowledge/architecture/design-patterns-gof.md +192 -0
  38. package/knowledge/architecture/distributed-patterns-cheatsheet.md +201 -0
  39. package/knowledge/architecture/saas-subscription-blueprint.md +355 -0
  40. package/knowledge/architecture/system-design-tradeoffs.md +231 -0
  41. package/knowledge/architecture/t3-fullstack-typesafe-stack.md +273 -0
  42. package/knowledge/copy/landing-copy-that-converts.md +168 -0
  43. package/knowledge/data/postgres-indexing-and-tuning.md +263 -0
  44. package/knowledge/data/schema-modeling-decisions.md +273 -0
  45. package/knowledge/data/supabase-rls-patterns.md +316 -0
  46. package/knowledge/data/zero-downtime-migrations.md +308 -0
  47. package/knowledge/devops/cicd-pipeline-best-practices.md +318 -0
  48. package/knowledge/devops/production-dockerfile.md +283 -0
  49. package/knowledge/devops/twelve-factor-app.md +398 -0
  50. package/knowledge/engineering/clean-code-principles.md +429 -0
  51. package/knowledge/engineering/effective-code-review.md +204 -0
  52. package/knowledge/engineering/testing-strategy-beyond-unit.md +307 -0
  53. package/knowledge/governance/risk-matrix.md +56 -0
  54. package/knowledge/integration/mcp-server-selection-matrix.md +235 -0
  55. package/knowledge/marketing/copy-que-converte.md +43 -0
  56. package/knowledge/marketing/funil-e-jornada.md +36 -0
  57. package/knowledge/negocios/proposta-vencedora.md +38 -0
  58. package/knowledge/negocios/roi-e-unit-economics.md +46 -0
  59. package/knowledge/pipeline/1-descobrir.md +26 -0
  60. package/knowledge/pipeline/2-estrategizar.md +26 -0
  61. package/knowledge/pipeline/3-estruturar.md +27 -0
  62. package/knowledge/pipeline/4-construir.md +27 -0
  63. package/knowledge/pipeline/5-endurecer.md +28 -0
  64. package/knowledge/pipeline/6-lancar.md +27 -0
  65. package/knowledge/pipeline/7-operar.md +27 -0
  66. package/knowledge/security/lgpd-conformidade-basica.md +35 -0
  67. package/knowledge/security/owasp-secure-coding-gates.md +220 -0
  68. package/knowledge/security/owasp-top10-threat-assessment.md +287 -0
  69. package/knowledge/security/threat-modeling-stride.md +34 -0
  70. package/knowledge/web-craft/a11y-audit-checklist.md +251 -0
  71. package/knowledge/web-craft/accessible-component-patterns.md +383 -0
  72. package/knowledge/web-craft/anti-ai-look.md +114 -0
  73. package/knowledge/web-craft/design-system-from-code.md +195 -0
  74. package/knowledge/web-craft/intrinsic-css-layout.md +420 -0
  75. package/knowledge/web-craft/style-cloning.md +185 -0
  76. package/knowledge/web-craft/visual-polish-review.md +183 -0
  77. package/package.json +55 -0
  78. package/runbooks/campanha-de-conteudo.md +36 -0
  79. package/runbooks/feature-em-projeto-existente.md +37 -0
  80. package/runbooks/mvp-startup.md +38 -0
  81. package/runbooks/resposta-a-incidente.md +37 -0
  82. package/squads/exemplo-conteudo/agents/editor-chefe.md +48 -0
  83. package/squads/exemplo-conteudo/agents/pesquisador.md +44 -0
  84. package/squads/exemplo-conteudo/agents/redator.md +45 -0
  85. package/squads/exemplo-conteudo/knowledge/estilo-editorial.md +21 -0
  86. package/squads/exemplo-conteudo/squad.yaml +19 -0
  87. package/squads/exemplo-conteudo/tasks/pesquisar-fontes.md +26 -0
  88. package/squads/exemplo-conteudo/tasks/planejar-pauta.md +27 -0
  89. package/squads/exemplo-conteudo/tasks/redigir-artigo.md +26 -0
  90. package/squads/exemplo-conteudo/tasks/revisar-artigo.md +27 -0
  91. package/squads/marketing/agents/analista.md +56 -0
  92. package/squads/marketing/agents/chefe-marketing.md +65 -0
  93. package/squads/marketing/agents/conteudo.md +55 -0
  94. package/squads/marketing/agents/copy.md +55 -0
  95. package/squads/marketing/agents/growth.md +56 -0
  96. package/squads/marketing/agents/social.md +55 -0
  97. package/squads/marketing/squad.yaml +17 -0
  98. package/squads/marketing/tasks/aprovar-campanha.md +43 -0
  99. package/squads/negocios/agents/chefe-negocios.md +65 -0
  100. package/squads/negocios/agents/financas-roi.md +55 -0
  101. package/squads/negocios/agents/suporte.md +55 -0
  102. package/squads/negocios/agents/vendas-proposta.md +56 -0
  103. package/squads/negocios/squad.yaml +17 -0
  104. package/squads/negocios/tasks/aprovar-proposta.md +40 -0
  105. package/squads/security/agents/appsec-reviewer.md +59 -0
  106. package/squads/security/agents/chefe-seguranca.md +65 -0
  107. package/squads/security/agents/compliance-auditor.md +60 -0
  108. package/squads/security/agents/threat-modeler.md +60 -0
  109. package/squads/security/squad.yaml +20 -0
  110. package/squads/security/tasks/aprovar-gate-seguranca.md +42 -0
  111. package/squads/security/tasks/emitir-parecer-conformidade.md +42 -0
  112. package/tasks/README.md +72 -0
  113. package/tasks/accessibility-wcag-checklist.md +69 -0
  114. package/tasks/advanced-elicitation.md +42 -0
  115. package/tasks/analyze-performance.md +54 -0
  116. package/tasks/analyze-project-structure.md +59 -0
  117. package/tasks/apply-qa-fixes.md +57 -0
  118. package/tasks/architect-analyze-impact.md +62 -0
  119. package/tasks/archive-squad.md +52 -0
  120. package/tasks/audit-codebase.md +53 -0
  121. package/tasks/build-component.md +61 -0
  122. package/tasks/calculate-roi.md +63 -0
  123. package/tasks/ci-cd-configuration.md +51 -0
  124. package/tasks/collect-visual-evidence.md +62 -0
  125. package/tasks/compose-molecule.md +57 -0
  126. package/tasks/consolidate-patterns.md +54 -0
  127. package/tasks/create-brownfield-prd.md +54 -0
  128. package/tasks/create-competitor-analysis.md +42 -0
  129. package/tasks/create-deep-research-prompt.md +62 -0
  130. package/tasks/create-doc.md +62 -0
  131. package/tasks/create-epic.md +49 -0
  132. package/tasks/create-front-end-spec.md +56 -0
  133. package/tasks/create-migration-plan.md +57 -0
  134. package/tasks/create-next-story.md +66 -0
  135. package/tasks/create-prd.md +53 -0
  136. package/tasks/create-project-brief.md +47 -0
  137. package/tasks/create-rls-policies.md +59 -0
  138. package/tasks/create-schema.md +57 -0
  139. package/tasks/create-service.md +55 -0
  140. package/tasks/create-squad.md +100 -0
  141. package/tasks/create-suite.md +62 -0
  142. package/tasks/db-apply-migration.md +56 -0
  143. package/tasks/db-domain-modeling.md +57 -0
  144. package/tasks/db-dry-run.md +50 -0
  145. package/tasks/db-env-check.md +57 -0
  146. package/tasks/db-load-csv.md +54 -0
  147. package/tasks/db-policy-apply.md +58 -0
  148. package/tasks/db-rollback.md +51 -0
  149. package/tasks/db-run-sql.md +61 -0
  150. package/tasks/db-seed.md +52 -0
  151. package/tasks/db-smoke-test.md +51 -0
  152. package/tasks/db-snapshot.md +48 -0
  153. package/tasks/db-verify-order.md +49 -0
  154. package/tasks/deliberate.md +46 -0
  155. package/tasks/design-indexes.md +59 -0
  156. package/tasks/dev-develop-story.md +61 -0
  157. package/tasks/document-project.md +59 -0
  158. package/tasks/execute-checklist.md +57 -0
  159. package/tasks/execute-epic-plan.md +52 -0
  160. package/tasks/execute-subtask.md +51 -0
  161. package/tasks/extend-pattern.md +63 -0
  162. package/tasks/extend-squad.md +60 -0
  163. package/tasks/extract-patterns.md +64 -0
  164. package/tasks/extract-tokens.md +59 -0
  165. package/tasks/facilitate-brainstorming-session.md +42 -0
  166. package/tasks/generate-ai-frontend-prompt.md +57 -0
  167. package/tasks/generate-documentation.md +60 -0
  168. package/tasks/generate-migration-strategy.md +57 -0
  169. package/tasks/generate-shock-report.md +56 -0
  170. package/tasks/mcp-management.md +66 -0
  171. package/tasks/orchestrate.md +50 -0
  172. package/tasks/perform-market-research.md +42 -0
  173. package/tasks/plan-create-context.md +57 -0
  174. package/tasks/plan-create-implementation.md +58 -0
  175. package/tasks/po-close-story.md +60 -0
  176. package/tasks/po-manage-story-backlog.md +59 -0
  177. package/tasks/po-pull-story.md +60 -0
  178. package/tasks/po-sync-story.md +59 -0
  179. package/tasks/pr-automation.md +50 -0
  180. package/tasks/pre-push-quality-gate.md +54 -0
  181. package/tasks/push.md +53 -0
  182. package/tasks/qa-browser-console-check.md +52 -0
  183. package/tasks/qa-create-fix-request.md +58 -0
  184. package/tasks/qa-evidence-requirements.md +55 -0
  185. package/tasks/qa-false-positive-detection.md +55 -0
  186. package/tasks/qa-fix-issues.md +55 -0
  187. package/tasks/qa-gate.md +53 -0
  188. package/tasks/qa-migration-validation.md +58 -0
  189. package/tasks/qa-nfr-assess.md +45 -0
  190. package/tasks/qa-review-story.md +56 -0
  191. package/tasks/qa-risk-profile.md +45 -0
  192. package/tasks/qa-security-checklist.md +64 -0
  193. package/tasks/qa-test-design.md +47 -0
  194. package/tasks/qa-trace-requirements.md +48 -0
  195. package/tasks/release-management.md +53 -0
  196. package/tasks/repository-cleanup.md +61 -0
  197. package/tasks/route.md +44 -0
  198. package/tasks/run-tests.md +50 -0
  199. package/tasks/security-audit.md +54 -0
  200. package/tasks/setup-database.md +60 -0
  201. package/tasks/setup-design-system.md +60 -0
  202. package/tasks/shard-doc.md +60 -0
  203. package/tasks/spec-assess-complexity.md +55 -0
  204. package/tasks/spec-critique.md +64 -0
  205. package/tasks/spec-gather-requirements.md +48 -0
  206. package/tasks/spec-research-dependencies.md +42 -0
  207. package/tasks/spec-write-spec.md +50 -0
  208. package/tasks/test-as-user.md +52 -0
  209. package/tasks/ux-create-wireframe.md +54 -0
  210. package/tasks/ux-user-research.md +55 -0
  211. package/tasks/validate-next-story.md +61 -0
  212. package/tasks/validate-squad.md +55 -0
  213. package/tasks/verify-subtask.md +52 -0
  214. package/tasks/version-management.md +45 -0
  215. package/templates/README.md +47 -0
  216. package/templates/architecture-tmpl.md +115 -0
  217. package/templates/competitor-analysis-tmpl.md +87 -0
  218. package/templates/epic-tmpl.md +83 -0
  219. package/templates/front-end-spec-tmpl.md +110 -0
  220. package/templates/market-research-tmpl.md +98 -0
  221. package/templates/migration-plan-tmpl.md +92 -0
  222. package/templates/prd-tmpl.md +95 -0
  223. package/templates/project-brief-tmpl.md +100 -0
  224. package/templates/qa-verdict-tmpl.md +73 -0
  225. package/templates/rls-policies-tmpl.md +93 -0
  226. package/templates/schema-design-tmpl.md +107 -0
  227. package/templates/spec-tmpl.md +88 -0
  228. package/templates/squad/agent-dna-tmpl.md +72 -0
  229. package/templates/squad/chief-dna-tmpl.md +98 -0
  230. package/templates/squad/squad-task-tmpl.md +50 -0
  231. package/templates/squad/squad-yaml-tmpl.md +47 -0
  232. package/templates/story-tmpl.md +63 -0
@@ -0,0 +1,195 @@
1
+ ---
2
+ id: design-system-from-code
3
+ domain: web-craft
4
+ agents: [ux-design-expert]
5
+ when: "ao consolidar um design system a partir de um codebase existente"
6
+ ---
7
+
8
+ # Design system a partir de código — consolidar o que já existe, sem inventar
9
+
10
+ Codebase real não tem design system. Tem **arqueologia**: três anos de PRs, quatro pessoas com gostos
11
+ diferentes, um copy-paste de Figma que ninguém atualizou, e `#3B82F6` digitado à mão em 47 lugares. O
12
+ trabalho aqui **não é desenhar** — é *auditar, agrupar e migrar* o que está espalhado, transformando
13
+ caos em tokens reutilizáveis **sem quebrar quem consome**. A regra-mãe: **todo token tem que ter
14
+ origem rastreável no código atual.** Você não está criando uma paleta nova — está nomeando a que já
15
+ existe e matando as divergências. Inventar uma cor "mais bonita" no meio da consolidação é trair o
16
+ trabalho: vira redesign disfarçado de auditoria, e ninguém pediu redesign.
17
+
18
+ ## O problema / os tells
19
+
20
+ Você está diante de um codebase que precisa de design system se vê 3+ destes:
21
+
22
+ 1. **Hex hardcoded espalhado** — `grep -rE '#[0-9a-fA-F]{3,6}'` retorna centenas de hits. O mesmo azul
23
+ aparece como `#3B82F6`, `#3b82f6`, `#3a83f7` (alguém errou de um dígito), `rgb(59,130,246)` e
24
+ `rgba(59,130,246,1)`. São "o mesmo azul" pro olho, cinco valores distintos pro computador.
25
+ 2. **Escalas tipográficas paralelas** — um componente usa `text-sm/text-base/text-lg` (Tailwind), outro
26
+ tem `font-size: 15px` cravado, um terceiro herda `1.05rem` de um CSS legado. Três escalas, zero
27
+ intenção. Você conta 11 tamanhos de fonte distintos numa tela só.
28
+ 3. **Spacing ad-hoc** — `margin-top: 13px`, `padding: 18px 22px`, `gap: 6px`. Números que não pertencem
29
+ a escala nenhuma, nascidos de "arrastar até parecer certo" no DevTools. O tell clássico: `17px`.
30
+ Ninguém escolhe 17 de propósito.
31
+ 4. **Variantes de componente duplicadas** — `Button`, `ButtonNew`, `PrimaryButton`, `CTAButton` e um
32
+ `<button className="btn-primary">` solto. Fazem a mesma coisa, divergem em 3px de padding e um
33
+ shade de hover. Cada um foi "mais rápido criar do novo do que achar o que existia".
34
+ 5. **z-index sem sistema** — `z-index: 9999`, `z-index: 99999`, `z-index: 100`, `z-index: 9998` (o
35
+ hack pra "ficar atrás do 9999"). Guerra de empilhamento, não arquitetura de camadas.
36
+ 6. **Sombra e raio por gosto do dia** — `box-shadow` com 6 receitas diferentes de blur/spread/opacity;
37
+ `border-radius` variando entre `4px`, `6px`, `8px`, `0.5rem` e `9999px` sem critério de uso.
38
+ 7. **Dark mode meia-boca** — metade dos componentes responde a `.dark`, a outra metade tem branco
39
+ cravado e "estoura" no tema escuro. Sintoma de cor hardcoded, não tokenizada.
40
+ 8. **O Figma e o código discordam** — o token "primary" no design tool é `#2563EB`, no código rodando
41
+ em produção é `#3B82F6`. A fonte da verdade é o que o usuário vê: **o código em produção**, não o
42
+ arquivo de design. Comece pelo código.
43
+
44
+ Anti-tell (o que NÃO é problema): dois valores próximos podem ser **intencionais** — `border` em `1px`
45
+ e divisor em `1px` mas com cores diferentes é correto. Nem toda repetição é dívida; só a **divergência
46
+ sem razão** é. Não tokenize ruído como se fosse sinal.
47
+
48
+ ## Os princípios do craft
49
+
50
+ ### 1. Inventário antes de opinião — meça, não ache
51
+
52
+ Não comece propondo paleta. Comece **extraindo a verdade** do código com comandos, não com olho:
53
+
54
+ ```bash
55
+ # Cores: todos os hex, normalizados e contados por frequência
56
+ grep -rohE '#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|rgba?\([^)]+\)' src/ \
57
+ | tr 'A-F' 'a-f' | sort | uniq -c | sort -rn
58
+
59
+ # Font-sizes: toda a escala real em uso
60
+ grep -rohE 'font-size:\s*[0-9.]+(px|rem|em)' src/ | sort | uniq -c | sort -rn
61
+
62
+ # Spacing: padding/margin/gap literais (o que escapou da escala)
63
+ grep -rohE '(margin|padding|gap)[^:]*:\s*[0-9.]+px' src/ | sort | uniq -c | sort -rn
64
+
65
+ # z-index: o mapa da guerra de empilhamento
66
+ grep -rohE 'z-index:\s*-?[0-9]+' src/ | sort | uniq -c | sort -rn
67
+
68
+ # Componentes que parecem o mesmo botão
69
+ grep -rlE 'Button|btn' src/components/ | sort
70
+ ```
71
+
72
+ A saída de frequência é ouro: o hex que aparece **89 vezes** é seu primitivo; o que aparece **1 vez** e
73
+ difere por um dígito do primitivo é divergência pra eliminar. Frequência separa o sistema (alto uso,
74
+ intencional) do acidente (uso único, erro de digitação).
75
+
76
+ ### 2. Cluster por proximidade perceptual, não por igualdade exata
77
+
78
+ `#3B82F6`, `#3b82f6` e `#3a83f7` são **o mesmo token**. Agrupe por distância de cor (ΔE), não por
79
+ string idêntica. Regra prática sem ferramenta: converta pra HSL e agrupe o que está dentro de ~2% em
80
+ cada canal. Cada cluster vira **um** primitivo; a variante mais frequente do cluster é a canônica, as
81
+ outras são aliases a migrar. Mesma lógica pra spacing: `13px`, `14px`, `15px` provavelmente queriam ser
82
+ `16px` — colapse pro valor da escala mais próximo, não preserve o acidente.
83
+
84
+ ### 3. Primitivos → semânticos (duas camadas, nunca uma)
85
+
86
+ O erro fatal é tokenizar direto pra uso: `$button-blue: #3B82F6`. Quando a marca trocar de azul, você
87
+ caça `button-blue` em 200 lugares. Faça **duas camadas**:
88
+
89
+ ```
90
+ PRIMITIVOS (a paleta crua, sem significado):
91
+ --blue-500: #3B82F6
92
+ --blue-600: #2563EB
93
+ --gray-50: #F9FAFB
94
+
95
+ SEMÂNTICOS (o significado, apontando pro primitivo):
96
+ --color-action: var(--blue-500)
97
+ --color-action-hover: var(--blue-600)
98
+ --color-surface: var(--gray-50)
99
+ --color-text-primary: var(--gray-900)
100
+ ```
101
+
102
+ Componentes consomem **só semânticos** (`--color-action`), nunca primitivos diretos. Trocar a marca =
103
+ mudar um apontamento. Dark mode = remapear semânticos pra outros primitivos, sem tocar em componente.
104
+ Essa indireção é o que separa um design system de uma lista de cores com nome.
105
+
106
+ ### 4. Nomeie por função, não por aparência
107
+
108
+ `--color-primary` é fraco (primário de quê?). `--color-danger`, `--color-action`, `--color-surface`,
109
+ `--color-border-subtle` carregam **intenção** — o consumidor sabe quando usar sem ler doc. E nunca
110
+ nomeie pela cor: `--color-green-success` quebra no dia que "sucesso" virar azul. O nome é o contrato;
111
+ a cor é detalhe de implementação.
112
+
113
+ ### 5. Meça consistência com um número, priorize a dívida com ele
114
+
115
+ "Está inconsistente" não move ninguém. **Tokenization coverage** move: `% de valores que vêm de token
116
+ vs hardcoded`. Calcule por categoria:
117
+
118
+ ```
119
+ cor: 38% tokenizado → 62% hardcoded (pior, ataca primeiro)
120
+ spacing: 71% tokenizado
121
+ tipografia: 84% tokenizado
122
+ ```
123
+
124
+ Priorize por **frequência × visibilidade × esforço**: a cor de ação aparece em todo CTA (alta
125
+ visibilidade), tem 62% solto (alto volume) e é troca mecânica (baixo esforço) → primeira da fila. O
126
+ `z-index` aparece em 6 lugares e mexer arrisca regressão de overlay → depois, com cuidado. Não migre
127
+ em ordem alfabética; migre em ordem de retorno.
128
+
129
+ ### 6. Migre com codemod e alias, nunca com find-and-replace cego
130
+
131
+ Trocar `#3B82F6` por `var(--color-action)` no braço pode quebrar onde aquele azul era **coincidência**
132
+ (um azul de ícone de terceiro que não devia seguir a marca). Migre assim:
133
+
134
+ 1. **Camada de alias primeiro**: defina o token apontando pro valor atual exato. Nada muda visualmente
135
+ — você só ganhou o nome.
136
+ 2. **Codemod scoped**: substitua o literal pelo token **arquivo por arquivo**, rodando o diff visual
137
+ (ou snapshot de teste) a cada lote. `jscodeshift`/`postcss` com escopo, não sed global.
138
+ 3. **Deprecação, não deleção**: o componente velho (`ButtonNew`) ganha um `@deprecated` apontando pro
139
+ canônico e continua funcionando. Você remove quando os consumidores migrarem — não no mesmo PR.
140
+ 4. **Visual regression como rede**: snapshot antes/depois. Se um pixel mexeu e você não previu, a
141
+ migração não era equivalente — investigue antes de seguir.
142
+
143
+ A migração correta é **invisível ao usuário**. Se a tela mudou, você fez redesign sem querer.
144
+
145
+ ### 7. Component canônico = consolidar variantes na de maior cobertura, com props
146
+
147
+ Cinco botões viram **um** `Button` com variantes explícitas — `variant="primary|secondary|ghost"`,
148
+ `size="sm|md|lg"`. A base é a variante de **maior uso real** (a que mais aparece no grep), não a "mais
149
+ nova" nem a "mais bonita". As divergências de 3px que cada um tinha viram ou um token de tamanho, ou
150
+ são apagadas como o acidente que eram. Quem consumia `CTAButton` ganha um alias deprecado
151
+ `CTAButton = (p) => <Button variant="primary" {...p} />` — migra sem PR de breaking change.
152
+
153
+ ### 8. A saída é três coisas, não um arquivo de cores
154
+
155
+ Entregue: **(a) tokens** em duas camadas, num formato consumível (CSS vars + JSON/W3C design tokens
156
+ pra ferramentas), **(b) componentes canônicos** com variantes e os antigos deprecados apontando pra
157
+ eles, e **(c) doc viva** que mostra cada token e componente *renderizado* (Storybook ou página de
158
+ estilo), com a regra de uso ("use `--color-action` em qualquer elemento clicável primário; nunca
159
+ hardcode azul"). Doc que é só uma tabela de hex morre na primeira semana; doc que renderiza o token e
160
+ diz quando usar é a que segura a consistência depois que você sai.
161
+
162
+ ## Checklist
163
+
164
+ Antes de declarar o design system consolidado — qualquer "não" é trabalho pendente:
165
+
166
+ - [ ] Rodei o inventário por **comando** (grep de cor/fonte/spacing/z-index) e tenho a contagem de
167
+ frequência, não só uma impressão?
168
+ - [ ] Agrupei valores por **proximidade perceptual** (clusters), não por string exata — e cada cluster
169
+ tem um canônico definido pela frequência?
170
+ - [ ] Os tokens têm **duas camadas** (primitivo → semântico) e os componentes consomem só semânticos?
171
+ - [ ] Os semânticos são nomeados por **função** (`--color-action`), nunca por aparência
172
+ (`--color-blue`)?
173
+ - [ ] Tenho um **número de cobertura** por categoria e a fila de migração está ordenada por retorno
174
+ (frequência × visibilidade × esforço), não alfabética?
175
+ - [ ] A migração usa **alias + codemod scoped + deprecação**, com visual regression a cada lote — e
176
+ nenhum consumidor quebrou?
177
+ - [ ] As variantes duplicadas viraram **um componente canônico** com props, e os antigos têm alias
178
+ deprecado funcionando?
179
+ - [ ] A saída tem os **três artefatos** (tokens em formato consumível, componentes canônicos, doc viva
180
+ que renderiza)?
181
+ - [ ] Cada token tem **origem rastreável** no código atual — não inventei cor/spacing "melhor" no meio?
182
+ - [ ] O usuário final **não vê diferença** depois da consolidação (migração invisível)?
183
+
184
+ ## Antes → depois
185
+
186
+ | Tell (codebase sem sistema) | Craft (consolidação) |
187
+ |---|---|
188
+ | `#3B82F6` digitado em 47 lugares + 4 variantes por erro de dígito | Um cluster perceptual → `--blue-500` primitivo → `--color-action` semântico; aliases migrados por codemod |
189
+ | `--button-blue: #3B82F6` consumido direto nos componentes | Duas camadas: componente usa `--color-action`, que aponta pro primitivo; trocar marca = um apontamento |
190
+ | `margin-top: 13px`, `padding: 18px`, `gap: 6px` (números do DevTools) | Colapsados pra escala mais próxima (`16px`/`8px`); literais fora de escala viram exceção justificada ou somem |
191
+ | `Button`, `ButtonNew`, `PrimaryButton`, `CTAButton`, `.btn-primary` | Um `<Button variant size>` (base = a de maior uso); os 4 antigos são alias `@deprecated` que ainda funcionam |
192
+ | `z-index: 9999 / 99999 / 9998` (guerra de empilhamento) | Escala semântica de camadas: `--z-dropdown: 10`, `--z-modal: 40`, `--z-toast: 60` |
193
+ | "Está tudo inconsistente" (impressão) | "Cor: 38% tokenizado, 62% solto, 89 ocorrências do azul de ação → primeira da fila" (número) |
194
+ | Entrega: um `colors.ts` com 30 hex nomeados | Entrega: tokens 2 camadas (CSS+JSON) + componentes canônicos + doc que renderiza cada token e diz quando usar |
195
+ | Find-and-replace global de `#3B82F6` → quebra o azul de um ícone de terceiro | Alias primeiro, codemod scoped por arquivo, visual regression a cada lote, migração invisível |
@@ -0,0 +1,420 @@
1
+ ---
2
+ id: intrinsic-css-layout
3
+ domain: web-craft
4
+ agents: [ux-design-expert, dev]
5
+ when: "ao montar layouts CSS resilientes e responsivos sem media queries frágeis"
6
+ ---
7
+
8
+ # Intrinsic CSS Layout — os primitives de Every Layout
9
+
10
+ Baseado em **Every Layout** (Heydon Pickering & Andy Bell). A tese central: pare de
11
+ "desenhar telas" em breakpoints fixos e passe a **compor primitivos de layout** que se adaptam
12
+ ao conteúdo e ao espaço disponível por conta própria. O navegador já sabe fazer layout — o
13
+ trabalho é **declarar restrições, não posições**. Layout intrínseco = o componente decide como
14
+ se arranjar com base no seu próprio conteúdo e no espaço do container, não em quanto mede a
15
+ viewport.
16
+
17
+ Isto casa direto com o pack `anti-ai-look`: layout editorial, ritmo de espaço com contraste e
18
+ composição que respira são justamente o que os primitives entregam **sem** cair no grid-de-3-cards
19
+ default.
20
+
21
+ ## O problema
22
+
23
+ Layout "feito por IA / por template" é, na prática, layout **extrínseco**: tudo amarrado a
24
+ breakpoints de pixel (`@media (max-width: 768px)`), larguras fixas, e o mesmo `gap-8` em tudo.
25
+ Os tells técnicos:
26
+
27
+ 1. **Media queries baseadas na viewport** para componentes que deveriam reagir ao *seu* container.
28
+ O card quebra a 768px mesmo dentro de uma sidebar de 300px — porque olha a tela, não a si mesmo.
29
+ 2. **Espaçamento aplicado item a item** (`margin-bottom` em cada elemento, ou `<br>`/divs vazias)
30
+ em vez de um ritmo declarado uma vez no container.
31
+ 3. **Larguras fixas em px** que estouram em telas estreitas ou criam linhas de texto longas demais
32
+ (medida ruim) em telas largas.
33
+ 4. **Centralização por hack** (`margin-left/right` mágicos, `position: absolute` com `left: 50%`
34
+ sem `transform`, flex aninhado desnecessário).
35
+ 5. **Grid rígido de N colunas** que precisa de media query para virar 2, depois 1 — em vez de
36
+ "encaixe quantas couberem".
37
+ 6. **Tudo no mesmo múltiplo de 8** — espaçamento uniforme, sem tensão, robótico.
38
+
39
+ A consequência: layout que parece o mesmo template em qualquer projeto, frágil em conteúdo real
40
+ (título com 1 ou 7 palavras, lista com 2 ou 40 itens) e cheio de `@media` remendado.
41
+
42
+ ## O conhecimento
43
+
44
+ ### Fundamento 1 — A "lobotomized owl" (`* + *`) para ritmo
45
+
46
+ O seletor `* + *` ("coruja lobotomizada") aplica margem **só entre** irmãos adjacentes — nunca no
47
+ primeiro nem no último. É a base do espaçamento intrínseco: você declara o ritmo **uma vez** no
48
+ container e ele vale para qualquer quantidade de filhos.
49
+
50
+ ```css
51
+ .stack > * + * {
52
+ margin-block-start: var(--space, 1.5rem);
53
+ }
54
+ ```
55
+
56
+ `margin-block-start` (não `margin-top`) respeita modo de escrita / direção. Nada de margem no
57
+ primeiro filho → sem colapso de margem indesejado com o container.
58
+
59
+ ### Fundamento 2 — Espaçamento fluido com `clamp()`
60
+
61
+ Em vez de trocar tamanhos em breakpoints, escale **continuamente** entre um mínimo e um máximo,
62
+ com a viewport como variável no meio:
63
+
64
+ ```css
65
+ :root {
66
+ /* clamp(MÍNIMO, PREFERIDO-fluido, MÁXIMO) */
67
+ --space-s: clamp(0.75rem, 0.69rem + 0.3vw, 0.94rem);
68
+ --space-m: clamp(1.13rem, 1.04rem + 0.45vw, 1.41rem);
69
+ --space-l: clamp(1.5rem, 1.38rem + 0.6vw, 1.88rem);
70
+ --space-xl: clamp(2.25rem, 2.07rem + 0.9vw, 2.81rem);
71
+
72
+ --step-0: clamp(1rem, 0.95rem + 0.25vw, 1.13rem); /* corpo */
73
+ --step-2: clamp(1.41rem, 1.24rem + 0.85vw, 1.91rem); /* h3 */
74
+ --step-4: clamp(1.95rem, 1.56rem + 1.95vw, 3.05rem); /* h1 */
75
+ }
76
+ ```
77
+
78
+ A escala fluida resolve o tell de espaçamento uniforme: defina poucos passos (`s`/`m`/`l`/`xl`)
79
+ com **contraste real** entre os extremos e use `--space` para parametrizar cada primitive.
80
+
81
+ ---
82
+
83
+ ### Os primitives
84
+
85
+ Cada primitive é uma classe utilitária componível, parametrizada por custom properties. Não há
86
+ media queries — a adaptação é intrínseca.
87
+
88
+ #### 1. Stack — ritmo vertical
89
+
90
+ Injeta espaço **entre** elementos empilhados. O bloco mais usado da web.
91
+
92
+ ```css
93
+ .stack {
94
+ display: flex;
95
+ flex-direction: column;
96
+ justify-content: flex-start;
97
+ }
98
+ .stack > * + * {
99
+ margin-block-start: var(--space, 1.5rem);
100
+ }
101
+ /* "split": empurra o que vier depois do 1º filho pro fim do container */
102
+ .stack > :nth-child(2) {
103
+ margin-block-end: auto;
104
+ }
105
+ ```
106
+
107
+ Variantes por escala e exceção local (sem reescrever o seletor):
108
+
109
+ ```css
110
+ [class^='stack'] > * { margin-block: 0; } /* reset de margens herdadas */
111
+ .stack-large > * + * { margin-block-start: 3rem; }
112
+ .stack-small > * + * { margin-block-start: 0.5rem; }
113
+
114
+ /* exceção: um espaço maior antes E depois de um elemento específico */
115
+ .stack-exception,
116
+ .stack-exception + * { --space: 3rem; }
117
+ ```
118
+
119
+ **Quando:** qualquer fluxo vertical — artigo, formulário, card. O `split` (`margin-block-end: auto`)
120
+ gruda um rodapé/CTA no fim de um card de altura variável.
121
+
122
+ #### 2. Box — a unidade com padding/borda coerentes
123
+
124
+ Caixa que **não vaza** em modo de alto contraste (a borda transparente vira visível em
125
+ `forced-colors`).
126
+
127
+ ```css
128
+ .box {
129
+ padding: var(--space, 1rem);
130
+ border: var(--border-thin, 1px) solid;
131
+ /* borda transparente vira visível em forced-colors: acessibilidade de graça */
132
+ outline: var(--border-thin, 1px) solid transparent;
133
+ outline-offset: calc(var(--border-thin, 1px) * -1);
134
+ color: var(--color-light, #fff);
135
+ background-color: var(--color-dark, #000);
136
+ }
137
+ .box * { color: inherit; }
138
+ /* inversão herda cor/fundo sem hardcode */
139
+ .box.invert {
140
+ color: var(--color-dark, #000);
141
+ background-color: var(--color-light, #fff);
142
+ }
143
+ ```
144
+
145
+ **Quando:** card, alerta, qualquer "superfície". Padding fluido via `--space`. Evite raio uniforme
146
+ em tudo (ver `anti-ai-look`): varie por propósito.
147
+
148
+ #### 3. Center — centraliza e impõe a medida (measure)
149
+
150
+ Centraliza horizontalmente **e** limita a largura da linha de texto (`measure` ~60ch para leitura
151
+ confortável). Sem container artificial.
152
+
153
+ ```css
154
+ .center {
155
+ box-sizing: content-box;
156
+ margin-inline: auto;
157
+ max-inline-size: var(--measure, 60ch);
158
+ padding-inline: var(--gutter, 1rem); /* respiro nas laterais */
159
+ }
160
+ /* variante: centraliza também filhos intrinsecamente menores que a measure */
161
+ .center-intrinsic {
162
+ display: flex;
163
+ flex-direction: column;
164
+ align-items: center;
165
+ }
166
+ ```
167
+
168
+ **Quando:** wrapper de conteúdo editorial/artigo. `--measure` controla o conforto de leitura; é
169
+ o antídoto pra linhas de 200 caracteres em telas largas.
170
+
171
+ #### 4. Cluster — agrupar coisas que quebram juntas
172
+
173
+ Para grupos de itens de tamanhos diferentes que devem **embrulhar** com espaçamento consistente:
174
+ tags, botões de ação, metadados, nav.
175
+
176
+ ```css
177
+ .cluster {
178
+ display: flex;
179
+ flex-wrap: wrap;
180
+ gap: var(--space, 1rem);
181
+ justify-content: var(--justify, flex-start);
182
+ align-items: var(--align, center);
183
+ }
184
+ ```
185
+
186
+ **Quando:** lista de tags, toolbar, grupo de botões, badges. `gap` cuida do espaço em qualquer
187
+ quebra de linha — nada de margens negativas modernas.
188
+
189
+ #### 5. Sidebar — duas colunas que viram empilhadas sozinhas (sem media query)
190
+
191
+ Conteúdo + barra lateral. A barra mantém uma largura ideal; quando o espaço aperta, **empilha
192
+ automaticamente** via `flex-wrap`. **CSS verbatim de Every Layout:**
193
+
194
+ ```css
195
+ .with-sidebar {
196
+ display: flex;
197
+ flex-wrap: wrap;
198
+ gap: 1em;
199
+ }
200
+ .sidebar {
201
+ /* a menor entre 20ch e 33.333%, nunca passando de 100% */
202
+ flex-basis: clamp(20ch, 33.333%, 100%);
203
+ flex-grow: 1;
204
+ }
205
+ .with-sidebar > :last-child {
206
+ flex-basis: 0;
207
+ flex-grow: 999; /* devora o espaço restante = vira "conteúdo principal" */
208
+ min-inline-size: 50%; /* abaixo disto, embrulha e empilha */
209
+ }
210
+ ```
211
+
212
+ **Quando:** doc + índice, produto + filtros, conteúdo + aside. O `min-inline-size: 50%` é o gatilho
213
+ de quebra — ajuste pra controlar quando empilha. Coloque a `.sidebar` antes ou depois conforme a
214
+ ordem visual desejada.
215
+
216
+ #### 6. Switcher — horizontal vira vertical num limiar de container
217
+
218
+ Alterna entre linha e coluna baseado no **container** (não na viewport). **CSS verbatim:**
219
+
220
+ ```css
221
+ .switcher {
222
+ display: flex;
223
+ flex-wrap: wrap;
224
+ gap: var(--space, 1rem);
225
+ --threshold: 30rem; /* abaixo disto, empilha */
226
+ }
227
+ .switcher > * {
228
+ flex-grow: 1;
229
+ /* o truque: valor enorme (empilha) quando container < threshold;
230
+ negativo/inválido (lado a lado) quando >= threshold */
231
+ flex-basis: calc((var(--threshold) - 100%) * 999);
232
+ }
233
+ /* quantity query: 5+ itens forçam vertical (não espreme demais) */
234
+ .switcher > :nth-last-child(n+5),
235
+ .switcher > :nth-last-child(n+5) ~ * {
236
+ flex-basis: 100%;
237
+ }
238
+ ```
239
+
240
+ **Quando:** 2–4 blocos de peso igual (features, passos, colunas de preço) que devem ir lado a lado
241
+ quando cabe e empilhar quando não. Diferente da Sidebar, aqui os itens têm **peso simétrico**.
242
+
243
+ #### 7. Cover — herói de altura mínima com conteúdo centralizado
244
+
245
+ Ocupa pelo menos a altura da viewport, centra o conteúdo principal vertical e acomoda
246
+ cabeçalho/rodapé opcionais.
247
+
248
+ ```css
249
+ .cover {
250
+ display: flex;
251
+ flex-direction: column;
252
+ min-block-size: 100vh; /* prefira 100svh em mobile p/ evitar pulo de barra */
253
+ padding: var(--space, 1rem);
254
+ }
255
+ .cover > * {
256
+ margin-block: var(--space, 1rem);
257
+ }
258
+ /* o elemento principal centraliza-se "empurrando" com auto dos dois lados */
259
+ .cover > .principal {
260
+ margin-block: auto;
261
+ }
262
+ /* header/footer colam nas pontas */
263
+ .cover > :first-child:not(.principal) { margin-block-start: 0; }
264
+ .cover > :last-child:not(.principal) { margin-block-end: 0; }
265
+ ```
266
+
267
+ **Quando:** hero de landing, splash, tela de login. Use `100svh`/`100dvh` em vez de `100vh` para
268
+ não pular com a barra do browser mobile.
269
+
270
+ #### 8. Grid — quantas colunas couberem, sem media query
271
+
272
+ O grid auto-responsivo canônico. As colunas se ajustam ao espaço; o `min()` evita estouro em telas
273
+ estreitíssimas.
274
+
275
+ ```css
276
+ .grid {
277
+ display: grid;
278
+ gap: var(--space, 1rem);
279
+ /* encaixa quantas colunas de >= --min couberem; cada uma estica até 1fr */
280
+ grid-template-columns: repeat(auto-fit, minmax(min(var(--min, 250px), 100%), 1fr));
281
+ /* alinha alturas e nivela linhas */
282
+ align-content: start;
283
+ }
284
+ ```
285
+
286
+ **Quando:** galeria, lista de cards, dashboard. `auto-fit` colapsa trilhas vazias (cards esticam pra
287
+ preencher); troque por `auto-fill` se quiser trilhas vazias preservadas. `min(var(--min), 100%)` é o
288
+ detalhe que impede a barra de rolagem horizontal em telas menores que `--min`.
289
+
290
+ #### 9. Frame — proporção fixa que recorta o conteúdo
291
+
292
+ Mantém uma razão de aspecto (16:9, 1:1) e recorta a imagem/vídeo dentro com `object-fit: cover`.
293
+
294
+ ```css
295
+ .frame {
296
+ aspect-ratio: var(--n, 16) / var(--d, 9);
297
+ overflow: hidden;
298
+ display: flex;
299
+ align-items: center;
300
+ justify-content: center;
301
+ }
302
+ .frame > img,
303
+ .frame > video {
304
+ inline-size: 100%;
305
+ block-size: 100%;
306
+ object-fit: cover;
307
+ }
308
+ ```
309
+
310
+ **Quando:** thumbnail, capa de card, embed de vídeo. `aspect-ratio` é suporte universal hoje — só
311
+ use o velho hack `padding-bottom: 56.25%` se precisar de browsers antigos.
312
+
313
+ #### 10. Reel — lista que rola na horizontal (carrossel honesto)
314
+
315
+ Rolagem horizontal com snap, sem JS. Itens mantêm largura própria e transbordam para o lado.
316
+
317
+ ```css
318
+ .reel {
319
+ display: flex;
320
+ gap: var(--space, 1rem);
321
+ overflow-x: auto;
322
+ overflow-y: hidden;
323
+ scroll-snap-type: x mandatory;
324
+ /* esconde a barra mas mantém rolagem por teclado/toque */
325
+ scrollbar-width: thin;
326
+ overscroll-behavior-inline: contain;
327
+ }
328
+ .reel > * {
329
+ flex: 0 0 var(--item-width, auto); /* não encolhe: preserva largura */
330
+ scroll-snap-align: start;
331
+ }
332
+ .reel > img { block-size: 100%; flex-basis: auto; width: auto; }
333
+ ```
334
+
335
+ **Quando:** galeria horizontal, "continue assistindo", chips roláveis. Garanta foco/teclado e
336
+ respeite `prefers-reduced-motion` ao animar o scroll.
337
+
338
+ #### 11. Imposter — sobrepor e centralizar sobre outro elemento
339
+
340
+ Centraliza um elemento sobre o pai (modal, badge, "esgotado" sobre um produto).
341
+
342
+ ```css
343
+ .imposter {
344
+ position: absolute;
345
+ inset-block-start: 50%;
346
+ inset-inline-start: 50%;
347
+ transform: translate(-50%, -50%);
348
+ }
349
+ /* variante "contida": nunca ultrapassa o pai, rola se for grande */
350
+ .imposter.contain {
351
+ --margin: 0px;
352
+ overflow: auto;
353
+ max-inline-size: calc(100% - (var(--margin, 0px) * 2));
354
+ max-block-size: calc(100% - (var(--margin, 0px) * 2));
355
+ }
356
+ ```
357
+
358
+ O pai precisa de `position: relative`. **Quando:** modal/dialog centralizado, selo sobre imagem,
359
+ tooltip. Para conteúdo realmente modal, prefira o elemento `<dialog>` nativo; o Imposter é pra
360
+ sobreposição puramente visual.
361
+
362
+ ### Composição — o todo é maior que as partes
363
+
364
+ O ganho real é **aninhar** primitives, cada um cuidando de uma dimensão:
365
+
366
+ ```html
367
+ <!-- Center impõe a measure → Stack dá ritmo vertical → Grid encaixa os cards -->
368
+ <div class="center" style="--measure: 70ch;">
369
+ <div class="stack" style="--space: var(--space-xl);">
370
+ <h1>Manifesto</h1>
371
+ <p>…</p>
372
+ <div class="grid" style="--min: 18rem; --space: var(--space-l);">
373
+ <article class="box stack">…</article>
374
+ <article class="box stack">…</article>
375
+ </div>
376
+ </div>
377
+ </div>
378
+ ```
379
+
380
+ Nenhuma media query. Cada primitive resolve uma responsabilidade; o conteúdo dita a quebra. Use o
381
+ **contraste de `--space`** entre seções (uma `--space-xl`, outra `--space-s`) para criar o ritmo
382
+ editorial que o pack `anti-ai-look` exige — em vez do `gap-8` uniforme.
383
+
384
+ ## Checklist
385
+
386
+ Antes de entregar um layout, qualquer "não" é um remendo a corrigir:
387
+
388
+ - [ ] O espaçamento vertical vem de **um** `* + *` no container, não de margens item a item?
389
+ - [ ] Há **zero** media queries de viewport para coisas que deveriam reagir ao container (usou
390
+ Sidebar/Switcher/Grid intrínsecos)?
391
+ - [ ] O wrapper de leitura tem `max-inline-size` em `ch` (measure ~60–70ch), não largura em px?
392
+ - [ ] O grid usa `repeat(auto-fit, minmax(min(--min, 100%), 1fr))` — encaixa o que cabe sozinho?
393
+ - [ ] Usei `clamp()` para espaço/tipografia fluida em vez de trocar valores em breakpoints?
394
+ - [ ] As propriedades são lógicas (`margin-block`, `inline-size`, `inset-inline`) e não físicas?
395
+ - [ ] As seções têm **contraste de `--space`** (ritmo), não todas no mesmo múltiplo?
396
+ - [ ] Cover usa `100svh`/`100dvh` (não `100vh`) pra não pular em mobile?
397
+ - [ ] Reel respeita teclado/foco e `prefers-reduced-motion`?
398
+ - [ ] Box mantém a borda transparente via `outline` pra sobreviver a `forced-colors`?
399
+
400
+ ## Tabela de decisão
401
+
402
+ | Preciso de… | Primitive | Parâmetro-chave |
403
+ |---|---|---|
404
+ | Ritmo entre elementos empilhados | **Stack** | `--space` (use a escala fluida) |
405
+ | Card / superfície com padding e borda coerentes | **Box** | `--space`, `.invert` |
406
+ | Limitar largura de leitura e centralizar | **Center** | `--measure` (~60–70ch) |
407
+ | Agrupar tags/botões que quebram juntos | **Cluster** | `--space`, `--justify` |
408
+ | Conteúdo + barra lateral que empilha sozinha | **Sidebar** | `flex-basis: clamp(...)`, `min-inline-size` |
409
+ | 2–4 blocos simétricos: lado a lado ou empilhados | **Switcher** | `--threshold` (30rem), quantity query |
410
+ | Hero de altura mínima com conteúdo centrado | **Cover** | `min-block-size: 100svh`, `margin-block: auto` |
411
+ | "Quantas colunas couberem" sem media query | **Grid** | `--min`, `auto-fit`/`auto-fill` |
412
+ | Proporção fixa recortando imagem/vídeo | **Frame** | `aspect-ratio`, `object-fit: cover` |
413
+ | Lista que rola na horizontal (carrossel) | **Reel** | `overflow-x: auto`, `scroll-snap` |
414
+ | Sobrepor/centralizar sobre outro elemento | **Imposter** | `position: absolute` + `translate(-50%,-50%)` |
415
+
416
+ **Sidebar vs Switcher:** Sidebar = pesos **assimétricos** (uma coluna fina fixa, uma elástica).
417
+ Switcher = pesos **simétricos** (todos iguais), tudo lado a lado ou tudo empilhado.
418
+
419
+ **`auto-fit` vs `auto-fill` no Grid:** `auto-fit` colapsa trilhas vazias e estica os itens
420
+ existentes; `auto-fill` mantém trilhas vazias (itens não esticam pra preencher sozinhos).