# Usando o PharmData DS com Next.js

Este documento explica como consumir o PharmData Design System em aplicações Next.js através do pacote `ds-nextjs/`, e como pedir ao Claude (ou a qualquer desenvolvedor) que construa um novo app sobre essa base.

---

## 1. O que é o `ds-nextjs`

`ds-nextjs/` é um pacote Next.js 14 (App Router) que vive dentro do próprio repositório do design-system. Ele oferece **wrappers React finos** sobre as classes CSS do DS principal, sem duplicar nenhum token ou estilo. Quando você edita uma cor em `tokens/colors.css`, o Next pega a mudança no próximo build — Flask, Oracle APEX e Next bebem da mesma torneira.

**Princípios de design:**

- **Zero duplicação de CSS.** Todo estilo vem de `../tokens/index.css` via `postcss-import`. Os componentes React são casca fina sobre as classes do DS.
- **Dark mode sem flash.** Configurado via `next-themes` para escrever `<html class="dark-mode">` antes da hidratação — mesmo seletor usado pelo DS original.
- **Componentes com estado interno por padrão.** Accordions, tabs, modais gerenciam seu próprio estado; quando precisar controlar de fora, o modo controlado estará disponível como opção (padrão shadcn/Radix).
- **Server Components quando possível.** Componentes sem interatividade (drops, cards, skeleton, breadcrumb) rodam como Server Components — zero JS no bundle.

## 2. Como rodar o pacote

```bash
cd ds-nextjs
npm install    # primeira vez
npm run dev    # sobe em http://localhost:3100
```

A porta 3100 é fixa no `package.json` para não conflitar com o Vigília (porta 3000) e outros apps do ecossistema.

## 3. Componentes disponíveis no MVP

| Wrapper | Classes do DS consumidas |
|---|---|
| `<Drop variant>` | `.drop .drop-*` — drops farmacêuticos com ícone Font Awesome automático |
| `<Card title>` | Classes Tailwind do preset: `bg-cloud`, `border-soft-arctic`, `rounded-xl`, `shadow-md` |
| `<SkeletonLine width height>` | `.skeleton-line .skeleton-w-* .skeleton-h-*` |
| `<SkeletonSubstanceCard />` | `.skeleton-substance-card` + filhos |
| `<BreadcrumbPharma items>` | `.breadcrumb-pharma` — hierarquia Substâncias → Composições → Formulações → Embalagens → Apresentações |

Componentes ainda não portados (candidatos óbvios para próximas iterações): `Button`, `StatCard`, `FeatureCard`, `Stepper`, `WorkflowActions`, `Accordion`, `Tabs`, `Modal`, `Alert`, `Tooltip`.

Quando um wrapper novo for necessário, a regra é simples: o componente React só compõe classes do DS, nunca define estilos próprios.

## 4. Estrutura de um componente wrapper

Um wrapper típico parece com isto:

```tsx
// components/ds/Drop.tsx
import type { ReactNode } from "react";

export type DropVariant = "dec" | "sub" | "lab" | "cnc" | /* ... */;

export interface DropProps {
  variant: DropVariant;
  shape?: "pill" | "circle";
  size?: "sm" | "md" | "lg";
  children?: ReactNode;
}

export function Drop({ variant, shape = "pill", size = "sm", children }: DropProps) {
  const classes = ["drop", `drop-${variant}`, `drop-${shape}`, `drop-${size}`]
    .join(" ");
  return <span className={classes}>{children}</span>;
}
```

Nada de CSS-in-JS, nada de `style={{}}`, nada de classes inventadas. A única lógica é tipar as props e montar o `className` correto.

## 5. Dark mode

O provider em `components/theme-provider.tsx` configura `next-themes` para usar a classe `dark-mode` na tag `<html>`:

```tsx
<NextThemesProvider
  attribute="class"
  value={{ light: "light", dark: "dark-mode" }}
>
  {children}
</NextThemesProvider>
```

Isso ativa automaticamente todas as regras `html.dark-mode { ... }` do `tokens/dark-mode.css`. O botão de alternância está em `components/theme-toggle.tsx`. Qualquer app novo que herdar o layout já tem dark mode funcionando — basta usar as variáveis CSS ou as classes semânticas do preset (`bg-cloud`, `text-graphite-depth`, etc.).

## 6. Container e layout

Use a classe `.ds-container` definida em `app/globals.css` para qualquer wrapper que precise de largura máxima e padding consistente:

