sass-imobiliaria/.specify/features/001-homepage/spec.md

391 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Feature Specification: Homepage (Página Inicial)
**Feature Branch**: `001-homepage`
**Created**: 2026-04-13
**Status**: Draft
---
## User Scenarios & Testing
### User Story 1 — Visitante Experimenta o Hero e a Navegação (Priority: P1)
Um visitante chega ao site da imobiliária e é imediatamente recebido por uma barra de navegação clara e uma seção hero visualmente impactante. O headline comunica a proposta de valor da agência, o subheadline fornece contexto de suporte, e um botão CTA proeminente convida o visitante a explorar os imóveis disponíveis.
**Why this priority**: O hero é a primeira impressão do site. Sem ele renderizar corretamente com conteúdo atualizado, nenhuma outra seção entrega valor significativo. Ele ancora a identidade visual e orienta o engajamento do visitante.
**Independent Test**: Pode ser testado de forma independente carregando a URL da homepage em qualquer navegador — a barra de navegação deve exibir o logotipo e os links, o hero deve mostrar o headline e subheadline configurados pelo admin, e o botão CTA deve estar visível e navegável para a listagem de imóveis.
**Acceptance Scenarios**:
1. **Given** o visitante abre a URL da homepage, **when** a página carrega, **then** a barra de navegação é visível com o logotipo da agência à esquerda e os links "Imóveis", "Sobre" e "Contato" à direita.
2. **Given** a página está carregada, **when** o visitante visualiza a seção hero, **then** ela exibe o headline atual, o subheadline (quando configurado), e um botão CTA com o rótulo configurado pelo admin (padrão: "Ver Imóveis").
3. **Given** o visitante clica no botão CTA do hero, **when** o clique é processado, **then** o navegador redireciona para a página de listagem de imóveis (`/imoveis`).
4. **Given** um admin atualizou o headline via painel administrativo, **when** o visitante carrega a homepage, **then** a seção hero exibe o novo headline sem necessidade de redeploy.
5. **Given** a homepage é acessada em dispositivo móvel (viewport 320px428px), **when** a página renderiza a seção hero, **then** todo o texto é legível, o botão CTA é tocável, e não há overflow horizontal.
---
### User Story 2 — Visitante Explora Imóveis em Destaque (Priority: P1)
Um visitante rola além da seção hero e encontra uma grade de imóveis curados em destaque. Cada card de imóvel fornece informações suficientes (foto, preço, tipo, estatísticas principais) para o visitante avaliar rapidamente o interesse e decidir clicar para ver mais detalhes.
**Why this priority**: Os imóveis em destaque são o conteúdo comercial primário da homepage. Esta seção conduz diretamente as consultas de imóveis e a conversão de visitante para lead. É a função de negócio central da homepage.
**Independent Test**: Pode ser testado de forma independente carregando a homepage e verificando que pelo menos um card de imóvel aparece na grade em destaque, com todos os campos obrigatórios visíveis (foto, título, preço, badge de tipo, quartos/banheiros/área). O teste pode ser executado contra um banco de dados com imóveis pré-configurados como destaque.
**Acceptance Scenarios**:
1. **Given** existem imóveis no sistema com o flag "featured" habilitado, **when** o visitante carrega a homepage, **then** a seção de imóveis em destaque exibe uma grade mostrando até N imóveis (configurável pelo admin), cada card contendo: foto principal, título do imóvel, preço formatado (R$), badge de tipo (Venda ou Aluguel), contagem de quartos, banheiros e área total em m².
2. **Given** nenhum imóvel está configurado como destaque, **when** o visitante carrega a homepage, **then** a seção de imóveis em destaque é ocultada ou exibe a mensagem "Nenhum imóvel em destaque no momento" — a grade não é renderizada vazia ou quebrada.
3. **Given** um card de imóvel está visível, **when** o visitante clica no card, **then** o navegador navega para a URL de detalhe daquele imóvel (`/imoveis/{slug}`).
4. **Given** um imóvel em destaque não possui foto cadastrada, **when** o card é renderizado, **then** ele exibe uma imagem placeholder em vez de um elemento de imagem quebrado.
5. **Given** a grade de imóveis em destaque é visualizada em tablet (768px1023px), **when** o layout renderiza, **then** a grade se adapta para 2 colunas sem overflow ou quebra de alinhamento.
---
### User Story 3 — Visitante Descobre a Agência e Inicia Contato (Priority: P2)
Um visitante que está interessado mas ainda não está pronto para navegar pelos imóveis rola pela seção Sobre para conhecer o background da agência, e em seguida encontra a seção CTA com informações de contato claras ou um convite para entrar em contato.
**Why this priority**: As seções Sobre e CTA suportam a construção de confiança e a geração de leads para visitantes que precisam de mais contexto antes de engajar com as listagens. São valiosas, mas não bloqueiam a funcionalidade MVP — a homepage funciona sem elas, embora as taxas de conversão se beneficiem significativamente de sua presença.
**Independent Test**: Pode ser testado de forma independente rolando a homepage além da seção de imóveis em destaque e verificando que (a) uma seção Sobre com nome e descrição da agência aparece, e (b) uma seção CTA com um convite de contato aparece antes do rodapé.
**Acceptance Scenarios**:
1. **Given** o visitante rola além da seção de imóveis em destaque, **when** a seção Sobre entra na viewport, **then** ela exibe o nome da agência e pelo menos um parágrafo de descrição.
2. **Given** o visitante continua rolando, **when** a seção CTA entra na viewport, **then** ela exibe um convite claro para contato com ao menos um elemento acionável (número de telefone, link de e-mail ou botão "Fale Conosco").
3. **Given** a página é rolada até o final, **when** o visitante chega ao rodapé, **then** o rodapé exibe as informações de contato da agência (ao mínimo: e-mail ou telefone) e links de navegação (Imóveis, Sobre, Contato).
---
### User Story 4 — Admin Configura o Conteúdo da Homepage (Priority: P1)
Um administrador faz login no painel administrativo e atualiza o headline e subheadline do hero da homepage. O admin também seleciona quais imóveis aparecem na grade em destaque habilitando ou desabilitando o flag "featured" nos imóveis individuais.
**Why this priority**: A capacidade de atualizar o conteúdo da homepage sem alterações de código é um requisito central do painel SaaS. Sem essa capacidade, a homepage é estática e o painel administrativo não entrega valor para o gerenciamento da homepage.
**Independent Test**: Pode ser testado de forma independente em dois cenários: (1) atualizar o headline via formulário de configurações da homepage no painel e verificar que a mudança aparece na homepage pública; (2) alternar o flag "featured" de um imóvel e verificar que a grade de destaque é atualizada. Ambas as ações podem ser testadas contra o painel com chamadas reais de API.
**Acceptance Scenarios**:
1. **Given** o admin está autenticado e na página de configurações da homepage, **when** o admin atualiza o headline e o subheadline e salva, **then** a homepage pública reflete o novo texto no próximo carregamento sem necessidade de redeploy.
2. **Given** o admin navega para a lista de imóveis no painel, **when** o admin habilita ou desabilita o flag "featured" em um imóvel e salva, **then** aquele imóvel aparece ou é removido da grade em destaque na homepage pública.
3. **Given** o admin tenta salvar a configuração da homepage com headline vazio, **when** o formulário é submetido, **then** o sistema rejeita o salvamento e exibe uma mensagem de validação — headline vazio não é permitido.
4. **Given** o admin seleciona imóveis em destaque, **when** mais imóveis que o máximo configurável são marcados como destaque, **then** o sistema exibe apenas até o limite definido na homepage (padrão: 6), priorizando por data de marcação.
---
### Edge Cases
- **Nenhum imóvel em destaque**: Se nenhum imóvel está marcado como featured, a seção deve ser oculta ou exibir "Nenhum imóvel em destaque no momento" — a página não deve lançar erro de renderização.
- **Imóvel sem foto**: Se um imóvel em destaque não possui foto, um placeholder genérico é exibido — o card não deve renderizar um elemento de imagem quebrado.
- **Headline muito longo**: Se o admin inserir um headline muito longo (120+ caracteres), a seção hero deve adaptar-se sem overflow de texto ou quebra de layout.
- **Estado de carregamento / rede lenta**: Enquanto a resposta da API de imóveis em destaque está pendente, a seção deve exibir skeleton loaders — sem flash de conteúdo ou espaço em branco.
- **Subheadline vazio**: O subheadline é opcional. Um subheadline vazio deve resultar na renderização do hero sem o elemento subheadline — não uma string vazia visível.
- **API indisponível**: Se o endpoint de configuração da homepage ou de imóveis falhar, a página deve renderizar uma versão degradada (conteúdo de fallback estático) em vez de uma tela de erro completa.
---
## Requirements
### Functional Requirements
- **FR-001**: O sistema DEVE renderizar uma barra de navegação contendo o logotipo da agência e links para as seções/páginas Imóveis, Sobre e Contato.
- **FR-002**: A barra de navegação DEVE ser sticky (visível durante a rolagem) em viewports desktop (≥768px).
- **FR-003**: A barra de navegação DEVE colapsar para um menu hamburger em viewports abaixo de 768px.
- **FR-004**: O sistema DEVE renderizar uma seção hero exibindo um headline, um subheadline opcional, e um botão CTA que navega para a listagem de imóveis.
- **FR-005**: O headline e o subheadline do hero DEVEM ser configuráveis por um admin autenticado via painel administrativo sem alterações de código ou redeploy.
- **FR-006**: O sistema DEVE renderizar uma seção de Imóveis em Destaque exibindo uma grade de imóveis marcados como "featured" por um admin.
- **FR-007**: Cada card de imóvel na grade DEVE exibir: uma foto principal, título do imóvel, preço formatado em R$ (pt-BR), badge de tipo (Venda ou Aluguel), contagem de quartos, contagem de banheiros e área total em m².
- **FR-008**: A grade de imóveis em destaque DEVE ser populada dinamicamente via API de backend — a lista NÃO DEVE exigir redeploy para ser atualizada.
- **FR-009**: O sistema DEVE limitar a grade em destaque a um número máximo configurável de entradas (padrão: 6, máximo suportado: 12).
- **FR-010**: Se nenhum imóvel estiver configurado como destaque, o sistema DEVE tratar esse estado graciosamente sem erros de renderização, ocultando a seção ou exibindo uma mensagem adequada.
- **FR-011**: Cards de imóvel DEVEM exibir uma imagem placeholder quando nenhuma foto estiver disponível.
- **FR-012**: O sistema DEVE renderizar uma seção Sobre/Empresa contendo ao mínimo o nome da agência e uma descrição breve.
- **FR-013**: O sistema DEVE renderizar uma seção Call-to-Action contendo um convite para contato com ao mínimo um elemento acionável.
- **FR-014**: O sistema DEVE renderizar um rodapé contendo informações de contato e links de navegação.
- **FR-015**: O painel administrativo DEVE fornecer uma interface para selecionar quais imóveis são exibidos na grade em destaque.
- **FR-016**: O painel administrativo DEVE rejeitar salvamentos de configuração de homepage com headline vazio, exibindo mensagem de validação ao admin.
### Non-Functional Requirements
#### Performance
- **NFR-001**: A homepage DEVE atingir um Largest Contentful Paint (LCP) abaixo de 2,5 segundos em conexão banda larga padrão (>10 Mbps).
- **NFR-002**: Os endpoints de API que suprem dados da homepage DEVEM responder em até 500ms sob carga normal (até 100 requisições concorrentes).
- **NFR-003**: Imagens de imóveis em destaque DEVEM ser servidas em formato web-otimizado — nenhuma imagem de thumbnail de card deve exceder 300 KB.
#### Responsiveness
- **NFR-004**: A homepage DEVE ser completamente funcional e visualmente íntegra nos seguintes breakpoints: 320px (mobile S), 375px (mobile M), 768px (tablet), 1024px (laptop), 1280px (desktop), 1440px (wide).
- **NFR-005**: A grade de imóveis em destaque DEVE se adaptar de 1 coluna em mobile para 2 colunas em tablet e 3 colunas em desktop (≥1024px).
- **NFR-006**: A tipografia do hero DEVE escalar responsivamente: 72px em desktop, 48px em tablet, 40px em mobile.
#### Accessibility
- **NFR-007**: Todas as imagens DEVEM ter texto `alt` descritivo (título do imóvel para fotos de imóveis; descrição para o logotipo).
- **NFR-008**: Todos os elementos interativos (links, botões) DEVEM ser navegáveis por teclado e ter estados de foco visíveis.
- **NFR-009**: Relações de contraste de cor DEVEM atender aos padrões WCAG 2.1 AA: mínimo 4,5:1 para texto de corpo, 3:1 para texto grande e componentes de UI.
- **NFR-010**: A página DEVE usar elementos HTML5 semânticos apropriados e papéis ARIA landmark (`<nav>`, `<main>`, `<footer>`, `<header>`) em toda a estrutura.
### Key Entities
- **HomepageConfig**: Representa o conteúdo configurável pelo admin para a homepage. Atributos principais: `hero_headline` (obrigatório, máx. 120 caracteres), `hero_subheadline` (opcional, máx. 240 caracteres), `hero_cta_label` (opcional, máx. 40 caracteres, padrão: "Ver Imóveis"), `hero_cta_url` (opcional, caminho relativo, padrão: "/imoveis"), `featured_properties_limit` (inteiro, padrão: 6, máximo: 12).
- **Property**: Representa um anúncio imobiliário. Atributos relevantes para a homepage: `id` (UUID), `title` (string), `type` (enum: `venda` | `aluguel`), `price` (decimal), `area_m2` (inteiro), `bedrooms` (inteiro), `bathrooms` (inteiro), `is_featured` (boolean), `slug` (string única). A entidade Property é compartilhada com a feature de listagem de imóveis.
- **PropertyPhoto**: Representa uma foto associada a um imóvel. A homepage usa apenas a foto principal (primeira por ordem de display). Atributos: `url` (string), `alt_text` (string), `display_order` (inteiro).
---
## Design Specifications
Toda a especificação visual segue o tema dark inspirado no Linear documentado em `DESIGN.md`.
### Color Application
| Element | Token | Value |
|---------|-------|-------|
| Page background | Marketing Black | `#08090a` |
| Navigation background (sticky) | Marketing Black semi-transparente | `rgba(8,9,10,0.85)` + backdrop-blur |
| Hero background (gradiente padrão) | Radial brand indigo fade | `radial-gradient(ellipse at center, rgba(94,106,210,0.08) 0%, #08090a 70%)` |
| Card/container background | Level 2 Surface | `rgba(255,255,255,0.03)` |
| Card border | Border Standard | `1px solid rgba(255,255,255,0.08)` |
| Card border hover | Border Standard brightened | `1px solid rgba(255,255,255,0.12)` |
| Primary text | Near-white | `#f7f8f8` |
| Secondary text | Silver-gray | `#d0d6e0` |
| Tertiary text / metadata | Muted gray | `#8a8f98` |
| CTA button background | Brand Indigo | `#5e6ad2` |
| CTA button hover | Accent Hover | `#828fff` |
| Badge tipo Venda | Brand Indigo pill | `rgba(94,106,210,0.15)` + borda `rgba(94,106,210,0.3)` |
| Badge tipo Aluguel | Neutral pill | `rgba(255,255,255,0.05)` + borda `rgba(255,255,255,0.1)` |
| Section dividers | Line Tint | sem divisor visível — espaçamento separa as seções |
| Footer background | Panel Dark | `#0f1011` |
### Typography Application
| Element | Style from DESIGN.md | Size | Weight | Letter Spacing |
|---------|----------------------|------|--------|----------------|
| Hero headline (desktop) | Display XL | 72px | 510 | -1.584px |
| Hero headline (tablet) | Display | 48px | 510 | -1.056px |
| Hero headline (mobile) | Heading 1 | 40px | 510 | -0.704px |
| Hero subheadline | Body Large | 18px | 400 | -0.165px |
| CTA button label | Label | 14px | 590 | normal |
| Section headings (ex: "Imóveis em Destaque") | Display | 48px (desktop) / 32px (mobile) | 510 | -1.056px / -0.704px |
| Property card title | Heading 3 | 20px | 590 | -0.24px |
| Property price | Body Semibold | 16px | 590 | normal |
| Property stats (quartos, banheiros, área) | Caption Large | 14px | 510 | -0.182px |
| Navigation links | Link Small | 14px | 510 | -0.182px |
| Footer links | Link Caption | 13px | 510 | -0.13px |
| About / CTA body text | Body | 16px | 400 | normal |
Toda a tipografia usa `Inter Variable` com OpenType features `"cv01", "ss03"` habilitadas globalmente via `font-feature-settings: "cv01", "ss03"`.
### Layout
- **Largura máxima do conteúdo**: 1200px, centralizado horizontalmente com margens `auto`.
- **Hero section**: mínimo 100vh de altura, layout de coluna única centralizado, padding: 120px superior / 80px inferior em desktop; 80px / 60px em mobile.
- **Grade de Imóveis em Destaque**: 3 colunas em desktop (≥1024px), 2 colunas em tablet (768px1023px), 1 coluna em mobile (<768px). Gap: 24px.
- **Espaçamento vertical entre seções**: 80px padding-top e padding-bottom em desktop; 60px em mobile.
- **Border radius dos cards**: 12px (Panel radius conforme DESIGN.md).
- **Fotos dos cards**: border-radius `12px 12px 0 0` (arredondado no topo), aspect-ratio 16:9.
### Component Notes
- **Navigation bar**: fundo `rgba(8,9,10,0.85)` com `backdrop-filter: blur(12px)`, `border-bottom: 1px solid rgba(255,255,255,0.05)`. Posição: sticky, `z-index` elevado.
- **Property card**: fundo `rgba(255,255,255,0.03)`, borda `1px solid rgba(255,255,255,0.08)`, radius 12px, com transição de hover aumentando levemente a opacidade do fundo e a borda.
- **CTA button (Primary)**: Background `#5e6ad2`, padding `10px 20px`, radius 6px, texto branco weight 590. Hover: `#828fff`.
- **Type badges**: pills com radius `9999px`, padding `2px 10px`, fonte 12px weight 510.
---
## API Contract
Os seguintes endpoints devem ser implementados pelo backend Flask para suportar a homepage.
### `GET /api/v1/homepage-config`
Retorna o conteúdo configurável pelo admin para a seção hero da homepage.
**Autenticação**: Nenhuma (endpoint público)
**Cache**: As respostas podem ser cacheadas por até 60 segundos (header `Cache-Control: public, max-age=60`).
**Response `200 OK`**:
```json
{
"hero": {
"headline": "Encontre o imóvel dos seus sonhos",
"subheadline": "Imóveis para comprar e alugar com a melhor assessoria da região.",
"cta_label": "Ver Imóveis",
"cta_url": "/imoveis"
},
"featured_properties_limit": 6
}
```
**Response `500 Internal Server Error`**:
```json
{
"error": "internal_server_error",
"message": "An unexpected error occurred."
}
```
---
### `GET /api/v1/properties?featured=true`
Retorna a lista de imóveis marcados como destaque, ordenados por prioridade de exibição.
**Autenticação**: Nenhuma (endpoint público)
**Query Parameters**:
| Parâmetro | Tipo | Obrigatório | Descrição |
|-----------|------|-------------|-----------|
| `featured` | boolean | sim (para este use case) | `true` filtra apenas imóveis em destaque |
| `limit` | integer | não | Máximo de resultados. Padrão: valor de `featured_properties_limit` da config. Máximo: 12. |
**Response `200 OK`**:
```json
{
"properties": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"title": "Apartamento Moderno no Centro",
"type": "venda",
"price": 450000.00,
"price_formatted": "R$ 450.000,00",
"area_m2": 85,
"bedrooms": 3,
"bathrooms": 2,
"primary_photo_url": "https://cdn.example.com/properties/abc123/main.jpg",
"primary_photo_alt": "Apartamento Moderno no Centro — foto principal",
"slug": "apartamento-moderno-no-centro",
"detail_url": "/imoveis/apartamento-moderno-no-centro"
}
],
"total": 4
}
```
**Response `400 Bad Request`** (parâmetros inválidos):
```json
{
"error": "invalid_parameter",
"message": "Parameter 'limit' must be an integer between 1 and 12."
}
```
**Response `500 Internal Server Error`**:
```json
{
"error": "internal_server_error",
"message": "An unexpected error occurred."
}
```
---
### `PUT /api/v1/admin/homepage-config`
Atualiza a configuração da homepage. Reservado para o painel administrativo (autenticação de admin obrigatória).
**Autenticação**: Bearer token (JWT), role `admin` obrigatória.
**Nota**: Este endpoint é referenciado para completude do contrato; sua especificação completa (autenticação, sessões, permissões) é definida na feature spec do Admin Panel.
**Request Body**:
```json
{
"hero": {
"headline": "string (obrigatório, máx. 120 caracteres)",
"subheadline": "string (opcional, máx. 240 caracteres)",
"cta_label": "string (opcional, máx. 40 caracteres)",
"cta_url": "string (opcional, caminho relativo válido)"
},
"featured_properties_limit": "integer (opcional, 112)"
}
```
**Response `200 OK`**: Retorna o objeto `HomepageConfig` atualizado com o mesmo schema de `GET /api/v1/homepage-config`.
**Response `400 Bad Request`** (validação falhou):
```json
{
"error": "validation_error",
"fields": {
"hero.headline": "This field is required and cannot be empty."
}
}
```
**Response `401 Unauthorized`** / **`403 Forbidden`**: Retornado quando o token está ausente, expirado ou sem a role `admin`.
---
### `PATCH /api/v1/admin/properties/{id}/featured`
Habilita ou desabilita o flag de destaque de um imóvel específico.
**Autenticação**: Bearer token (JWT), role `admin` obrigatória.
**Nota**: Endpoint referenciado para completude. Especificação completa na feature spec de gerenciamento de imóveis do Admin Panel.
**Request Body**:
```json
{
"is_featured": true
}
```
**Response `200 OK`**:
```json
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"is_featured": true
}
```
---
## Out of Scope
Os itens a seguir estão explicitamente excluídos desta especificação de feature e serão tratados em specs separadas:
- **Página de detalhe do imóvel**: Clicar em um card de imóvel navega para a URL de detalhe, mas o layout, conteúdo e API da página de detalhe são uma feature separada.
- **Busca e filtros de imóveis**: A funcionalidade de busca (filtrar por faixa de preço, localização, tipo, quartos, etc.) é uma feature separada. O botão CTA do hero linka para a listagem; qualquer interface de busca na homepage está fora de escopo.
- **Autenticação e UI do Painel Administrativo**: O fluxo de login do admin, layout do painel, navegação e gerenciamento de sessão são features separadas. Esta spec define apenas a view pública da homepage e o contrato de API que o painel consumirá.
- **Página de Listagem de Imóveis**: A listagem completa em `/imoveis` com paginação, filtros e ordenação é uma feature separada.
- **Backend de Formulário de Contato**: O processamento de submissão de formulário de contato, entrega de e-mail e armazenamento de leads são features separadas. O CTA da homepage pode linkar para uma página de contato ou fornecer e-mail/telefone estático.
- **Suporte multi-idioma (i18n)**: Português (pt-BR) é o único idioma suportado. Internacionalização está fora de escopo.
- **SEO / Meta Tags avançadas**: Open Graph tags, dados estruturados (JSON-LD para `RealEstateListing`) e geração de sitemap são concerns separados.
- **Integração de Analytics**: Eventos de rastreamento (GA4, Hotjar, etc.) estão fora de escopo para esta feature.
- **Conteúdo editável via admin das seções Sobre e Rodapé**: Na versão inicial, o conteúdo das seções Sobre, CTA e Rodapé é estático. Uma spec futura pode adicionar gerenciamento dessas seções pelo admin.
---
## Success Criteria
### Measurable Outcomes
- **SC-001**: Um visitante pode chegar à homepage e clicar para ver um imóvel em destaque em menos de 30 segundos sem nenhuma orientação taxa de conclusão da tarefa primária 90% em testes de usabilidade.
- **SC-002**: A homepage carrega e exibe o conteúdo acima da dobra (hero + navegação) em até 2,5 segundos em conexão banda larga padrão.
- **SC-003**: Um admin pode atualizar o headline do hero e vê-lo refletido na homepage pública em até 60 segundos, sem intervenção de desenvolvedor.
- **SC-004**: Um admin pode alterar quais imóveis estão em destaque e ver a grade da homepage ser atualizada em até 60 segundos, sem redeploy.
- **SC-005**: A homepage renderiza sem regressões visuais em todos os 6 breakpoints definidos (320px, 375px, 768px, 1024px, 1280px, 1440px).
- **SC-006**: Todos os requisitos de contraste de cor WCAG 2.1 AA são atendidos em toda a homepage verificado por auditoria de acessibilidade automatizada com zero violações críticas.
- **SC-007**: A seção de imóveis em destaque renderiza corretamente com 0, 1 ou 6 imóveis marcados como featured sem erros de JavaScript ou layouts quebrados em nenhum desses estados.
---
## Assumptions
- A agência opera exclusivamente no Brasil; toda formatação de moeda usa o locale pt-BR (prefixo R$, ponto como separador de milhar, vírgula como separador decimal).
- A homepage é renderizada como React SPA com client-side data fetching; esta spec não prescreve a estratégia de renderização (CSR/SSR/SSG).
- O sistema de autenticação do painel admin (login, sessão, JWT) é implementado como feature separada e é um pré-requisito para a User Story 4 (Admin Configura Conteúdo).
- Fotos de imóveis são armazenadas externamente (object storage / CDN) e referenciadas por URL na resposta da API. A homepage não realiza upload de arquivos.
- O conteúdo das seções Sobre e CTA (descrição da agência, informações de contato) é considerado estático para a versão inicial e não requer configurabilidade via admin nesta spec.
- O conteúdo do rodapé (links e informações de contato) é HTML estático para a versão inicial.
- O número máximo de imóveis em destaque exibidos na homepage tem padrão 6, configurável pelo admin até no máximo 12.
- Links de cards de imóveis apontam para `/imoveis/{slug}` mesmo que a página de detalhe ainda não esteja implementada. Links temporariamente quebrados são aceitáveis durante o desenvolvimento em fases.
- A fonte Inter Variable é carregada via fonte auto-hospedada ou CDN com OpenType features `"cv01", "ss03"` habilitadas globalmente via `font-feature-settings`.
- O painel admin está hospedado na mesma origem ou com CORS configurado adequadamente para os endpoints `/api/v1/admin/*`.