# ENPASA — MCP do Design System

Contexto de projeto para qualquer agente que for criar ou editar páginas do site ENPASA.
**Leia inteiro antes de mexer.** Fonte da verdade visual: Figma `wqedn1zreYQ9ouFhOGyGaZ` ("Enpasa 2026"), frame `enpasa-style-guide` (`258:1670`).

- Home: `27:151` · Sobre: `27:152` · Áreas de atuação: `73:1562` · Saneamento: `38:2547` · Cases: `73:4107` · Case interna: `86:4512` · Contato: `86:6204` · Carreiras: `92:6742`
- Símbolos: Navbar `28:5538` (fechado) / `256:5196` (aberto) · Footer `265:811` · `[cta newsletter]` `463:1466` · `[slider nav]` `552:993` · Button `256:5129`
- Status: **Home, Sobre, Áreas de atuação, Saneamento, Cases, Case interna, Contato e Carreiras prontas.** Faltam: Terraplanagem e Pavimentação (links do menu já apontam para `areas-de-atuacao-terraplanagem.html` / `-pavimentacao.html`). WordPress: projeto à parte em `_wordpress/` (ver §16).

---

## 1. Estrutura de arquivos

```
enpasa/
├─ src/pages/*.html        ← EDITE AQUI (conteúdo único de cada página)
├─ src/partials/*.html     ← blocos repetidos: head, sprite, header, footer, cta-newsletter, slider-nav
├─ build.py                ← python3 build.py  → gera index.html, sobre.html… na raiz
├─ css/tokens.css          ← todas as variáveis (cores, fontes, escala, espaços, movimento)
├─ css/base.css            ← reset, container, tipografia, reveal
├─ css/components.css      ← header/menu, botões, tags, cards, sliders, CTA, footer, loader
├─ css/pages/<pagina>.css  ← estilos exclusivos de cada página
├─ js/main.js              ← loader, tema do header, menu, reveal, zoom/parallax, sliders (todas as páginas)
├─ js/<pagina>.js          ← comportamento exclusivo (home.js: hero e galeria · sobre.js: lightbox)
├─ assets/{img,svg,fonts,video}
└─ _dev/frame.html         ← ferramenta de teste de viewport (não vai para o WordPress)
```

**Regra de ouro:** os `.html` da raiz são **gerados**. Nunca edite direto — o `build.py` sobrescreve. Edite `src/` e rode `python3 build.py`.
Para incluir um partial: `<!-- @include partials/footer.html -->`; com variável: `<!-- @include partials/slider-nav.html variant=light -->` (troca `{{variant}}`).

Servidor local: `cd enpasa && python3 -m http.server 5192` (launch.json já tem a config `enpasa`).
Teste de viewport real: `http://localhost:5192/_dev/frame.html?page=index.html&w=390&h=760&s=1` (`w`/`h` = tamanho simulado, `s` = escala visual).

## 2. Cores (style guide 01)

| Token | Valor | Uso |
|---|---|---|
| `--c-primary` | `#1F76DD` | Azul primário: títulos de destaque em fundo escuro, cards de serviço, linhas decorativas, botões |
| `--c-primary-dark` | `#063D88` | Texto/títulos em fundo claro; fundo da Liderança |
| `--c-gold` | `#9E7B3E` | Tags, números dos indicadores, títulos de clientes/depoimentos |
| `--c-gray` | `#808285` | Cinza neutro (logo Rain, textos secundários) |
| `--c-bg-dark` | `#0A1628` | Fundo escuro principal, cards sobre fundo `card-dark` |
| `--c-card-dark` | `#111D33` | Container/card sobre escuro, seção Cases |
| `--c-light` | `#F5F7FA` | Fundo claro, texto sobre escuro |
| `--c-white` | `#FFFFFF` | Fundo "branco puro" (Sobre) |
| `--c-border` | `rgba(31,118,221,.2)` | Borda de card |

Blocos "claros" (fundo `#FFF` ou `#F5F7FA`) = `data-theme="light"`. Qualquer outro = `data-theme="dark"`.