```tsx
<main>
  <div className="ds-container py-10">{children}</div>
</main>
```

A classe tem `max-width: 72rem`, `margin: auto`, e padding horizontal de 32 px (48 px a partir de 768 px). Ela é imune a regras globais do DS que possam afetar `main` ou seus descendentes diretos.

## 7. Como pedir para construir um novo app

Para que o Claude (ou qualquer desenvolvedor) construa um app novo sobre esta base, o prompt deve deixar três coisas explícitas:

### 7.1 Que é Next.js consumindo o `ds-nextjs`

Evita que o desenvolvedor caia no DS CSS puro (Flask/APEX) ou invente outro stack.

### 7.2 O que o app faz

Uma frase sobre o objetivo e quem usa. Não precisa de especificação detalhada — o contexto do ecossistema PharmData (Lector, PRISMA, RPDA) já é conhecido.

### 7.3 Onde mora o código novo

Dois caminhos possíveis:

- **Rota nova dentro de `ds-nextjs/app/X`** — mais rápido, ideal para protótipos e provas de conceito. O app compartilha dependências, layout e tema com as demos existentes.
- **Pasta nova em outro diretório importando de `ds-nextjs/components/ds/`** — para apps que vão virar produto. Exige um workspace pnpm ou link local, mas isola dependências e permite deploy independente.

### 7.4 Template de prompt

> "Cria um app Next.js usando o `ds-nextjs` como base de componentes para **[objetivo em uma frase]**. **[Rota nova em `ds-nextjs/app/X` | Pasta nova em `/caminho/Y` importando de `ds-nextjs`]**. Usuários: **[quem usa]**. Telas principais: **[lista curta]**."

### 7.5 Exemplos concretos

> "Cria um app Next.js usando o ds-nextjs para curadoria de substâncias ativas. Rota nova em `ds-nextjs/app/curadoria`. Usuário: farmacêutico curador do Lector. Telas: lista de substâncias pendentes, detalhe com evidence pack, ação de aprovar/rejeitar."

> "Cria um app Next.js separado em `/Users/eugenio/pharmdata/prisma-frontend` importando componentes do ds-nextjs. Objetivo: navegação hierárquica RPDA sobre o banco PRISMA. Telas: busca de substância, drill-down composição → formulação → embalagem → apresentação."

### 7.6 O que não precisa dizer

Os seguintes pontos são padrão e aplicados automaticamente:

- Usar tokens do DS em vez de cores hardcoded
- Dark mode automático via `html.dark-mode`
- Componentes com estado interno por padrão
- Server Components onde possível
- Português brasileiro nos textos da interface
- Sem emojis
- Credenciais via `~/.pharmdata.env` (nunca `.env` local)

### 7.7 O que vale mencionar quando aplicável

- **Banco de dados**, se o app precisa conectar ao Oracle (`PHD_DATA_*`, `PHD_APP_*`, `PRISMA_*`)
- **Autenticação**, se necessária
- **Nível de rigor**: protótipo descartável vs. produto real
- **Referências visuais**: telas no Pencil, showcase existente, ou screenshot de inspiração
- **Integração com HTMX/Flask existente**: se o app vai conviver com templates Flask legados

## 8. Migrando um app Next.js existente para o `ds-nextjs`

Quando já existe um app Next.js funcionando (com Tailwind padrão, shadcn/ui, ou CSS próprio) e você quer que ele passe a consumir o PharmData DS, o processo é uma **migração visual** — preservar rotas, APIs, lógica de negócio e comportamento, trocando apenas tokens, componentes e layout.

### 8.1 Três níveis de escopo

Escolha o escopo antes de disparar o prompt. Cada nível é um superset do anterior.

| Nível | O que muda | Esforço | Quando usar |
|---|---|---|---|
| **1. Só tokens** | Paleta, tipografia, spacing, border-radius. Componentes continuam como estão. | Baixo | App novo que acabou de sair de um starter, ainda sem muitos componentes customizados. Impacto visual grande com trabalho mínimo. |
| **2. Tokens + wrappers** | O nível 1 mais substituição de componentes equivalentes (`Button`, `Card`, drops, skeletons) pelos do `ds-nextjs`. | Médio | App consolidado com muitos componentes, mas que pode coexistir com shadcn/ui ou outros. |
| **3. Migração completa** | Tudo do nível 2 mais: dark mode via `next-themes` com classe `dark-mode`, layout com `.ds-container`, remoção de shadcn/ui e CSS custom que conflite. | Alto | App que vai virar produto oficial do ecossistema PharmData e precisa estar 100% alinhado. |

