# 016 — Bookmark reading anchor

**Status:** Implemented  
**Created:** 2026-06-04  
**See also:** [015 — EPUB bookmarks and notes](015-epub-bookmarks-notes.md)

## Objective

Let users jump to a bookmark to review a passage without overwriting their true reading position. While peeking, show a high-visibility control to return to where they were reading.

## Definitions

| Term | Meaning |
|------|---------|
| **Reading anchor** | EPUB CFI (+ optional %) captured immediately before a bookmark peek |
| **Peek mode** | Temporary view at a bookmark location; server `ReadingProgress` is not updated |
| **Resume** | Jump back to the reading anchor and re-enable progress persistence |

## Problem (before)

“Go to passage” called `jumpToCfi`, which triggered `locationChanged` and debounced `PATCH /books/ebooks/{id}/progress/`, replacing `epub_location` and `current_position` with the bookmark. Library progress and the next reading session started at the bookmark instead of the real position.

## Triggers (enter peek mode)

- In-reader: **Go to passage** in [`BookMarkersPanel`](../frontend/src/components/reader/BookMarkersPanel.tsx)
- Global: **Go to passage** on [`/bookmarks-notes`](../frontend/src/components/annotations/BookmarksNotesPage.tsx) → `/read/:id` with `state.epubLocation` (bookmark CFI)

## Non-triggers

- Table of contents navigation
- Prev / next page buttons
- Creating a new bookmark from text selection
- Opening the book normally from the library (no `epubLocation` in router state)

## UX

### Resume control

- Component: [`ResumeReadingButton`](../frontend/src/components/reader/ResumeReadingButton.tsx)
- Visible only when `isBookmarkPeekActive && readingAnchor != null`
- Position: right edge, **above** the next-page chevron (`.reader-page-nav--next`)
- Style: warm accent (`#ea580c` / `#f97316`), white label/icon; distinct from muted gray nav buttons
- Action: `resumeReadingAnchor()` — hides control, returns to anchor CFI
- i18n: `reader.resumeReading`, `reader.resumeReadingAria`

### Anchor policy

- First anchor is captured when peek starts; **additional “Go to passage” clicks while peeking do not replace the anchor** until the user resumes or leaves the reader.

## Progress rules

| Mode | `PATCH .../progress/` |
|------|------------------------|
| Normal reading | Yes (debounced on `locationChanged`, sync after locations ready) |
| Bookmark peek | **No** — `flushProgress` / `scheduleProgress` no-op |
| After resume | Yes — flush anchor CFI and percentage once |

### Load from bookmarks page

1. Fetch saved `ReadingProgress` from API.
2. If `state.epubLocation` is set and saved `epub_location` exists → store saved location as **anchor**, set peek mode, open at bookmark CFI.
3. Do not persist bookmark location as progress during peek.

### In-reader peek

1. Capture current `location` (CFI) as anchor (if valid).
2. Enter peek mode, jump to bookmark CFI.

## API

No backend changes in v1. Anchor is session-only in [`useEpubReader`](../frontend/src/hooks/useEpubReader.ts).

## Verification

1. Read to ~30%, open markers, **Go to passage** on an early bookmark → jumps; after debounce, library/API progress still reflects ~30% (not bookmark).
2. Orange **Back to reading** appears above the next chevron only during peek.
3. Tap resume → returns to ~30%; button hides; progress saves resume.
4. From `/bookmarks-notes`, **Go to passage** → peek + resume using saved progress as anchor.
5. TOC / prev / next do not show the resume button.
6. EN/ES strings present.

## Out of scope

- PDF reader
- Multiple anchor history stack
- Backend `resume_epub_location` field
- Peek mode for TOC jumps