## 3. Tipografia

Fontes **self-hosted** (`assets/fonts`, latin + latin-ext): **Michroma** 400 (display) e **Roboto** 400/500/600/700 (corpo).
Michroma é muito larga (~0,75em por caractere): sempre confira quebra de linha em larguras pequenas.

| Token | Desktop ≥1280 | Tablet 768–1279 | Mobile ≤767 / celular deitado | Fonte | Onde |
|---|---|---|---|---|---|
| `--fs-hero` | 72 | 56 | 30 (28 deitado) | Michroma | Hero da home |
| `--fs-h2` | 44 | 36 | 24 | Michroma | Títulos de seção (Sobre) |
| `--fs-h3` | 40 | 32 | 22 | Michroma | Títulos de seção (Home), CTA |
| `--fs-stat` | 38 | 32 | 28 | Michroma | Números dos stats |
| `--fs-service` | 36 | 30 (clamp 18–2.7vw) | 24 | Michroma | Título flutuante de serviço |
| `--fs-h4` | 32 | 28 | 24 | Michroma | Menu, títulos de galeria/clientes/cases |
| `--fs-kicker` | 24 | 20 | 14 | Michroma CAPS | Kicker |
| `--fs-h6` | 20 | 20 | 18 | Michroma | Título de card de case |
| `--fs-tag` | 15 | 15 | 14 | Michroma | Submenu |
| `--fs-lead` | 18 | 18 | 16 | Roboto 500 | Subtítulo/corpo primário |
| `--fs-body` | 16 | 16 | 16 | Roboto 400 | Corpo |
| `--fs-small` | 14 | 14 | 14 | Roboto 400/600 | Texto de card, link, botão |
| `--fs-label` | 12 | 12 | 12 | Roboto 700 CAPS | Tag, label de stat |
| `--fs-h5` | 24 | 24 | 22 | Roboto 700 | Título MVV |

Line-heights: hero 1.1 · títulos 1.2/1.3 · texto 1.3 · corpo longo 1.5.
**Mobile (acessibilidade):** nenhum texto abaixo de 12px (só labels em caixa alta); corpo nunca abaixo de 14px; alvos de toque ≥ 40×40px (setas, dots têm área estendida via `::before`).

## 4. Espaçamento e grid

- Escala: 8 · 16 · 24 · 32 · 48 · 64 · 96 (`--s-*`).
- `--gap-page`: 64 (desktop) · 40 (tablet) · 20 (mobile). `--gap-section` (respiro vertical): 96 · 80 · 56. `--gap-grid` (entre cards): 24 · 20 · 16.
- **Largura máxima 1440** (`--page-max`; conteúdo útil 1312). Acima disso a página **não cresce**: fundos vão de ponta a ponta, o conteúdo fica centralizado com as mesmas proporções do design.
- Breakpoints: `≥1280` desktop · `768–1279` tablet (`max-width:1279px`) · `≤767` mobile (`max-width:767px`) · **mobile deitado** = `(max-height:520px) and (orientation:landscape)` (usa escala tipográfica de celular, mas layout por largura).
- Raios: 5 (botão menu) · 10 (botão cheio) · 12 (logo) · 16 (card) · 20 (CTA, foto) · 999 (tag).

## 5. Componentes (classes)