### 8.2 Template de prompt

> "Migra o app Next.js em **[caminho absoluto]** para usar o `ds-nextjs` do PharmData. Stack atual: **[stack resumido em uma frase]**. Escopo: **[só tokens | tokens + wrappers | migração completa]**. Preserva rotas, APIs e lógica de negócio — só troca o visual. **[Mantém independente | Move para dentro de ds-nextjs como rota]**."

### 8.3 O que mencionar junto

1. **Caminho absoluto do app.** Ex.: `/Users/eugenio/pharmdata/lector-web`.
2. **Stack atual resumido.** Uma frase é suficiente. Exemplos:
   - "Next 14 com Tailwind padrão e shadcn/ui"
   - "Next 13 com CSS Modules e paleta própria"
   - "Next 14 recém-criado via `create-next-app`, sem customização"
3. **Escopo da migração.** Um dos três níveis da tabela acima.
4. **Destino**: continua como app independente (o caso normal — ele apenas *consome* o DS) ou vira rota dentro do `ds-nextjs`.
5. **Exceções explícitas**, se houver. Ex.: "não toca nas telas de autenticação", "preserva o dashboard que acabei de entregar".

### 8.4 Exemplos concretos

**Exemplo 1 — Nível 1, protótipo recente:**

> "Migra o app Next.js em `/Users/eugenio/pharmdata/explorer` para usar o ds-nextjs. Stack atual: Next 14 recém-criado via `create-next-app`, Tailwind padrão, ainda sem componentes customizados. Escopo: só tokens. Mantém independente. Preserva rotas e APIs."

**Exemplo 2 — Nível 2, app consolidado:**

> "Migra o app Next.js em `/Users/eugenio/pharmdata/patos-ui` para usar o ds-nextjs. Stack atual: Next 14 com Tailwind e shadcn/ui. Escopo: tokens + wrappers. Substitui os botões, cards e badges pelos equivalentes do ds-nextjs; deixa os diálogos do shadcn como estão. Mantém independente. Não toca na tela de login."

**Exemplo 3 — Nível 3, migração completa:**

> "Migra o app Next.js em `/Users/eugenio/pharmdata/lector-web` para usar o ds-nextjs. Stack atual: Next 14, Tailwind com cinzas hardcoded, shadcn/ui, tema dark feito na mão. Escopo: migração completa. Remove shadcn, adota `next-themes` com classe `dark-mode`, envolve o layout com `.ds-container`, troca todas as cores hardcoded por tokens do DS. Mantém independente. Preserva rotas, APIs e lógica."

### 8.5 Como o Claude vai executar

Antes de tocar código, o Claude vai:

1. **Inventariar o app** — mapear rotas, componentes, uso de cores hardcoded, dependências de UI (shadcn/ui, Radix, Headless UI, etc.).
2. **Propor um plano em etapas** — tipicamente: (a) instalar `next-themes` e importar os tokens do DS; (b) atualizar `tailwind.config` com o preset; (c) substituir o layout raiz e o container; (d) migrar componentes um a um, começando pelos mais simples (Button, Card, Badge) antes dos complexos (Tabs, Modal, Form); (e) remover CSS custom e dependências redundantes.
3. **Pedir confirmação antes de mudanças destrutivas** — remover shadcn, apagar CSS custom, mudar estrutura de pastas.
4. **Verificar visualmente** — rodar o dev server e conferir as telas principais antes de declarar completo.

Se você quiser pular a etapa de plano e ir direto, adicione ao prompt: *"executa direto sem pedir confirmação, só me mostra o diff no final"*. Use com cuidado — só em apps pequenos onde você consegue revisar tudo de uma vez.

### 8.6 Migrando de Tailwind + HTMX (Flask) para Next.js

Este é o caso específico de apps PharmData atuais: templates Jinja/Flask servindo HTML renderizado no servidor, Tailwind via CDN, HTMX para interatividade parcial (swaps, lazy loading, formulários). A migração para Next não é um simples "troca de framework" — muda o modelo mental inteiro: de *servidor renderiza tudo e manda pedaços* para *cliente pede dados via API e monta o HTML localmente*.

#### 8.6.1 O que a migração envolve

