diff --git a/.paul/ROADMAP.md b/.paul/ROADMAP.md
index 5120d7e..4d5743e 100644
--- a/.paul/ROADMAP.md
+++ b/.paul/ROADMAP.md
@@ -47,8 +47,9 @@ Szczegóły w `wp-content/plugins/yacht-booking-system/PROJECT-STATUS.md`.
- [ ] 09-01: UX/UI polish kalendarza — half-day na pierwszym/ostatnim dniu rezerwacji + paleta widgetu pasująca do strony
- [x] 09-02: Globalna synchronizacja iCal — wspólny Google Calendar z podziałem na jachty po prefiksie nazwy w tytule eventu (export feed + import URL + alias jachtu) ✅ 2026-05-06
- [x] 09-03: Cleanup OAuth + per-yacht iCal — usunięcie martwego kodu (3 pliki GCal/OAuth, per-yacht feedy, pole "Google Calendar ID") + cleanup migration "po cichu" ✅ 2026-05-06
-- [ ] 09-04: Security audit i poprawki
-- [ ] 09-05: Testy + tłumaczenia + dokumentacja
+- [x] 09-04: Globalna sync iCal (tryb wspólny kalendarz, bez filtrowania) + nowy widget "wszystkie jachty" (kolory per-jacht, half-day, bez ukośników, formularz inquiry, privacy w REST) ✅ 2026-05-07
+- [ ] 09-05: Security audit i poprawki
+- [ ] 09-06: Testy + tłumaczenia + dokumentacja
---
*Roadmap created: 2026-05-05*
diff --git a/.paul/STATE.md b/.paul/STATE.md
index 0050f8f..dfad300 100644
--- a/.paul/STATE.md
+++ b/.paul/STATE.md
@@ -11,20 +11,20 @@ See: .paul/PROJECT.md (updated 2026-05-05)
Milestone: v1.0 Production Release (v1.0.0)
Phase: 9 of 9 (Finalizacja) — In progress
-Plan: 09-03 — Complete (Cleanup OAuth + per-yacht iCal)
-Status: Loop closed, ready for next plan (09-04)
-Last activity: 2026-05-06 — Closed loop 09-03 (3 pliki OAuth usunięte, per-yacht iCal wycofany, migration po cichu)
+Plan: 09-04 — Complete (Global iCal sync + widget "wszystkie jachty")
+Status: Loop closed, ready for next plan (09-05 Security audit)
+Last activity: 2026-05-07 — Closed loop 09-04 (tryb global iCal, widget zbiorczy z formularzem inquiry, privacy w REST title)
Progress:
-- Milestone: [█████████░] 92%
-- Phase 9: [██████░░░░] 60% (3 of 5 plans complete)
+- Milestone: [█████████░] 95%
+- Phase 9: [██████░░░░] 67% (4 of 6 plans complete)
## Loop Position
Current loop state:
```
PLAN ──▶ APPLY ──▶ UNIFY
- ✓ ✓ ✓ [Loop 09-03 complete, ready for 09-04]
+ ✓ ✓ ✓ [Loop 09-04 complete, ready for 09-05]
```
## Accumulated Context
@@ -51,15 +51,16 @@ None.
## Session Continuity
-Last session: 2026-05-06 (paused — end of productive day, 2 pełne pętle zamknięte)
-Stopped at: Loop 09-03 zamknięty + handoff utworzony
-Next action: Run /paul:plan to plan 09-04 (Security audit). Klient wykonuje deploy FTP zmienionych plików i aktywację pluginu (cleanup migration uruchomi się automatycznie).
-Resume file: .paul/HANDOFF-2026-05-06.md
+Last session: 2026-05-07
+Stopped at: Loop 09-04 zamknięty — tryb global iCal + widget zbiorczy w produkcji
+Next action: Run /paul:plan to plan 09-05 (Security audit). Klient: usuń `test-overlap-bookings.php` z FTP.
+Resume file: .paul/phases/09-finalizacja/09-04-SUMMARY.md
Resume context:
-- Faza 9: 3/5 planów ukończonych (60%), milestone v1.0 92%
-- Plugin sprowadzony do jednego mechanizmu sync (globalny iCal) — kontekst w 09-02 i 09-03 SUMMARY
+- Faza 9: 4/6 planów ukończonych (67%), milestone v1.0 95%
+- Plugin produkcyjnie obsługuje 2 tryby sync iCal (per_yacht, global) + nowy widget `[yacht_calendar_all]`
+- Privacy hardening REST: brak `customer_name` w title eventów (precedens dla security audit)
+- Plugin w wersji 1.1.0 (bump z 1.0.0)
- Brak open issues, brak deferred items, brak blockers
-- Sesja zaczęła z 09-01 zamknięte, kończy z 09-03 zamknięte (2 pełne pętle PLAN→APPLY→UNIFY w jednej sesji)
---
*STATE.md — Updated after every significant action*
diff --git a/.paul/changelog/2026-05-07.md b/.paul/changelog/2026-05-07.md
new file mode 100644
index 0000000..bffa7de
--- /dev/null
+++ b/.paul/changelog/2026-05-07.md
@@ -0,0 +1,29 @@
+# 2026-05-07
+
+## Co zrobiono
+
+- [Faza 9, Plan 04] Globalna sync iCal (tryb wspólny kalendarz) + nowy widget "wszystkie jachty"
+- Settings: nowe pole "Tryb synchronizacji iCal" (per_yacht / global) z whitelistą i bezpiecznym defaultem
+- ICal_Import: rozgałęzienie `run_per_yacht_mode()` / `run_global_calendar_mode()`, nowa stała `GLOBAL_CALENDAR_SOURCE`, niezależny cleanup obu trybów
+- REST: nowy endpoint `GET /availability/all` (timed 12:00→12:00, kolory z palety per-jacht, privacy w title)
+- Frontend: widget Elementor `Calendar_Widget_All` + shortcode `[yacht_calendar_all]` z layoutem 2-kolumnowym (kalendarz + formularz inquiry z wyborem jachtu)
+- Privacy hardening: REST nie wystawia `customer_name` w title eventów (defense-in-depth: JS `eventContent` zwraca pusty html)
+- UX iteracje po checkpoincie: ciemny styl kalendarza (emulacja `/rezerwacja-maja/`), select w spójnym stylu z innymi inputami, instrukcja, server-side legenda, kolor wspólnych eventów `#7fb3d5` (jasnoniebieski)
+- Bump wersji pluginu 1.0.0 → 1.1.0
+
+## Zmienione pliki
+
+- `wp-content/plugins/yacht-booking-system/yacht-booking-system.php`
+- `wp-content/plugins/yacht-booking-system/includes/class-settings.php`
+- `wp-content/plugins/yacht-booking-system/includes/class-installer.php`
+- `wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php`
+- `wp-content/plugins/yacht-booking-system/admin/class-admin.php`
+- `wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php`
+- `wp-content/plugins/yacht-booking-system/api/class-rest-controller.php`
+- `wp-content/plugins/yacht-booking-system/frontend/class-shortcode.php`
+- `wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget-all.php` (nowy)
+- `wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar-all.css` (nowy)
+- `wp-content/plugins/yacht-booking-system/frontend/assets/js/calendar-all.js` (nowy)
+- `test-overlap-bookings.php` (test helper, do skasowania z FTP po teście)
+- `.paul/phases/09-finalizacja/09-04-PLAN.md`
+- `.paul/phases/09-finalizacja/09-04-SUMMARY.md`
diff --git a/.paul/governance/governance_2026-05-07.jsonl b/.paul/governance/governance_2026-05-07.jsonl
new file mode 100644
index 0000000..bce287f
--- /dev/null
+++ b/.paul/governance/governance_2026-05-07.jsonl
@@ -0,0 +1,60 @@
+{"ts":"2026-05-07T11:38:05Z","tool":"Bash","cmd":"mkdir -p \".paul/phases/09-finalizacja\" 2>&1; ls \".paul/phases/09-finalizacja/\" 2>&1\",\"description\":\"Ensure phase dir exists\"},\"tool_response\":{\"stdout\":\"09-01-PLAN.md\\n09-01-SUMMARY.md\","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:40:34Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\.paul\\\\phases\\\\09-finalizacja\\\\09-04-PLAN.md","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:40:49Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\.paul\\\\ROADMAP.md","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:41:01Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:41:17Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:43:11Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\includes\\\\class-settings.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:43:16Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\includes\\\\class-installer.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:43:27Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\admin\\\\class-admin.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:43:34Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\admin\\\\class-admin.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:43:48Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\admin\\\\class-admin.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:44:13Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\integrations\\\\ical\\\\class-ical-import.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:44:23Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\integrations\\\\ical\\\\class-ical-import.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:44:51Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\integrations\\\\ical\\\\class-ical-import.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:45:10Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\integrations\\\\ical\\\\class-ical-import.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:45:18Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\api\\\\class-rest-controller.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:45:28Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\api\\\\class-rest-controller.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:45:51Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\api\\\\class-rest-controller.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:46:21Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\class-calendar-widget-all.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:46:31Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\class-shortcode.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:46:46Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:47:10Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:47:39Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:47:54Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:48:32Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:48:46Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:48:59Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:49:07Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\includes\\\\class-yacht-booking.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:49:25Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\includes\\\\class-yacht-booking.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:49:33Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\includes\\\\class-yacht-booking.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:49:52Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\yacht-booking-system.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T11:49:57Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\yacht-booking-system.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:14:15Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\class-calendar-widget-all.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:14:36Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:14:44Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:14:59Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:15:13Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:15:45Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:19:10Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\includes\\\\class-yacht-booking.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:22:31Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\class-calendar-widget-all.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:22:40Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:23:25Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\class-calendar-widget-all.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:23:42Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:27:00Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:31:45Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:31:55Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:32:16Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\api\\\\class-rest-controller.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:32:33Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\api\\\\class-rest-controller.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:32:45Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\class-calendar-widget-all.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:32:55Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\js\\\\calendar-all.js","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:37:44Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:38:01Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\frontend\\\\assets\\\\css\\\\calendar-all.css","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:39:24Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\api\\\\class-rest-controller.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:40:50Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\test-overlap-bookings.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:45:42Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\wp-content\\\\plugins\\\\yacht-booking-system\\\\api\\\\class-rest-controller.php","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:48:49Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\.paul\\\\phases\\\\09-finalizacja\\\\09-04-SUMMARY.md","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:49:17Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\.paul\\\\changelog\\\\2026-05-07.md","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:49:31Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:49:49Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:50:00Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\jachty3.pagedev.pl\\\\.paul\\\\ROADMAP.md","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
+{"ts":"2026-05-07T12:56:14Z","tool":"Bash","cmd":"rm test-overlap-bookings.php && echo \"Usunięto test-overlap-bookings.php\"\",\"description\":\"Delete test helper file\"},\"tool_response\":{\"stdout\":\"Usunięto test-overlap-bookings.php\",\"stde","cwd":"/c/visual studio code/projekty/jachty3.pagedev.pl"}
diff --git a/.paul/phases/09-finalizacja/09-04-PLAN.md b/.paul/phases/09-finalizacja/09-04-PLAN.md
new file mode 100644
index 0000000..689a8bd
--- /dev/null
+++ b/.paul/phases/09-finalizacja/09-04-PLAN.md
@@ -0,0 +1,329 @@
+---
+phase: 09-finalizacja
+plan: 04
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - wp-content/plugins/yacht-booking-system/includes/class-settings.php
+ - wp-content/plugins/yacht-booking-system/includes/class-installer.php
+ - wp-content/plugins/yacht-booking-system/admin/class-admin.php
+ - wp-content/plugins/yacht-booking-system/admin/views/settings-page.php
+ - wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php
+ - wp-content/plugins/yacht-booking-system/api/class-rest-controller.php
+ - wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php
+ - wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget-all.php (NEW)
+ - wp-content/plugins/yacht-booking-system/frontend/class-shortcode.php
+ - wp-content/plugins/yacht-booking-system/assets/js/calendar-all.js (NEW)
+ - wp-content/plugins/yacht-booking-system/assets/css/calendar-all.css (NEW)
+autonomous: false
+delegation: off
+---
+
+
+## Goal
+Wprowadzić tryb "globalnej" synchronizacji iCal (wszystkie eventy z jednego feedu trafiają do wspólnego storage bez per-yacht matchingu) oraz nowy publiczny widget kalendarza pokazujący zajętość WSZYSTKICH publikowanych jachtów na jednej siatce, z kolorami per-jacht i wizualnym efektem "half-day" na pierwszym/ostatnim dniu rezerwacji.
+
+## Purpose
+- Klient prowadzi jeden wspólny Google Calendar do wszystkich jachtów. Obecny tryb wymaga prefiksu w SUMMARY ("Maja - Klient") i wyrzuca nierozpoznane eventy. Nowy tryb pozwala importować je wszystkie bez utraty (np. "Pierwszy dzień szkoły") jako wydarzenia informacyjne na wspólnym widoku.
+- Frontend ma jedno miejsce ("kalendarz floty") gdzie potencjalny klient widzi wszystkie zajętości naraz, bez rozpraszającego efektu ukośników z trybu per-jacht. Half-day daje wizualny sygnał, że ktoś może wynająć od/do południa.
+
+## Output
+- Settings: nowy select `ical_sync_mode` (`per_yacht` | `global`)
+- iCal Import: gałąź `global` zapisuje WSZYSTKIE eventy do wspólnego storage (`_booking_source = 'ical_global_calendar'`, brak yacht_id), bez wpisów do `wp_yacht_availability`
+- REST: `GET /availability/all` — zwraca eventy FullCalendar dla wszystkich jachtów + globalne wydarzenia, z kolorami auto-paleta i czasami timed (12:00 → 12:00)
+- Nowy widget Elementor `Yacht_Calendar_All_Widget` + shortcode `[yacht_calendar_all]` renderujący FullCalendar timed-grid z legendą jachtów
+
+
+
+
+- **Unmatched** — Co zrobić z eventami iCal bez prefiksu lub z nieznaną nazwą jachtu?
+ → Odpowiedź: Dodatkowa opcja w ustawieniach przełączająca tryb sync. Tryb `per_yacht` (obecny — match po prefiksie) lub `global` (jeden wspólny kalendarz, wszystkie eventy zapisywane bez przypisywania do jachtów; w danym dniu może być kilka wydarzeń).
+- **Widget zakres** — Nowy widget pokazuje które jachty?
+ → Odpowiedź: Wszystkie publikowane jachty (auto, `post_status = publish`).
+- **Rozróżnienie** — Jak odróżnić rezerwacje różnych jachtów?
+ → Odpowiedź: Kolor per jacht z auto palety (predefiniowana tablica kolorów indeksowana wg kolejności yacht_id, deterministycznie).
+- **Half-day** — Jak pokazać start/koniec w połowie dnia?
+ → Odpowiedź: FullCalendar timed events. Dane all-day konwertowane na timed (start = data 12:00, end = data+1 12:00) na poziomie REST endpointu.
+
+
+## Project Context
+@.paul/PROJECT.md
+@.paul/ROADMAP.md
+@.paul/STATE.md
+@.paul/codebase/architecture.md
+@.paul/codebase/db_schema.md
+
+## Prior Work
+@.paul/phases/09-finalizacja/09-02-SUMMARY.md
+@.paul/phases/09-finalizacja/09-03-SUMMARY.md
+
+## Source Files
+@wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php
+@wp-content/plugins/yacht-booking-system/includes/class-settings.php
+@wp-content/plugins/yacht-booking-system/admin/class-admin.php
+@wp-content/plugins/yacht-booking-system/admin/views/settings-page.php
+@wp-content/plugins/yacht-booking-system/api/class-rest-controller.php
+@wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget.php
+@wp-content/plugins/yacht-booking-system/frontend/class-shortcode.php
+@wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php
+@wp-content/plugins/yacht-booking-system/includes/class-installer.php
+
+
+
+
+## AC-1: Settings — przełącznik trybu synchronizacji iCal
+```gherkin
+Given admin otwiera "Yacht Booking → Settings → Synchronizacja"
+When zobaczy nowe pole "Tryb synchronizacji iCal" z opcjami "Per jacht" i "Wspólny kalendarz"
+And wybiera "Wspólny kalendarz" i zapisuje
+Then opcja `yacht_booking_ical_sync_mode` w wp_options = "global"
+And formularz pokazuje wybraną wartość po reload
+And opis pomocniczy wyjaśnia różnicę między trybami (per_yacht: matching po prefiksie / global: wszystkie eventy bez filtrowania)
+```
+
+## AC-2: Import iCal w trybie globalnym — wszystkie eventy bez filtrowania
+```gherkin
+Given `yacht_booking_ical_sync_mode = "global"` i feed URL ustawiony
+And feed zawiera 32 eventy (z prefiksami "Kubuś -", "Maja -", bez prefiksu "Pierwszy dzień szkoły", bez SUMMARY itp.)
+When uruchamia się hook `yacht_booking_ical_global_import`
+Then powstaje booking dla KAŻDEGO eventu z UID i `start`/`end` (poza past events)
+And `_booking_source = "ical_global_calendar"`, `_booking_yacht_id = 0`, `_booking_status = "confirmed"`
+And eventy NIE są wpisywane do `wp_yacht_availability` (nie blokują dostępności żadnego jachtu)
+And eventy bez SUMMARY otrzymują domyślny tytuł (np. "Wydarzenie kalendarza")
+And ponowne uruchomienie cron-u (idempotencja) — bookingi z tymi samymi UID są aktualizowane, nie duplikowane
+And eventy obecne w DB ale brakujące w nowym feedzie są usuwane (stale cleanup)
+```
+
+## AC-3: Import iCal w trybie per-jacht — bez regresji
+```gherkin
+Given `yacht_booking_ical_sync_mode = "per_yacht"` (domyślne dla istniejących instalacji)
+When uruchamia się hook globalnego importu
+Then zachowanie jest IDENTYCZNE jak przed tą zmianą (matching po prefiksie SUMMARY, wpisy do `wp_yacht_availability`, stale cleanup ograniczony do `_booking_source = "ical_import_global"`)
+And istniejące bookingi importowane wcześniej w trybie per-jacht działają dalej i są nadal aktualizowane
+```
+
+## AC-4: REST endpoint `GET /availability/all`
+```gherkin
+Given istnieje min. 2 publikowane jachty (np. "Kubuś", "Maja") z rezerwacjami
+And w trybie globalnym istnieją wydarzenia z `_booking_source = "ical_global_calendar"`
+When klient niezalogowany wywołuje `GET /wp-json/yacht-booking/v1/availability/all?start=2026-05-01&end=2026-12-31`
+Then odpowiedź to JSON tablica obiektów FullCalendar event:
+ { id, title, start (ISO datetime z "T12:00:00"), end (ISO datetime z "T12:00:00"), color, yacht_id }
+And bookingi per-jacht mają `color` z deterministycznej palety (tablica 8 kolorów indeksowana wg kolejności yacht_id)
+And globalne wydarzenia mają osobny kolor (np. szary `#7f8c8d`) i `yacht_id = 0`
+And tylko bookingi `confirmed`/`pending` są zwracane (nie `cancelled`/`rejected`)
+And `start <= end` zachowane
+```
+
+## AC-5: Nowy widget i shortcode
+```gherkin
+Given strona z `[yacht_calendar_all]` lub widgetem Elementor "Yacht Calendar (wszystkie jachty)"
+When klient otwiera stronę
+Then widoczny FullCalendar w widoku miesięcznym (dayGridMonth)
+And eventy z `GET /availability/all` są renderowane jako timed events 12:00 → 12:00 (efekt half-day na pierwszym/ostatnim dniu rezerwacji)
+And nad/pod kalendarzem jest legenda kolorów (kropka + nazwa jachtu) auto-generowana z palety
+And widget jest read-only (brak formularza rezerwacji, brak klikalności dnia)
+And brak ukośników (cell background pełny / pusty)
+```
+
+## AC-6: Auto paleta kolorów per jacht
+```gherkin
+Given lista jachtów posortowana po ID rosnąco
+When system mapuje yacht_id → kolor
+Then używana jest stała tablica min. 8 kolorów (np. #3498db, #e74c3c, #2ecc71, #f39c12, #9b59b6, #1abc9c, #34495e, #d35400)
+And mapowanie jest deterministyczne (yacht_id → index modulo długość palety) — ten sam yacht zawsze ten sam kolor
+And paleta jest wspólna dla REST endpointu i frontendowej legendy
+```
+
+
+
+
+
+
+ Task 1: Settings — przełącznik trybu sync iCal + zachowanie per_yacht jako default
+
+ wp-content/plugins/yacht-booking-system/includes/class-settings.php,
+ wp-content/plugins/yacht-booking-system/includes/class-installer.php,
+ wp-content/plugins/yacht-booking-system/admin/class-admin.php,
+ wp-content/plugins/yacht-booking-system/admin/views/settings-page.php
+
+
+ 1. `Settings`: dodaj typowany getter `get_ical_sync_mode()` zwracający `'per_yacht'` lub `'global'` (default: `'per_yacht'`). Klucz opcji: `yacht_booking_ical_sync_mode`. Dodaj setter w obecnym wzorcu klasy.
+ 2. `Installer`: dopisz default opcji `yacht_booking_ical_sync_mode = 'per_yacht'` do tablicy defaultów (nie nadpisuj istniejącej wartości jeśli jest).
+ 3. `Admin::process_settings_save()`: obsłuż nowe pole formularza (sanitize_text_field + whitelista wartości; nieznane → fallback `per_yacht`).
+ 4. `settings-page.php` (sekcja "Synchronizacja"): dodaj `
+
+ - W WP Admin → Settings widzę nowe pole, mogę zapisać "Wspólny kalendarz" i po reload jest zaznaczone.
+ - `wp option get yacht_booking_ical_sync_mode` zwraca `global`.
+ - `php -l` na każdym zmienionym pliku.
+
+ AC-1 satisfied.
+
+
+
+ Task 2: ICal_Import — gałąź global (storage bez per-yacht matchingu, idempotencja, stale cleanup)
+
+ wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php
+
+
+ 1. W `run_global_import()` po pobraniu i sparsowaniu eventów odczytaj `Settings::get_ical_sync_mode()`.
+ 2. Jeśli `per_yacht` — kod bez zmian (obecna ścieżka match po prefiksie + wpisy do availability).
+ 3. Jeśli `global` — pomiń `build_yacht_lookup_map()` / `match_yacht_by_prefix()`. Dla KAŻDEGO eventu (z UID + start + end, pomijając past events) wywołaj nową metodę `upsert_global_calendar_event($event, $existing_id)`:
+ - Wstawia/aktualizuje CPT `yacht_booking` z metami: `_booking_source = 'ical_global_calendar'`, `_booking_yacht_id = 0`, `_booking_status = 'confirmed'`, `_ical_event_uid = uid`, `_booking_start_date`, `_booking_end_date`, `_booking_customer_name = 'Google Calendar (kalendarz wspólny)'`, `_booking_total_price = 0`, `_booking_notes = summary`.
+ - Tytuł postu: `summary` lub fallback `__( 'Wydarzenie kalendarza', 'yacht-booking' )` gdy puste.
+ - NIE wywołuj `Availability::mark_as_booked()` (wydarzenia globalne nie blokują dostępności jachtów).
+ 4. Stale cleanup: w trybie global pobierz mapę istniejących bookingów po `_booking_source = 'ical_global_calendar'` (nowa stała `GLOBAL_CALENDAR_SOURCE`) i usuń te których UID brakuje w nowym feedzie (`wp_delete_post`, force).
+ 5. Stale cleanup w trybie per_yacht musi pozostać ograniczony do `_booking_source = 'ical_import_global'` (obecna stała) — nie tykać bookingów `ical_global_calendar` w drugą stronę i odwrotnie. Dwie stałe, dwie ścieżki cleanup.
+ 6. Logowanie: w trybie global loguj liczbę zaimportowanych / zaktualizowanych / usuniętych eventów.
+ Avoid: dotykanie `wp_yacht_availability` w trybie global. Avoid: zmiana sygnatury `run_global_import()` (cron callback).
+
+
+ - Test ręczny: ustaw URL na lokalną kopię `D:\temp\basic.ics` (zhostowaną w WP uploads lub serve), włącz tryb `global`, uruchom `wp cron event run yacht_booking_ical_global_import`.
+ - W WP Admin → Bookings widzę ~30 nowych pozycji z prefiksem "GCal:" lub tytułem eventu, brak wpływu na dostępność `yacht`.
+ - Drugie uruchomienie cron-u nie tworzy duplikatów (count się zgadza).
+ - `wp db query "SELECT COUNT(*) FROM wp_yacht_availability WHERE booking_id IN (SELECT post_id FROM wp_postmeta WHERE meta_key='_booking_source' AND meta_value='ical_global_calendar')"` zwraca 0.
+ - Przełącz na `per_yacht` i uruchom — nowa logika nie ma efektu, stara działa jak wcześniej.
+ - `php -l`.
+
+ AC-2 + AC-3 satisfied.
+
+
+
+ Task 3: REST endpoint /availability/all — agregacja wszystkich jachtów + globalnych eventów z kolorami i timed
+
+ wp-content/plugins/yacht-booking-system/api/class-rest-controller.php,
+ wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php
+
+
+ 1. W `Rest_Controller`: dodaj nową metodę `get_all_availability( $request )` zarejestrowaną jako `GET /yacht-booking/v1/availability/all` (callback w `register_rest_routes()`, `permission_callback => '__return_true'`).
+ 2. Walidacja parametrów `start`, `end` (Y-m-d, opcjonalne — default: pierwszy dzień bieżącego miesiąca / + 12 mies.).
+ 3. Pobierz publikowane jachty (`get_posts` post_type=yacht). Zbuduj mapę `yacht_id => color` przez nową statyczną metodę `Rest_Controller::get_yacht_color_palette( array $yacht_ids )`:
+ - Stała tablica 8 kolorów hex.
+ - Mapuj `yacht_id` (sortowane rosnąco) na `palette[ index % count(palette) ]`.
+ - Stała kolor globalnego eventu: `#7f8c8d`.
+ 4. Query bookings: `post_type = yacht_booking`, status `confirmed` lub `pending`, daty przecinające `start`–`end`. Per booking zwróć:
+ ```
+ {
+ id: booking_id,
+ title: ' — ' lub tytuł postu dla global,
+ start: 'T12:00:00',
+ end: 'T12:00:00',
+ color: ,
+ yacht_id:
+ }
+ ```
+ 5. Globalne eventy (`_booking_source = ical_global_calendar`) traktowane jednolicie z yacht_id=0 i kolorem szarym; tytuł = `_booking_notes` lub post_title.
+ 6. Pomiń `cancelled`/`rejected`.
+ 7. W `Yacht_Booking::register_rest_routes()` upewnij się, że nowa trasa się rejestruje (jeśli rejestracja jest delegowana do `Rest_Controller::register_routes()` — bez zmiany).
+ Avoid: cache na poziomie endpointu (małe wolumeny, prosto). Avoid: dodawanie nowych zależności / SDK.
+
+
+ - `curl 'https:///wp-json/yacht-booking/v1/availability/all?start=2026-05-01&end=2026-12-31'` zwraca tablicę JSON z polami { id, title, start, end, color, yacht_id }.
+ - Każdy yacht_id ma stały kolor między requestami.
+ - Bookingi per-yacht mają yacht_id != 0; globalne mają yacht_id = 0 i kolor `#7f8c8d`.
+ - Daty zawierają `T12:00:00`.
+ - `php -l`.
+
+ AC-4 + AC-6 satisfied.
+
+
+
+ Task 4: Widget Elementor + shortcode "yacht_calendar_all" + JS/CSS
+
+ wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget-all.php (NEW),
+ wp-content/plugins/yacht-booking-system/frontend/class-shortcode.php,
+ wp-content/plugins/yacht-booking-system/assets/js/calendar-all.js (NEW),
+ wp-content/plugins/yacht-booking-system/assets/css/calendar-all.css (NEW),
+ wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php
+
+
+ 1. **Nowy widget** `Yacht_Calendar_All_Widget` (extends `\Elementor\Widget_Base`) — wzorowany na `Calendar_Widget`, name=`yacht-calendar-all`, title=`Yacht Calendar (wszystkie jachty)`, ikona kalendarza. `render()` wypisuje ``.
+ 2. **Shortcode** `[yacht_calendar_all]` w `Shortcode` (lub nowa metoda) — bez atrybutów. Wypisuje ten sam markup co widget.
+ 3. **`Yacht_Booking`**: rejestracja widgetu w `register_elementor_widgets()` (dopisz obok istniejącego). Conditional enqueue assets `calendar-all.js`/`calendar-all.css` gdy w treści jest shortcode lub na stronie z widgetem (rozszerz obecny mechanizm).
+ 4. **`calendar-all.js`** (IIFE jQuery): inicjalizacja FullCalendar v6 (CDN), `initialView: 'dayGridMonth'`, `events: `, `displayEventTime: false`, `eventDisplay: 'block'`. Po `eventDidMount` dodaj klasę `.is-half-day-start` / `.is-half-day-end` do pierwszej/ostatniej komórki eventu (na podstawie hours = 12). Renderuj legendę (lista jachtów + kolorów) pobraną z dodatkowego endpointu `GET /availability/all/legend` LUB wyciągniętą z eventów po pierwszym fetch (wybierz prostsze — preferuj wyciąganie z eventów na froncie).
+ 5. **`calendar-all.css`** — minimalistyczny styl: ukryj kropkę przy timed event, pełne wypełnienie kafelka kolorem eventu, half-day cell renderowany przez gradient `linear-gradient(to right, transparent 50%, var(--color) 50%)` na pierwszym dniu i odwrotnie na ostatnim. Brak ukośników. Mobile-first.
+ 6. Brak modal-a / formularza rezerwacji — read-only.
+ Avoid: npm/bundler — FullCalendar via CDN jak istniejący widget. Avoid: dotykanie istniejącego widgetu/CSS.
+
+
+ - `php -l` na nowych/zmienionych plikach PHP.
+ - Strona z `[yacht_calendar_all]` renderuje kalendarz z eventami pobranymi z REST.
+ - Eventy z różnych jachtów mają różne kolory (paleta).
+ - Pierwszy/ostatni dzień rezerwacji wizualnie wypełniony do połowy (gradient/half cell).
+ - Brak konsoli błędów JS.
+ - Widget pojawia się w panelu Elementor pod kategorią pluginu.
+
+ AC-5 satisfied (półdniowe rendery + legenda + read-only). AC-6 deterministyczna paleta wspólna z REST.
+
+
+
+
+ - Settings: nowa opcja "Tryb synchronizacji iCal" (per_yacht / global)
+ - iCal Import: tryb global importuje wszystkie eventy bez filtrowania, nie blokuje dostępności jachtów
+ - REST: `GET /availability/all` zwraca wszystkie rezerwacje + globalne eventy z kolorami i timed (12:00)
+ - Frontend: shortcode `[yacht_calendar_all]` + widget Elementor "Yacht Calendar (wszystkie jachty)" z efektem half-day i legendą kolorów
+
+
+ 1. Deploy plików przez FTP (ftp-kr) i ewentualnie aktywuj plugin (jeśli wymagane przez Installer dla nowej opcji).
+ 2. Wejdź w WP Admin → Yacht Booking → Settings → sekcja Synchronizacja: ustaw "Wspólny kalendarz", podaj URL feedu (lub tymczasowo `D:\temp\basic.ics` wystawiony przez serwer testowy), zapisz.
+ 3. Uruchom ręcznie `yacht_booking_ical_global_import` (np. WP-CLI: `wp cron event run yacht_booking_ical_global_import` lub przycisk "Synchronizuj teraz" jeśli istnieje).
+ 4. Sprawdź WP Admin → Bookings: powinny pojawić się ~30 wydarzeń bez yacht_id.
+ 5. Zweryfikuj że dostępność jachtów (kalendarz pojedynczego jachtu) się NIE zmieniła.
+ 6. Stwórz testową stronę z `[yacht_calendar_all]`. Otwórz w przeglądarce.
+ 7. Sprawdź: a) różne kolory dla "Maja" i "Kubuś", b) szare dla globalnych, c) pierwszy/ostatni dzień rezerwacji wypełniony do połowy, d) brak ukośników, e) legenda widoczna.
+ 8. Przełącz tryb na "Per jacht", uruchom cron — sprawdź że stary mechanizm nadal działa (matching po prefiksie, wpisy w availability).
+
+ Type "approved" to continue, or describe issues to fix
+
+
+
+
+
+
+## DO NOT CHANGE
+- `frontend/class-calendar-widget.php` (istniejący widget per-jacht — kopiujemy NOWY plik, nie dotykamy starego)
+- `assets/js/calendar.js`, `assets/css/calendar.css` (assety istniejącego widgetu)
+- Schema tabeli `wp_yacht_availability` — nie dodajemy kolumn
+- `Booking::create()` flow (REST POST /bookings) — flow rezerwacji frontendowej bez zmian
+- Settings: nie zmieniamy domyślnej wartości `ical_sync_mode` na `global` (regresja). Default = `per_yacht`.
+- Stała `ICal_Import::GLOBAL_IMPORT_SOURCE = 'ical_import_global'` (per-jacht stale cleanup) — dodajemy DRUGĄ stałą `GLOBAL_CALENDAR_SOURCE = 'ical_global_calendar'`, nie zmieniamy istniejącej
+
+## SCOPE LIMITS
+- Brak konfigurowalnej palety kolorów (color picker per jacht) — auto paleta z hardcoded tablicy. Color picker w meta jachtu = osobny plan jeśli klient zechce.
+- Brak osobnego widoku "tylko globalne wydarzenia" — globalne pokazują się tylko na nowym wspólnym widgecie.
+- Brak konfiguracji shortcode (atrybuty `yachts=`, `view=`) — wszystkie publikowane, dayGridMonth.
+- Brak klikalności dnia / formularza rezerwacji na nowym widgecie — read-only podgląd.
+- Brak migracji istniejących bookingów `_booking_source = ical_import_global` na nowy storage. Klient musi ręcznie usunąć stare jeśli przełączy się trwale na global.
+- Bez zmian dla widgetu Elementor istniejącego (per-jacht) — dwa widgety obok siebie.
+
+
+
+
+Before declaring plan complete:
+- [ ] `php -l` na każdym zmienionym/nowym pliku PHP — bez błędów
+- [ ] `wp option get yacht_booking_ical_sync_mode` zwraca poprawną wartość po zapisie
+- [ ] W trybie `global` po cron-imporcie liczba wydarzeń w `Bookings` ≈ liczba VEVENT z feedu (poza past)
+- [ ] W trybie `global` brak wpisów do `wp_yacht_availability` dla `_booking_source = ical_global_calendar`
+- [ ] W trybie `per_yacht` zachowanie identyczne jak przed planem (regression check)
+- [ ] `GET /availability/all` zwraca poprawny JSON dla niezalogowanego klienta
+- [ ] Strona z `[yacht_calendar_all]` renderuje się bez błędów JS w konsoli
+- [ ] Half-day visual widoczny na pierwszym i ostatnim dniu każdej rezerwacji
+- [ ] Legenda kolorów spójna z kolorami eventów
+- [ ] Wszystkie acceptance criteria spełnione
+
+
+
+- Klient może przełączyć tryb sync w settings i zobaczyć efekt po cron-imporcie
+- Wszystkie eventy z basic.ics (32) są zaimportowane w trybie global (poza past events)
+- Nowy widget pokazuje wszystkie jachty + globalne eventy z kolorami i half-day
+- Brak regresji w trybie per-jacht
+- Brak regresji w istniejącym widgecie per-jacht
+- Brak nowych ostrzeżeń PHP / błędów konsoli
+
+
+
diff --git a/.paul/phases/09-finalizacja/09-04-SUMMARY.md b/.paul/phases/09-finalizacja/09-04-SUMMARY.md
new file mode 100644
index 0000000..79e0213
--- /dev/null
+++ b/.paul/phases/09-finalizacja/09-04-SUMMARY.md
@@ -0,0 +1,210 @@
+---
+phase: 09-finalizacja
+plan: 04
+subsystem: api, ui, integrations
+tags: [ical, fullcalendar, elementor, rest, privacy]
+
+requires:
+ - phase: 09-finalizacja
+ provides: globalna sync iCal (09-02), cleanup OAuth (09-03)
+provides:
+ - tryb sync iCal "wspólny kalendarz" (storage bez per-yacht matchingu)
+ - REST endpoint /availability/all (agregacja + privacy)
+ - widget Elementor + shortcode [yacht_calendar_all]
+ - paleta kolorów per-jacht (Rest_Controller::YACHT_COLOR_PALETTE)
+ - privacy: tytuły eventów nie zawierają nazwisk klientów (REST + JS)
+affects: [security audit, dokumentacja]
+
+tech-stack:
+ added: []
+ patterns:
+ - View helper pattern (Calendar_All_View) — render wspólny dla widgetu i shortcode
+ - Eager-load REST controller (constants/static methods used in frontend)
+ - Privacy-by-default: REST endpoint nie wystawia nazwisk klientów
+
+key-files:
+ created:
+ - wp-content/plugins/yacht-booking-system/frontend/class-calendar-widget-all.php
+ - wp-content/plugins/yacht-booking-system/frontend/assets/css/calendar-all.css
+ - wp-content/plugins/yacht-booking-system/frontend/assets/js/calendar-all.js
+ modified:
+ - wp-content/plugins/yacht-booking-system/api/class-rest-controller.php
+ - wp-content/plugins/yacht-booking-system/integrations/ical/class-ical-import.php
+ - wp-content/plugins/yacht-booking-system/includes/class-settings.php
+ - wp-content/plugins/yacht-booking-system/includes/class-installer.php
+ - wp-content/plugins/yacht-booking-system/includes/class-yacht-booking.php
+ - wp-content/plugins/yacht-booking-system/admin/class-admin.php
+ - wp-content/plugins/yacht-booking-system/frontend/class-shortcode.php
+ - wp-content/plugins/yacht-booking-system/yacht-booking-system.php
+
+key-decisions:
+ - "Tryb sync `global` = osobna ścieżka cleanup, dwie stałe source (per-yacht / global)"
+ - "Privacy: title eventów na REST = nazwa jachtu (per_yacht) lub generyczne 'Rezerwacja' (global), bez customer_name"
+ - "View helper `Calendar_All_View::render()` — wspólny markup widget + shortcode"
+ - "Eager-load Rest_Controller w load_dependencies() — używany przez frontend View, nie tylko REST"
+ - "Half-day visual: dynamiczny gradient JS na bazie szerokości komórki dnia (FC nie ma natywnej obsługi half-day w dayGrid)"
+ - "Kolor wspólnych eventów: jasnoniebieski #7fb3d5 (po iteracjach: #7f8c8d → #bc1834 → #7fb3d5)"
+
+patterns-established:
+ - "Privacy-by-default w REST: tytuły eventów bez customer_name nawet w trybie per_yacht"
+ - "Settings z whitelistą wartości (`per_yacht`/`global`) + fallback do bezpiecznego defaultu"
+ - "Stała paleta kolorów współdzielona REST ↔ frontend (Rest_Controller::YACHT_COLOR_PALETTE)"
+
+duration: ~120min
+started: 2026-05-07T11:30:00Z
+completed: 2026-05-07T13:30:00Z
+---
+
+# Phase 09 Plan 04: Globalna sync iCal + widget wszystkich jachtów
+
+**Plugin obsługuje teraz dwa tryby synchronizacji iCal (per-jacht / wspólny) i ma drugi widget kalendarza pokazujący zajętość wszystkich jachtów na jednej siatce z paletą kolorów per-jacht, half-day gradientem i ciemnym formularzem zapytania po prawej stronie.**
+
+## Performance
+
+| Metric | Value |
+|--------|-------|
+| Duration | ~120min (z iteracjami UX po checkpoincie) |
+| Started | 2026-05-07T11:30:00Z |
+| Completed | 2026-05-07T13:30:00Z |
+| Tasks | 4 auto + 1 checkpoint + 5 iteracji UX po checkpoincie |
+| Files modified | 8 zmodyfikowanych + 3 nowe + 1 testowy (test-overlap-bookings.php) |
+
+## Acceptance Criteria Results
+
+| Criterion | Status | Notes |
+|-----------|--------|-------|
+| AC-1: Settings — przełącznik trybu sync iCal | Pass | Pole select w sekcji "Synchronizacja", domyślnie `per_yacht` |
+| AC-2: Import iCal w trybie globalnym (wszystkie eventy) | Pass | Wszystkie eventy z basic.ics importowane, brak wpisów do `wp_yacht_availability` |
+| AC-3: Import iCal w trybie per_yacht (bez regresji) | Pass | Stara ścieżka `run_per_yacht_mode()` działa identycznie, własna stała cleanup |
+| AC-4: REST endpoint `/availability/all` | Pass | Zwraca FullCalendar events z timed 12:00→12:00 i kolorami |
+| AC-5: Widget + shortcode | Pass | Po iteracjach: ciemne tło, formularz inquiry z select jachtów, bez tytułów eventów |
+| AC-6: Auto paleta kolorów per jacht | Pass | `YACHT_COLOR_PALETTE` (8 kolorów) deterministyczna po yacht_id |
+
+## Accomplishments
+
+- **Tryb global iCal** — klient prowadzi jeden wspólny Google Calendar, wszystkie eventy (32 z basic.ics) są importowane bez filtrowania prefiksem; nie blokują dostępności jachtów (`yacht_id=0`).
+- **Wspólny widget z formularzem inquiry** — `[yacht_calendar_all]` + Elementor "Kalendarz Jachtów (wszystkie)" pokazuje siatkę miesięczną z paskami rezerwacji w kolorach palety per-jacht (lub jednolity jasnoniebieski w trybie global), formularz "Zapytaj o rezerwację" po prawej w ciemnym stylu identycznym jak `/rezerwacja-maja/`.
+- **Privacy-by-default** — REST endpoint `/availability/all` nie wystawia `customer_name` w `title` eventów; w trybie global tytuł = generyczne "Rezerwacja", w per_yacht = sama nazwa jachtu. Defense-in-depth: JS `eventContent` zwraca pusty html (nawet gdyby title trafił do REST, nie wyrenderuje się w DOM).
+- **Half-day visual** — dynamiczny gradient JS na pierwszym/ostatnim dniu rezerwacji (yacht zwracany/odbierany w południe), liczony na bazie szerokości komórki dnia (FullCalendar dayGrid nie ma natywnej obsługi).
+
+## Files Created/Modified
+
+| File | Change | Purpose |
+|------|--------|---------|
+| `wp-content/plugins/yacht-booking-system/yacht-booking-system.php` | Modified | Bump wersji 1.0.0 → 1.1.0 (uruchamia Installer::install + cache busting) |
+| `includes/class-settings.php` | Modified | `get_ical_sync_mode()` z whitelistą wartości |
+| `includes/class-installer.php` | Modified | Default option `yacht_booking_ical_sync_mode = per_yacht` |
+| `includes/class-yacht-booking.php` | Modified | Eager-load Rest_Controller, rejestracja widgetu, conditional enqueue, detekcja shortcode/widget |
+| `admin/class-admin.php` | Modified | Pole select trybu sync + obsługa zapisu w `process_settings_save()` |
+| `integrations/ical/class-ical-import.php` | Modified | Rozgałęzienie `run_per_yacht_mode()` / `run_global_calendar_mode()`, nowa stała `GLOBAL_CALENDAR_SOURCE`, metody `upsert_global_calendar_event()`, `get_existing_global_calendar_map()` |
+| `api/class-rest-controller.php` | Modified | Stałe `YACHT_COLOR_PALETTE` + `GLOBAL_EVENT_COLOR`, route + metoda `get_all_availability()`, `get_yacht_color_palette()`, privacy w title |
+| `frontend/class-shortcode.php` | Modified | Shortcode `[yacht_calendar_all]` |
+| `frontend/class-calendar-widget-all.php` | Created | Widget Elementor `Calendar_Widget_All` + helper `Calendar_All_View` (server-side legenda + formularz inquiry z select jachtów) |
+| `frontend/assets/css/calendar-all.css` | Created | Tła komórek emulujące paletę single-yacht (semi-transparent na ciemnym tle), styl select, ukryte tytuły eventów |
+| `frontend/assets/js/calendar-all.js` | Created | FullCalendar init, dynamiczny gradient half-day, submit handler dla formularza inquiry z dropdownem jachtów |
+| `test-overlap-bookings.php` | Created (root) | Test helper dodający 2 nakładające się eventy (do usunięcia po teście) |
+
+## Decisions Made
+
+| Decision | Rationale | Impact |
+|----------|-----------|--------|
+| Dwie stałe source (`ical_import_global` per-yacht, `ical_global_calendar` global) | Pozwala niezależny cleanup w obu trybach bez krzyżowych usunięć | Przełączanie trybów nie usuwa eventów z drugiego trybu |
+| Privacy: brak `customer_name` w REST title | Wcześniej `title` zawierało "Maja — Jan Kowalski" — nazwiska klientów na publicznym REST | Nawet po inspekcji DOM/API nazwisk nie ma |
+| View helper `Calendar_All_View::render()` zamiast duplikacji widget+shortcode | DRY | Zmiana markupu w jednym miejscu |
+| Eager-load Rest_Controller w `load_dependencies()` | Frontend View używa stałych palety + statyk metod | Bez tego: `Class 'Rest_Controller' not found` przy renderze |
+| Half-day przez dynamiczny gradient JS (a nie czyste CSS) | FullCalendar dayGrid nie ma natywnej obsługi half-day; CSS nie zna szerokości segmentu | Wymaga `requestAnimationFrame` w `eventDidMount` |
+| Klasa wrappera `yacht-calendar-all-wrapper` (bez `yacht-calendar-wrapper`) | Calendar.js inicjalizuje wszystko z `.yacht-calendar-wrapper` → kolizja | Drugi widget niezależny od starego JS |
+| Kolor wspólnych eventów: `#7fb3d5` (jasnoniebieski) | Iteracje z klientem: szary `#7f8c8d` → czerwony `#bc1834` (zbyt agresywny) → jasnoniebieski | Spójny z legendą + komfort wizualny |
+| Tła komórek `rgba(245,249,255, 0.4)` na `#0e2036` | Emulacja efektu `yacht-day-available` bg-event nad ciemnym parent containerem w `/rezerwacja-maja/` | Spójny styl z istniejącym widgetem per-jacht |
+
+## Deviations from Plan
+
+### Summary
+
+| Type | Count | Impact |
+|------|-------|--------|
+| Auto-fixed | 6 | UX poprawki po checkpoincie + privacy hardening |
+| Scope additions | 1 | Privacy w REST (poza pierwotnym scope) |
+| Deferred | 0 | Wszystko ukończone |
+
+**Total impact:** Solidne UX iteracje + bonus privacy hardening (chroni przed wyciekiem nazwisk klientów).
+
+### Auto-fixed Issues
+
+**1. Path discrepancies — assets w `frontend/assets/` zamiast root `assets/`**
+- **Found during:** Task 4 (widget assets)
+- **Issue:** Plan referował `assets/js/`, `assets/css/`, `admin/views/settings-page.php` — w projekcie tych ścieżek nie ma
+- **Fix:** Użyłem faktycznej struktury (`frontend/assets/{css,js}/`, formularz settings inline w `class-admin.php`)
+- **Verification:** Pliki utworzone w prawidłowych miejscach, conditional enqueue działa
+- **Commit:** część zmiany w `class-yacht-booking.php`
+
+**2. `Class 'Rest_Controller' not found` przy frontend renderze**
+- **Found during:** Po pierwszym deploy (raportowane przez klienta)
+- **Issue:** Rest_Controller ładowany lazy w `register_rest_routes()`, View używa stałych palety przy frontend render
+- **Fix:** Dodano `require_once api/class-rest-controller.php` w `Yacht_Booking::load_dependencies()` (eager)
+- **Verification:** Brak fatal errors po reload
+- **Commit:** `includes/class-yacht-booking.php`
+
+**3. Brakujący formularz inquiry + brakująca legenda + brakująca instrukcja**
+- **Found during:** Po checkpoincie human-verify
+- **Issue:** Pierwsza wersja widgetu była tylko kalendarzem; klient oczekiwał layoutu jak na `/rezerwacja-maja/` (calendar + form right)
+- **Fix:** Dodano `Calendar_All_View` render z `.yacht-inquiry-layout`, server-side legenda (działa nawet przed JS), instrukcję, formularz inquiry z `