Bucharest Photofest 2026 · WITNESS · Document unic

BPFmap · Roadmap & Audit

Actualizat
12 Iun 2026
Versiune app
V495+ · 44 777 linii
Festival
9–18 Oct · 119 zile
Stack
Vanilla JS · Leaflet/Mapbox · Airtable (build-time)
Acest fișier înlocuiește toate audit-urile și roadmap-urile anterioare (mai 2026), arhivate în old : examples : tests/_archive_audits/. Un singur document, actualizat la fiecare sesiune majoră.
01

Checklist lansare — obligatoriu înainte de orice link public

Singura listă care contează operațional. Verificată la 2026-06-12 prin grep pe sursă.
#ItemStatusAcțiune
L1PAT Airtable în client✓ REZOLVATPAT rotat (9 iun), client citește data.json, zero token în sursă. Verificat: 0 match-uri
L2XSS — bpfEscapeHTML coverage⚠ PARȚIALHelper + CSP există, dar doar 7 utilizări vs ~30 sink-uri identificate. Audit coverage final necesar
L3DEBUG_TODAY = "11 Oct" · linia 7281● ACTIVFlip la "" în ziua lansării. PROTEJAT până atunci — nu se atinge în dev
L4BPF_TEST_DATE ×2 · liniile 33581, 34163● ACTIVFlip la lansare. Idem — PROTEJAT în dev
L5Mapbox token — restricție referrer? NEVERIFICAT2 min în Mapbox dashboard: HTTP referrer restriction pe pk.*
L6PWA icons (192 + 512)● LIPSESCmanifest.json există și e linkat (linia 20), dar fără icoane. Asset grafic de creat
L7console.log debug dumps? DE VERIFICATStrip înainte de prod
L8QA final pe device real (iPhone via Tailscale)○ TODOSafe-area, notch, home indicator, momentum scroll
L9Re-run build.py cu date finale○ TODOÎn ziua lansării, după înghețarea programului în Airtable
Reminder permanent: orice share extern / deploy = verifică întâi L1–L4.
02

Ce e LIVE — sinteza implementărilor V344 → V495

Istoric condensat pe capabilități. Detaliile per-V-block sunt în arhivă.
ZonăCapabilități livrateUltima iterație
WelcomeOverlay cinematic (foto + 5 gradiente radiale), WITNESS editorial, countdown pre/live/ended, Tonight surface, filter strip (Open Now / Nearby), 3 CTA-uriV446 + S5
Map / HomefitBounds adaptiv, popup follows pin, popup ascuns la sheet expandat, markeri cu status dot, quick-filter Open Now pe dotV374, V485
SearchHybrid typed search (VENUE / EVENT / ARTIST chips colorate), limit 8, silent closeV375
Venue sheetMinimised (număr, status, event count) + Expanded (hero foto, events glass cards, chips, date/oră pe rânduri separate), frosted glass, twin CTA Directions/Navigation (decizie user — NU se unifică)V478–V490
Directions / RDPCard A→B cinematic, ETA + distanță, polyline animat, X close, CTA-uri coral/glassV355–V462
Walking navTurn card, GPS badge glass, progress, arrival celebration, Start Walking popup compactV450–V487
Programme / TodayFullscreen panel, calendar grid 2 rânduri, default Today, time-of-day grouping, NOW line, past dimming, day header „Day N" editorial (fix definitiv 12 iun — spans în template), tipografie fără caps/bold excesivV488–V495 + fix
SavedBookmark venue+event, localStorage, panel carduri compacte (50px, delete 32px), empty state elegant, sync hearts programme↔savedS3 + V489/V495
Festival InfoFullscreen, hero, key facts, Explore cards, parteneri logo boxes, ordine: KF → Explore → Partners → Get Involved → Stay ConnectedV443 + V495
Tab bar5 items (Home/Today/Saved/Map/Info), dark glass blur(52px), alb activ, safe-area, sync la mode changeV480–V482
Add to calendarICS per event, buton wiredS2
Micro-interactionsSpring tap pe cards / CTAs / tab bar / detail expandV492 (S9.3)
Design tokens:root complet (brand, white-alpha 29 pași, fs/sp/r/z) + 1343 migrăriSprint 4
SecuritateCSP meta, bpfEscapeHTML helper, PAT build-time, .env gitignoredS6 + 9 iun
PWAmanifest.json linkat, viewport-fit, theme-color, apple-meta completeV461