| Componente | Classe | Notas |
|---|---|---|
| Container | `.container` | Largura 1312 + `--gap-page` |
| Seção | `.section` + `.section--light/--white/--dark/--card/--blue` | Sempre com `data-theme` |
| Cabeçalho de seção | `.section-header` > `__title` `__text` | Kicker opcional `.t-kicker` |
| Botão-link (secundário) | `.btn-link` (`--dark` em fundo claro) | Texto CAPS 14px/500, linha 100px; hover = barra azul 4px cresce |
| Botão cheio (primário) | `.btn` (`--outline`, `--gold`) | Borda 4px, raio 10 |
| Link "Saiba mais →" | `.link-arrow` | Ícone via `<use href="#i-arrow-right">` |
| Tag | `.tag` | Pill dourado |
| Card indicador | `.stat-card` (home) · `.ind-card` (sobre) | |
| Card serviço | `.service-card` > `__title` (azul, sobrepõe 5px) + `__body` | Título e card têm a mesma cor: a sobreposição é intencional |
| Card case | `.case-card` | Imagem 220px |
| Slider | `.slider[data-slider]` > `.slider__track` + `partials/slider-nav.html` | Ver §7 |
| CTA | `partials/cta-newsletter.html` | **Repetir em todas as páginas** |
| Header/Menu | `partials/header.html` | Ver §6 |
| Footer | `partials/footer.html` | |
| Padrão de fundo | `.bg-strip` (img, `aria-hidden`) | Style guide 11. Absoluto, antes/depois de blocos importantes; evitar usos seguidos (a cada 2–3 blocos). Idealmente 1x após o Hero e antes/depois da primeira introdução. |
| Loader | `[data-loader]` | Some quando fontes + `load` + "holds" da página terminam |

## 6. Header flutuante e menu

- Logo (esq.) + botão de menu (dir.) **fixos** (`position:fixed`), ícone flutuante. Clique abre o painel lateral azul (variação `aberto=true` do Navbar); o botão vira seta ←.
- **Troca de cor automática** (`initHeaderTheme` em `main.js`): lê o `data-theme` do bloco que está sob a linha y=40px.
  `dark` → logo **branco**, botão claro com barras azuis · `light` → logo **azul**, botão azul com barras brancas.
  Hero (vídeo) e qualquer bloco que não seja branco/`#F5F7FA` = `dark`. **Todo bloco novo precisa de `data-theme`.**
- O logo é `<symbol id="logo-enpasa">` (usa `currentColor`) no sprite inline — nunca use `<img>` para ele.
- Menu: links 32px Michroma (24 mobile), submenu de "Áreas de Atuação" sempre visível, sublinhado cresce no hover, item da página atual com `aria-current="page"` (JS compara `location`).
- Acessibilidade: `aria-expanded/controls`, `inert` no painel fechado, foco vai ao 1º link, **Tab preso** no painel, **Esc** fecha, devolve foco ao botão, rolagem do body travada, overlay clicável.
- Mobile: painel ocupa 100% da tela, submenu empilhado. Deitado: tipografia reduzida e painel rolável.

## 7. Sliders

`data-slider` no `.slider`:
- `mobile` — **"[slider no mobile]"**: grid no desktop/tablet, carrossel só ≤767px (scroll-snap nativo, `--slide-w` define a largura do slide, com "espiada" do próximo).
- `always` — carrossel em qualquer largura (Cases: 3/2/1 por vez). A navegação **só aparece se houver mais de uma posição** (com 3 cases no desktop ela fica oculta; com mais cases aparece sozinha).
- `fade` — **"[slider … em fade]"** (logos de clientes ≤767px): pares de logos alternam em fade, autoplay 3,6s, pausa em hover/foco/aba oculta; com `prefers-reduced-motion` mostra todos os logos em grade.

Navegação (`partials/slider-nav.html`, ref. frame `[slider nav]`): setas circulares 40px + dots (ativo 42×7 branco/azul-escuro, demais 32×4 azul). `variant=dark|light` ajusta cor para o fundo. Teclado: ←/→ no trilho; dots e setas são `<button>` com `aria-label`; trilho tem `role="region"` + `aria-roledescription="carrossel"`.
Para o Sobre: em MVV, o bloco **Valores entra como 3º slide** no mobile.

## 8. Movimento

- Easing único: **expo-out** `cubic-bezier(0.16,1,0.3,1)` (`--ease`); durações 0.35 / 0.8 / 1.1s. Sem entradas extras além do reveal.
- `.reveal` (+ `data-reveal="scale|fade|left|right"`, `data-reveal-delay="1-8"` = stagger de 90ms). Entra via IntersectionObserver **depois do loader**. Sem JS o conteúdo aparece normalmente (`.js` só é adicionada por script no `<head>`).
- `data-zoom` (+ `data-zoom-section` no pai): zoom curtíssimo do fundo ligado ao scroll (1 → 1.08). Usado no `[cta newsletter]`.
- `data-parallax="px"`: desloca padrões decorativos (variável `--py`).
- `prefers-reduced-motion`: reveal sem animação, sem zoom/parallax, sem auto-scroll, sem autoplay.

