[idea:rookery-timeline]

    @rookery/timeline

    Keeps a dated lifecycle log on the tags of an idea, from when it was created to whatever stages a ladder of its own names, and draws the rail that orders them.

    A lifecycle is a dictionary of stage names to dates, folded into the note’s own tags, so it travels with the note and any view that can read tags can read it.

    #import "@rookery/core:0.1.0": idea, rookery
    #import "@rookery/timeline:0.1.0": timeline-tags, timeline-view
    #show: rookery
    
    #let NOW = datetime(year: 2027, month: 1, day: 5)
    
    /* Three stage names are reserved: scheduled, deadline and closed. Every other
       rung is vocabulary you invent for the thing you are tracking. A stage may
       also be a dictionary rather than a bare date, needing a timestamp: and
       taking an optional note:. */
    #let wolf = timeline-tags(
      deadline: datetime(year: 2026, month: 11, day: 1),
      timeline: (
        submitted:         datetime(year: 2026, month: 10, day: 28),
        longlisted:        datetime(year: 2026, month: 12, day: 15),
        "first-interview": datetime(year: 2027, month: 1, day: 20),
      ),
    )
    
    #idea("wolf", tags: wolf)[A round in flight.]
    #timeline-view((created: datetime(year: 2026, month: 10, day: 1)), wolf, today: NOW)

    Taking the dates as arguments

    The package also ships a skin, so the stages can be arguments instead of a fragment you merge yourself.

    #import "@rookery/timeline:0.1.0": idea, rookery, window
    
    /* Writing the same stage twice, once as an argument and again inside
       timeline:, is an error rather than a last-one-wins. Number a stage that
       genuinely happens more than once (review-1, review-2) and match it with a
       review-* family rung. */
    #idea("ship", deadline: d, timeline: (submitted: d2))[Cut the release.]