# BPFmap · Next Sessions

Backlog ordered by session. Items mapped to audit in `BPFmap · Roadmap & Audit · 2026.pdf`.

---

## ✓ Done — Session 2026-05-01

- **V355 · Directions Panel (RDP)** — replaces `.route-header` in `mode-route` with cinematic A→B card (atmospheric layered gradients, discrete edge glow ETA-aware, dot color-coded for fast/slow), 3-col detail strip (ETA · Distance · Arrive). Walking indicator chip on the A→B line.
- **V355 follow-up** — sheet bg in `mode-route` aligned with nav-modal cinematic gradient (warm coral top-right + cool navy bottom-left + indigo-purple base). CTAs restyled: primary matches `.nav-option.nav-apple` (warm coral gradient), secondary matches `.nav-option.nav-google` (glass white-translucent). Footer copy (`.route-note`) hidden — info already surfaced in card + strip.
- **P26 · `display=swap`** — already present in Google Fonts URL (line 10).
- **V369 · P8 countdown** — pre/live/ended states anchored after `.empty-stats`. Festival window `9–18 Oct 2026`, 10 days total. `.bpf-cd` line with green pulse dot during live state.
- **V370 · P15 "What's on today"** — surfaced only during live festival, computed from `venues[].events[].date === todayLabel`. Honors `DEBUG_TODAY` for parity with programme logic.
- **V373 · Welcome overlay final hierarchy** — fixes two-state issue (V371 + V372 conflict) via MutationObserver re-apply. Edition chip moved ABOVE "Welcome to" with cinematic gradient dot + integrated countdown (`Opens in X days` / `Day X of 10` / `Festival ended`). Theme + period line `Witness · 9–18 October` injected where chip used to be. `.bpf-wo-edition` (V372 badge) hidden. Explore CTA text opacity reduced from 0.94 → 0.68 (more discrete).
- Fixed stale stats text `"16–25 May"` → `"9–18 Oct 2026"` in `V367_WELCOME` injection.

---

## ✓ Done — V381 (2026-05-02 third iteration)

Per feedback on V380:

### Spacing
- Gap topbar→search reduced again: top `90 → 72` (visible gap **8px** confirmed live)

### Filter button active state — chromatic fixed
- From heavy red/coral gradient → subtle **cream tint** (`rgba(247,224,146,0.20)` overlay on dark base) with cream border + cream dot indicator. Less aggressive, more elegant.

### Navigation modal
- Kicker text rebuilt: "Directions" → **"Navigation"** (via JS innerHTML keeping dot span)
- Cancel button breathing: `+14px` margin-top, `+10px` padding, divider `+18/16px` margins

### Directions state refinements
- **Chip lighter**: `rgba(255,255,255,0.13)` bg + `rgba(255,255,255,0.22)` border (was 0.07/0.13)
- **X-close aligned with chip baseline**: `top:8` (was 14), 26×26 (was 28×28)
- **Line A→B unified via `::before`**: single continuous gradient white → accent (no more 2 segments). Old `.rdp-ab-line` segments hidden via `background:transparent`. CSS:
  ```css
  .rdp-ab-row::before {
    position: absolute; top:50%; left:13px; right:13px; height:2px;
    background: linear-gradient(90deg, white 0% → 0.35 35% → accent 70% → accent 100%);
  }
  ```
- **CTA order reverted**: removed `flex-direction: row-reverse` → Back to Venue first (left, secondary), Navigation second (right, primary)
- **"Your location" 2-line display** via JS innerHTML replace (`Your<br>location`)

### Venue sheet
- `.sh-chip` chips +15%: font 9.5 → 11px, padding 6×12 → 8×14

### Welcome filter strip
- `.bpf-flt-btn.bpf-flt-t1` more visible: bg `rgba(255,255,255,0.16)` (was lower), text 0.96, font-weight 600
- Icons removed from Open Now + Nearby buttons (svg + dot display:none)

