# countdown@0.1

**Status:** normative. **Inherits:** [`../conventions.md`](../conventions.md) — envelope,
preservation rules, safe rendering, and shared diagnostic codes `MDTO001`–`MDTO099`. It does
**not** inherit the shared item model: a countdown has no items.
**Schema:** [`schema.json`](schema.json). **Fixtures:** [`fixtures/`](fixtures/).
**Owns diagnostic codes:** `MDTO600`–`MDTO699`.

**Companion skill:** [Authoring and editorial guidance](https://markdownto.ai/specs/countdown.skill.md) (non-normative).

---

## 1. Purpose

`countdown@0.1` describes an **absolute-target countdown**: a moment with a title and useful
Markdown context that becomes a live, accessible timer without ceasing to be a readable document.
The target is an RFC 3339 timestamp with an explicit offset, so every reader counts toward the same
instant and no renderer guesses a timezone.

---

## 2. Grammar

### 2.1 Envelope

```yaml
---
markdownto: countdown@0.1
title: Artemis launch window
target: 2027-02-03T18:30:00Z
precision: seconds
completion-message: The window is open.
---
```

| Key | Type | Meaning |
|---|---|---|
| `target` | RFC 3339 date-time | Required destination instant; `Z` or an explicit numeric offset is mandatory. |
| `precision` | `seconds` \| `minutes` | Smallest displayed unit. Optional; default `seconds`. |
| `completion-message` | non-empty string | Message shown when the target is reached. Optional; default `Time is up.` |

A wrong YAML type is shared `MDTO007`. A missing target is `MDTO600`; a string that is not a real,
offset-qualified RFC 3339 instant is `MDTO601`; an unknown precision is `MDTO602`; and an empty
completion message is `MDTO603`.

### 2.2 Document structure

`##` means a **supporting section** — context, agenda, travel notes, launch criteria, or anything a
person needs beside the clock. One optional leading `#` title heading is allowed before other body
content. A later `#`, or any heading deeper than `##`, is `MDTO604`; an empty `##` is `MDTO605`.
Ordinary GFM blocks beneath sections are content. They carry no timer state and may include lists,
quotes, code, tables, links, and images. A countdown has no items, so task checkboxes are ordinary
Markdown content and no item diagnostic fires.

The timer has three deterministic states relative to a caller-supplied `now`: `upcoming` when
`now < target`, `complete` otherwise, and `invalid` only when validation already failed. Displayed
units are days, hours, minutes, and (for `precision: seconds`) seconds. Values never go negative.

### 2.3 Canonical IR

The IR sits at `result.countdown`, beside `result.document`. It carries the target string exactly as
written, `targetEpochMs`, the effective precision and completion message, supporting sections with
their source spans, the complete frontmatter map, and the document position. Serialization is the
identity function over the original bytes.

### 2.4 Diagnostics

| Code | Severity | Meaning |
|---|---|---|
| `MDTO600` | error | Required frontmatter key `target` is missing. |
| `MDTO601` | error | `target` is not a real RFC 3339 date-time with `Z` or an explicit offset. |
| `MDTO602` | error | `precision` is not `seconds` or `minutes`. |
| `MDTO603` | error | `completion-message` is empty. |
| `MDTO604` | error | Heading level is invalid; only one leading `#` and `##` sections are structural. |
| `MDTO605` | error | A `##` supporting section has no name. |

---

## 3. Rationale

**Why an absolute target.** A duration such as "three hours" needs a hidden start instant, pause
state, and persistence policy. An absolute date-time is already complete state: two offline readers
agree, a refresh loses nothing, and git history remains meaningful.

**Why the offset is mandatory.** A date-time without one is a local wall-clock reading, not an
instant. Guessing the reader's timezone makes a countdown look precise while disagreeing by hours.

**Why the prose stays first-class.** A timer is rarely useful alone. The launch criteria, event link,
or cooking instructions remain readable in any Markdown viewer; the live view intensifies the same
file instead of replacing it.

**Relationship to the shared item model.** None: the document's repeated units are display digits,
not authored items. A checkbox written in the body is ordinary content and is never re-read as timer
state.

---

## 4. Examples

Minimal valid file:

```markdown
---
markdownto: countdown@0.1
target: 2027-01-01T00:00:00Z
---

The new year begins everywhere at the instant above.
```

Invalid target (`MDTO601` on line 3):

```markdown
---
markdownto: countdown@0.1
target: 2027-01-01 00:00
---
```

---

## 5. Verb reference

`countdown@0.1` owns the vocabulary **status**.

| Verb | Signature | Source edit |
|---|---|---|
| `status` | `mdto countdown status [--at <RFC3339>]` | None. Reports the target, state, and remaining units at the sampled instant. |

`mdto countdown status --at ...` is deterministic and offline. Its JSON form emits
`{target, at, state, remainingMs, days, hours, minutes, seconds}`. The HTML renderer exposes the
same state continuously: it updates once per declared precision, announces completion once through
an ARIA live region, pauses updates while the page is hidden, and catches up when it becomes visible.

### Common flags

`--file <path>` · `--at <RFC3339>` · `--json` · `--help`