## 9. Home — comportamentos específicos

1. **Loader** segura a abertura até o vídeo poder tocar (`canplaythrough`; 8s de limite; erro → mostra o poster).
2. **Hero**: `<video muted loop playsinline>` em `position:sticky` (fica fixo). A 1ª tela é só o vídeo; ~4,5s depois (se o usuário não interagiu) o site rola sozinho (expo-out, 1.8s) até a 2ª tela, onde o texto entra sobre o vídeo; um escurecimento progressivo (`--hero-dim`) garante leitura. Qualquer wheel/touch/tecla cancela o auto-scroll.
3. **Galeria**: 2 conjuntos de 3 fotos empilhados; ao rolar (centro da galeria cruza 42% da tela) o conjunto A faz fade out e B fade in (com stagger); rolando para cima volta. No mobile os 6 viram carrossel (sem troca por scroll).
4. Cases = slider `always`; Clientes = slider `fade`; Soluções = `mobile`.

## 10. Sobre — comportamentos específicos

- Vitrine com **lightbox de vídeo**: `<button data-lightbox-open data-video="URL">` (YouTube/Vimeo/.mp4). Vazio = mensagem "em breve". Poster: `style="--vitrine-poster:url(...)"` em `.vitrine__poster`.
- Indicadores (6 cards), MVV, Liderança (5 pessoas, LinkedIn), Atuação (3 colunas), Depoimentos (3).
- Sliders `mobile` em MVV (+Valores), Liderança, Atuação, Depoimentos.

## 11. Imagens, SVG e performance

- Fotos em **JPG otimizado** (≤1600px) com `width`/`height`, `loading="lazy"`, `decoding="async"`. Fora da 1ª dobra sempre lazy.
- Decorativos: `alt=""` + `aria-hidden`. Conteúdo: `alt` descritivo. Ícones inline via sprite (`#i-arrow-right`, `#i-arrow-left`, `#i-image`, `#logo-enpasa`).
- Fontes com `font-display:swap`, preload das 2 principais.

## 12. Conversão para WordPress (guia)

| Aqui | WordPress |
|---|---|
| `partials/head.html` | `wp_head()` + `wp_enqueue_style/script` (tokens → base → components → página) |
| `partials/sprite.html` + `header.html` | `header.php` (ou `template-parts/header.php`); menu → `wp_nav_menu` (manter classes `.menu-link`, `.submenu-link`, `.site-menu__list`, `.site-menu__sub`) |
| `partials/footer.html` | `footer.php` |
| `partials/cta-newsletter.html` | `template-parts/cta-newsletter.php` (ou bloco/ACF Options) |
| `partials/slider-nav.html` | `template-parts/slider-nav.php` com variável `variant` |
| `src/pages/*.html` | `page-*.php` / templates; textos → ACF/Gutenberg |
| Cases | CPT `case` (+ taxonomia = tag) alimentando `.case-card` em slider `always` |
| Equipe, depoimentos, clientes | CPT/Repeater ACF; mesma marcação |

`js/main.js` e `css/*` entram em todas as páginas; `home.js`, `sobre.js` e `css/pages/*` só no template correspondente. O JS é independente de framework (sem jQuery) e age por `data-*`, então funciona com Elementor/Gutenberg desde que a marcação seja mantida. Caminhos `assets/...` precisam virar `get_template_directory_uri()`.

## 13. Pendências / dados faltando