### Welcome overlay — new editorial layout
- 3-line editorial mapped to old positions:
  - Lead (where "Welcome to" was): **`Opens in X days`** / `Day X of 10` / `Festival ended`
  - Brand (where "Bucharest Photofest" was): **`Witness`** (56px light)
  - Year (where "2026" was): **`9–18 October`** (28px light)
- Edition chip preserved at top: `● THE 11TH EDITION` (countdown removed from chip — moved to lead line)
- 3 CTAs single row: **Explore the map** | **Festival Info** | **Access**
- Access click: opens `APP_SETTINGS.welcome_access_url` if set, else toast "Access info — coming soon"
- **Flash fix**: V381 watches body via MutationObserver + `isV381Applied()` check (looks for `Witness` brand text + `#bpfWoAccFinal`). Re-applies on every V371/V372/V373 wipe. Lock flag `_v381Applying` prevents recursion.
- All V371/V372 elements no longer needed are hidden via CSS: `.bpf-wo-stats, .bpf-wo-editorial, .bpf-wo-dates, .bpf-wo-witness, .bpf-wo-welcome, .bpf-wo-tagline, .bpf-wo-facts, .bpf-wo-hr, .bpf-wo-theme`

### Icons refresh (V381 set)
- Filter: 2 sliders with **filled circular knobs** (cleaner than V378 outline)
- Target: navigation arrow filled (Apple Maps style)
- Calendar: rounded rect + binders + horizontal divider + today-dot
- Bookmark: ribbon with 20% inner fill + outline

### V381 follow-ups (TODO)
- **Access URL** — add `welcome_access_url` to BPF_Settings (Bucket B Airtable schema expansion). Until then, click shows toast.
- **P17 Saved full impl** still pending.
- **Programme button active state** when festival live (TODO from V380).

## ✓ Done — V380 final (2026-05-02 second iteration)

Per feedback on V378:

### Buttons + menu chromatic coherence (match nav modal)
- Buttons + menuPanel switched from light → **DARK warm cinematic** matching nav modal background:
  - Buttons: `radial-gradient(247,224,146,0.10) → rgba(15,18,28,0.86)` glass + warm border
  - menuPanel: full nav-modal gradient (warm coral top-right + cool navy bottom-left + indigo→purple base)
  - Filter buttons inside menu: dark text default, warm gradient on `.active`
- menuBtn `.v376-active` state: stronger warm cinematic gradient (red→coral→cream blend) with cream dot indicator

### Spacing
- `top: 98 → 90` for searchbar + controls (tighter gap from topbar — user reported 16px previously, now CSS top:90 should give visible 6-8px on device)

### Result tags → CHIP pills
- Padding `3×7 → 6×10`, border-radius `5 → 999` (full pill), font 8 → 8.5
- Same height as result row, matches CTA chip style (Open Now / Nearby)

### Directions state major refresh
- **Kicker rebuilt**: "Route preview" → **"Directions"** via JS innerHTML replacement (keeps gradient dot)
- **X close button** injected top-right of `.rdp` — closes route, returns to mode-selected
- **Card chromatic**: dark → **light glass** (`rgba(255,255,255,0.07)` + blur 20px) on dark sheet
- Edge glow KEPT (red/green based on ETA fast/slow)
- **Walking chip removed** from line; line UNIFIED (`.rdp-ab-walk { display:none }` + line margin collapse)
- **TO label**: "To Venue X" → just "To" via MutationObserver lock
- **Strip 3-row layout**: ETA label / xx min value / **Walking** (third row, 14px font same as value, color synced via class observer to fast/slow color)
- **Tighter padding** above/below strip (4px instead of 6-8)
- **CTA swap**: 
  - `flex-direction: row-reverse` puts Navigation FIRST visually
  - Navigation gets warm coral gradient (was nav-apple style → now used for primary)
  - Back to Venue gets neutral glass secondary
