diff --git a/CHANGELOG.md b/CHANGELOG.md
index 456a8f6..9b13015 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,48 +1,76 @@
# Changelog
-All notable changes to this project are documented in this file.
+Todas as mudanças relevantes deste projeto são documentadas aqui.
-This project follows Semantic Versioning.
+Este projeto segue o Versionamento Semântico.
+
+## [0.2.0] - 2026-02-19
+
+### Adicionado
+
+- Modo headless: passar `null` (ou `undefined`) como `target` executa a animação sem nenhum elemento DOM. Os valores são entregues exclusivamente pelo callback `onUpdate`. Permite uso em Node.js, frameworks SSR (Next.js, Nuxt, Remix) e ambientes de teste sem jsdom.
+- Adicionada opção `sleep` (número em ms): tempo de espera antes de a animação iniciar. `0` (padrão) mantém o comportamento atual. O timer é cancelado automaticamente por `stop()`, `pause()` e `destroy()`. Útil para escalonar múltiplos contadores sem `setTimeout` manual.
+- Adicionado getter `waiting` nas instâncias: retorna `true` enquanto o `sleep` estiver pendente.
+- `end` agora é opcional quando um elemento DOM é fornecido. A biblioteca lê o `element.textContent`, remove caracteres não numéricos e usa o valor parseado como destino da animação — um valor renderizado pelo servidor (ex.: PHP) já é suficiente, sem configuração extra.
+- `decimals` agora é inferido automaticamente do texto do elemento quando ambos `end` e `decimals` são omitidos (ex.: elemento com `"15.50"` define `decimals: 2` automaticamente).
+- Adicionadas declarações TypeScript nativas (`src/counterup.d.ts`): tipos completos para `CounterUpOptions`, `CounterUpInstance`, `CounterUpGroupInstance`, `CounterUpTarget`, `EasingFunction`, `FormatterFunction` e `CounterUpCallback`, com overloads precisos que diferenciam instância única (target `null` ou `Element`) de instância de grupo (seletor, `NodeList`, array). Sem dependência de `@types/*`.
+
+### Corrigido
+
+- Corrigido `ReferenceError: requestAnimationFrame is not defined` em ambientes sem browser, introduzindo polyfills internos `raf`/`caf` que usam `setTimeout`/`clearTimeout` com `Date.now()` como timestamp.
+- Corrigido `ReferenceError: document is not defined` ao passar um seletor CSS string em ambientes sem DOM. Agora é lançado um erro claro e acionável.
+- Corrigido `TypeError: Cannot set properties of undefined` no wrapper UMD quando carregado como ES module em Node.js (pacotes com `"type": "module"`). O contexto global agora usa `globalThis` como alvo primário, com `window` e `this` como fallback.
+- Corrigido `TypeError: Cannot set property 'textContent' of null` quando `element` é `null` em modo headless. A função `render` agora protege a escrita no DOM.
+- Corrigido `setupObserver` tentando chamar `IntersectionObserver.observe(null)` em modo headless. A configuração do observer agora é ignorada quando não há elemento.
+
+### Alterado
+
+- O global UMD agora é `counterUp` (a função diretamente) em vez de `CounterUp` (um objeto namespace). O uso via `
```
+---
+
## API
### `counterUp(target, options)`
-`target`: seletor CSS, elemento DOM, `NodeList` ou array de elementos.
+**`target`** — o que animar:
+
+| Tipo | Exemplo | Comportamento |
+|---|---|---|
+| `string` | `"#id"`, `".classe"` | Seleciona via `document.querySelectorAll` |
+| `Element` | `document.getElementById("x")` | Usa o elemento diretamente |
+| `NodeList` / `HTMLCollection` | `document.querySelectorAll(".x")` | Anima todos os elementos |
+| `Element[]` | `[el1, el2]` | Anima todos os elementos do array |
+| `null` / `undefined` | `null` | **Modo headless** — sem DOM, use `onUpdate` |
+
+---
+
+### Opções
+
+#### Valores
+
+| Opção | Tipo | Padrão | Descrição |
+|---|---|---|---|
+| `start` | `number` | `0` | Número de onde a animação parte. O contador começa exibindo este valor. |
+| `end` | `number` | auto | Número até onde a animação conta. **Quando omitido**, a biblioteca lê o `textContent` do elemento e usa esse valor como destino — ou seja, o valor já renderizado no HTML é suficiente. Necessário em modo headless. |
+| `duration` | `number` | `2000` | Tempo total da animação em milissegundos. `0` pula diretamente para o valor de `end`. |
+
+#### Formatação
+
+| Opção | Tipo | Padrão | Descrição |
+|---|---|---|---|
+| `decimals` | `number` | auto | Quantidade de casas decimais exibidas. **Quando omitido** junto com `end`, é inferido automaticamente do `textContent` do elemento (ex.: `"15.50"` → `2`). |
+| `prefix` | `string` | `""` | Texto adicionado **antes** do número (ex.: `"R$ "`, `"$"`). |
+| `suffix` | `string` | `""` | Texto adicionado **depois** do número (ex.: `"%"`, `" pts"`). |
+| `locale` | `string` | `"pt-BR"` | Locale para `Intl.NumberFormat`. Controla separadores decimais e de milhar (ex.: `"en-US"`, `"de-DE"`). |
+| `useGrouping` | `boolean` | `true` | Exibe separador de milhar conforme o locale (`1.000` vs `1000`). |
+| `formatter` | `function \| null` | `null` | Função de formatação personalizada. Substitui toda a lógica de formatação padrão. Recebe `(value, element, index)` e deve retornar uma string. |
+
+#### Animação
+
+| Opção | Tipo | Padrão | Descrição |
+|---|---|---|---|
+| `easing` | `string \| function` | `"easeOutCubic"` | Curva de aceleração da animação. Strings aceitas: `"linear"`, `"easeInOutQuad"`, `"easeOutCubic"`. Também aceita uma função `(t: number) => number` onde `t` vai de `0` a `1`. |
+
+#### Comportamento
+
+| Opção | Tipo | Padrão | Descrição |
+|---|---|---|---|
+| `sleep` | `number` | `0` | Tempo de espera em milissegundos antes de a animação começar. `0` inicia imediatamente. Útil para escalonar múltiplos contadores ou aguardar após um elemento entrar na viewport. O sleep é cancelado se `.stop()`, `.pause()` ou `.destroy()` for chamado antes de ele disparar. |
+| `autostart` | `boolean` | `true` | Inicia a animação automaticamente ao criar a instância. Se `false`, a animação fica aguardando uma chamada manual a `.start()`. |
+| `startOnView` | `boolean` | `false` | Usa `IntersectionObserver` para iniciar a animação somente quando o elemento entra na viewport. Ignorado em modo headless (sem DOM). |
+| `once` | `boolean` | `true` | Usado com `startOnView`: se `true`, a animação dispara apenas na primeira vez que o elemento aparecer. Se `false`, reinicia toda vez que o elemento entrar na viewport. |
+
+#### IntersectionObserver (usado com `startOnView`)
+
+| Opção | Tipo | Padrão | Descrição |
+|---|---|---|---|
+| `root` | `Element \| null` | `null` | Elemento raiz do `IntersectionObserver`. `null` usa o viewport da janela. |
+| `rootMargin` | `string` | `"0px"` | Margem ao redor do root, no formato CSS (ex.: `"0px 0px -100px 0px"`). Permite disparar antes ou depois do elemento estar completamente visível. |
+| `threshold` | `number \| number[]` | `0.1` | Fração do elemento que precisa estar visível para disparar. `0.1` = 10%, `1` = 100% visível. |
+
+#### Callbacks
+
+| Opção | Tipo | Descrição |
+|---|---|---|
+| `onUpdate` | `function \| null` | Chamado a cada frame da animação com `(value, element, index)`. `element` é `null` em modo headless. |
+| `onComplete` | `function \| null` | Chamado uma vez quando a animação termina com `(value, element, index)`. `element` é `null` em modo headless. |
+
+---
+
+### Instância — elemento único
+
+#### Métodos
+
+| Método | Descrição |
+|---|---|
+| `.start()` | Inicia a animação. Se estiver pausada, retoma do ponto onde parou. Se já estiver rodando, não faz nada. |
+| `.pause()` | Pausa a animação preservando o progresso atual. |
+| `.resume()` | Retoma a animação do ponto em que foi pausada. |
+| `.stop()` | Para a animação e reseta o progresso interno (mas não o valor exibido). |
+| `.reset()` | Para a animação e volta o valor exibido para `start`. |
+| `.set(value)` | Define o valor exibido diretamente, sem animação. Para qualquer animação em curso. |
+| `.update(nextEnd, nextOptions?)` | Muda o valor final (e opcionalmente outras opções) e reinicia a animação do valor atual. |
+| `.destroy()` | Para a animação, desconecta o observer e marca a instância como destruída. Chamadas subsequentes são ignoradas. |
+
+#### Getters
+
+| Getter | Tipo | Descrição |
+|---|---|---|
+| `.value` | `number` | Valor numérico atual (sem formatação). |
+| `.running` | `boolean` | `true` se a animação estiver em execução. |
+| `.paused` | `boolean` | `true` se a animação estiver pausada. |
+| `.waiting` | `boolean` | `true` se a animação estiver aguardando o `sleep` disparar. |
-`options`:
+---
-- `start` (number, padrão `0`)
-- `end` (number, padrão `100`)
-- `duration` (number em ms, padrão `2000`)
-- `decimals` (number, padrão `0`)
-- `prefix` (string)
-- `suffix` (string)
-- `locale` (string, padrão `pt-BR`)
-- `useGrouping` (boolean, padrão `true`)
-- `easing` (`"linear"` | `"easeInOutQuad"` | `"easeOutCubic"` | function)
-- `formatter` (function)
-- `autostart` (boolean, padrão `true`)
-- `startOnView` (boolean, padrão `false`): inicia quando o elemento entra na viewport
-- `once` (boolean, padrão `true`): com `startOnView`, anima apenas uma vez
-- `root` (Element|null, padrão `null`): root do `IntersectionObserver`
-- `rootMargin` (string, padrão `"0px"`): margem do `IntersectionObserver`
-- `threshold` (number|number[], padrão `0.1`): threshold do `IntersectionObserver`
-- `onUpdate` (function)
-- `onComplete` (function)
+### Instância de grupo — múltiplos elementos
-`formatter`, `onUpdate` e `onComplete` recebem: `(value, element, index)`.
+Retornada quando `target` resolve para mais de um elemento.
-### Instância (1 elemento)
+#### Métodos
-Métodos: `start()` (inicia ou retoma se pausado), `pause()`, `resume()`, `stop()`, `reset()`, `set(value)`, `update(nextEnd, nextOptions?)`, `destroy()`
+Os mesmos da instância única, aplicados a todos os elementos:
+`start()`, `pause()`, `resume()`, `stop()`, `reset()`, `destroy()`
-Getters: `value`, `running`, `paused`
+**`set(value | value[])`** — aceita um único valor (aplicado a todos) ou um array (um valor por elemento).
-### Instância de grupo (vários elementos)
+**`update(nextEnd | nextEnd[], nextOptions?)`** — aceita um único valor final ou um array de valores finais.
-Métodos: `start()`, `pause()`, `resume()`, `stop()`, `reset()`, `set(value|array)`, `update(nextEnd|array, nextOptions?)`, `destroy()`
+#### Getters
-Getters: `values`, `running`, `paused`, `count`
+| Getter | Tipo | Descrição |
+|---|---|---|
+| `.values` | `number[]` | Array com o valor atual de cada elemento. |
+| `.running` | `boolean` | `true` se ao menos um elemento estiver animando. |
+| `.paused` | `boolean` | `true` se ao menos um elemento estiver pausado. |
+| `.waiting` | `boolean` | `true` se ao menos um elemento estiver aguardando o `sleep` disparar. |
+| `.count` | `number` | Quantidade de elementos no grupo. |
-## Build (somente para desenvolvimento da biblioteca)
+---
+
+### Exemplos de controle manual
+
+```js
+const counter = counterUp("#score", { end: 500, autostart: false });
+
+// Inicia manualmente
+counter.start();
+
+// Pausa e retoma
+counter.pause();
+counter.resume();
+
+// Muda o valor exibido sem animação
+counter.set(250);
+
+// Muda o alvo e reinicia a animação
+counter.update(1000, { duration: 800 });
+
+// Lê o valor atual em qualquer momento
+console.log(counter.value);
+
+// Libera recursos ao remover o componente
+counter.destroy();
+```
+
+---
+
+## TypeScript
+
+O pacote inclui declarações nativas em `src/counterup.d.ts`. Nenhuma instalação extra é necessária.
+
+```ts
+import { counterUp } from "@nullsablex/counter-up";
+import type {
+ CounterUpOptions,
+ CounterUpInstance,
+ CounterUpGroupInstance,
+} from "@nullsablex/counter-up";
+
+// Instância única — tipo inferido automaticamente
+const counter: CounterUpInstance = counterUp("#total", {
+ end: 1000,
+ duration: 1500,
+ prefix: "R$ ",
+ decimals: 2,
+ onComplete: (value) => console.log("Fim:", value),
+});
+
+// Modo headless — target null → CounterUpInstance garantido
+const headless: CounterUpInstance = counterUp(null, {
+ start: 0,
+ end: 100,
+ duration: 2000,
+ onUpdate: (value) => updateProgressBar(value),
+});
+
+// Opções reutilizáveis com tipagem
+const opts: CounterUpOptions = {
+ duration: 1800,
+ easing: "easeOutCubic",
+ locale: "en-US",
+};
+
+counterUp(".metric", opts);
+```
+
+### Tipos exportados
+
+| Tipo | Descrição |
+|---|---|
+| `CounterUpOptions` | Interface completa de opções |
+| `CounterUpInstance` | Instância retornada para elemento único ou headless |
+| `CounterUpGroupInstance` | Instância retornada para múltiplos elementos |
+| `CounterUpTarget` | União de todos os tipos aceitos como `target` |
+| `EasingFunction` | `(t: number) => number` |
+| `FormatterFunction` | `(value, element, index) => string` |
+| `CounterUpCallback` | Assinatura de `onUpdate` e `onComplete` |
+
+---
+
+## Build (desenvolvimento da biblioteca)
```bash
npm run build
@@ -138,20 +327,24 @@ npm run build
Arquivos gerados em `dist/`:
-- `counterup.esm.js`
-- `counterup.esm.min.js`
-- `counterup.umd.js`
-- `counterup.umd.min.js`
+- `counterup.esm.js` — ESM sem minificação
+- `counterup.esm.min.js` — ESM minificado
+- `counterup.umd.js` — UMD sem minificação
+- `counterup.umd.min.js` — UMD minificado (indicado para uso via `
+