- **Vídeo do hero**: já está em `assets/video/hero.mp4` (enviado pelo cliente: 1280×720, ~7s, 10,7MB). Para produção, considere recomprimir (H.264 ≤ 4MB) e adicionar `.webm`.
- Vídeo institucional do Sobre (`data-video`).
- Foto do José Claudio Vieira e fotos dos depoimentos (placeholders); depoimentos são *lorem ipsum* do Figma.
- Links reais: LinkedIn de cada liderança e da empresa; páginas ainda inexistentes (`areas-de-atuacao*.html`, `cases.html`, `carreiras.html`, `contato.html`).
- Ícone YouTube do footer existe vazio no Figma — omitido.

## PRÓXIMOS PASSOS

1. Páginas internas na ordem: Áreas de atuação → Saneamento (e demais) → Cases → Case interna → Contato → Carreiras. Cada uma: `src/pages/x.html` + `css/pages/x.css` (+ js se precisar), reaproveitando componentes. Pedir o `get_design_context` do nó correspondente.
2. Revisão final de acessibilidade (contraste do dourado `#9E7B3E` sobre `#F5F7FA` é ~3.7:1 → só para texto ≥ 18px/negrito ou decorativo).
3. Conversão para WordPress (§12).


## 14. Navegação (swup 4) e transições

- `js/vendor/swup.umd.js` + head-plugin (troca `<link>` de CSS por página). Container trocado: `<div id="swup" data-page="NOME">` (main + footer + modais). **Header/menu ficam fora** e persistem.
- Saída: cortina **#063D88** sobe cobrindo a página (0.85s, expo-out, com logo). Entrada: a cortina continua e sai por cima (1s) revelando o topo; os `.reveal` do topo disparam ~380ms depois (a "transição de entrada nos topos").
- Todo JS de página se registra com `Enpasa.page('nome', {init, destroy})` e o nome vem de `data-page`. `main.js` refaz reveal, zoom/parallax, sliders e tema do header a cada página. Todos os scripts são carregados em todas as páginas (`partials/scripts.html`); o CSS de página é trocado pelo head-plugin.
- Links ignorados pelo swup: `target="_blank"`, `#`, `mailto:`, `tel:`, `data-no-swup`. Requer servidor (não funciona em `file://`; cai para navegação normal).
- Hero da Home: vídeo **sem loop** (para no último frame). Após 4,5s sem interação rola até o texto e então o 1º bloco (só vídeo) é removido (`.hero.is-settled`): o texto vira o topo. Rolou antes → nada é forçado; voltou ao topo antes de completar → o relógio de 4,5s recomeça. Reduced-motion: já nasce "settled".
- Botão de menu: sem fundo; o fundo (claro em fundo escuro / azul em fundo claro) só aparece no hover/foco e com o menu aberto.
- Sobre: vídeo de fundo `assets/video/sobre-bg.webm` (placeholder do cliente, ~18MB, 4K — reduzir para produção) + lightbox do institucional.

## 15. Páginas internas — mapa

| Arquivo | Frame | Notas |
|---|---|---|
| `areas-de-atuacao.html` | 73:1562 | Hero + padrão, Saneamento (foto P&B), Outras áreas |
| `areas-de-atuacao-saneamento.html` | 38:2547 | Soluções (6), Diferenciais (4), banner P&B com zoom, cases-slider (partial) |
| `cases.html` | 73:4107 | Filtro por área (`data-cases-filter`, `.case-item[data-cat]`); 3 primeiros com foto, demais placeholder |
| `case-sao-lourenco.html` | 86:4512 | Hero com foto, escopo + metadados, destaques, números, 2 fotos P&B → cor ao centralizar (`data-color-on-view`) |
| `contato.html` | 86:6204 | Canais, escritório (mapa) |
| `carreiras.html` | 92:6742 | Cultura (4 valores), Vagas → LinkedIn da empresa |

## 16. WordPress (`_wordpress/`)

Homologação em https://enpasa.chuva.tech. Tema próprio com 20 blocos ACF (`enpasa/*`), um por seção, com o mesmo HTML deste site; o CSS e o JS vêm daqui por `_wordpress/build.sh`. Design system visual em `design-system.html` (`/design-system/` no WordPress). Detalhes e caminho para produção em `_wordpress/README.md`.