Bug-uri istorice închise — nu re-deschide

BugRezoluție
Day header „Day 513 Oct"_fixDayHeaders (V436/V437) colapsa span-urile via textContent self-assignment. Fix: template emite spans direct + guards (12 iun)
C1 forensic touch-action:noneEliminat de pe FI hero / prog-header — 0 match-uri în sursă
B2 popup peste sheet expandatFix V374 — single CSS rule
Tab bar safe-area strip · venue bottom edge · strong inline regressionToate închise (vezi arhivă)
03

Probleme deschise — prioritizate

P1 — înainte de lansare (în afara checklist-ului §1)

#ProblemăOrigineNote
P1.1XSS coverage — wrap toate sink-urile innerHTML cu date AirtableSB-2Doar 7/~30 wrapped. O sesiune dedicată cu grep sistematic
P1.2window.bpfVenues stale → Saved/Tonight pot afișa date vechiforensic C5Fix 1 linie. De verificat dacă mai e cazul cu data.json build-time
P1.3Boot setIntervals fără timeout (20+) — battery drain dacă CDN flakeH-F1setTimeout(() => clearInterval(...), 10000) per interval
P1.4MutationObservers fără disconnect (8+) — CPU cumulativH-F2Pattern: store + disconnect înainte de re-create
P1.5Geolocation dublu-prompt + 3 timeout-uri diferiteH-F3Un singur watchPosition, 8s/60s
P1.6data.json fetch fail silențios pe rețele lenteH-U4Skeleton shimmer după 600ms + toast pe catch

P2 — ar trebui, dacă e capacitate

#ProblemăNote
P2.1Deep link ?venue= + Web Share APIPress/marketing blocat fără; pereche cu In-Light
P2.2Token migration faza 2 — --fs-*/--sp-*/--r-* în rulesets vechiDeclarate, ~0% aplicate în componente vechi. Cod NOU le folosește obligatoriu
P2.3Easing/duration tokens — 86 tranziții cu 4+ easingsStandardizare pe cubic-bezier(.22,.8,.24,1)
P2.4Cod mort: V330 search handler (~6508–6525), .bpf-prog-past duplicatCleanup rapid
P2.5FEST_START/FEST_END redeclarate 5×O singură sursă
P2.6Toast triplu → un singur bpfToast()H-U3
P2.7Filter-state polling 250ms + programme-bg 200msEvent-driven în loc de poll
P2.8Events nesortate cronologic în listăBucket AFTERNOON→EVENING→AFTERNOON observat. Sort pe start_time înainte de render

P3 — post-festival