- **Footer copy hidden**: `.route-note` AND `#routeFooterNote` (`.rh-footer-note`) both display:none

### Architecture note
V380 placed at end of `</body>` for source-order specificity win. Earlier V377_REFINEMENT block disabled by V378_FINAL_BUTTONS being later in source — V380 supersedes both.

### V380 follow-ups (TODO)
- Verify visible gap on user's real device (CSS top:90 → expected ~6-8px). May need ±2px adjustment.
- Icon further iteration if user still wants more "wow" — current set: filter sliders, location arrow filled, calendar with today-dot, bookmark with split-fill.
- Saved/Shortlist (P17) full implementation — placeholder toast remains.

## ✓ Done — V378 buttons refinement (2026-05-02)

Per feedback on V376 buttons stack:

- **Spacing**: searchbar+controls `top: 106 → 98` (gap from topbar bottom: 16 → 8px per user expectation)
- **Buttons size**: 48×48 → **37×37** (matches searchbar height for visual harmony)
- **Icons upgraded** (more modern):
  - Filters: sliders style (2 horizontal lines with circular knobs) — clearer "controls" semantic
  - My-location: location arrow (Apple Maps style — triangle inside circle, filled center)
  - Programme: calendar with today-dot indicator
  - Saved: bookmark with split-fill (16% inner opacity + outline)
- **menuBtn active state** — when `state.activeFilter !== 'all'`: warm BPFmap chromatic gradient (cream → coral → red), warm border, dot indicator color-matched
- **menuPanel chromatic redesign** — top aligned with button (`top: 98`), width `176 → 120` (-32%), warm gradient bg (cream/coral), `right: 60` (sits to LEFT of buttons stack), warm hover/active states for filter buttons
- **Search placeholder**: copy `"Search venue, event or route"` → `"Search venues, events or artists"` (plural, includes artist), color `rgba(13,23,51,0.40)` (more faded for discreteness)
- **Result tags** (search results): from filled box → **transparent + colored border + colored text** (matches Open Now / Nearby chip pattern)
  - venue: 1px border #4a64b3 + text #4a64b3
  - event: 1px border #a07020 + text #a07020
  - artist: 1px border #b66a4c + text #b66a4c
- **Welcome chip cleanup**: Programme chip hidden (canonical = floating Programme button, no redundancy)
- **Festival Info chip**: hidden when filters active (`body.v377-filtered` class) — irrelevant in filtered context
- Filter active polling: setInterval 250ms checks `state.activeFilter`, toggles `.v376-active` on menuBtn + `.v377-filtered` on body

### Strategy decisions documented

**Q: Programme button vs sheet CTA → ANSWERED**: Removed from welcome (canonical = button). Buttons stack handles always-accessible navigation; welcome chips focus on quick-start (filters + festival info).

**Q: Festival Info coherence → ANSWERED**: Stays in welcome chips (read-once context). NOT in buttons stack. Hidden when filters active. Future: accessible from Programme sheet header.

### V378 follow-ups (TODO)

- **Saved/Shortlist (P17)** full implementation — bookmark icon in venue sheet + localStorage
- **Active dots** for centerBtn (when location centered) and programmeBtn (when festival live)
- **Verify on real device**: gap measurement between topbar and searchbar (8px expected) — if user reports otherwise, adjust by ±2-4px CSS

## ✓ Done — Bucket A · Buttons stack (2026-05-02)