- **Rotas Flask → rotas Next.** Cada `@app.route("/x")` vira uma página em `app/x/page.tsx`.
- **Templates Jinja → componentes React.** Blocos `{% if %}` viram `{condicao && ...}`; loops `{% for %}` viram `.map()`; `{% extends %}` vira o `layout.tsx`.
- **HTMX swaps → Server Components + Server Actions** (ou rotas de API). A maioria dos `hx-get` vira Server Component renderizando no servidor; os `hx-post` viram Server Actions (`"use server"`).
- **Backend Flask continua vivo.** O Next não substitui o Flask de cara. Padrão recomendado: Flask vira API (`/api/*`) e o Next consome via `fetch` nos Server Components. Ou, se o app Flask for pequeno, a lógica migra junto para Route Handlers do Next (`app/api/*/route.ts`).
- **Jinja filters customizados → funções TypeScript.** Filtros tipo `|format_date`, `|drop_class` viram helpers em `lib/formatters.ts`.
- **Autenticação via session Flask → `next-auth` ou equivalente.** Migração exige planejamento separado; raramente é escopo do mesmo PR.

#### 8.6.2 Decisões que precisam ser tomadas antes

1. **Flask continua ou desaparece?**
   - *Continua como API*: o Next só vira frontend, consumindo endpoints REST do Flask. Migração rápida, backend intocado.
   - *Desaparece*: toda a lógica do Flask (rotas, queries Oracle, scrapers) migra para Route Handlers do Next ou para um backend Python separado (FastAPI). Migração pesada, mas monólito final mais limpo.
2. **Migração big-bang ou incremental?**
   - *Big-bang*: app Flask vira legado, Next sobe do zero com paridade de telas. Arriscado em apps grandes.
   - *Incremental*: Next e Flask convivem por um tempo, Next absorve rotas uma a uma. Reverse proxy (nginx ou middleware Next) roteia pelo caminho. Mais seguro.
3. **HTMX interativo vs. React interativo.** HTMX faz interatividade com HTML puro; React faz com estado. Nem tudo que era `hx-swap` precisa virar `useState` — muitos casos resolvem com Server Components + revalidação (`revalidatePath`). A regra: se a interação só muda o que aparece na tela com base em dados do servidor, use Server Component. Se muda com base em input do usuário no cliente (filtros, forms com validação ao vivo), use Client Component.
4. **Oracle: conexão direta do Next ou via Flask?** Se Flask continua como API, ele mantém a conexão. Se Flask desaparece, o Next precisa de um driver Oracle em Node — possível (`oracledb`), mas adiciona complexidade. Padrão recomendado para o ecossistema PharmData: **manter Flask como camada de API para o Oracle**, Next só como frontend.

#### 8.6.3 Template de prompt

> "Migra o app Flask+HTMX em **[caminho absoluto do Flask]** para Next.js usando o `ds-nextjs` do PharmData. Backend Flask: **[continua como API | desaparece, lógica vai para Route Handlers do Next]**. Estratégia: **[big-bang | incremental, começando pelas rotas X e Y]**. Destino do código Next: **[pasta nova em /caminho/Z | rota dentro de ds-nextjs/app/Z]**. Telas a migrar nesta primeira rodada: **[lista curta]**. Autenticação: **[manter Flask session via proxy | migrar depois, fora deste escopo]**. Preserva URLs públicas (usuários não podem perceber mudança de rota)."

#### 8.6.4 Exemplos concretos

**Exemplo A — Incremental, Flask continua como API:**

> "Migra o app Flask+HTMX em `/Users/eugenio/pharmdata/lector` para Next.js usando o ds-nextjs. Backend Flask continua como API — expõe os endpoints `/api/substancias`, `/api/evidence-packs`, `/api/curadoria` e o Next consome via fetch. Estratégia incremental: nesta rodada só migra a tela de lista de substâncias pendentes (`/curadoria/pendentes`) e a tela de detalhe (`/curadoria/<id>`). Destino: pasta nova em `/Users/eugenio/pharmdata/lector-next`. Autenticação: mantém Flask session, Next faz proxy. Preserva as URLs públicas — o nginx vai rotear `/curadoria/*` para o Next e o resto continua no Flask."

**Exemplo B — Big-bang, app pequeno, tudo migra:**