#Item
P3.1CSS architecture overhaul — consolidare V-layers, BEM/CSS layers (B4/P25 — „do not lose this item")
P3.2new Function()window[name] (17 locuri; blochează strict CSP)
P3.3Route cache + sessionStorage persist (cost Mapbox −30-60%)
P3.4Live ETA polling + distance progress indicator
P3.5P18 Plan my day — rută multi-venue
P3.6Service Worker offline-first
P3.73D buildings Mapbox (risc baterie — evaluare)
P3.8Single MutationObserver dispatcher global, debounced
04

Obiective strategice — propuneri end-to-end

Audit proaspăt (iunie 2026), ecran cu ecran, pe starea reală V495. Filozofia: app-ul e deja peste orice referință de categorie la craft vizual; ce rămâne e finisaj de detaliu + robustețe operațională. Nicio refactorizare mare pre-festival.

Constrângeri respectate (decizii user, nu re-deschide): twin CTA Directions/Navigation rămâne · fără QR / AI-chat / AR / ratings / ticketing · test-date flags neatinse.

4.1 · Welcome screen

IdeeImpactEfort
Cascadă intro stagger (kicker→title→edition→CTAs, 100-200ms) — singurul „WOW" rămas nelivratALTS · CSS only, spec în arhivă
„Tonight's pick" editorial pe welcome când festivalul e live (1 event, ora + venue)ALTM
Parallax discret pe foto la scroll/tiltMEDM · defer dacă e timp scurt

4.2 · Map / Home

IdeeImpactEfort
Marker hover/selected feedback mai vizibil (scale 1.06 + inel cream 1px)MEDS
Dark map tiles după 20:00 — festival = seară; harta light noaptea e receALTS–M
Decongestie markeri la zoom mic dacă venues se suprapun în centruMEDM

4.3 · Search

IdeeImpactEfort
Click pe EVENT/ARTIST → venue expandat + scroll-to-event (azi: doar selectVenue)ALTM
transition pe result hover (lipsește, sec)LOWS

4.4 · Venue sheet

IdeeImpactEfort
„Open until 21:00" / „Opens at 10:00" exact (P5) — azi doar status genericALTS
Walking time pe minimised hero când locația e activă (P6)ALTS
Share venue (Web Share API) — pereche cu deep link P2.1ALTS
Photo gallery în expanded (S9.2 rămas) — dacă Airtable are assetsMEDM

4.5 · Programme / Today

IdeeImpactEfort
Sort cronologic strict în zi (P2.8 — bug real observat)ALTS
„Now / Starting soon" chip pe event cards când e aziMEDS
Empty state pe zile fără evenimente („No events this day — see Day N")MEDS

4.6 · Saved

IdeeImpactEfort
Conflict warning subtil (2 saved events suprapuse orar)MEDM
Share-saved-URL (hash #saved=...) — pereche cu deep linksMEDS

4.7 · Festival Info

IdeeImpactEfort
Linkuri parteneri funcționale + access URL real din Airtable (welcome_access_url — câmp încă neadăugat?)MEDS · depinde de schema

4.8 · Transversal

IdeeImpactEfort
Robustețe sesiune lungă — P1.3/P1.4/P1.5 ca pachet unic „stability pass"ALTM · 1 sesiune
Haptic feedback (Vibration API) pe tab bar + save — Android only, progressiveLOWS
Loading skeleton la primul paint (data.json fetch)MEDS

Ordine de atac recomandată — sesiuni următoare

  1. Sesiunea „ultimele detalii UI/UX" (cea anunțată — urgent): punctele user + quick wins S din §4 (sort cronologic, open-until, search transitions, marker feedback)
  2. Stability pass (P1.3–P1.6) — 1 sesiune
  3. XSS coverage final (P1.1) — 1 sesiune
  4. Share / deep-link pack (P2.1 + share venue + saved-URL) — 1 sesiune
  5. Welcome cascade + Tonight's pick — 1 sesiune
  6. Checklist lansare §1 — T-7 zile înainte de 9 oct
05

Referințe tehnice — capcane cunoscute

Citește înainte de orice cod nou.
CapcanăDetaliu
Arhitectură V-block append-only<style id="BPFMAP_VXX_CSS"> + <script id="BPFMAP_VXX_JS"> înainte de </body>. Blocurile târzii câștigă la specificitate egală. NU edita V-blocks vechi decât pentru bug-uri la sursă
Day headerTemplate-ul emite .phd-num/.phd-date direct (linia ~7452). Orice cod care face textContent = pe .prog-day-hd-title DISTRUGE span-urile — guards există în V436/V437, nu adăuga alți writers
.bpf-saved-panel colisionV402 (vechi) vs Sprint 3 — panouri noi în zona Saved au nevoie de !important sau alt nume de clasă
V369 .empty-hero :not() whitelistElemente noi în welcome au nevoie de ID-override + flex order
SPRINT6 debounce 180msrebuildGroups re-injectează .bpf-prog-group după fiecare mutație pe #programmeList — post-procesoarele rulează la 220ms+
Preview serverServește COPIE din /tmp (BPFmap.html + data.json). După edit: re-copy sau restart server, altfel verifici cod vechi
TokensCod CSS NOU folosește obligatoriu var(--bpf-*), --fs-*, --sp-*, --r-*, --z-* (:root, liniile ~26–135)
Variabile cheie--bpf-sheet-clearance = tabbar + safe-area + 8px — orice sheet flotant o respectă
Getters fragilenew Function("return venues") în S3/S5 — nu replica pattern-ul; folosește window.bpfVenues (și ține-l fresh)
Easing canoniccubic-bezier(.22,.8,.24,1) / 0.22s — semnătura motion a brandului