diff --git a/JUNIOR_CALENDAR_MULTISELECT_UPDATE.md b/JUNIOR_CALENDAR_MULTISELECT_UPDATE.md
new file mode 100644
index 0000000..17e1ba8
--- /dev/null
+++ b/JUNIOR_CALENDAR_MULTISELECT_UPDATE.md
@@ -0,0 +1,161 @@
+# Update — Calendar multi-select drag feedback (bug fixes)
+
+**Audience:** the junior developer who implemented the calendar multi-select feature.
+**Area:** `frontend/` only. No backend changes. This is a small, focused follow-up — the feature works, these are two visual/interaction bugs in the *drag-to-select* behavior.
+
+> Great work on the feature — bars, week numbers, bulk apply and the legend all look good. There are exactly **two** things to fix, described below. Please change **only** what's needed for these two; don't touch the save/bulk-apply logic, the bar rendering, or the modal behavior.
+
+---
+
+## The two bugs (what the user sees vs. what they want)
+
+### Bug 1 — Days are NOT highlighted *while* you drag-select
+
+**What happens now:** When you press and drag across days, the day cells stay white during the drag. The blue "selected" highlight (light blue background + blue border) only appears **after** you release the mouse and the "Plan N days" dialog opens.
+
+**What we want:** As soon as you start dragging, every day in the current selection range should be highlighted **immediately and live**, updating as you drag over more days — and it should look just like the **hover** state of a single day. The highlight must be visible *during* the drag, before the dialog appears.
+
+### Bug 2 — The day numbers get text-selected (blue "selecting text" boxes)
+
+**What happens now:** While dragging, the browser selects the day-number text, so the numbers (1, 2, 3, …) get the blue "highlighted text" look — exactly like dragging to select text on a web page. You can see this on the numbers in both screenshots.
+
+**What we want:** Dragging across the calendar must **never** select text. No day number (or any other calendar text) should get the text-selection highlight while dragging.
+
+---
+
+## Root cause (so the fix is obvious)
+
+### Bug 1 root cause — in `src/pages/Calendar.tsx`
+
+The `.calendar-day--selected` highlight is driven by the `selectedDates` state, which is passed down to ``.
+
+But `selectedDates` is **only written in the `pointerup` handler** (the `useEffect` around lines 29–49):
+
+```ts
+const handlePointerUp = () => {
+ if (isDragging && dragAnchor && dragCurrent) {
+ const dates = datesInRange(dragAnchor, dragCurrent)
+ setSelectedDates(new Set(dates)) // <-- only happens on RELEASE
+ ...
+ setIsModalOpen(true)
+ }
+ setIsDragging(false)
+}
+```
+
+During the drag itself, only `dragAnchor` and `dragCurrent` change (via `handlePointerEnter`). Because `selectedDates` is still empty until release, nothing is highlighted while dragging. That's the whole bug — it's a *timing* problem, not a styling problem.
+
+### Bug 2 root cause — in `src/pages/calendar.css`
+
+`.calendar-day` (and its `.calendar-day__number` child) have **no `user-select` rule**, so the browser's default text selection kicks in during a drag. Note the week-number cells (`.calendar__week-number`) already set `user-select: none` — the day cells just need the same.
+
+---
+
+## Exactly what to change
+
+### Fix 1 — show the selection live during the drag (`src/pages/Calendar.tsx`)
+
+Render the highlight from a **derived "preview" set** instead of only the committed `selectedDates`. While dragging, the preview is the range between the anchor and the current day; otherwise it's the committed selection.
+
+Add this just before the `return` (near where `firstSelectedDate` is computed, ~line 184):
+
+```ts
+// Dates to highlight in the grid. While dragging, show a live preview of the
+// range under the cursor; otherwise show the committed selection.
+const highlightedDates =
+ isDragging && dragAnchor && dragCurrent
+ ? new Set(datesInRange(dragAnchor, dragCurrent))
+ : selectedDates
+```
+
+Then pass `highlightedDates` (not `selectedDates`) to the week:
+
+```tsx
+
+```
+
+**Important — do NOT change `selectedDates` itself or how it's used elsewhere.** The committed `selectedDates` is what `handleSavePlannedDay` / `handleDeletePlannedDay` read on save. We are only changing **what gets rendered as highlighted**, not what gets saved. Leave the `pointerup` handler and the save logic exactly as they are.
+
+**Make the highlight match hover.** The look is already close, but make sure `.calendar-day--selected` matches `.calendar-day:hover` so "selecting" and "hovering" look identical. In `src/pages/calendar.css` the hover rule is:
+
+```css
+.calendar-day:hover {
+ border-color: #0066cc;
+ box-shadow: 0 2px 8px rgba(0, 102, 204, 0.1);
+ background-color: #f9fbff;
+}
+```
+
+The existing `.calendar-day--selected` (lines ~117–121) already uses the same three values, so this should need no change — just verify they stay in sync. Do **not** invent a new selected color; the requirement is "same as hover."
+
+### Fix 2 — stop text selection while dragging (`src/pages/calendar.css`)
+
+Add `user-select: none` to the day cell so dragging can never select the numbers. Put it on `.calendar-day` (it will also cover the `.calendar-day__number` child):
+
+```css
+.calendar-day {
+ /* ...existing rules... */
+ user-select: none;
+ -webkit-user-select: none; /* Safari */
+}
+```
+
+Keep both lines — Safari still needs the `-webkit-` prefix, and ESLint/CI won't complain about it. (If you prefer, you can instead add it once to the grid container `.calendar__grid` so it covers the whole calendar; either is acceptable, but `.calendar-day` is the minimal, targeted change.)
+
+---
+
+## What NOT to touch
+
+- The bulk-apply / save loop in `handleSavePlannedDay`, and the delete logic.
+- The spanning-bar rendering, lane layout, or `CalendarWeek` props (other than the one value passed to `selectedDates`).
+- The modal, week-number gutter, or legend.
+- `selectedDates` state semantics — it stays the *committed* selection used for saving.
+
+---
+
+## How to verify (manual)
+
+1. Turn on week numbers in Settings (optional) and open the calendar.
+2. Press on a day and drag across several days **without releasing**:
+ - ✅ Every day under the drag is highlighted live (same look as hovering one day), updating as you move.
+ - ✅ No day number gets the blue text-selection box; nothing on the calendar looks like selected text.
+3. Release the mouse: the "Plan N days" dialog opens and the same days stay highlighted (unchanged from today).
+4. Cancel/Save: highlight clears (unchanged from today).
+5. A single click still opens the single-day modal (unchanged).
+
+---
+
+## Tests (must stay green + add coverage)
+
+CI gates from `frontend/` — all must pass:
+
+```bash
+npx tsc --noEmit
+npm run lint # zero warnings
+npm run coverage # 90% gate
+```
+
+Add a test in `src/pages/Calendar.test.tsx` (or the existing multi-select test) proving the **live** highlight:
+
+- Fire `pointerDown` on one current-month day, then `pointerEnter` on a later day **without** firing `pointerup`.
+- Assert that the cells in that range now have the `calendar-day--selected` class **before** any `pointerup` — this is exactly the behavior that was missing.
+
+(There is no clean unit assertion for "text isn't selectable" — that's enforced by the CSS rule; cover it in the manual check above. If you want a guard, a small test asserting `.calendar-day` has the expected class is enough; the `user-select` value itself isn't worth asserting in jsdom.)
+
+Don't delete or weaken any existing calendar test to make things pass (see `AGENTS.md`). After the change, run `graphify update .`.
+
+---
+
+## Definition of done
+
+- [ ] Dragging highlights the day range **live**, matching the hover look, before the dialog opens.
+- [ ] No text (day numbers or otherwise) gets selected while dragging.
+- [ ] Committed selection, save/bulk-apply, delete, modal, bars, week numbers and legend all behave exactly as before.
+- [ ] A test covers the live (pre-`pointerup`) highlight.
+- [ ] `tsc --noEmit`, `npm run lint` (0 warnings), `npm run coverage` (≥90%) pass; existing tests still green.
+- [ ] `graphify update .` run.
+```
diff --git a/frontend/src/pages/calendar.css b/frontend/src/pages/calendar.css
index d7ac1ec..2ea9b3f 100644
--- a/frontend/src/pages/calendar.css
+++ b/frontend/src/pages/calendar.css
@@ -115,8 +115,13 @@
}
.calendar-day--selected {
- background-color: #e3f2fd;
+ background-color: #f9fbff;
border-color: #0066cc;
+ box-shadow: 0 2px 8px rgba(0, 102, 204, 0.1);
+}
+
+.calendar-day--selected:hover {
+ background-color: #f0f8ff;
}
.calendar-day__events {
@@ -257,6 +262,10 @@
font-weight: 600;
font-size: 12px;
color: #999;
+ background-color: #fafafa;
+ border-right: 1px solid #d0d0d0;
+ pointer-events: none;
+ user-select: none;
}
.calendar__week-number {
@@ -267,8 +276,11 @@
font-weight: 600;
font-size: 11px;
color: #999;
- border-right: 1px solid #e0e0e0;
+ border-right: 1px solid #d0d0d0;
background-color: #fafafa;
+ pointer-events: none;
+ user-select: none;
+ min-height: 84px;
}
.calendar__week-number-text {