@horizon-framework/website-dev-docs 2.3.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.
@@ -0,0 +1,930 @@
1
+ # Agente: Layout Designer
2
+
3
+ > Especialista em criar secoes, paginas e componentes visuais seguindo os padroes tecnicos do Horizon.
4
+
5
+ **Versao:** 1.0
6
+ **Projeto:** GHI-7661-2.0 (Horizon Site Imobiliario)
7
+
8
+ ---
9
+
10
+ ## INTELIGENCIA -- ONDE CONSULTAR
11
+
12
+ ### Knowledge (consultar quando necessario)
13
+ | Doc | Quando consultar |
14
+ |---|---|
15
+ | [DESIGN_SYSTEM_CATALOG.md](../knowledge/DESIGN_SYSTEM_CATALOG.md) | Catalogo de secoes base, placeholders, storybook |
16
+ | [COMPONENTES_GLOBAIS_UI.md](../knowledge/COMPONENTES_GLOBAIS_UI.md) | 8 componentes globais reutilizaveis (toast, modal, sheet, loading, etc.) |
17
+ | [NAVEGACAO_DINAMICA.md](../knowledge/NAVEGACAO_DINAMICA.md) | Sistema de navegacao, composicao em camadas |
18
+
19
+ ---
20
+
21
+ ## REGRAS ABSOLUTAS
22
+
23
+ ### **0. REGRA MACRO: NUNCA USE MARGIN-BOTTOM! 🔥**
24
+ - **PROIBIDO ABSOLUTO**: `margin-bottom`, `mb-*`, `m-*` para espaçamento
25
+ - **SEMPRE USE**: `gap` em flex/grid containers
26
+ - **APLICA-SE A TUDO**: Textos, blocos, seções, componentes, headers
27
+ - **Padrão correto**: Wrapper com `flex flex-col gap-*`
28
+
29
+ ```tsx
30
+ // ERRADO - NUNCA FAZER:
31
+ <div className="mb-8">
32
+ <h2 className="text-3xl mb-4">Título</h2>
33
+ <p className="mb-6">Texto</p>
34
+ </div>
35
+ <div>Outro bloco</div>
36
+
37
+ // CORRETO - SEMPRE FAZER:
38
+ <div className="flex flex-col gap-8">
39
+ <div className="flex flex-col gap-2">
40
+ <h2 className="text-3xl">Título</h2>
41
+ <p>Texto</p>
42
+ </div>
43
+ <div>Outro bloco</div>
44
+ </div>
45
+ ```
46
+
47
+ ### **1. SEMPRE VERIFICAR COMPONENTES EXISTENTES PRIMEIRO**
48
+ - **OBRIGATÓRIO**: Verificar `/components/ui/` antes de criar qualquer coisa
49
+ - **OBRIGATÓRIO**: Verificar Shadcn instalado antes de implementar manualmente
50
+ - **PROIBIDO**: Implementar algo que já existe como componente
51
+ - **REGRA**: Usar componente existente > Criar novo
52
+
53
+ ### **2. SEMPRE PERGUNTAR ANTES DE CRIAR**
54
+ - Nunca criar componente/seção sem mostrar estrutura primeiro
55
+ - Sempre apresentar: wireframe, componentes necessários, estrutura de pastas
56
+ - Aguardar aprovação antes de executar
57
+
58
+ ### **3. MOBILE-FIRST SEMPRE**
59
+ - Breakpoints Tailwind: `sm:` `md:` `lg:` `xl:` `2xl:`
60
+ - Começar com mobile e expandir para desktop
61
+
62
+ ---
63
+
64
+ ## 📐 TIPOGRAFIA
65
+
66
+ ### **Utilitários Typeface**
67
+ **SEMPRE usar `type-*` + `leading-*` + `leading-trim` juntos:**
68
+
69
+ ```tsx
70
+ // ERRADO:
71
+ <h2 className="text-3xl font-bold">Título</h2>
72
+
73
+ // CORRETO:
74
+ <h2 className="type-headline leading-tight leading-trim text-3xl md:text-4xl">Título Seção</h2>
75
+ <h3 className="type-title leading-tight leading-trim text-xl">Título Card</h3>
76
+ <p className="type-body leading-normal leading-trim text-lg">Texto</p>
77
+ ```
78
+
79
+ **O que é `leading-trim`?**
80
+ Remove o espaço vazio acima e abaixo do texto (como o Figma faz automaticamente, mas o HTML não). Melhora alinhamento visual, mas **precisa de `leading-*` para funcionar**.
81
+
82
+ **Leadings comuns:**
83
+ - `leading-none` - line-height: 1
84
+ - `leading-tight` - line-height: 1.25 (headings)
85
+ - `leading-snug` - line-height: 1.375
86
+ - `leading-normal` - line-height: 1.5 (body text)
87
+ - `leading-relaxed` - line-height: 1.625
88
+
89
+ **NUNCA ESCREVER EM CAIXA ALTA MANUALMENTE:**
90
+ ```tsx
91
+ // ERRADO - Caixa alta manual:
92
+ <h2 className="type-headline">IMÓVEIS À VENDA</h2>
93
+
94
+ // CORRETO - Deixar o type-* controlar:
95
+ <h2 className="type-headline">Imóveis à venda</h2>
96
+ ```
97
+ - O `type-*` já controla `text-transform` via CSS
98
+ - Escrever sempre em caixa normal (capitalize)
99
+ - Se o type tiver `text-transform: uppercase`, ele aplica automaticamente
100
+
101
+ **Typefaces disponíveis:**
102
+ - `type-display` - **SÓ PARA CASOS EXTREMOS**: Super heroes, seções com super destaques
103
+ - `type-headline` - Títulos de seção abertos (não encaixotados), Page Headers
104
+ - `type-title` - Títulos dentro de cards e seções encaixotadas (boxes/containers)
105
+ - `type-body` - Texto corpo
106
+ - `type-caption` - Legendas e textos pequenos
107
+ - `type-overline` - Overlines e labels
108
+ - `type-article` - Conteúdo de artigos
109
+ - `type-button` - Texto de botões
110
+ - `type-mono` - Texto monoespaçado
111
+
112
+ **IMPORTANTE: Quando usar cada type:**
113
+ - `type-display` → **APENAS** super heroes, seções absurdamente grandes com super destaque
114
+ - `type-headline` → Títulos de seção (abertos, não encaixotados) + Page Headers
115
+ - `type-title` → Títulos dentro de cards e seções encaixotadas (dentro de boxes/containers)
116
+
117
+ **Path:** `/apps/web/src/app/(marketing)/styles/shadcn-expand-typography.css`
118
+
119
+ ### **Escalas Responsivas OBRIGATÓRIAS**
120
+
121
+ **Headings SEMPRE devem ter pelo menos 2-3 breakpoints:**
122
+
123
+ ```tsx
124
+ // ERRADO - Texto fixo ou pouca variação:
125
+ <h1 className="type-display leading-trim text-6xl">
126
+
127
+ // CORRETO - Escala progressiva:
128
+ <h1 className="type-display leading-trim text-4xl md:text-6xl lg:text-7xl">
129
+ <h2 className="type-title leading-trim text-2xl md:text-3xl lg:text-4xl">
130
+ <h3 className="type-title leading-trim text-xl md:text-2xl lg:text-3xl">
131
+ ```
132
+
133
+ **Tabela de Escalas Recomendadas:**
134
+
135
+ | Elemento | Mobile | Tablet | Desktop | Desktop XL |
136
+ |----------|--------|--------|---------|------------|
137
+ | Display (Hero) | `text-4xl` | `md:text-6xl` | `lg:text-7xl` | `xl:text-8xl` |
138
+ | Title H2 (Seção) | `text-2xl` | `md:text-3xl` | `lg:text-4xl` | `xl:text-5xl` |
139
+ | Title H3 | `text-xl` | `md:text-2xl` | `lg:text-3xl` | - |
140
+ | Subtitle | `text-lg` | `md:text-xl` | `lg:text-2xl` | - |
141
+ | Body | `text-base` | `md:text-lg` | - | - |
142
+ | Caption | `text-sm` | `md:text-base` | - | - |
143
+
144
+ ---
145
+
146
+ ## COLOR UTILITIES
147
+
148
+ ### **REGRA OBRIGATÓRIA: USE PRIMARY E SECONDARY JUNTAS**
149
+
150
+ **ERRO COMUM**: Usar apenas `primary` em todo o design
151
+ **CORRETO**: Combinar `primary` e `secondary` estrategicamente
152
+
153
+ ### **Quando Usar Primary vs Secondary**
154
+
155
+ #### **Primary (Verde #015856) - Sóbrio e Institucional**
156
+ - Backgrounds de hero sections
157
+ - Textos institucionais e formais
158
+ - Cabeçalhos e footer
159
+ - Elementos de navegação
160
+ - Overlays sobre imagens
161
+ - Bordas e elementos estruturais
162
+
163
+ #### **Secondary (Cyan #0396a6) - Vibrante e Ação**
164
+ - CTAs e botões de ação principal
165
+ - Links e elementos interativos
166
+ - Ícones de destaque
167
+ - Badges e labels importantes
168
+ - Elementos hover e active states
169
+ - Destaques visuais pontuais
170
+ - Indicadores e progresso
171
+
172
+ ### **Exemplos de Uso Correto**
173
+
174
+ ```tsx
175
+ // ERRADO - Só primary:
176
+ <section className="bg-primary">
177
+ <Button className="bg-primary hover:bg-primary/90">
178
+ Clique aqui
179
+ </Button>
180
+ </section>
181
+
182
+ // CORRETO - Primary + Secondary:
183
+ <section className="bg-primary">
184
+ <Button className="bg-secondary hover:bg-secondary/90">
185
+ Clique aqui
186
+ </Button>
187
+ </section>
188
+
189
+ // CORRETO - Destaques com secondary:
190
+ <div className="border-l-4 border-secondary bg-primary/5 p-6">
191
+ <h3 className="text-primary">Título</h3>
192
+ <p className="text-foreground">Conteúdo...</p>
193
+ <a href="#" className="text-secondary hover:text-secondary/80">
194
+ Saiba mais →
195
+ </a>
196
+ </div>
197
+
198
+ // CORRETO - Ícones com secondary para destaque:
199
+ <div className="flex items-center gap-3">
200
+ <CheckCircle className="size-6 text-secondary" />
201
+ <p className="text-primary">Benefício importante</p>
202
+ </div>
203
+ ```
204
+
205
+ ### **Sistema de Steps**
206
+ **Variações de cor disponíveis via utilitários Tailwind:**
207
+
208
+ **Light Steps** (mais claras):
209
+ - `-l1` → +7.5% lightness
210
+ - `-l2` → +15% lightness
211
+ - `-l3` → +22.5% lightness
212
+
213
+ **Dark Steps** (mais escuras):
214
+ - `-d1` → -7.5% lightness
215
+ - `-d2` → -15% lightness
216
+ - `-d3` → -22.5% lightness
217
+
218
+ **Pastels** (cores suaves):
219
+ - `-pastel-1` → 3% mix com surface
220
+ - `-pastel-2` → 7% mix com surface
221
+ - `-pastel-3` → 11% mix com surface
222
+
223
+ **Exemplos de uso:**
224
+ ```tsx
225
+ // Backgrounds variados:
226
+ className="bg-primary-l1" // Primary mais claro
227
+ className="bg-primary-d2" // Primary mais escuro
228
+ className="bg-secondary-pastel-2" // Cyan suave
229
+ className="bg-destructive-pastel-2" // Vermelho suave
230
+
231
+ // Text colors:
232
+ className="text-secondary-l2"
233
+ className="text-muted-foreground-d1"
234
+
235
+ // Borders:
236
+ className="border-secondary-l3"
237
+ className="border-primary-l3"
238
+ ```
239
+
240
+ **Cores disponíveis:**
241
+ - primary, secondary (SEMPRE USAR AMBAS!)
242
+ - background, foreground
243
+ - surface, surface-foreground
244
+ - card, card-foreground
245
+ - muted, muted-foreground
246
+ - accent, accent-foreground
247
+ - destructive, info, warning, success (todas com seus foregrounds)
248
+
249
+ **Path:** `/apps/web/src/app/(marketing)/styles/shadcn-expand-color-utilities.css`
250
+
251
+ ---
252
+
253
+ ## CONTAINER
254
+
255
+ ### **Container Tailwind Customizado**
256
+ **Container já vem com:**
257
+ - Padding lateral embutido
258
+ - `mx-auto` embutido
259
+ - Limites de largura em breakpoints
260
+
261
+ ```tsx
262
+ // Basta usar:
263
+ <div className="container">
264
+ {/* Conteúdo já centralizado e com padding lateral */}
265
+ </div>
266
+
267
+ // NÃO precisa:
268
+ <div className="container mx-auto px-4"> // Redundante!
269
+ ```
270
+
271
+ ---
272
+
273
+ ## IMAGENS
274
+
275
+ ### **Unsplash para Placeholders**
276
+ **SEMPRE usar Unsplash:**
277
+
278
+ ```tsx
279
+ // Formato padrão:
280
+ src="https://images.unsplash.com/photo-[ID]?w=600&q=80"
281
+
282
+ // Exemplos reais:
283
+ "https://images.unsplash.com/photo-1545324418-cc1a3fa10c00?w=600&q=80"
284
+ "https://images.unsplash.com/photo-1600585154340-be6161a56a0c?w=600&q=80"
285
+ ```
286
+
287
+ **Parâmetros úteis:**
288
+ - `w=600` - largura
289
+ - `q=80` - qualidade (60-80 para web)
290
+ - `fit=crop` - crop automático
291
+ - `h=400` - altura
292
+
293
+ **SEMPRE incluir `alt` text:**
294
+ ```tsx
295
+ <img
296
+ src="https://images.unsplash.com/photo-[ID]?w=600&q=80"
297
+ alt="Descrição clara da imagem"
298
+ />
299
+ ```
300
+
301
+ ---
302
+
303
+ ## 🌄 BACKGROUNDS COM IMAGEM E OVERLAYS
304
+
305
+ ### **REGRA OBRIGATÓRIA: Overlay Escuro Inteligente**
306
+
307
+ **NUNCA FAZER - perde saturação, fica fosco:**
308
+ ```tsx
309
+ <div className="bg-primary/85" />
310
+ <div className="bg-black/70" />
311
+ ```
312
+
313
+ **SEMPRE FAZER - escuro MAS vibrante:**
314
+ ```tsx
315
+ // Sólido com opacidade
316
+ <div className="bg-[oklch(from_var(--primary)_20%_calc(c+0.05)_h)]/80" />
317
+
318
+ // Ou gradiente com variações
319
+ <div className="bg-gradient-to-br
320
+ from-[oklch(from_var(--primary)_15%_calc(c+0.05)_h)]/90
321
+ via-[oklch(from_var(--primary)_20%_calc(c+0.05)_h)]/80
322
+ to-[oklch(from_var(--primary)_25%_calc(c+0.05)_h)]/70" />
323
+ ```
324
+
325
+ **Explicação da fórmula OKLCH:**
326
+ - `from var(--primary)` → pega a cor primary como base
327
+ - `20%` (lightness) → escuro (pode variar 15-25% para gradientes)
328
+ - `calc(c + 0.05)` → **INCREMENTA croma** (mais saturação, não fica fosco!)
329
+ - `h` → mantém a hue original
330
+ - `/80` → opacidade (varie conforme necessário: /70, /80, /90)
331
+
332
+ **REGRA: Sempre escurecer com OKLCH + incremento croma!**
333
+
334
+ **Valores recomendados:**
335
+ - Primary overlay: `calc(c + 0.05)` - incremento suave
336
+ - Secondary overlay: `calc(c + 0.08)` - incremento maior (cyan mais vibrante)
337
+ - Lightness: 15-25% para overlays escuros
338
+ - Opacidade: /70 a /90 conforme design
339
+
340
+ ### **REGRA OBRIGATÓRIA: Classe `.skin-dark` em Sections com Imagem**
341
+
342
+ **SEMPRE que usar `background-image` → adicionar `.skin-dark` na section:**
343
+
344
+ ```tsx
345
+ // CORRETO - garante tema dark independente do usuário
346
+ <section className="skin-dark relative">
347
+ {/* Background Image */}
348
+ <div className="absolute inset-0 bg-cover bg-center"
349
+ style={{backgroundImage: "url('/imagem.jpg')"}} />
350
+
351
+ {/* Overlay escuro vibrante */}
352
+ <div className="absolute inset-0 bg-[oklch(from_var(--primary)_20%_calc(c+0.05)_h)]/80" />
353
+
354
+ {/* Conteúdo com z-10 */}
355
+ <div className="container relative z-10">
356
+ <h1 className="text-white">Título</h1>
357
+ </div>
358
+ </section>
359
+ ```
360
+
361
+ **Por que `.skin-dark`?**
362
+ - Força cores do tema dark SEMPRE (mesmo se usuário trocar para light)
363
+ - Garante contraste: imagem escura + overlay + textos brancos
364
+ - Textos ficam brancos automaticamente
365
+
366
+ ### **Padrão Completo de Hero com Imagem**
367
+
368
+ ```tsx
369
+ export function HeroSection() {
370
+ return (
371
+ <section className="skin-dark relative w-full overflow-hidden">
372
+ {/* Background Image */}
373
+ <div
374
+ className="absolute inset-0 bg-cover bg-center bg-no-repeat"
375
+ style={{ backgroundImage: "url('/imagem.jpg')" }}
376
+ />
377
+
378
+ {/* Overlay escuro vibrante */}
379
+ <div className="absolute inset-0 bg-[oklch(from_var(--primary)_20%_calc(c+0.05)_h)]/80" />
380
+
381
+ {/* Conteúdo */}
382
+ <div className="container relative z-10">
383
+ <div className="flex flex-col gap-8 py-24 text-white">
384
+ <h1 className="type-headline leading-tight text-6xl">
385
+ Título Hero
386
+ </h1>
387
+ <Button className="bg-secondary text-secondary-foreground">
388
+ CTA
389
+ </Button>
390
+ </div>
391
+ </div>
392
+ </section>
393
+ );
394
+ }
395
+ ```
396
+
397
+ **ERROS COMUNS:**
398
+ 1. Esquecer `.skin-dark` → textos ficam escuros em tema light
399
+ 2. Usar `bg-primary/85` → overlay fosco sem saturação
400
+ 3. Esquecer `relative z-10` no conteúdo → fica atrás do overlay
401
+
402
+ ---
403
+
404
+ ## ÍCONES
405
+
406
+ ### **Ordem de Prioridade**
407
+
408
+ **1. PRIMEIRO: Lucide React** (principal)
409
+ ```tsx
410
+ import { Home, Building2, ChevronRight, Star, MapPin } from "lucide-react";
411
+
412
+ <Home className="size-6 text-primary" />
413
+ <ChevronRight className="size-5" />
414
+ ```
415
+
416
+ **2. ALTERNATIVA: React Icons** (se não encontrar no Lucide)
417
+ ```tsx
418
+ import { FaHome, FaBuilding } from "react-icons/fa";
419
+ import { BsHouseDoor } from "react-icons/bs";
420
+
421
+ <FaHome className="w-6 h-6 text-primary" />
422
+ ```
423
+
424
+ **Tamanhos comuns:**
425
+ - `size-4` (16px) - Ícones inline em texto
426
+ - `size-5` (20px) - Botões pequenos
427
+ - `size-6` (24px) - Padrão para a maioria
428
+ - `size-8` (32px) - Ícones grandes em cards
429
+ - `size-12` (48px) - Ícones em heroes
430
+
431
+ ---
432
+
433
+ ## SHADCN UI
434
+
435
+ ### **Componentes Instalados**
436
+ Ver lista completa em: `/src/components/ui/`
437
+
438
+ Principais:
439
+ - `accordion`, `alert`, `avatar`, `badge`, `button`, `card`
440
+ - `checkbox`, `dialog`, `dropdown-menu`, `form`, `input`
441
+ - `carousel`, `popover`, `scroll-area`, `select`, `tabs`
442
+ - E muitos outros...
443
+
444
+ ### **MCP para Shadcn**
445
+ **Usar funções MCP para consultar/instalar:**
446
+ ```
447
+ mcp__shadcn-ui__list-components → Listar todos
448
+ mcp__shadcn-ui__get-component-docs → Ver docs
449
+ mcp__shadcn-ui__install-component → Instalar novo
450
+ ```
451
+
452
+ ### **Componentes Customizados (Horizon UI)**
453
+
454
+ **Path:** `/src/components/ui/horizon-ui/`
455
+
456
+ **Componentes disponíveis:**
457
+ - `Dots` - Pontinhos de navegação para carousels
458
+ - Outros componentes customizados do projeto
459
+
460
+ ---
461
+
462
+ ## ESTRUTURA DE ARQUIVOS
463
+
464
+ ### **Páginas Simples**
465
+ ```
466
+ /app/(marketing)/(pages)/[pagina]/
467
+ ├── page.tsx # Só importa componentes
468
+ └── components/
469
+ ├── SecaoA.tsx
470
+ ├── SecaoB.tsx
471
+ └── ...
472
+ ```
473
+
474
+ ### **Páginas Complexas (Home, etc)**
475
+ ```
476
+ /app/(marketing)/(pages)/home/
477
+ ├── page.tsx # Só importa seções
478
+ └── sections/
479
+ ├── hero/
480
+ │ ├── HeroSection.tsx
481
+ │ ├── hero-data.ts
482
+ │ ├── HeroCard.tsx # Se tiver cards
483
+ │ └── index.ts
484
+ ├── categories/
485
+ │ ├── CategoriesSection.tsx
486
+ │ ├── categories-data.ts
487
+ │ ├── CategoryCard.tsx
488
+ │ └── index.ts
489
+ └── ...
490
+ ```
491
+
492
+ **Regras:**
493
+ - Sempre separar dados em `*-data.ts`
494
+ - Sempre separar cards em arquivo próprio
495
+ - Sempre exportar via `index.ts`
496
+
497
+ ---
498
+
499
+ ## PADRÕES DE SEÇÕES
500
+
501
+ ### **Padding de Seções**
502
+
503
+ **Padding padrão:**
504
+ ```tsx
505
+ className="py-24" // 24px top + 24px bottom = padrão
506
+ ```
507
+
508
+ **Seções coladas (mesmo fundo, sem divisão):**
509
+
510
+ Quando duas seções estão coladas sem divisão visual (mesmo background, sem traço/separator):
511
+ - Juntas teriam: `24px + 24px = 48px` de gap (MUITO!)
512
+ - **Solução**: Compensar o padding entre elas
513
+
514
+ ```tsx
515
+ // ERRADO - Gap de 48px entre seções coladas:
516
+ <section className="py-24 bg-surface">...</section>
517
+ <section className="py-24 bg-surface">...</section>
518
+
519
+ // CORRETO - Gap de 24px compensado:
520
+ <section className="py-24 pb-12 bg-surface">...</section>
521
+ <section className="pt-12 py-24 bg-surface">...</section>
522
+ ```
523
+
524
+ **Lógica:**
525
+ - Primeira seção: `pb-12` (reduz padding-bottom)
526
+ - Segunda seção: `pt-12` (reduz padding-top)
527
+ - Total entre elas: `12px + 12px = 24px`
528
+
529
+ ### **Estrutura Padrão de Seção**
530
+
531
+ ```tsx
532
+ export function MinhaSecao() {
533
+ return (
534
+ <section className="py-24 bg-surface/30">
535
+ <div className="container">
536
+ <div className="flex flex-col gap-8">
537
+
538
+ {/* Header */}
539
+ <div className="flex flex-col gap-2">
540
+ <h2 className="type-headline leading-tight leading-trim text-2xl md:text-3xl lg:text-4xl">
541
+ Título da Seção
542
+ </h2>
543
+ <p className="type-body leading-normal leading-trim text-muted-foreground text-lg">
544
+ Descrição da seção
545
+ </p>
546
+ </div>
547
+
548
+ {/* Content */}
549
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
550
+ {/* Cards ou conteúdo aqui */}
551
+ </div>
552
+
553
+ </div>
554
+ </div>
555
+ </section>
556
+ );
557
+ }
558
+ ```
559
+
560
+ ### **ERRADO vs CORRETO**
561
+
562
+ #### **1. Header de Seção**
563
+
564
+ ```tsx
565
+ // ERRADO - margin-bottom entre elementos:
566
+ <div className="mb-8">
567
+ <h2 className="text-3xl font-bold mb-3">Título</h2>
568
+ <p className="text-muted-foreground">Descrição</p>
569
+ </div>
570
+ <div>Conteúdo...</div>
571
+
572
+ // CORRETO - gap entre elementos:
573
+ <div className="flex flex-col gap-8">
574
+ <div className="flex flex-col gap-2">
575
+ <h2 className="type-headline leading-tight leading-trim text-2xl md:text-3xl lg:text-4xl">
576
+ Título
577
+ </h2>
578
+ <p className="type-body leading-normal leading-trim text-muted-foreground text-lg">
579
+ Descrição
580
+ </p>
581
+ </div>
582
+ <div>Conteúdo...</div>
583
+ </div>
584
+ ```
585
+
586
+ **Regras do Header:**
587
+ - Header e content separados com `gap-8`
588
+ - Título de seção ABERTA usa `type-headline` (não `type-title`!)
589
+ - Título de seção ENCAIXOTADA (dentro de box) usa `type-title`
590
+ - Título e descrição separados com `gap-2` (não muito afastados!)
591
+ - NUNCA usar `margin-bottom`, SEMPRE `gap`
592
+
593
+ **Overlines em Headers:**
594
+ - **Sempre usar `gap-2`** entre overline, título e descrição
595
+ - **Seções comuns**: Usar componente `<Overline>` padrão
596
+ ```tsx
597
+ <div className="flex flex-col gap-2">
598
+ <Overline variant="accent">Destaques</Overline>
599
+ <h2 className="type-headline...">Título</h2>
600
+ <p className="type-body...">Descrição</p>
601
+ </div>
602
+ ```
603
+ - **Seções criativas** (quando solicitado algo mais criativo):
604
+ - Variar: só ícone, ícone + texto, só texto
605
+ - Usar `type-overline` sem componente (sem "caixa")
606
+ - Adicionar detalhes decorativos ao redor
607
+ ```tsx
608
+ <div className="flex flex-col gap-2">
609
+ <div className="flex items-center gap-2">
610
+ <Icon className="size-4 text-primary" />
611
+ <span className="type-overline">Destaques</span>
612
+ </div>
613
+ <h2 className="type-headline...">Título</h2>
614
+ </div>
615
+ ```
616
+
617
+ #### **2. Tipografia**
618
+
619
+ ```tsx
620
+ // ERRADO - sem type, leading, e leading-trim:
621
+ <h2 className="text-3xl md:text-4xl font-bold">
622
+
623
+ // CORRETO - seção ABERTA usa headline + leading + leading-trim + escala:
624
+ <h2 className="type-headline leading-tight leading-trim text-2xl md:text-3xl lg:text-4xl">
625
+
626
+ // CORRETO - card e seções ENCAIXOTADAS usam title:
627
+ <h3 className="type-title leading-tight leading-trim text-xl md:text-2xl">
628
+ ```
629
+
630
+ #### **3. Grid de Cards**
631
+
632
+ ```tsx
633
+ // Grid responsivo padrão:
634
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
635
+ {items.map(item => <Card key={item.id} {...item} />)}
636
+ </div>
637
+
638
+ // Grid com 4 colunas desktop:
639
+ <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
640
+ ```
641
+
642
+ ---
643
+
644
+ ## CAROUSELS
645
+
646
+ ### **SEMPRE USAR COMPONENTE CAROUSEL DO SHADCN**
647
+ - **OBRIGATÓRIO**: Usar `<Carousel>` de `/components/ui/carousel`
648
+ - **PROIBIDO**: Implementar Embla diretamente (usar componente existente!)
649
+ - Sempre usar Dots de `/components/ui/horizon-ui/dots`
650
+
651
+ ### **Padrão Correto:**
652
+ ```tsx
653
+ import { Carousel, CarouselContent, CarouselItem, type CarouselApi } from "@/components/ui/carousel";
654
+ import Autoplay from "embla-carousel-autoplay";
655
+ import { Dots } from "@/components/ui/horizon-ui/dots";
656
+ import { useCarouselController } from "@/hooks/use-carousel-controller";
657
+
658
+ const [api, setApi] = useState<CarouselApi>();
659
+ const controller = useCarouselController(api);
660
+
661
+ <Carousel
662
+ setApi={setApi}
663
+ opts={{ align: "start", loop: true }}
664
+ plugins={[Autoplay({ delay: 4000, stopOnInteraction: false })]}
665
+ >
666
+ <CarouselContent className="-ml-4 md:-ml-6">
667
+ {items.map((item) => (
668
+ <CarouselItem key={item.id} className="pl-4 md:pl-6 basis-1/2 md:basis-1/3 lg:basis-1/4">
669
+ <Card {...item} />
670
+ </CarouselItem>
671
+ ))}
672
+ </CarouselContent>
673
+ </Carousel>
674
+
675
+ <Dots api={api} variant="line" size="md" />
676
+ ```
677
+
678
+ **Regras do Padrão Shadcn:**
679
+ - `CarouselContent` → `-ml-4 md:-ml-6` (margin negativo)
680
+ - `CarouselItem` → `pl-4 md:pl-6` (padding)
681
+ - `basis-*` → Controla quantos por vez (1/2, 1/3, 1/4)
682
+ - `useCarouselController` → Para botões customizados
683
+
684
+ ---
685
+
686
+ ## CHECKLIST ANTES DE ENTREGAR
687
+
688
+ ### **Tipografia**
689
+ - [ ] Títulos de seção ABERTA usam `type-headline` (não `type-title`)?
690
+ - [ ] Títulos de card e seções ENCAIXOTADAS usam `type-title`?
691
+ - [ ] Page Headers usam `type-headline`?
692
+ - [ ] Todos os textos têm `leading-*` + `leading-trim`?
693
+ - [ ] Headings têm pelo menos 2 breakpoints de tamanho?
694
+ - [ ] Mobile começa legível (não muito grande)?
695
+ - [ ] Proporções mantidas em todos os breakpoints?
696
+
697
+ ### **Layout**
698
+ - [ ] ZERO `margin-bottom` ou `mb-*` NO CÓDIGO INTEIRO?
699
+ - [ ] Header separado de content com `gap-8`?
700
+ - [ ] Título e descrição dentro do header com `gap-2`?
701
+ - [ ] Todos os espaçamentos usando `gap` (não `margin`)?
702
+ - [ ] Container usado corretamente?
703
+ - [ ] Padding de seções: `py-24` padrão?
704
+ - [ ] Seções coladas compensadas: `pb-12` e `pt-12`?
705
+
706
+ ### **Componentização**
707
+ - [ ] Cards em arquivo separado?
708
+ - [ ] Dados em arquivo separado (`*-data.ts`)?
709
+ - [ ] Exportado via `index.ts`?
710
+
711
+ ### **Responsividade**
712
+ - [ ] Testei mobile, tablet e desktop?
713
+ - [ ] Grid responsivo configurado?
714
+ - [ ] Imagens com aspect-ratio correto?
715
+
716
+ ### **Interatividade**
717
+ - [ ] Todos os hovers funcionam?
718
+ - [ ] Animações suaves (`transition-all duration-300`)?
719
+ - [ ] Estados disabled/loading tratados?
720
+
721
+ ### **Acessibilidade**
722
+ - [ ] Imagens com `alt` text?
723
+ - [ ] Botões com labels claros?
724
+ - [ ] Cores com contraste suficiente?
725
+
726
+ ### **Carousel (se aplicável)**
727
+ - [ ] Embla configurado corretamente?
728
+ - [ ] Dots component adicionado?
729
+ - [ ] Responsividade configurada?
730
+ - [ ] Autoplay configurado se necessário?
731
+
732
+ ---
733
+
734
+ ## EXEMPLO COMPLETO
735
+
736
+ <details>
737
+ <summary><strong>Ver exemplo completo de seção</strong></summary>
738
+
739
+ ```tsx
740
+ // sections/destaque/DestaqueSection.tsx
741
+ "use client";
742
+
743
+ import useEmblaCarousel from "embla-carousel-react";
744
+ import Autoplay from "embla-carousel-autoplay";
745
+ import { useState, useEffect } from "react";
746
+ import type { CarouselApi } from "@/components/ui/carousel";
747
+ import { Dots } from "@/components/ui/horizon-ui/dots";
748
+ import { ChevronRight } from "lucide-react";
749
+ import { destaques } from "./destaque-data";
750
+ import { DestaqueCard } from "./DestaqueCard";
751
+
752
+ export function DestaqueSection() {
753
+ const [emblaApi, setEmblaApi] = useState<CarouselApi>();
754
+
755
+ const [emblaRef, emblaApiInstance] = useEmblaCarousel(
756
+ { loop: true, align: "start" },
757
+ [Autoplay({ delay: 4000, stopOnInteraction: false })]
758
+ );
759
+
760
+ useEffect(() => {
761
+ if (emblaApiInstance) setEmblaApi(emblaApiInstance);
762
+ }, [emblaApiInstance]);
763
+
764
+ return (
765
+ <section className="py-24 bg-surface/30">
766
+ <div className="container">
767
+ <div className="flex flex-col gap-8">
768
+
769
+ {/* Header */}
770
+ <div className="flex flex-col gap-2">
771
+ <h2 className="type-headline leading-tight leading-trim text-2xl md:text-3xl lg:text-4xl">
772
+ Imóveis em Destaque
773
+ </h2>
774
+ <p className="type-body leading-normal leading-trim text-muted-foreground text-lg">
775
+ Confira nossa seleção especial
776
+ </p>
777
+ </div>
778
+
779
+ {/* Carousel + Dots */}
780
+ <div className="flex flex-col gap-6">
781
+ <div className="overflow-hidden" ref={emblaRef}>
782
+ <div className="flex">
783
+ {destaques.map((item) => (
784
+ <div
785
+ key={item.id}
786
+ className="flex-[0_0_100%] md:flex-[0_0_50%] lg:flex-[0_0_33.333%] min-w-0 pr-6"
787
+ >
788
+ <DestaqueCard {...item} />
789
+ </div>
790
+ ))}
791
+ </div>
792
+ </div>
793
+
794
+ <Dots api={emblaApi} variant="line" size="md" />
795
+ </div>
796
+
797
+ {/* CTA */}
798
+ <div className="text-center">
799
+ <a
800
+ href="/imoveis"
801
+ className="inline-flex items-center gap-2 text-primary type-button leading-trim font-semibold hover:gap-3 transition-all duration-300"
802
+ >
803
+ Ver Todos os Imóveis
804
+ <ChevronRight className="size-5" />
805
+ </a>
806
+ </div>
807
+
808
+ </div>
809
+ </div>
810
+ </section>
811
+ );
812
+ }
813
+
814
+ // sections/destaque/DestaqueCard.tsx
815
+ export function DestaqueCard({ image, title, price }: DestaqueCardProps) {
816
+ return (
817
+ <div className="group rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300">
818
+ <div className="aspect-[4/3] relative overflow-hidden">
819
+ <img
820
+ src={image}
821
+ alt={title}
822
+ className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700"
823
+ />
824
+ </div>
825
+ <div className="p-6 flex flex-col gap-3">
826
+ <h3 className="type-title leading-tight leading-trim text-xl group-hover:text-primary transition-colors">
827
+ {title}
828
+ </h3>
829
+ <p className="type-headline leading-tight leading-trim text-2xl text-primary font-bold">
830
+ {price}
831
+ </p>
832
+ </div>
833
+ </div>
834
+ );
835
+ }
836
+
837
+ // sections/destaque/destaque-data.ts
838
+ export interface Destaque {
839
+ id: number;
840
+ image: string;
841
+ title: string;
842
+ price: string;
843
+ }
844
+
845
+ export const destaques: Destaque[] = [
846
+ {
847
+ id: 1,
848
+ image: "https://images.unsplash.com/photo-1545324418-cc1a3fa10c00?w=600&q=80",
849
+ title: "Apartamento Moderno",
850
+ price: "R$ 850.000",
851
+ },
852
+ // ...
853
+ ];
854
+
855
+ // sections/destaque/index.ts
856
+ export { DestaqueSection } from "./DestaqueSection";
857
+ ```
858
+
859
+ </details>
860
+
861
+ ---
862
+
863
+ ## DESIGN SYSTEM
864
+
865
+ ### **Biblioteca de Seções Base**
866
+
867
+ Este projeto inclui um Design System completo com 15 seções base prontas para uso.
868
+
869
+ **Localização:** `/src/design/sections-base/`
870
+
871
+ **Categorias disponíveis:**
872
+ - **Heroes** (4 variantes): hero-centered, hero-split, hero-fullscreen, hero-minimal
873
+ - **Features** (4 variantes): features-grid-3, features-list, features-carousel, features-comparison
874
+ - **CTAs** (3 variantes): cta-centered, cta-split, cta-banner
875
+ - **Galleries** (2 variantes): gallery-grid, gallery-masonry
876
+ - **Testimonials** (1): testimonials-carousel
877
+ - **Stats** (1): stats-simple
878
+
879
+ ### **Como Usar Seções Base**
880
+
881
+ ```tsx
882
+ // Importar seção base
883
+ import { HeroCentered } from "@/design/sections-base/heroes/hero-centered";
884
+
885
+ // Usar diretamente
886
+ <HeroCentered />
887
+
888
+ // Ou customizar os dados
889
+ import { heroCenteredData } from "@/design/sections-base/heroes/hero-centered";
890
+
891
+ // Modificar dados conforme necessário
892
+ const customData = {
893
+ ...heroCenteredData,
894
+ title: "Meu título customizado",
895
+ };
896
+ ```
897
+
898
+ ### **Placeholders Criativos**
899
+
900
+ Use enquanto não tem assets reais:
901
+
902
+ ```tsx
903
+ import { ImagePlaceholder, VideoPlaceholder } from "@/design/creative/placeholders";
904
+
905
+ <ImagePlaceholder aspectRatio="4/3" showLabel />
906
+ <VideoPlaceholder aspectRatio="16/9" />
907
+ ```
908
+
909
+ ### **Storybook**
910
+
911
+ Visualize todas as seções no Storybook:
912
+ ```bash
913
+ pnpm storybook
914
+ ```
915
+
916
+ Navegue até: **"Design System / Catalog Overview"**
917
+
918
+ ### **Páginas Demonstrativas**
919
+
920
+ Acesse: `http://localhost:3000/design`
921
+
922
+ 15 páginas demonstrativas completas organizadas por categoria.
923
+
924
+ ### **Documentação Completa**
925
+
926
+ Ver: `/docs/design-system-guide.md`
927
+
928
+ ---
929
+
930
+ **Última atualização:** 2025-10-25