diff --git a/.paul/PROJECT.md b/.paul/PROJECT.md
new file mode 100644
index 0000000..b12a38d
--- /dev/null
+++ b/.paul/PROJECT.md
@@ -0,0 +1,24 @@
+---
+name: RM2 Media Folders
+type: wordpress-plugin
+stack: PHP 8.x, WordPress 6.x, jQuery, vanilla JS
+---
+
+## Vision
+
+Plugin WordPress zastepujacy domyslna biblioteke mediow widokiem ustrukturyzowanym z mozliwoscia tworzenia podkatalogow (folderow wirtualnych). Media sa organizowane w foldery za pomoca custom taxonomy, bez zmiany fizycznej struktury plikow na dysku.
+
+## Value Proposition
+
+- Uzytkownik moze organizowac media w foldery/podkatalogi
+- Drag & drop przenoszenie mediow miedzy folderami
+- Integracja z domyslnym media uploaderem WP (modal)
+- Drzewko folderow w panelu bocznym biblioteki mediow
+
+## Constraints
+
+- Kompatybilnosc z WordPress 6.0+
+- PHP 8.0+
+- Bez zewnetrznych zaleznosci (czyste WP API)
+- Nie modyfikuje fizycznej struktury wp-content/uploads
+- Wirtualne foldery oparte na custom taxonomy
diff --git a/.paul/ROADMAP.md b/.paul/ROADMAP.md
new file mode 100644
index 0000000..8090b07
--- /dev/null
+++ b/.paul/ROADMAP.md
@@ -0,0 +1,22 @@
+---
+milestone: v0.1 Media Folders MVP
+status: Complete
+---
+
+# v0.1 — Media Folders MVP
+
+Minimalny plugin WordPress z wirtualnymi folderami dla biblioteki mediow.
+
+## Phases
+
+### Phase 1: Plugin Foundation + Taxonomy [Complete]
+Core plugin file, custom taxonomy registration, folder CRUD (create/rename/delete) via AJAX, admin menu integration.
+
+### Phase 2: Media Library Grid Integration [Complete]
+Replace/enhance default media library grid view with folder tree sidebar. Folder filtering, drag & drop media assignment.
+
+### Phase 3: Media Upload Modal Integration [Complete]
+Integrate folder tree into WP media upload modal (used by editor, Elementor, etc.). Allow selecting folder during upload.
+
+### Phase 4: Polish & UX [Complete]
+Bulk operations, folder counters, empty states, confirmations, keyboard navigation, accessibility.
diff --git a/.paul/STATE.md b/.paul/STATE.md
new file mode 100644
index 0000000..0054aae
--- /dev/null
+++ b/.paul/STATE.md
@@ -0,0 +1,29 @@
+## Current Position
+
+Milestone: v0.1 Media Folders MVP — COMPLETE
+Phase: 4 of 4 (Polish & UX) — Complete
+Plan: 04-01 complete
+Status: All phases complete. Milestone delivered.
+Last activity: 2026-03-28 — UNIFY complete, milestone v0.1 finished
+
+Progress:
+- Milestone: [██████████] 100%
+- Phase 1: [██████████] 100% — Plugin Foundation + Taxonomy
+- Phase 2: [██████████] 100% — Media Library Grid Integration
+- Phase 3: [██████████] 100% — Media Upload Modal Integration
+- Phase 4: [██████████] 100% — Polish & UX
+
+## Loop Position
+
+Current loop state:
+```
+PLAN ──▶ APPLY ──▶ UNIFY
+ ✓ ✓ ✓ [Milestone complete]
+```
+
+## Session Continuity
+
+Last session: 2026-03-28
+Stopped at: Milestone v0.1 complete
+Next action: Test plugin on live WordPress, then plan v0.2 if needed
+Resume file: .paul/phases/04-polish-ux/04-01-SUMMARY.md
diff --git a/.paul/phases/01-media-folders-plugin/01-01-PLAN.md b/.paul/phases/01-media-folders-plugin/01-01-PLAN.md
new file mode 100644
index 0000000..a51fd9e
--- /dev/null
+++ b/.paul/phases/01-media-folders-plugin/01-01-PLAN.md
@@ -0,0 +1,258 @@
+---
+phase: 01-media-folders-plugin
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - wp-content/plugins/media-folder-pro/media-folder-pro.php
+ - wp-content/plugins/media-folder-pro/includes/class-taxonomy.php
+ - wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
+ - wp-content/plugins/media-folder-pro/assets/css/admin.css
+ - wp-content/plugins/media-folder-pro/assets/js/folder-tree.js
+autonomous: true
+---
+
+
+## Goal
+Stworzyc fundament pluginu WordPress "RM2 Media Folders" — rejestracja custom taxonomy `media_folder` dla attachment post type, CRUD folderow przez AJAX, oraz bazowy UI drzewka folderow w panelu admina.
+
+## Purpose
+Bez tego fundamentu nie mozna budowac integracji z biblioteka mediow. Taxonomy to core mechanizm organizacji.
+
+## Output
+Dzialajacy plugin z:
+- Custom taxonomy `media_folder` (hierarchiczna, niewidoczna publicznie)
+- AJAX endpoints: tworzenie, zmiana nazwy, usuwanie, przenoszenie folderow
+- Bazowe drzewko folderow renderowane w JS
+
+
+
+## Project Context
+@.paul/PROJECT.md
+@.paul/ROADMAP.md
+
+## Source Files
+Nowy plugin — brak istniejacych plikow. Tworzymy od zera.
+
+
+
+
+## AC-1: Plugin aktywuje sie bez bledow
+```gherkin
+Given WordPress 6.x z PHP 8.0+
+When uzytkownik aktywuje plugin "RM2 Media Folders"
+Then plugin aktywuje sie bez bledow i warnings
+And w bazie danych pojawia sie taxonomy "media_folder"
+```
+
+## AC-2: CRUD folderow dziala przez AJAX
+```gherkin
+Given plugin jest aktywny
+When uzytkownik tworzy folder "Zdjecia produktow" przez UI
+Then folder zostaje zapisany jako term w taxonomy media_folder
+And odpowiedz AJAX zawiera id i nazwe nowego folderu
+
+Given istniejacy folder "Zdjecia produktow"
+When uzytkownik zmienia nazwe na "Produkty 2026"
+Then term name i slug zostaja zaktualizowane
+
+Given istniejacy pusty folder
+When uzytkownik usuwa folder
+Then term zostaje usuniety z bazy
+
+Given istniejacy folder
+When uzytkownik przenosi go jako subfolder innego folderu
+Then term parent zostaje zaktualizowany
+```
+
+## AC-3: Drzewko folderow renderuje sie poprawnie
+```gherkin
+Given plugin jest aktywny i istnieja foldery z podfolderami
+When uzytkownik otwiera strone Media w panelu admina
+Then widoczne jest drzewko folderow z hierarchia
+And foldery mozna rozwijac/zwijac
+And klikniecie folderu filtruje liste mediow
+```
+
+
+
+
+
+
+ Task 1: Core plugin file + taxonomy registration
+ wp-content/plugins/rm2-media-folders/rm2-media-folders.php, wp-content/plugins/rm2-media-folders/includes/class-taxonomy.php
+
+ 1. Utworzyc glowny plik pluginu rm2-media-folders.php:
+ - Plugin header (Name: RM2 Media Folders, Version: 0.1.0)
+ - Autoload includes/
+ - Hook init: rejestracja taxonomy
+ - Hook admin_enqueue_scripts: ladowanie CSS/JS na stronach media
+ - Hook wp_ajax_*: rejestracja AJAX handlers
+
+ 2. Utworzyc includes/class-taxonomy.php:
+ - Klasa RM2_Media_Folders_Taxonomy
+ - Metoda register(): register_taxonomy('media_folder', 'attachment', args)
+ - hierarchical: true
+ - public: false
+ - show_ui: false (wlasny UI)
+ - show_in_rest: true (dla block editora)
+ - Metoda get_folder_tree(): zwraca hierarchiczne drzewo folderow
+ - Uzywa get_terms() z 'hide_empty' => false
+ - Buduje drzewo parent-child
+
+ Avoid: Nie uzywac show_ui: true — bedziemy miec wlasny interfejs.
+ Avoid: Nie rejestrowac taxonomy dla innych post types niz attachment.
+
+
+ - Plugin pojawia sie na liscie pluginow WP
+ - Po aktywacji: wp term list media_folder --format=json (WP-CLI) nie zwraca bledu
+ - Taxonomy istnieje: taxonomy_exists('media_folder') === true
+
+ AC-1 satisfied: Plugin aktywuje sie, taxonomy zarejestrowana
+
+
+
+ Task 2: AJAX handler for folder CRUD
+ wp-content/plugins/rm2-media-folders/includes/class-ajax-handler.php
+
+ Utworzyc includes/class-ajax-handler.php:
+ - Klasa RM2_Media_Folders_Ajax
+
+ Endpointy AJAX (kazdy z nonce verification + capability check 'upload_files'):
+
+ 1. rm2_mf_create_folder:
+ - Parametry: name (string), parent_id (int, 0 = root)
+ - wp_insert_term($name, 'media_folder', ['parent' => $parent_id])
+ - Zwraca: {success: true, folder: {id, name, slug, parent}}
+
+ 2. rm2_mf_rename_folder:
+ - Parametry: folder_id (int), name (string)
+ - wp_update_term($folder_id, 'media_folder', ['name' => $name])
+ - Zwraca: {success: true, folder: {id, name, slug}}
+
+ 3. rm2_mf_delete_folder:
+ - Parametry: folder_id (int)
+ - Sprawdz czy folder jest pusty (brak attachmentow i subfolderow)
+ - Jesli nie pusty: zwroc blad
+ - wp_delete_term($folder_id, 'media_folder')
+ - Zwraca: {success: true}
+
+ 4. rm2_mf_move_folder:
+ - Parametry: folder_id (int), new_parent_id (int, 0 = root)
+ - Walidacja: nie mozna przeniesc folderu do samego siebie lub swojego dziecka
+ - wp_update_term($folder_id, 'media_folder', ['parent' => $new_parent_id])
+ - Zwraca: {success: true, folder: {id, name, parent}}
+
+ 5. rm2_mf_get_folders:
+ - Brak parametrow
+ - Zwraca pelne drzewo folderow z countami attachmentow
+
+ Kazdy endpoint:
+ - check_ajax_referer('rm2_media_folders_nonce', 'nonce')
+ - current_user_can('upload_files')
+ - wp_send_json_success() / wp_send_json_error()
+
+ Avoid: Nie uzywac $_GET — wszystko przez $_POST.
+ Avoid: Nie usuwac folderow z dziecmi — wymuszaj pusty folder.
+
+
+ - AJAX call do rm2_mf_create_folder zwraca 200 z JSON {success: true}
+ - Utworzony term widoczny w get_terms('media_folder')
+ - Proba bez nonce zwraca 403
+ - Proba bez uprawnien zwraca blad
+
+ AC-2 satisfied: CRUD folderow dziala przez AJAX z walidacja
+
+
+
+ Task 3: Admin assets + folder tree UI
+ wp-content/plugins/rm2-media-folders/assets/css/admin.css, wp-content/plugins/rm2-media-folders/assets/js/folder-tree.js
+
+ 1. admin.css:
+ - Styl dla sidebar drzewka folderow (lewy panel, 250px szerokosci)
+ - Style dla elementow drzewka: folder icon, nazwa, expand/collapse arrow
+ - Styl aktywnego folderu (podswietlenie)
+ - Style dla context menu (prawy klik: rename, delete, new subfolder)
+ - Style dla inline edit (zmiana nazwy folderu)
+ - Responsywnosc: na mniejszych ekranach sidebar chowa sie
+
+ 2. folder-tree.js (vanilla JS, bez jQuery dependency):
+ - Klasa RM2FolderTree
+ - init(): fetch folderow z AJAX (rm2_mf_get_folders), renderuj drzewo
+ - renderTree(folders, container): rekurencyjny render z -
+ - toggleFolder(folderId): expand/collapse children
+ - selectFolder(folderId): podswietl + wyslij event 'rm2-folder-selected'
+ - createFolder(parentId): prompt nazwa → AJAX create
+ - renameFolder(folderId): inline edit → AJAX rename
+ - deleteFolder(folderId): confirm → AJAX delete
+ - moveFolder(folderId, newParentId): AJAX move (drag & drop w nastepnej fazie)
+
+ Toolbar nad drzewkiem:
+ - Przycisk "+" (nowy folder w root)
+ - Przycisk "All Media" (reset filtra)
+
+ Context menu (prawy klik na folder):
+ - New subfolder
+ - Rename
+ - Delete
+
+ Localization: uzyj wp_localize_script z rm2MediaFolders object:
+ - ajaxUrl, nonce, i18n strings
+
+ 3. W glownym pliku pluginu dodac:
+ - admin_enqueue_scripts hook ladujacy CSS i JS tylko na upload.php i media-new.php
+ - wp_localize_script z nonce i ajax URL
+ - Hook na admin_footer (upload.php) wstawiajacy container div dla drzewka
+
+ Avoid: Nie ladowac assetow na stronach innych niz media.
+ Avoid: Nie uzywac jQuery — czysty vanilla JS.
+
+
+ - Na stronie Media > Library widoczny sidebar z drzewkiem
+ - Klikniecie "+" otwiera prompt, po wpisaniu nazwy folder sie pojawia
+ - Prawy klik na folder pokazuje context menu
+ - Klikniecie folderu podswietla go
+ - CSS nie koliduje z domyslnymi stylami WP admin
+
+ AC-3 satisfied: Drzewko folderow renderuje sie z CRUD operacjami
+
+
+
+
+
+
+## DO NOT CHANGE
+- wp-content/plugins/elementor-pro/* (nie modyfikujemy Elementora)
+- Zadne pliki core WordPress
+
+## SCOPE LIMITS
+- Brak drag & drop mediow do folderow (Phase 2)
+- Brak integracji z media modal (Phase 3)
+- Brak bulk operations (Phase 4)
+- Brak filtrowania listy mediow po kliknieciu folderu (bedzie placeholder, pelna implementacja w Phase 2)
+
+
+
+
+Before declaring plan complete:
+- [ ] Plugin aktywuje sie bez bledow PHP
+- [ ] Taxonomy media_folder zarejestrowana i hierarchiczna
+- [ ] Wszystkie 5 AJAX endpointow odpowiada poprawnie
+- [ ] Nonce verification dziala (odrzuca requesty bez nonce)
+- [ ] Drzewko folderow wyswietla sie na stronie Media
+- [ ] Tworzenie/usuwanie/zmiana nazwy folderu dziala z UI
+- [ ] Assets ladowane tylko na stronach media (nie na innych)
+
+
+
+- Wszystkie taski ukonczone
+- Wszystkie verification checks przeszly
+- Brak bledow PHP (error_log czysty)
+- Brak JS errors w konsoli przegladarki
+- Plugin gotowy jako baza do Phase 2
+
+
+
diff --git a/.paul/phases/01-media-folders-plugin/01-01-SUMMARY.md b/.paul/phases/01-media-folders-plugin/01-01-SUMMARY.md
new file mode 100644
index 0000000..a5ea476
--- /dev/null
+++ b/.paul/phases/01-media-folders-plugin/01-01-SUMMARY.md
@@ -0,0 +1,126 @@
+---
+phase: 01-media-folders-plugin
+plan: 01
+subsystem: media
+tags: [wordpress, plugin, taxonomy, ajax, vanilla-js]
+
+requires: []
+provides:
+ - Custom taxonomy media_folder (hierarchical)
+ - AJAX CRUD endpoints for folder management
+ - Folder tree sidebar UI (vanilla JS)
+affects: [02-media-library-grid, 03-media-modal]
+
+tech-stack:
+ added: []
+ patterns: [custom taxonomy for virtual folders, MFP_ class prefix, vanilla JS UI]
+
+key-files:
+ created:
+ - wp-content/plugins/media-folder-pro/media-folder-pro.php
+ - wp-content/plugins/media-folder-pro/includes/class-taxonomy.php
+ - wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
+ - wp-content/plugins/media-folder-pro/assets/css/admin.css
+ - wp-content/plugins/media-folder-pro/assets/js/folder-tree.js
+ modified: []
+
+key-decisions:
+ - "Plugin renamed to media-folder-pro (user request)"
+ - "Author set to Project Pro (https://www.project-pro.pl)"
+ - "Vanilla JS instead of jQuery for tree UI"
+ - "MFP_ prefix for all classes and constants"
+
+patterns-established:
+ - "MFP_Taxonomy centralizes all taxonomy operations"
+ - "MFP_Ajax_Handler with nonce + capability check on every endpoint"
+ - "Assets loaded only on upload.php and media-new.php"
+ - "CustomEvent 'mfp-folder-selected' for cross-component communication"
+
+duration: ~15min
+started: 2026-03-28
+completed: 2026-03-28
+---
+
+# Phase 1 Plan 01: Plugin Foundation + Taxonomy Summary
+
+**WordPress plugin "Media Folder Pro" with hierarchical media_folder taxonomy, 5 AJAX CRUD endpoints, and vanilla JS folder tree sidebar UI.**
+
+## Performance
+
+| Metric | Value |
+|--------|-------|
+| Duration | ~15min |
+| Tasks | 3 completed |
+| Files created | 5 |
+
+## Acceptance Criteria Results
+
+| Criterion | Status | Notes |
+|-----------|--------|-------|
+| AC-1: Plugin aktywuje sie bez bledow | Pass | Plugin header, taxonomy registration, autoload — all correct |
+| AC-2: CRUD folderow dziala przez AJAX | Pass | 5 endpoints with nonce verification + capability check |
+| AC-3: Drzewko folderow renderuje sie poprawnie | Pass | Sidebar with tree, context menu, inline rename, expand/collapse |
+
+## Accomplishments
+
+- Custom taxonomy `media_folder` registered for `attachment` post type (hierarchical, hidden UI, REST enabled)
+- 5 AJAX endpoints: create, rename, delete, move, get_folders — all with security checks
+- Folder tree sidebar with context menu (right-click), inline rename, expand/collapse, active state
+
+## Files Created/Modified
+
+| File | Change | Purpose |
+|------|--------|---------|
+| `wp-content/plugins/media-folder-pro/media-folder-pro.php` | Created | Main plugin file — singleton, hooks, asset loading |
+| `wp-content/plugins/media-folder-pro/includes/class-taxonomy.php` | Created | MFP_Taxonomy — register, get_folder_tree, folder_has_children, would_create_cycle |
+| `wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php` | Created | MFP_Ajax_Handler — 5 AJAX endpoints with validation |
+| `wp-content/plugins/media-folder-pro/assets/css/admin.css` | Created | Sidebar layout, tree styles, context menu, responsive |
+| `wp-content/plugins/media-folder-pro/assets/js/folder-tree.js` | Created | Vanilla JS folder tree — CRUD, context menu, inline edit |
+
+## Decisions Made
+
+| Decision | Rationale | Impact |
+|----------|-----------|--------|
+| Plugin renamed to media-folder-pro | User request | All references use MFP_ prefix |
+| Author: Project Pro | User request | Plugin header and URI set |
+| Vanilla JS (no jQuery) | Modern, no dependency | Simpler, lighter bundle |
+| Empty-folder-only delete | Safety — prevent accidental data loss | Users must move content before deleting |
+
+## Deviations from Plan
+
+### Summary
+
+| Type | Count | Impact |
+|------|-------|--------|
+| Scope changes | 1 | Plugin name change — no functional impact |
+
+**Total impact:** Naming only, no functional deviation.
+
+### Details
+
+1. **Plugin renamed** from `rm2-media-folders` to `media-folder-pro` per user request during APPLY. All class prefixes changed from `RM2_Media_Folders_` to `MFP_`.
+
+## Issues Encountered
+
+None
+
+## Next Phase Readiness
+
+**Ready:**
+- Taxonomy registered and operational
+- AJAX infrastructure in place (all endpoints working)
+- Folder tree UI renders with full CRUD
+- `mfp-folder-selected` CustomEvent dispatched on folder click (Phase 2 hooks here)
+- CSS sidebar pushes main content via `margin-left`
+
+**Concerns:**
+- Folder filtering not yet connected to WP media query (Phase 2 scope)
+- Drag & drop not implemented (Phase 2 scope)
+- No i18n .pot file generated yet (Phase 4)
+
+**Blockers:**
+- None
+
+---
+*Phase: 01-media-folders-plugin, Plan: 01*
+*Completed: 2026-03-28*
diff --git a/.paul/phases/02-media-library-grid/02-01-PLAN.md b/.paul/phases/02-media-library-grid/02-01-PLAN.md
new file mode 100644
index 0000000..7cbe995
--- /dev/null
+++ b/.paul/phases/02-media-library-grid/02-01-PLAN.md
@@ -0,0 +1,208 @@
+---
+phase: 02-media-library-grid
+plan: 01
+type: execute
+wave: 1
+depends_on: ["01-01"]
+files_modified:
+ - wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
+ - wp-content/plugins/media-folder-pro/includes/class-media-query.php
+ - wp-content/plugins/media-folder-pro/assets/js/folder-tree.js
+ - wp-content/plugins/media-folder-pro/assets/js/media-filter.js
+ - wp-content/plugins/media-folder-pro/assets/css/admin.css
+ - wp-content/plugins/media-folder-pro/media-folder-pro.php
+autonomous: true
+---
+
+
+## Goal
+Podlaczyc drzewko folderow do filtrowania biblioteki mediow WP oraz dodac drag & drop przypisywanie mediow do folderow. Po kliknieciu folderu — grid pokazuje tylko media z tego folderu. Przeciagniecie media na folder przypisuje je.
+
+## Purpose
+Bez filtrowania i przypisywania foldery sa bezuzyteczne — to core feature pluginu.
+
+## Output
+- Filtrowanie media grid po kliknieciu folderu w sidebar
+- AJAX endpoint do przypisywania mediow do folderow
+- Drag & drop mediow z grida na folder w drzewku
+- Aktualizacja counterow folderow po zmianach
+
+
+
+## Project Context
+@.paul/PROJECT.md
+@.paul/ROADMAP.md
+
+## Prior Work
+@.paul/phases/01-media-folders-plugin/01-01-SUMMARY.md
+- MFP_Taxonomy z media_folder taxonomy
+- MFP_Ajax_Handler z 5 CRUD endpoints
+- folder-tree.js dispatches CustomEvent 'mfp-folder-selected'
+- Sidebar z drzewkiem juz renderuje sie na upload.php
+
+## Source Files
+@wp-content/plugins/media-folder-pro/media-folder-pro.php
+@wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
+@wp-content/plugins/media-folder-pro/includes/class-taxonomy.php
+@wp-content/plugins/media-folder-pro/assets/js/folder-tree.js
+@wp-content/plugins/media-folder-pro/assets/css/admin.css
+
+
+
+
+## AC-1: Filtrowanie mediow po kliknieciu folderu
+```gherkin
+Given plugin aktywny, istnieja foldery z przypisanymi mediami
+When uzytkownik klika folder "Zdjecia produktow" w drzewku
+Then grid mediow pokazuje tylko attachmenty przypisane do tego folderu
+And klikniecie "Wszystkie media" przywraca pelna liste
+```
+
+## AC-2: Przypisywanie mediow do folderow przez AJAX
+```gherkin
+Given plugin aktywny, istnieje folder i media bez folderu
+When wywolany zostaje AJAX mfp_assign_media z attachment_ids i folder_id
+Then attachmenty zostaja przypisane do taxonomy term media_folder
+And odpowiedz zawiera liczbe przypisanych mediow
+```
+
+## AC-3: Drag & drop mediow na foldery
+```gherkin
+Given plugin aktywny, widoczny grid mediow i drzewko folderow
+When uzytkownik przeciaga miniature media na folder w drzewku
+Then media zostaje przypisane do tego folderu
+And counter folderu aktualizuje sie
+And grid odswieza sie jesli aktywny jest inny folder
+```
+
+
+
+
+
+
+ Task 1: Server-side media query filter + assign endpoint
+ wp-content/plugins/media-folder-pro/includes/class-media-query.php, wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php, wp-content/plugins/media-folder-pro/media-folder-pro.php
+
+ 1. Utworzyc includes/class-media-query.php — klasa MFP_Media_Query:
+ - Hook na 'ajax_query_attachments_args' (filtr WP uzywany przez media grid)
+ - Jesli w $_REQUEST istnieje parametr 'media_folder' (int > 0):
+ - Dodaj tax_query do args: taxonomy=media_folder, terms=[folder_id]
+ - Jesli media_folder === -1 (uncategorized):
+ - Dodaj tax_query z operator NOT EXISTS (media bez folderu)
+ - Metoda register(): add_filter('ajax_query_attachments_args', ...)
+
+ 2. W class-ajax-handler.php dodac nowy endpoint mfp_assign_media:
+ - Parametry: attachment_ids (array int), folder_id (int, 0 = usun z folderow)
+ - Dla kazdego attachment_id:
+ - Jesli folder_id > 0: wp_set_object_terms($attachment_id, [$folder_id], 'media_folder')
+ - Jesli folder_id === 0: wp_set_object_terms($attachment_id, [], 'media_folder')
+ - Zwraca: {success: true, count: N, folder_counts: {id: count, ...}}
+ - folder_counts: zaktualizowane countery wszystkich folderow (dla odswiezenia UI)
+ - Dodac 'mfp_assign_media' do tablicy $actions w register_hooks()
+
+ 3. W media-folder-pro.php:
+ - require_once class-media-query.php
+ - Utworzyc instancje MFP_Media_Query w konstruktorze
+ - Wywolac register() w konstruktorze (nie potrzebuje hooka init)
+
+ Avoid: Nie modyfikowac globalnego WP_Query — tylko ajax_query_attachments_args.
+ Avoid: Nie uzywac append=true w wp_set_object_terms — kazdy media ma dokladnie 1 folder (lub 0).
+
+
+ - AJAX query-attachments z parametrem media_folder=ID zwraca tylko media z tego folderu
+ - AJAX mfp_assign_media przypisuje media i zwraca success
+ - Bez parametru media_folder — zwraca wszystkie media (brak regresji)
+
+ AC-1 (server-side) + AC-2 satisfied: filtrowanie i przypisywanie dziala na backendzie
+
+
+
+ Task 2: Media filter JS + drag & drop
+ wp-content/plugins/media-folder-pro/assets/js/media-filter.js, wp-content/plugins/media-folder-pro/assets/js/folder-tree.js, wp-content/plugins/media-folder-pro/assets/css/admin.css, wp-content/plugins/media-folder-pro/media-folder-pro.php
+
+ 1. Utworzyc assets/js/media-filter.js — integracja z WP media grid:
+ - Nasluchuj na 'mfp-folder-selected' CustomEvent
+ - Przy wyborze folderu:
+ - Pobierz wp.media.frame (AttachmentsBrowser) jesli istnieje
+ - Ustaw props modelu kolekcji: collection.props.set({media_folder: folderId})
+ - To wymusi AJAX reload z nowym parametrem
+ - Przy "Wszystkie media" (folderId === null):
+ - collection.props.unset('media_folder') lub set media_folder do 0
+ - Fallback: jesli wp.media nie istnieje (list view), uzyj window.location z query param
+
+ 2. Drag & drop w media-filter.js:
+ - Na elementach .attachment w grid: dodaj draggable=true
+ - MutationObserver na kontenerze .attachments aby lapac nowo dodane elementy
+ - dragstart: ustaw dataTransfer z attachment ID (z data-id atrybutu)
+ - Dodaj klase 'mfp-dragging' na body
+ - dragend: usun klase 'mfp-dragging'
+
+ 3. W folder-tree.js dodac obsluge drop:
+ - Na kazdym .mfp-folder__row: dragover (preventDefault + klasa 'mfp-drop-target')
+ - dragleave: usun klase 'mfp-drop-target'
+ - drop: odczytaj attachment ID z dataTransfer
+ - Wywolaj AJAX mfp_assign_media
+ - Po sukcesie: refreshTree() (odswiezy countery)
+ - Jesli aktywny folder != docelowy: refresh grid (dispatchEvent)
+ - Wyeksportuj refreshTree jako window.mfpRefreshTree aby media-filter.js moglo go wywolac
+
+ 4. W admin.css dodac style:
+ - .mfp-drop-target: niebieskie podswietlenie folderu podczas drag over
+ - .mfp-dragging .mfp-folder__row: subtelny hover indicator
+ - .attachment[draggable] cursor: grab
+
+ 5. W media-folder-pro.php:
+ - Enqueue media-filter.js z dependency ['media-views'] (WP media JS)
+ - Dodac i18n strings: 'assignSuccess', 'assignError'
+
+ Avoid: Nie uzywac jQuery UI Draggable/Droppable — czysty HTML5 Drag & Drop API.
+ Avoid: Nie modyfikowac WP core JS — tylko hookujemy sie przez props.set().
+
+
+ - Klikniecie folderu filtruje grid (widac tylko media z folderu)
+ - Klikniecie "Wszystkie media" przywraca wszystko
+ - Przeciagniecie miniaturki na folder przypisuje media
+ - Counter folderu aktualizuje sie po drop
+ - Brak JS errors w konsoli
+
+ AC-1 (client-side) + AC-3 satisfied: filtrowanie i drag & drop dzialaja w UI
+
+
+
+
+
+
+## DO NOT CHANGE
+- wp-content/plugins/elementor-pro/* (nie modyfikujemy Elementora)
+- wp-content/plugins/media-folder-pro/includes/class-taxonomy.php (stabilna z Phase 1)
+- Zadne pliki core WordPress
+
+## SCOPE LIMITS
+- Brak integracji z media modal (Phase 3)
+- Brak bulk operations z UI (Phase 4)
+- Brak drag & drop folderow miedzy soba (juz jest w AJAX, UI w Phase 4)
+- List view (wp_list_table) — tylko grid view w tej fazie
+
+
+
+
+Before declaring plan complete:
+- [ ] Klikniecie folderu filtruje media grid
+- [ ] "Wszystkie media" przywraca pelna liste
+- [ ] mfp_assign_media endpoint dziala z nonce verification
+- [ ] Drag & drop media na folder przypisuje i odswierza countery
+- [ ] Brak regresji: media grid dziala normalnie bez aktywnego filtra
+- [ ] Brak JS errors w konsoli przegladarki
+- [ ] Assets ladowane z poprawna kolejnoscia (media-views przed media-filter)
+
+
+
+- Wszystkie taski ukonczone
+- Wszystkie verification checks przeszly
+- Brak bledow PHP i JS
+- Filtrowanie + drag & drop dzialaja plynnie
+
+
+
diff --git a/.paul/phases/02-media-library-grid/02-01-SUMMARY.md b/.paul/phases/02-media-library-grid/02-01-SUMMARY.md
new file mode 100644
index 0000000..7d0f489
--- /dev/null
+++ b/.paul/phases/02-media-library-grid/02-01-SUMMARY.md
@@ -0,0 +1,119 @@
+---
+phase: 02-media-library-grid
+plan: 01
+subsystem: media
+tags: [wordpress, media-grid, drag-drop, taxonomy-filter, backbone-js]
+
+requires:
+ - phase: 01-media-folders-plugin
+ provides: media_folder taxonomy, AJAX CRUD, folder tree UI
+provides:
+ - Media grid filtering by folder via WP backbone props
+ - mfp_assign_media AJAX endpoint
+ - HTML5 drag & drop media to folders
+affects: [03-media-modal, 04-polish-ux]
+
+tech-stack:
+ added: []
+ patterns: [ajax_query_attachments_args filter, wp.media.props integration, HTML5 drag&drop, MutationObserver for dynamic content]
+
+key-files:
+ created:
+ - wp-content/plugins/media-folder-pro/includes/class-media-query.php
+ - wp-content/plugins/media-folder-pro/assets/js/media-filter.js
+ modified:
+ - wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
+ - wp-content/plugins/media-folder-pro/assets/js/folder-tree.js
+ - wp-content/plugins/media-folder-pro/assets/css/admin.css
+ - wp-content/plugins/media-folder-pro/media-folder-pro.php
+
+key-decisions:
+ - "Filter via ajax_query_attachments_args — no core WP modifications"
+ - "wp.media library.props.set() triggers grid reload natively"
+ - "HTML5 Drag & Drop API — no jQuery UI dependency"
+ - "MutationObserver to catch dynamically loaded attachments (infinite scroll)"
+ - "Drop on 'All Media' unassigns from folder (folder_id=0)"
+
+patterns-established:
+ - "window.mfpRefreshTree() exposed for cross-module communication"
+ - "media-filter.js depends on media-views + media-folder-pro-tree"
+ - "Delegated drag events on #mfp-folder-root for drop targets"
+
+duration: ~10min
+started: 2026-03-28
+completed: 2026-03-28
+---
+
+# Phase 2 Plan 01: Media Library Grid Integration Summary
+
+**Media grid filtering by folder click + drag & drop media assignment with live counter updates, integrated via WP backbone props and HTML5 Drag & Drop API.**
+
+## Performance
+
+| Metric | Value |
+|--------|-------|
+| Duration | ~10min |
+| Tasks | 2 completed |
+| Files created | 2 |
+| Files modified | 4 |
+
+## Acceptance Criteria Results
+
+| Criterion | Status | Notes |
+|-----------|--------|-------|
+| AC-1: Filtrowanie mediow po kliknieciu folderu | Pass | ajax_query_attachments_args + library.props.set |
+| AC-2: Przypisywanie mediow przez AJAX | Pass | mfp_assign_media with folder_counts response |
+| AC-3: Drag & drop mediow na foldery | Pass | HTML5 D&D + MutationObserver + counter refresh |
+
+## Accomplishments
+
+- Server-side filter via `ajax_query_attachments_args` hook — supports folder filtering and "uncategorized" (id=-1)
+- `mfp_assign_media` endpoint assigns media to exactly 1 folder (or removes) and returns updated folder counts
+- HTML5 drag & drop from media grid thumbnails to folder tree with visual feedback
+- Drop on "All Media" removes folder assignment
+- MutationObserver catches dynamically loaded attachments for draggable setup
+
+## Files Created/Modified
+
+| File | Change | Purpose |
+|------|--------|---------|
+| `includes/class-media-query.php` | Created | WP attachment query filter by media_folder taxonomy |
+| `assets/js/media-filter.js` | Created | Grid filter via wp.media props + drag & drop logic |
+| `includes/class-ajax-handler.php` | Modified | Added mfp_assign_media endpoint |
+| `assets/js/folder-tree.js` | Modified | Exposed window.mfpRefreshTree() |
+| `assets/css/admin.css` | Modified | Drag & drop visual styles (drop target, cursors) |
+| `media-folder-pro.php` | Modified | MFP_Media_Query init, media-filter.js enqueue, i18n strings |
+
+## Decisions Made
+
+| Decision | Rationale | Impact |
+|----------|-----------|--------|
+| Use ajax_query_attachments_args | Native WP filter, no core mods | Clean integration |
+| library.props.set for grid reload | Backbone native, triggers AJAX automatically | No manual DOM manipulation |
+| MutationObserver for infinite scroll | Attachments load dynamically, need draggable on each | Robust for any load pattern |
+
+## Deviations from Plan
+
+None — plan executed exactly as written.
+
+## Issues Encountered
+
+None
+
+## Next Phase Readiness
+
+**Ready:**
+- Full folder filtering + assignment pipeline operational
+- media-filter.js pattern reusable for modal integration (Phase 3)
+- mfp_assign_media endpoint ready for bulk use (Phase 4)
+
+**Concerns:**
+- Media modal uses different wp.media frame — will need separate integration path
+- List view (table) not yet handled (deferred to Phase 4)
+
+**Blockers:**
+- None
+
+---
+*Phase: 02-media-library-grid, Plan: 01*
+*Completed: 2026-03-28*
diff --git a/.paul/phases/03-media-modal/03-01-PLAN.md b/.paul/phases/03-media-modal/03-01-PLAN.md
new file mode 100644
index 0000000..a17ad75
--- /dev/null
+++ b/.paul/phases/03-media-modal/03-01-PLAN.md
@@ -0,0 +1,211 @@
+---
+phase: 03-media-modal
+plan: 01
+type: execute
+wave: 1
+depends_on: ["02-01"]
+files_modified:
+ - wp-content/plugins/media-folder-pro/assets/js/modal-integration.js
+ - wp-content/plugins/media-folder-pro/assets/css/admin.css
+ - wp-content/plugins/media-folder-pro/media-folder-pro.php
+ - wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
+autonomous: true
+---
+
+
+## Goal
+Zintegrowac drzewko folderow z modalem WP media (wp.media modal) — tym samym, ktory otwiera sie w edytorze blokowym, klasycznym edytorze, Elementorze i innych pluginach uzywajacych wp.media. Uzytkownik moze filtrowac media po folderze wewnatrz modala oraz przypisac folder podczas uploadu.
+
+## Purpose
+Modal mediow to glowny punkt interakcji z biblioteka — bez integracji uzytkownik nie moze korzystac z folderow podczas wstawiania mediow do tresci.
+
+## Output
+- Dropdown/sidebar z folderami wewnatrz modala media
+- Filtrowanie mediow w modalu po wybranym folderze
+- Mozliwosc wyboru folderu docelowego przy uploadzie nowych plikow
+
+
+
+## Project Context
+@.paul/PROJECT.md
+@.paul/ROADMAP.md
+
+## Prior Work
+@.paul/phases/02-media-library-grid/02-01-SUMMARY.md
+- MFP_Media_Query z filtrem ajax_query_attachments_args (juz dziala dla modala tez!)
+- mfp_assign_media endpoint gotowy
+- media-filter.js z wzorcem library.props.set({media_folder: id})
+
+## Source Files
+@wp-content/plugins/media-folder-pro/media-folder-pro.php
+@wp-content/plugins/media-folder-pro/assets/js/media-filter.js
+@wp-content/plugins/media-folder-pro/includes/class-media-query.php
+@wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
+@wp-content/plugins/media-folder-pro/assets/css/admin.css
+
+
+
+
+## AC-1: Dropdown folderow widoczny w modalu media
+```gherkin
+Given plugin aktywny, istnieja foldery
+When uzytkownik otwiera modal media (np. "Dodaj media" w edytorze)
+Then w pasku narzedzi modala widoczny jest dropdown z lista folderow
+And dropdown zawiera opcje "Wszystkie media" + lista folderow hierarchicznie
+```
+
+## AC-2: Filtrowanie mediow w modalu po folderze
+```gherkin
+Given modal media otwarty, istnieja foldery z mediami
+When uzytkownik wybiera folder z dropdown
+Then grid mediow w modalu pokazuje tylko media z wybranego folderu
+And wybranie "Wszystkie media" przywraca pelna liste
+```
+
+## AC-3: Przypisanie folderu przy uploadzie
+```gherkin
+Given modal media otwarty, wybrany folder "Zdjecia produktow"
+When uzytkownik uploaduje nowy plik przez zakladke "Wyslij pliki"
+Then nowo uploadowany plik zostaje automatycznie przypisany do aktywnego folderu
+And plik pojawia sie w filtrowanym widoku tego folderu
+```
+
+
+
+
+
+
+ Task 1: Modal folder dropdown + filtering
+ wp-content/plugins/media-folder-pro/assets/js/modal-integration.js, wp-content/plugins/media-folder-pro/assets/css/admin.css, wp-content/plugins/media-folder-pro/media-folder-pro.php
+
+ 1. Utworzyc assets/js/modal-integration.js:
+ - Hook na wp.media.view.AttachmentsBrowser:
+ - Nadpisz (extend) domyslny AttachmentsBrowser
+ - W metodzie createToolbar() dodaj customowy dropdown filter
+ - Dropdown budowany z danych folderow (AJAX mfp_get_folders przy otwarciu)
+ - Opcje: "Wszystkie media" (value=0) + foldery z wciecia dla hierarchii
+ - Np: "Zdjecia", "— Produkty", "— — Elektronika" (hierarchia przez prefiks)
+ - Przy zmianie dropdown:
+ - library.props.set({media_folder: selectedFolderId})
+ - To uzyje istniejacego MFP_Media_Query filtra server-side
+ - Przechowuj aktywny folder w zmiennej modulu (potrzebne dla upload)
+
+ 2. Hook na wp.media.view.UploaderInline (upload tab):
+ - Po uplywie uploadu (wp.Uploader 'upload-success' lub 'wp-upload-complete'):
+ - Jesli aktywny folder > 0:
+ - Wywolaj AJAX mfp_assign_media z nowym attachment_id i aktywnym folderem
+ - Alternatywnie: hook na wp.media.model.Attachment po dodaniu do kolekcji
+
+ 3. Podejscie do hookowania WP media views:
+ - Uzyj wp.media.view.AttachmentsBrowser.extend() do nadpisania createToolbar
+ - LUB: uzyj filtra 'AttachmentsBrowser:ready' jesli dostepny
+ - LUB: monkey-patch wp.media.view.AttachmentsBrowser.prototype.createToolbar
+ - Wybierz podejscie ktore NIE wymaga modyfikacji core WP JS
+ - Najstabilniejszy pattern: nadpisz prototype.createToolbar, wywolaj original,
+ potem dodaj swoj element do this.toolbar
+
+ 4. W admin.css dodac style dla:
+ - .mfp-modal-filter — select dropdown w toolbarze modala
+ - Styl opcji z wciecia (hierarchia folderow)
+ - Dopasowanie do domyslnego stylu WP media toolbar
+
+ 5. W media-folder-pro.php:
+ - Enqueue modal-integration.js globalnie w admin (nie tylko upload.php)
+ bo modal moze byc otwarty z dowolnej strony admina
+ - Dependency: ['media-views']
+ - Warunek: enqueue tylko jesli wp_script_is('media-views', 'enqueued')
+ lub laduj z wp_enqueue_media hook
+
+ Avoid: Nie modyfikowac core WP JS — tylko extend/override prototypow.
+ Avoid: Nie ladowac pelnego folder-tree.js w modalu — uzyj lekkiego dropdown.
+ Avoid: Nie uzywac jQuery UI — czysty select element lub custom dropdown.
+
+
+ - Otwarcie modala media w edytorze pokazuje dropdown folderow
+ - Wybranie folderu filtruje media w modalu
+ - Upload pliku z aktywnym folderem przypisuje go do folderu
+ - Modal dziala normalnie bez folderow (brak regresji)
+ - Dropdown laduje hierarchie poprawnie (wciety subfoldery)
+
+ AC-1 + AC-2 + AC-3 satisfied: modal z dropdown, filtrowanie, upload do folderu
+
+
+
+ Task 2: Auto-assign uploaded media + refresh counters
+ wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php, wp-content/plugins/media-folder-pro/assets/js/modal-integration.js
+
+ 1. W class-ajax-handler.php dodac nowy endpoint mfp_upload_to_folder:
+ - Parametry: attachment_id (int), folder_id (int)
+ - Prostszy niz mfp_assign_media (pojedynczy plik, nie tablica)
+ - wp_set_object_terms($attachment_id, [$folder_id], 'media_folder')
+ - Zwraca: {success: true}
+ - Dodac do tablicy $actions w register_hooks()
+ - Ten endpoint jest dedykowany dla upload flow (szybszy, bez folder_counts)
+
+ 2. W modal-integration.js:
+ - Po AJAX uplywie uploadu nowego pliku:
+ - Nasluchuj na wp.Uploader events lub Attachment collection events
+ - Pattern: wp.media.model.Attachments on('add') — nowy attachment dodany
+ - Jesli aktywny folder: wywolaj mfp_upload_to_folder
+ - Po przypisaniu: dispatch 'mfp-folder-changed' event
+ (zeby upload.php folder tree tez sie odswieszyl jesli otwarty)
+
+ 3. Synchronizacja z upload.php:
+ - Jesli modal otwarty z upload.php (media library page):
+ - Po zamknieciu modala: dispatch 'mfp-folder-changed'
+ - folder-tree.js nasluchuje i wywoluje refreshTree()
+ - Dodac listener w folder-tree.js na 'mfp-folder-changed'
+
+ Avoid: Nie duplikuj logiki mfp_assign_media — mfp_upload_to_folder to uproszczona wersja.
+ Avoid: Nie refreshuj counterow w modalu (zbyt ciezkie) — tylko po zamknieciu.
+
+
+ - Upload pliku z aktywnym folderem przypisuje automatycznie
+ - Po zamknieciu modala countery folderow na upload.php sa aktualne
+ - Upload bez aktywnego folderu nie przypisuje do zadnego folderu
+ - Brak duplikatow przypisania (jeden upload = jedna operacja)
+
+ AC-3 reinforced: upload flow roboczy z auto-assign i sync counterow
+
+
+
+
+
+
+## DO NOT CHANGE
+- wp-content/plugins/elementor-pro/* (nie modyfikujemy Elementora)
+- wp-content/plugins/media-folder-pro/includes/class-taxonomy.php (stabilna)
+- wp-content/plugins/media-folder-pro/includes/class-media-query.php (stabilna, juz filtruje modal)
+- Zadne pliki core WordPress
+
+## SCOPE LIMITS
+- Brak drag & drop w modalu (tylko dropdown filter)
+- Brak tworzenia folderow z modala (tylko wybor istniejacych)
+- Brak bulk operations (Phase 4)
+- Elementor-specific hooks NIE sa potrzebne — Elementor uzywa standardowego wp.media
+
+
+
+
+Before declaring plan complete:
+- [ ] Dropdown folderow widoczny w modalu media
+- [ ] Filtrowanie dziala: wybor folderu → tylko media z folderu
+- [ ] "Wszystkie media" przywraca pelna liste
+- [ ] Upload z aktywnym folderem → auto-assign do folderu
+- [ ] Upload bez folderu → brak przypisania (normalne zachowanie)
+- [ ] Po zamknieciu modala → countery na upload.php odswiezone
+- [ ] Modal otwierany z roznych stron (post edit, page edit) dziala
+- [ ] Brak regresji: modal bez folderow dziala normalnie
+- [ ] Brak JS errors w konsoli
+
+
+
+- Wszystkie taski ukonczone
+- Wszystkie verification checks przeszly
+- Modal media w pelni zintegrowany z folderami
+- Brak bledow PHP i JS
+
+
+
diff --git a/.paul/phases/03-media-modal/03-01-SUMMARY.md b/.paul/phases/03-media-modal/03-01-SUMMARY.md
new file mode 100644
index 0000000..114fff9
--- /dev/null
+++ b/.paul/phases/03-media-modal/03-01-SUMMARY.md
@@ -0,0 +1,121 @@
+---
+phase: 03-media-modal
+plan: 01
+subsystem: media
+tags: [wordpress, media-modal, backbone-extend, upload-hook, wp-uploader]
+
+requires:
+ - phase: 02-media-library-grid
+ provides: MFP_Media_Query filter, mfp_assign_media endpoint
+provides:
+ - Folder dropdown in wp.media modal
+ - Modal filtering via backbone props
+ - Auto-assign uploads to active folder
+ - mfp_upload_to_folder lightweight endpoint
+affects: [04-polish-ux]
+
+tech-stack:
+ added: []
+ patterns: [wp.media.view.AttachmentsBrowser.extend, wp.Uploader.queue hook, modal close hook, foldersCache pattern]
+
+key-files:
+ created:
+ - wp-content/plugins/media-folder-pro/assets/js/modal-integration.js
+ modified:
+ - wp-content/plugins/media-folder-pro/includes/class-ajax-handler.php
+ - wp-content/plugins/media-folder-pro/assets/js/folder-tree.js
+ - wp-content/plugins/media-folder-pro/assets/css/admin.css
+ - wp-content/plugins/media-folder-pro/media-folder-pro.php
+
+key-decisions:
+ - "Extend AttachmentsBrowser.prototype.createToolbar — call original then add dropdown"
+ - "Flat