- **V376** — buttons redesign per audit 2026-05-02:
  - Hamburger (`☰` Unicode) eliminated as concept; `#menuBtn` rebranded to **Filters** with proper funnel SVG icon (under-the-hood reuses `#menuPanel` dropdown).
  - `#centerBtn` icon swapped from paper-plane (which was actually a "send" glyph) to **crosshair/target** SVG.
  - 2 new buttons appended to `.controls`: **`#programmeBtn`** (calendar icon, click → `openProgramme()`) and **`#savedBtn`** (bookmark icon, P17 placeholder showing toast `"Saved venues coming soon · bookmark from venue sheets to start"`).
  - Stack: 4 × 48×48 buttons, gap 8px, 216px total height.
  - Searchbar + controls descended `top: 94px → 106px` (+12px breathing room from topbar, ~5-10% increase).
  - Search-results panel `top: 60px → 72px` (matches new searchbar baseline).
  - Geolocation fallback **toast** on denied/timeout — `code === 1` shows "Location access denied · enable in browser settings", else "Could not get your location · try again". Capture-phase listener so probe runs before V333 attaches success path.

### Bucket A follow-ups (TODO — keep in scope)
- **Saved/Shortlist (P17)** full implementation — bookmark icon in venue sheet, localStorage persistence, savedBtn opens panel with saved venues.
- **Filters button active dot** — show `.v376-active` indicator when `state.activeFilter !== 'all'`.
- **Programme button active state** — subtle bg tint when `festState() === 'live'`.

## ⏸ Pending — Bucket B & C (Airtable)
See `AUDIT_2026-05-02_airtable_buttons.html` for full audit. Awaiting decisions on:
- Bulk-add path (CSV manual vs API)
- Schema expansion timing
- Phase 2 wire timing (dedicated session)

## ✓ Done — Session B · Search rebuild (2026-05-01)