> "Migra o app Flask+HTMX em `/Users/eugenio/pharmdata/patos-viewer` para Next.js usando o ds-nextjs. Backend Flask desaparece — a lógica de queries Oracle vai para Route Handlers em `app/api/*/route.ts` do Next usando o driver `oracledb`. Estratégia big-bang: migra as 4 telas existentes de uma vez. Destino: pasta nova em `/Users/eugenio/pharmdata/patos-next`. Autenticação: ainda não existe no app atual, fica fora do escopo. Credenciais Oracle via `~/.pharmdata.env`."

**Exemplo C — Rota dentro do `ds-nextjs`, protótipo descartável:**

> "Migra a tela `/explorador/substancias` do Flask em `/Users/eugenio/pharmdata/lector` para uma rota nova dentro do `ds-nextjs` em `app/explorador/substancias`. É protótipo para mostrar em reunião, não precisa de API — usa dados mockados em `lib/mock-substancias.ts` replicando a estrutura que o Flask retorna hoje. Não toca no app Flask original."

#### 8.6.5 Como o Claude vai executar

1. **Mapeamento do Flask original** — lista rotas (`@app.route`), templates Jinja usados, blocos HTMX (`hx-get`, `hx-post`, `hx-swap`, `hx-target`), filtros Jinja customizados, dependências Python.
2. **Propor mapeamento para Next** — tabela de "rota Flask → arquivo Next", "template Jinja → componente React", "endpoint HTMX → Server Component ou Route Handler". Pede confirmação antes de começar a escrever código.
3. **Configuração do Next** — cria `ds-nextjs`-like setup (Tailwind preset, globals.css com tokens, `next-themes`, `.ds-container`) ou importa do `ds-nextjs` via workspace.
4. **Migração tela a tela** — começa pela mais simples (lista estática), valida visualmente, depois as interativas.
5. **Paridade visual** — roda Flask e Next lado a lado, compara screenshot. Só declara completa quando bate.
6. **Pede review antes de deletar Flask** — nunca apaga código Flask sem confirmação explícita.

#### 8.6.6 Armadilhas específicas da migração Flask → Next

- **HTMX `hx-swap="innerHTML"` não é React.** Em HTMX você troca o HTML interno de um div; em React você atualiza estado e deixa o diff virtual cuidar. Traduzir literalmente dá código anti-idiomático.
- **Jinja `{% include %}` vira componente React, não `import`.** Um include Jinja é um bloco de HTML reutilizável — o equivalente React é um componente que recebe props, não um import de arquivo.
- **CSRF tokens do Flask não existem no Next.** Next tem seu próprio modelo (Server Actions têm proteção automática). Se o backend Flask continua, os Route Handlers do Next precisam repassar o CSRF token para as chamadas autenticadas.
- **Sessões Flask + rotas Next no mesmo domínio.** Cookies de sessão do Flask são lidos pelo Next via `cookies()` no Server Component, mas a validação precisa bater com a lógica Flask — exige compartilhar `SECRET_KEY` ou um endpoint `/api/whoami` no Flask que o Next chama.
- **URLs internas hardcoded nos templates.** `{{ url_for('view_substancia', id=123) }}` do Jinja vira string literal no React — precisa ser catalogado e trocado por helpers tipados (`routes.substancia(id)`).
- **HTMX `hx-trigger="load"` usado para lazy loading.** Em Next vira `Suspense` com Server Component que faz o fetch — padrão diferente, resultado final mais limpo.

---

### 8.7 Armadilhas comuns a evitar

- **Shadcn/ui + tokens do DS ao mesmo tempo.** Funciona, mas gera CSS duplicado e conflitos de cor. Se adotar o DS, remova o shadcn gradualmente.
- **Dark mode com duas fontes de verdade.** Se o app já tem dark mode feito na mão via `class="dark"`, migrar para `class="dark-mode"` exige trocar todos os seletores. O Claude faz isso automaticamente no nível 3, mas não no nível 1.
- **Importar CSS do DS duas vezes.** O preset Tailwind e o import de `tokens/index.css` cobrem coisas diferentes — o primeiro é para classes utilitárias, o segundo é para as variáveis CSS e os componentes. Ambos são necessários; não é duplicação.
- **Cores hardcoded em arquivos não-CSS.** Valores em strings JavaScript (ex.: `color: '#fff'` em um `style={{}}`) escapam da validação do DS. O Claude deve procurar e trocar por `var(--cloud)` ou remover o inline style.

---

## 9. Quando adicionar um componente ao `ds-nextjs`

Se o app novo precisa de um componente que ainda não tem wrapper React:

1. **Verifique se o componente já existe como CSS** no DS principal (`tokens/`, `src/components/`). Se sim, criar o wrapper é trivial.
2. **Se não existir no DS**, ele deve ser adicionado primeiro lá — nunca no app. A regra do CLAUDE.md global aplica: "Se algo não existe no DS mas é necessário, informar para adicionar diretamente no DS — nunca improvisar no app."
3. **O wrapper React mora em `ds-nextjs/components/ds/<Nome>.tsx`** e é re-exportado pelo `index.ts`.

## 10. Princípio de durabilidade — CSS é ativo, React é conveniência

O ecossistema React/Next escolheu velocidade de iteração sobre estabilidade. Cada major quebra o contrato com as libs downstream: Next 14 → 16 em menos de dois anos, React 18 → 19 mudando APIs de Server Components, peer deps que travam `npm install` por causa de uma linha no `package.json`. Não é acidente — é o modelo de desenvolvimento assumindo que todo mundo atualiza junto, o que nunca acontece num ecossistema real com apps em estágios diferentes.

O PharmData DS responde a isso com uma separação deliberada entre dois ativos de naturezas diferentes:

- **DS como CSS é o ativo durável.** Tokens (`tokens/index.css`), preset Tailwind e classes de componentes são imunes a mudanças de versão de React ou Next. São texto, não código executável. Um app em Next 14, outro em Next 16, um legado em Flask+Jinja — todos consomem o mesmo CSS sem negociação de versão. É onde mora o valor real do DS.
- **DS como componentes React (`ds-nextjs`) é conveniência de curto prazo.** Os wrappers poupam digitar `className` e adicionam tipos, mas acoplam o app a uma versão específica de React/Next. Quando a conveniência começa a custar mais do que o benefício — caso do Vigília em Next 16 consumindo wrappers em Next 14 — volte ao ativo durável.

**Regras práticas que decorrem desse princípio:**

1. **Separar CSS de JS no consumo.** Toda vez que um app puder consumir o DS como CSS (tokens + preset Tailwind) em vez de como componente React importado, uma dimensão inteira de incompatibilidade desaparece. Prefira essa rota sempre que houver qualquer atrito de versão.
2. **Tratar wrappers React como código descartável.** Os wrappers do `ds-nextjs` são cascas finas de ~10 linhas, sem estado, sem lógica. Copiar os arquivos para dentro do app consumidor em vez de importar via workspace não é dívida técnica — é desacoplamento barato. A dívida só existiria se os wrappers tivessem lógica complexa, e por design eles nunca têm.
3. **Pinar versões e atualizar deliberadamente.** Nunca deixar o `^` do npm resolver peer deps sozinho entre apps que estão em versões diferentes de Next. Enquanto o contrato entre um app e o DS for só CSS, cada um pode ser atualizado no seu tempo.
4. **Aceitar que o `ds-nextjs` vai envelhecer.** Ele é um MVP. Se daqui a alguns meses ele estiver em Next 14 e o resto do ecossistema em Next 17, não é problema: atualiza-se quando um app novo precisar, ou aposenta-se o pacote e mantém-se apenas os tokens CSS. O core do DS não depende de framework nenhum e nunca vai depender.

Essa separação é o que permite que o DS atenda simultaneamente Flask+Jinja, Oracle APEX, HTML estático e Next.js sem virar refém de nenhum deles. Quando um framework quebra, o ativo durável segue intacto.

---

## 11. Limitações conhecidas

- **Tailwind CDN não é usado.** O `ds-nextjs` tem Tailwind instalado via npm (necessário para Next.js). O preset TypeScript em `tailwind.config.ts` espelha `integrations/tailwind-preset/tailwind.config.js`; quando um deles for alterado, o outro precisa ser atualizado manualmente. Considerar extrair um preset compartilhado no futuro.
- **Font Awesome via CDN.** O `globals.css` faz `@import` da CDN. Para apps em produção sem internet, trocar por `@fortawesome/fontawesome-free` instalado via npm.
- **Os componentes interativos ainda não existem.** Accordion, Tabs, Modal, Stepper precisam ser portados quando forem usados pela primeira vez. A decisão de API (controlada vs. não-controlada) é tomada tela a tela.

---

*Documento criado em 2026-04-12. Atualizado em 2026-04-12 com a seção 10 sobre princípio de durabilidade (CSS como ativo, React como conveniência). Atualizar sempre que a arquitetura do `ds-nextjs` mudar ou quando novos componentes forem portados.*