- **V375 · P19 search rebuild** — hybrid typed search:
  - Search bar height **46→37px** (-19.6%) · right edge **86→132px** (narrower, roughly mirrors `.brand` topbar pill).
  - Search results sheet right edge same as searchbar; padding/radius tightened.
  - Result row: typed chips with color-coded tags — `VENUE` (blue #4a64b3), `EVENT` (amber #a07020), `ARTIST` (coral #b66a4c).
  - Search index: `v.name`, `v.address`, `v.type` (venue) · `ev.title`, `ev.meta` (event) · `ev.author` (artist, aggregated by lowercased name with `eventsCount` + `venuesSet`).
  - Limit raised 5 → 8.
  - No-results state: panel closes silently (zero copy, intuitive).
  - Click handler: all types currently `selectVenue(v.id)` (TODO: scroll-to-event for EVENT, filter-by-author for ARTIST).
- Verified at runtime: `cinema` → 2 VENUE results · `juhan` → 2 EVENT + 1 ARTIST aggregated · `xyzqwerty` → silent close.

### Session B follow-ups (TODO — keep in scope)

- **Scroll-to-event** on EVENT/ARTIST result click — open venue sheet expanded + scroll events list to matching event id.
- **Runtime width measurement** of `.brand` pill — compute exact `right` value for search bar to mirror brand width per viewport (currently static 132px).
- **Search input visibility during typing** — results panel currently covers search input (pre-existing behavior, top:60 vs searchbar 68-105). Either lower panel top (top:115+) or keep searchbar visually persistent with input echo at top of results panel.

## ✓ Done — Session A · Map & popup behaviour (2026-05-01)

- **V374 · Chunk 1 (B2 fix)** — popup now hidden when sheet has `.sheet-expanded` class. Single CSS rule, eliminates visual noise (popup + expanded sheet both showing same venue info).
- **V374 · Chunk 2 (fitCity adaptive)** — replaced fixed `setView(center, 14.2)` with `fitBounds(bounds, paddings)` + `maxZoom: 15`. Welcome view now adapts to actual venue spread, sensible margins (40px sides, 128px top, dynamic bottom). Inherited by `mode-searching` and reset-filter via center button.
- **V374 · Chunk 3 (centerSelectedVenue real pan)** — function previously didn't pan, only showed popup. Now pans map so pin sits in visible area above sheet. Reuses V363 pattern (project → offset → unproject → panTo) with 0.44s ease.
- **V374 · Chunk 4 (route mode paddings)** — `sheetBottomPadding('route')` updated 128 → **290** as single source of truth. `mapRef.fitBounds` monkey-patched: any call in mode-route receives `paddingTopLeft: [28, 96]` + `paddingBottomRight: [28, 310]`, overriding V336's hardcoded [28, 138]. Fixes "myLocation south + venue north" scenario where pins were hidden under sheet.
- **V374 · Issue 1 follow-up** — fitCity paddings tightened: `paddingTopLeft: [40, 152]` (was 128 — search bar ends at y=140, needed clearance) + `paddingBottomRight: [40, btmPad+22]` (breathing buffer for discreet panning). Bottommost venue no longer cut off.
- **V374 · Issue 2 follow-up** — sheet-expand pin centering: V363's observer uses `topPx=88` (no search bar clearance, pin lands under search pill). New V374 observer registers AFTER V363 in DOMContentLoaded, fires same MutationObserver trigger, panTo cancels V363's animation and lands at corrected target with `topPx=160`. Same `topPx` applied to `centerSelectedVenue` for consistency.
- Resolver helper: `getGlobal()` via `Function` constructor reads bare const/let globals (`map`, `bounds`, `state`, `selectedVenue`) safely from script-scope without window assignment.

## ⏸ Deferred — handle in dedicated sessions

### ~~Session B · Search bar~~ — DONE (see top of file)

Follow-ups still open in TODO list above (scroll-to-event · runtime width · input visibility).

### Session C · Airtable audit (NEW · prerequisite for P9 + others)

Scope: full pass of Airtable schema vs app needs. Outputs: list of fields to add per table.

Confirmed gaps so far:
- `BPF_Settings` · `welcome_hero_image_url` — for P9 (welcome editorial bg image, deferred until field exists).
- `BPF_Events` · artist/curator fields — verify for P19.
- `BPF_Venues` · `featured` boolean — for P16 ("Editor's Pick" tag).

### Backlog · Lower priority (next audit cycle)

| Ref | Item | Notes |
|---|---|---|
| **B4** | CSS specificity debt V35x–V36x consolidation | TECHNICAL · audit explicitly says "no urgency before festival". Risky pass: many overlapping `!important`. Schedule a dedicated cleanup session, ideally post-festival. **Do not lose this item.** |
| **P5** | Open until / Opens at exact hours | HIGH · venue hero status text |
| **P6** | Walking time when location active | HIGH · uses real geolocation |
| **P7** | Add to calendar per event | HIGH · ICS already present in code (`addToCalendar` ~line 7097), needs button wiring |
| **P9** | Welcome hero editorial image | HIGH · blocked by Airtable field (Session C) |
| **P10** | Next event in minimised hero | HIGH · extract soonest from events array |
| **P11** | Share venue (Web Share API) | HIGH · pairs with P20 |
| **P12** | Dark map tiles after 20:00 | MEDIUM |
| **P13** | Grabber functional or hidden | MEDIUM · ties to B1 |
| **P14** | Featured venue rotation | EDITORIAL |
| **P16** | Editor's Pick tag | EDITORIAL · blocked by Airtable boolean |
| **P17** | Personal shortlist | ENGAGEMENT · localStorage |
| **P18** | Plan my day · multi-venue route | DIFFERENTIATOR |
| **P20** | Deep link URL params | ECOSYSTEM · pairs with In-Light |
| **P21** | Service Worker offline | ADVANCED |
| **P25** | CSS refactor | TECHNICAL · post-festival, ties to B4 |

### Open bugs

| Ref | Bug | Priority |
|---|---|---|
| B1 | Grabber visible but non-functional in empty state | UX — Session A or B |
| B2 | Popup stays visible when sheet expanded | VISUAL — **Session A** |
| B3 | Welcome entry animation re-trigger glitch | MINOR |
| B4 | CSS specificity debt | TECHNICAL — backlog, post-festival |
