From d7e7d248cbe41cd7a9ef9c2fb022b6c4831f99a3 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 31 May 2026 15:22:56 +0000
Subject: [PATCH] =jakevan complete

---
 build/menu/index.asset.php                                             |    2 
 build/faq/index.css                                                    |   87 
 src/summary/render.php                                                 |    2 
 build/drawer-menu/index-rtl.css                                        |    3 
 build/forms/index.js                                                   |  748 ++++
 build/gmbreviews/index.css                                             |    3 
 build/drawer-menu/index.js                                             |  346 ++
 build/menu/style-index-rtl.css                                         |    3 
 build/video/index.css.map                                              |    1 
 jvb.php                                                                |   11 
 build/drawer-menu/index.css                                            |    3 
 build/faq/index.js                                                     |  480 ++
 build/feed/style-index.css.map                                         |    1 
 build/forms/block.json                                                 |    2 
 inc/managers/DashboardManager.php                                      |    1 
 inc/registrar/config/seo/Resolver.php                                  |   14 
 inc/rest/routes/FeedRoutes.php                                         |   20 
 build/timeline/style-index-rtl.css                                     |  122 
 assets/js/concise/CRUD.js                                              |    7 
 assets/js/concise/Gallery.js                                           |   15 
 build/faq/style-index.css.map                                          |    1 
 build/gmbreviews/render.php                                            |  207 -
 build/summary/index.js                                                 |  388 ++
 build/faq/style-index-rtl.css                                          |   78 
 build/menu/index.css                                                   |    3 
 build/summary/render.php                                               |    2 
 inc/blocks/DrawerMenuBlock.php                                         |   76 
 build/gmbreviews/style-index.css.map                                   |    1 
 assets/js/concise/Queue.js                                             |    3 
 build/video/block.json                                                 |    2 
 src/feed/style.scss                                                    |   23 
 build/menu/view.js                                                     |   46 
 build/summary/style-index.css.map                                      |    1 
 build/drawer-menu/render.php                                           |   40 
 build/gmbreviews/index.js                                              |  409 ++
 build/summary/style-index-rtl.css                                      |   30 
 build/menu/index.js.map                                                |    1 
 build/menu/index.js                                                    |  358 ++
 build/summary/index.css                                                |   25 
 build/feed/style-index.css                                             |  267 +
 build/feed/index.asset.php                                             |    2 
 build/summary/index.css.map                                            |    1 
 src/feed/view.js                                                       |   84 
 build/gmbreviews/view.js                                               |    7 
 build/glossary/index-rtl.css                                           |    3 
 src/video/block.json                                                   |    2 
 build/glossary/style-index-rtl.css                                     |  110 
 build/gmbreviews/index.asset.php                                       |    2 
 build/timeline/index.js                                                |  358 ++
 inc/meta/Meta.php                                                      |    5 
 build/drawer-menu/style-index.css                                      |   92 
 inc/blocks/_setup.php                                                  |   31 
 build/glossary/index.js                                                |  358 ++
 inc/blocks/FAQBlock.php                                                |    6 
 build/feed/view.js.map                                                 |    1 
 build/video/index.css                                                  |  131 
 build/timeline/style-index.css                                         |  124 
 assets/js/min/populate.min.js                                          |    2 
 build/feed/index.js                                                    |  603 +++
 build/faq/view.js.map                                                  |    1 
 build/video/style-index.css                                            |  171 +
 build/menu/view.asset.php                                              |    2 
 build/forms/style-index-rtl.css                                        |    3 
 build/video/style-index-rtl.css                                        |  169 +
 build/menu/style-index.css                                             |    3 
 inc/managers/ErrorHandler.php                                          |    4 
 build/drawer-menu/index.asset.php                                      |    2 
 build/gmbreviews/style-index.css                                       |  129 
 build/glossary/index.css                                               |    3 
 build/timeline/index.css                                               |    3 
 build/gmbreviews/index-rtl.css                                         |    3 
 build/faq/index.js.map                                                 |    1 
 build/menu/index-rtl.css                                               |    3 
 build/faq/index-rtl.css                                                |   85 
 src/drawer-menu/render.php                                             |   40 
 build/feed/view.js                                                     |  690 ++++
 build/glossary/index.js.map                                            |    1 
 build/glossary/view.js                                                 |  166 +
 build/forms/view.js                                                    |  117 
 build/timeline/style-index.css.map                                     |    1 
 build/summary/view.asset.php                                           |    2 
 build/glossary/style-index.css.map                                     |    1 
 build/timeline/index.asset.php                                         |    2 
 build/drawer-menu/style-index-rtl.css                                  |   90 
 build/video/style-index.css.map                                        |    1 
 build/faq/view.js                                                      |   84 
 build/faq/style-index.css                                              |   80 
 build/video/view.asset.php                                             |    2 
 inc/blocks/GMBReviewBlock.php                                          |  237 +
 build/summary/index.js.map                                             |    1 
 build/timeline/index-rtl.css                                           |    3 
 build/menu/view.js.map                                                 |    1 
 build/video/index.asset.php                                            |    2 
 build/video/view.js                                                    |   49 
 build/timeline/view.js                                                 |    7 
 assets/js/min/queue.min.js                                             |    2 
 build/summary/index-rtl.css                                            |   23 
 inc/registrar/config/seo/Schema.php                                    |    5 
 build/forms/index.asset.php                                            |    2 
 build/gmbreviews/style-index-rtl.css                                   |  127 
 build/forms/index-rtl.css                                              |    3 
 build/summary/view.js                                                  |    7 
 assets/js/min/gallery.min.js                                           |    2 
 build/faq/index.css.map                                                |    1 
 src/drawer-menu/style.scss                                             |    2 
 build/feed/style-index-rtl.css                                         |  265 +
 build/timeline/view.asset.php                                          |    2 
 build/video/view.js.map                                                |    1 
 src/gmbreviews/render.php                                              |  207 -
 build/feed/index.js.map                                                |    1 
 inc/managers/SEO/render/Traits/_Properties/sourceOrganizationTrait.php |   14 
 inc/blocks/FeedBlock.php                                               |   87 
 inc/managers/SEO/BreadcrumbManager.php                                 |    1 
 inc/registrar/Registrar.php                                            |   28 
 build/forms/view.js.map                                                |    1 
 build/glossary/view.js.map                                             |    1 
 assets/js/min/crud.min.js                                              |    2 
 build/gmbreviews/index.js.map                                          |    1 
 assets/js/concise/PopulateForm.js                                      |   32 
 build/forms/index.css                                                  |    3 
 build/drawer-menu/style-index.css.map                                  |    1 
 build/glossary/view.asset.php                                          |    2 
 build/glossary/index.asset.php                                         |    2 
 build/summary/index.asset.php                                          |    2 
 build/forms/view.asset.php                                             |    2 
 build/video/index-rtl.css                                              |  129 
 build/forms/style-index.css                                            |    3 
 build/summary/style-index.css                                          |   32 
 assets/css/nav.min.css                                                 |    2 
 build/glossary/style-index.css                                         |  112 
 build/faq/index.asset.php                                              |    2 
 build/timeline/index.js.map                                            |    1 
 build/drawer-menu/index.js.map                                         |    1 
 src/forms/block.json                                                   |    2 
 build/feed/view.asset.php                                              |    2 
 /dev/null                                                              |    1 
 build/forms/index.js.map                                               |    1 
 build/video/index.js                                                   |  587 +++
 build/video/index.js.map                                               |    1 
 package.json                                                           |    4 
 build/faq/view.asset.php                                               |    2 
 build/gmbreviews/view.asset.php                                        |    2 
 142 files changed, 8,944 insertions(+), 682 deletions(-)

diff --git a/1webpack.config.js b/1webpack.config.js
deleted file mode 100644
index 657c69c..0000000
--- a/1webpack.config.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const defaultConfig = require('@wordpress/scripts/config/webpack.config');
-
-module.exports = {
-    ...defaultConfig,
-    entry: {
-        QueueManager: './src/QueueManager.js'
-    }
-};
diff --git a/assets/css/nav.min.css b/assets/css/nav.min.css
index 809a1a8..3227b17 100644
--- a/assets/css/nav.min.css
+++ b/assets/css/nav.min.css
@@ -1 +1 @@
-nav,nav ol,nav ul{--padding:0 1rem;--wrap:nowrap;font-family:var(--heading)}nav,nav a,nav li,nav ol,nav ul,ul.socials{display:flex;flex-direction:var(--dir,row);justify-content:var(--justify,flex-start);align-items:var(--align,center);gap:var(--gap,0);flex-wrap:var(--wrap,nowrap);height:var(--btn,3rem);max-width:100%;padding:0;margin:0}nav.col,nav.col ul{height:max-content}nav>ul{width:100%;overflow:auto hidden}nav li{width:max-content;--justify:center;max-inline-size:none;padding:0;list-style:none}nav.fill li{width:100%}nav a,nav button{--justify:center;width:100%;white-space:nowrap;text-transform:uppercase;border-radius:0;background-color:transparent;text-decoration:none}nav a{padding:var(--padding)}nav .toggle{aspect-ratio:1;border:1px solid rgb(var(--base));color:rgb(var(--contrast))}nav .current a,nav a.current,nav a:focus,nav a:focus:visited,nav button:focus{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast))}.toggle .icon-caret-down{transform:rotate(0);transition:transform var(--trans-base)}.open>.row>.toggle .icon-caret-down,.open>.toggle .icon-caret-down{transform:rotate(900deg)}.has-submenu{position:relative}ul.submenu{--dir:column;height:max-content;position:absolute;top:100%;right:0;max-height:0;transform:scaleY(0);transform-origin:top;width:100%;min-width:max-content;background-color:rgba(var(--base),var(--op-3));border:2px solid rgba(var(--base),var(--op-3));transition:max-height var(--trans-base),transform var(--trans-base);box-shadow:var(--shdw-none);overflow:hidden}.submenu li{background-color:rgba(var(--base),var(--op-6));border:1px solid rgb(var(--base-50))}.submenu a{height:var(--chipchip)}.open>ul.submenu{transform:scaleY(1);max-height:1000%;box-shadow:rgba(var(--base),var(--op-45)) var(--shdw)}.screen-reader-text{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}nav a:focus:not(:focus-visible){outline:0}nav a:focus-visible{outline:1px solid rgb(var(--action-0));outline-offset:1px}nav.always{overflow:visible;transition:width var(--trans-base);width:max-content}nav.always>ul{--dir:column;--align:center;--justify:flex-end;--gap:0;height:100vh;max-height:none;position:fixed;right:-300vw;bottom:0;width:100vw;padding:var(--btn) 0;overflow:hidden auto;transition:right var(--trans-base)}nav.always.open>ul{right:0}nav.always li{width:100%}nav.always.fixed{width:var(--btn);height:var(--btn);bottom:0;right:0;overflow:hidden}nav.always.fixed .toggle.main{background-color:rgb(var(--base))}nav.always.fixed .toggle.main:focus,nav.always.fixed .toggle.main:hover{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast))}nav.mobile .toggle.main{width:var(--btn);transition:width var(--trans-base)}nav.mobile .icon-list,nav.mobile .icon-x{--w:32px}nav.mobile .icon-x,nav.mobile.open .icon-list{display:none}nav.mobile .icon-list,nav.mobile.open .icon-x{display:block}nav.mobile.open>ul{--dir:column;z-index:var(--z-9);background-color:rgba(var(--base),var(--op-6));width:100vw;height:100vh;overflow:hidden auto;right:0;bottom:0;position:fixed;padding:var(--btn) 0}nav.always>ul::before,nav.mobile.open>ul::before{content:'';z-index:-1;position:absolute;inset:0;filter:blur(5px)}nav.always.open .main.toggle,nav.mobile.open .main.toggle{position:fixed;bottom:0;left:0;width:100vw;z-index:var(--z-10);aspect-ratio:unset}nav.always>ul,nav.always>ul:before,nav.mobile.open>ul,nav.mobile.open>ul::before{background-color:rgba(var(--base),var(--op-6))}@media (max-width:767px){nav.col{height:var(--btn)}nav.mobile>ul{--dir:column;--align:center;--justify:flex-end;--gap:0;height:100%;max-height:none;position:relative;right:-300vw;width:100vw;padding:var(--btn) 0 0;overflow:hidden auto}nav.mobile.open>ul{right:0}}@media (min-width:768px){nav.mobile:not(.always) .toggle.main{display:none}}nav#breadcrumbs{height:max-content;--wrap:wrap;--gap:0;width:max-content;max-width:var(--full);position:absolute;background-color:rgba(var(--base),var(--op-4));font-size:var(--txt-x-small);padding:.125em;z-index:var(--z-5)}nav#breadcrumbs ol{height:max-content;--wrap:wrap}nav#breadcrumbs li{width:max-content;height:var(--chip);--wrap:nowrap}nav#breadcrumbs li::after{content:'/';color:rgb(var(--contrast-200));padding:0 .25rem}nav#breadcrumbs li:last-of-type::after{display:none}nav#breadcrumbs a{height:var(--chip)}nav#breadcrumbs a,nav#breadcrumbs span{padding:0 .125rem;color:rgb(var(--contrast));text-transform:none}nav#breadcrumbs a:focus{background-color:transparent;color:rgb(var(--action-0))}nav.fixed{position:fixed;box-shadow:rgba(var(--base),var(--op-45)) var(--shdw);z-index:var(--z-9)}nav.fixed.bottom{left:0;bottom:0;width:calc(100% - var(--btn))}nav.fixed:not(.always) ul{--justify:space-between;width:100%;background-color:rgb(var(--base));padding:0 .25rem}nav.fixed:not(.always) li{flex:1}nav.fixed a{--align:center;--gap:1rem;--w:var(--chip_);color:rgb(var(--contrast));font-size:var(--txt-x-small)}@media (min-width:768px){nav.fixed a{font-size:var(--txt-medium)}}nav.on-this-page.on-this-page{--justify:space-between;position:fixed;bottom:0;left:0;width:100vw;z-index:var(--z-5);background-color:rgba(var(--base),var(--op-45));max-width:none;margin:0!important}body:has(nav.fixed) nav.on-this-page{bottom:var(--btn)}nav.on-this-page button{order:3;padding:0 1rem;width:max-content;aspect-ratio:unset}nav.on-this-page.open button{order:0}nav.on-this-page ul{width:100%;--gap:0}nav.on-this-page a{padding:0}nav.on-this-page .active a{background-color:rgba(var(--base),var(--op-6));color:rgb(var(--action-contrast))}nav.on-this-page #back-to-top span{display:none}nav.on-this-page .active a{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast))}nav.letters,nav.letters a,nav.letters li,nav.letters ul{height:var(--chip)}nav.letters li{max-width:calc(7.69% - 2px)}nav.letters ul{--wrap:wrap}@media (min-width:768px){nav.letters,nav.letters ul{height:var(--chip)}nav.letters ul{--wrap:nowrap}nav.letters li{max-width:none}nav.letters a{padding:.25rem .66rem}}nav.index{--justify:space-between;--padding:0;background-color:rgba(var(--base),var(--op-6))}nav.index,nav.index a,nav.index button,nav.index li,nav.index ul{min-height:var(--chipchip);height:var(--chipchip)}nav.index ul{width:100%}nav.index li{flex-shrink:0;transform:scaleX(0);max-width:0;overflow:hidden}nav.index li.active,nav.index li.adj{transform:scaleX(1);width:100%;flex-shrink:1;max-width:none}@media (max-width:767px){.index li.adj{transform:scaleX(0);max-width:0}}nav.index.open{--dir:column-reverse;height:var(--maxHeight);width:100%;--align:flex-end;background-color:rgba(var(--base),var(--op-6));backdrop-filter:blur(5px);z-index:var(--z-10)}nav.index.open ul{min-height:max-content;--dir:column}nav.index.open li{width:100%;max-width:100%!important;transform:scaleX(1);overflow:visible}nav.index.open a{--justify:center;padding:0 2rem 0 0}nav.condensed,nav.condensed a,nav.condensed li,nav.condensed ul{height:max-content;width:max-content;--wrap:wrap;min-height:var(--chip)}.condensed ul{--justify:center;--dir:row}nav.condensed{--gap:0 .25rem;width:100%;--justify:center}nav.condensed li+li::before{content:'·';padding:0 .25em}nav.condensed a{font-size:var(--txt-x-small);padding:0 .25rem;text-transform:none;border-bottom:2px solid transparent}nav .current a,nav a.current,nav a:focus,nav a:focus:visited,nav button:focus{background-color:transparent;color:rgb(var(--contrast));border-color:rgb(var(--action-0))}ul.socials{--dir:row;height:max-content;--gap:.5rem;--justify:flex-end;--wrap:nowrap;overflow:auto hidden;touch-action:pan-x;width:100%}ul.socials li{list-style:none}.always ul.socials{width:100vw;--justify:stretch}.always ul.socials li{flex:1;--justify:center;--align:center}.always ul.socials a{display:inline-flex}ul.socials a{display:inline-block;font-size:var(--txt-x-small);padding:.25rem .5rem;max-width:none}ul.socials .icon{margin:0}ul.socials .icon+span:not(.screen-reader-text){margin-left:.5rem}nav.tabs{padding-bottom:2px;touch-action:pan-x pan-y;--wrap:nowrap;overflow:auto hidden}nav.tabs button.active{cursor:default}nav.tabs button{font-family:var(--heading);font-size:var(--txt-x-small);border-bottom:4px solid transparent}nav.tabs button.active,nav.tabs button.active:hover{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast));border-color:rgb(var(--base))}.tab-content nav.tabs button{height:var(--chip_);padding:.25rem .75rem;min-height:0}.tab-content h2{margin:0 0 .5rem}.tab-content nav.tabs{height:max-content;background-color:rgb(var(--base));--gap:0}.tab-content .tab-content nav.tabs{background-color:rgb(var(--base-100))}.tab-content .tab-content .tab-content nav.tabs{background-color:rgb(var(--base-200))}.tab-content nav.tabs button.active h2{color:rgb(var(--action-0))}nav.menu a{padding:.5rem .66rem}nav.share{height:max-content;margin:1rem 0}nav.share ul{overflow:visible}nav.share h4{display:inline-block;width:max-content;margin:.25rem .5rem .25rem 0;font-size:var(--txt-x-small)}.wp-site-blocks>header,body>header{--dir:row;--justify:space-between;position:sticky;top:0;left:0;right:0;height:var(--btn);width:100vw;display:flex;align-items:var(--align,center);justify-content:var(--justify,space-between);padding:0 .5rem;background-color:rgb(var(--base));box-shadow:rgba(var(--base),var(--op-45)) var(--shdw);z-index:var(--z-9)}.wp-site-blocks>header img{width:var(--btn)}.dashboard-nav{width:100%}nav.filters{--dir:row;overflow:auto hidden}nav.filters .filter{width:auto;padding:.25rem .75rem}nav.term-navigation:has([hidden]){display:none}nav.pagination{width:100%}nav.pagination>a{min-width:var(--chipchip)}nav.pagination>ul{margin:0 auto}nav.pagination:not(:has(a+ul)){margin-left:var(--chipchip)}nav.pagination:not(:has(ul+a)){margin-right:var(--chipchip)}.pagination.condensed li+li::before{display:none}.pagination li.current{width:var(--chip_);height:var(--chip_);background-color:rgb(var(--action-0));border-radius:var(--radius);line-height:1}.pagination.condensed a{font-size:var(--txt-medium);width:var(--chip_);height:var(--chip_)}
\ No newline at end of file
+nav,nav ol,nav ul{--padding:0 1rem;--wrap:nowrap;font-family:var(--heading)}nav,nav a,nav li,nav ol,nav ul,ul.socials{display:flex;flex-direction:var(--dir,row);justify-content:var(--justify,flex-start);align-items:var(--align,center);gap:var(--gap,0);flex-wrap:var(--wrap,nowrap);height:var(--btn,3rem);max-width:100%;padding:0;margin:0}nav.col,nav.col ul{height:max-content}nav>ul{width:100%;overflow:auto hidden}nav li{width:max-content;--justify:center;max-inline-size:none;padding:0;list-style:none}nav.fill li{width:100%}nav a,nav button{--justify:center;width:100%;white-space:nowrap;text-transform:uppercase;border-radius:0;background-color:transparent;text-decoration:none}nav a{padding:var(--padding)}nav .toggle{aspect-ratio:1;border:1px solid rgb(var(--base));color:rgb(var(--contrast))}nav .current a,nav a.current,nav a:focus,nav a:focus:visited,nav button:focus{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast))}.toggle .icon-caret-down{transform:rotate(0);transition:transform var(--trans-base)}.open>.row>.toggle .icon-caret-down,.open>.toggle .icon-caret-down{transform:rotate(900deg)}.has-submenu{position:relative}ul.submenu{--dir:column;height:max-content;position:absolute;top:100%;right:0;max-height:0;transform:scaleY(0);transform-origin:top;width:100%;min-width:max-content;background-color:rgba(var(--base),var(--op-3));border:2px solid rgba(var(--base),var(--op-3));transition:max-height var(--trans-base),transform var(--trans-base);box-shadow:var(--shdw-none);overflow:hidden}.submenu li{background-color:rgba(var(--base),var(--op-6));border:1px solid rgb(var(--base-50))}.submenu a{height:var(--chipchip)}.open>ul.submenu{transform:scaleY(1);max-height:1000%;box-shadow:rgba(var(--base),var(--op-45)) var(--shdw)}.screen-reader-text{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}nav a:focus:not(:focus-visible){outline:0}nav a:focus-visible{outline:1px solid rgb(var(--action-0));outline-offset:1px}nav.always{overflow:visible;transition:width var(--trans-base);width:max-content}nav.always>ul{--dir:column;--align:center;--justify:flex-end;--gap:0;height:100vh;max-height:none;position:fixed;right:-300vw;bottom:0;width:100vw;padding:var(--btn) 0;overflow:hidden auto;transition:right var(--trans-base)}nav.always.open>ul{right:0}nav.always li{width:100%}nav.always.fixed{width:var(--btn);height:var(--btn);bottom:0;right:0;overflow:hidden}nav.always.fixed .toggle.main{background-color:rgb(var(--base))}nav.always.fixed .toggle.main:focus,nav.always.fixed .toggle.main:hover{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast))}nav.mobile .toggle.main{width:var(--btn);transition:width var(--trans-base)}nav.mobile .icon-list,nav.mobile .icon-x{--w:32px}nav.mobile .icon-x,nav.mobile.open .icon-list{display:none}nav.mobile .icon-list,nav.mobile.open .icon-x{display:block}nav.mobile.open>ul{--dir:column;z-index:var(--z-9);background-color:rgba(var(--base),var(--op-6));width:100vw;height:100vh;overflow:hidden auto;right:0;bottom:0;position:fixed;padding:var(--btn) 0}nav.always>ul::before,nav.mobile.open>ul::before{content:'';z-index:-1;position:absolute;inset:0;filter:blur(5px)}nav.always.open .main.toggle,nav.mobile.open .main.toggle{position:fixed;bottom:0;left:0;width:100vw;z-index:var(--z-10);aspect-ratio:unset}nav.always>ul,nav.always>ul:before,nav.mobile.open>ul,nav.mobile.open>ul::before{background-color:rgba(var(--base),var(--op-6))}@media (max-width:767px){nav.col{height:var(--btn)}nav.mobile>ul{--dir:column;--align:center;--justify:flex-end;--gap:0;height:100%;max-height:none;position:relative;right:-300vw;width:100vw;padding:var(--btn) 0 0;overflow:hidden auto}nav.mobile.open>ul{right:0}}@media (min-width:768px){nav.mobile:not(.always) .toggle.main{display:none}}nav#breadcrumbs{height:max-content;--wrap:wrap;--gap:0;width:max-content;max-width:var(--full);position:absolute;background-color:rgba(var(--base),var(--op-4));font-size:var(--txt-x-small);padding:.125em;z-index:var(--z-5)}nav#breadcrumbs ol{height:max-content;--wrap:wrap;--justify:flex-start}nav#breadcrumbs li{width:max-content;height:var(--chip);--wrap:nowrap}nav#breadcrumbs li::after{content:'/';color:rgb(var(--contrast-200));padding:0 .25rem}nav#breadcrumbs li:last-of-type::after{display:none}nav#breadcrumbs a{height:var(--chip)}nav#breadcrumbs a,nav#breadcrumbs span{padding:0 .125rem;color:rgb(var(--contrast));text-transform:none}nav#breadcrumbs a:focus{background-color:transparent;color:rgb(var(--action-0))}nav.fixed{position:fixed;box-shadow:rgba(var(--base),var(--op-45)) var(--shdw);z-index:var(--z-9)}nav.fixed.bottom{left:0;bottom:0;width:calc(100% - var(--btn))}nav.fixed:not(.always) ul{--justify:space-between;width:100%;background-color:rgb(var(--base));padding:0 .25rem}nav.fixed:not(.always) li{flex:1}nav.fixed a{--align:center;--gap:1rem;--w:var(--chip_);color:rgb(var(--contrast));font-size:var(--txt-x-small)}@media (min-width:768px){nav.fixed a{font-size:var(--txt-medium)}}nav.on-this-page.on-this-page{--justify:space-between;position:fixed;bottom:0;left:0;width:100vw;z-index:var(--z-5);background-color:rgba(var(--base),var(--op-45));max-width:none;margin:0!important}body:has(nav.fixed) nav.on-this-page{bottom:var(--btn)}nav.on-this-page button{order:3;padding:0 1rem;width:max-content;aspect-ratio:unset}nav.on-this-page.open button{order:0}nav.on-this-page ul{width:100%;--gap:0}nav.on-this-page a{padding:0}nav.on-this-page .active a{background-color:rgba(var(--base),var(--op-6));color:rgb(var(--action-contrast))}nav.on-this-page #back-to-top span{display:none}nav.on-this-page .active a{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast))}nav.letters,nav.letters a,nav.letters li,nav.letters ul{min-height:var(--chip);height:max-content}nav.letters li{width:calc(7.69% - 2px)}nav.letters ul{--wrap:wrap}@media (min-width:768px){nav.letters,nav.letters ul{height:var(--chip)}nav.letters ul{--wrap:nowrap}nav.letters li{width:inherit}nav.letters a{padding:.25rem .66rem}}nav.index{--justify:space-between;--padding:0;background-color:rgba(var(--base),var(--op-6))}nav.index,nav.index a,nav.index button,nav.index li,nav.index ul{min-height:var(--chipchip);height:var(--chipchip)}nav.index ul{width:100%}nav.index li{flex-shrink:0;transform:scaleX(0);max-width:0;overflow:hidden}nav.index li.active,nav.index li.adj{transform:scaleX(1);width:100%;flex-shrink:1;max-width:none}@media (max-width:767px){.index li.adj{transform:scaleX(0);max-width:0}}nav.index.open{--dir:column-reverse;height:var(--maxHeight);width:100%;--align:flex-end;background-color:rgba(var(--base),var(--op-6));backdrop-filter:blur(5px);z-index:var(--z-10)}nav.index.open ul{min-height:max-content;--dir:column}nav.index.open li{width:100%;max-width:100%!important;transform:scaleX(1);overflow:visible}nav.index.open a{--justify:center;padding:0 2rem 0 0}nav.condensed,nav.condensed a,nav.condensed li,nav.condensed ul{height:max-content;width:max-content;--wrap:wrap;min-height:var(--chip)}.condensed ul{--justify:center;--dir:row}nav.condensed{--gap:0 .25rem;width:100%;--justify:center}nav.condensed li+li::before{content:'·';padding:0 .25em}nav.condensed a{font-size:var(--txt-x-small);padding:0 .25rem;text-transform:none;border-bottom:2px solid transparent}nav .current a,nav a.current,nav a:focus,nav a:focus:visited,nav button:focus{background-color:transparent;color:rgb(var(--contrast));border-color:rgb(var(--action-0))}ul.socials{--dir:row;height:max-content;--gap:.5rem;--justify:flex-end;--wrap:nowrap;overflow:auto hidden;touch-action:pan-x;width:100%}ul.socials li{list-style:none}.always ul.socials{width:100vw;--justify:stretch}.always ul.socials li{flex:1;--justify:center;--align:center}.always ul.socials a{display:inline-flex}ul.socials a{display:inline-block;font-size:var(--txt-x-small);padding:.25rem .5rem;max-width:none}ul.socials .icon{margin:0}ul.socials .icon+span:not(.screen-reader-text){margin-left:.5rem}nav.tabs{padding-bottom:2px;touch-action:pan-x pan-y;--wrap:nowrap;overflow:auto hidden}nav.tabs button.active{cursor:default}nav.tabs button{font-family:var(--heading);font-size:var(--txt-x-small);border-bottom:4px solid transparent}nav.tabs button.active,nav.tabs button.active:hover{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast));border-color:rgb(var(--base))}.tab-content nav.tabs button{height:var(--chip_);padding:.25rem .75rem;min-height:0}.tab-content h2{margin:0 0 .5rem}.tab-content nav.tabs{height:max-content;background-color:rgb(var(--base));--gap:0}.tab-content .tab-content nav.tabs{background-color:rgb(var(--base-100))}.tab-content .tab-content .tab-content nav.tabs{background-color:rgb(var(--base-200))}.tab-content nav.tabs button.active h2{color:rgb(var(--action-0))}nav.menu a{padding:.5rem .66rem}nav.share{height:max-content;margin:1rem 0}nav.share ul{overflow:visible}nav.share h4{display:inline-block;width:max-content;margin:.25rem .5rem .25rem 0;font-size:var(--txt-x-small)}.wp-site-blocks>header,body>header{--dir:row;--justify:space-between;position:sticky;top:0;left:0;right:0;height:var(--btn);width:100vw;display:flex;align-items:var(--align,center);justify-content:var(--justify,space-between);padding:0 .5rem;background-color:rgb(var(--base));box-shadow:rgba(var(--base),var(--op-45)) var(--shdw);z-index:var(--z-9)}.wp-site-blocks>header img{width:var(--btn)}.dashboard-nav{width:100%}nav.filters{--dir:row;overflow:auto hidden}nav.filters .filter{width:auto;padding:.25rem .75rem}nav.term-navigation:has([hidden]){display:none}nav.pagination{width:100%}nav.pagination>a{min-width:var(--chipchip)}nav.pagination>ul{margin:0 auto}nav.pagination:not(:has(a+ul)){margin-left:var(--chipchip)}nav.pagination:not(:has(ul+a)){margin-right:var(--chipchip)}.pagination.condensed li+li::before{display:none}.pagination li.current{width:var(--chip_);height:var(--chip_);background-color:rgb(var(--action-0));border-radius:var(--radius);line-height:1}.pagination.condensed a{font-size:var(--txt-medium);width:var(--chip_);height:var(--chip_)}
\ No newline at end of file
diff --git a/assets/js/concise/CRUD.js b/assets/js/concise/CRUD.js
index 82b8b4c..7ee64ff 100644
--- a/assets/js/concise/CRUD.js
+++ b/assets/js/concise/CRUD.js
@@ -1294,17 +1294,20 @@
 		this.ui.modals.edit.form.dataset.formId = `edit-${itemID}`;
 
 
+		this.isPopulating = true;
+
 		this.modals.edit.handleOpen();
 		this.forms.registerForm(this.ui.modals.edit.form, {cache: false,
 			autoUpload: true,});
 
 
-		this.isPopulating = true;
 		this.populate.populate(this.ui.modals.edit.form, item);
 		//For quill/taxonomy selector's async setups
 		requestAnimationFrame(() => {
 			requestAnimationFrame(() => {
-				this.isPopulating = false;
+				setTimeout(() => {
+					this.isPopulating = false;
+				}, 50);
 			});
 		});
 
diff --git a/assets/js/concise/Gallery.js b/assets/js/concise/Gallery.js
index 948ab0f..9abf84c 100644
--- a/assets/js/concise/Gallery.js
+++ b/assets/js/concise/Gallery.js
@@ -42,7 +42,8 @@
 				image: '.image',
 				leftImage: '.image-left',
 				rightImage: '.image-right',
-				counter: '.counter'
+				counter: '.counter',
+				caption: 'details .item-info'
 			},
 		}
 		this.ui = window.uiFromSelectors(this.elements);
@@ -66,6 +67,10 @@
 		let selector = filtered ? `[data-gallery="${filtered}"]` : this.elements.imageSelector;
 		this.items = Array.from(document.querySelectorAll(selector))
 			.map((img, index) => {
+				let caption = img.nextElementSibling && img.nextElementSibling.tagName === 'FIGCAPTION' ?
+					img.nextElementSibling.textContent :
+					'';
+
 				return {
 					id: img.dataset.id||index,
 					srcset: img.srcset || img.src, // Clone the srcset from page
@@ -73,7 +78,8 @@
 					src: img.currentSrc || img.src, // Fallback
 					full: img.dataset.full || img.src,
 					alt: img.alt || '',
-					element: img
+					element: img,
+					caption: caption
 				};
 			});
 	}
@@ -387,7 +393,10 @@
 		galleryImg.src = item.src; // Fallback
 		galleryImg.alt = item.alt;
 
-		// ALWAYS load full resolution for zoom quality
+		this.ui.gallery.caption.textContent = item.caption;
+
+
+
 		if (item.full && item.full !== item.src) {
 			const fullImg = new Image();
 			fullImg.onload = () => {
diff --git a/assets/js/concise/PopulateForm.js b/assets/js/concise/PopulateForm.js
index be44bfa..edfda97 100644
--- a/assets/js/concise/PopulateForm.js
+++ b/assets/js/concise/PopulateForm.js
@@ -59,7 +59,7 @@
 	populateField(field, name, value) {
 
 		let type = this.formHelper.getFieldType(field);
-		if (!type || this.isEmptyValue(name) || this.isEmptyValue(value)) return;
+		if (!type || this.isEmptyValue(name)) return;
 
 		const handlers = {
 			'repeater': this.populateRepeater.bind(this),
@@ -93,12 +93,23 @@
 	}
 
 	populateRepeater(field, name, value) {
-		if (!value || !Array.isArray(value)) return;
-
 		const container = field.querySelector('.repeater-items');
 		let template = field.querySelector('template')?.className ?? false;
 		if (!container || !template) return;
 
+		// Normalize: server/store may return an object with numeric keys instead of an array
+		if (typeof value === 'string') {
+			try { value = JSON.parse(value); } catch(e) { value = []; }
+		}
+		if (value && !Array.isArray(value) && typeof value === 'object') {
+			value = Object.values(value);
+		}
+
+		if (!value || !Array.isArray(value) || value.length === 0) {
+			window.removeChildren(container);
+			return;
+		}
+
 		window.removeChildren(container);
 
 		value.forEach((data, index) => {
@@ -123,12 +134,23 @@
 		});
 	}
 	populateTagList(field, name, value) {
-		if (!value || !Array.isArray(value)) return;
 
 		const container = field.querySelector('.tag-items');
 		let template = field.querySelector('template')?.className ?? false;
 		if (!container || !template) return;
 
+		if (typeof value === 'string') {
+			try { value = JSON.parse(value); } catch(e) { value = []; }
+		}
+		if (value && !Array.isArray(value) && typeof value === 'object') {
+			value = Object.values(value);
+		}
+
+		if (!value || !Array.isArray(value) || value.length === 0) {
+			window.removeChildren(container);
+			return;
+		}
+
 		window.removeChildren(container);
 
 		value.forEach((data, index) => {
@@ -192,7 +214,6 @@
 	}
 	populateTaxonomy(field, name, value) {
 		let termIds = this.splitIDs(value);
-		if (termIds.length === 0) return;
 
 		const hiddenInput = field.querySelector(`input[type="hidden"][name="${name}"]`);
 		if (hiddenInput) {
@@ -213,7 +234,6 @@
 			return;
 		}
 
-		if (this.isEmptyValue(value)) return;
 		const ids = this.splitIDs(value);
 		if (ids.length === 0) return;
 		const hiddenInput = field.querySelector(`input[type="hidden"]`);
diff --git a/assets/js/concise/Queue.js b/assets/js/concise/Queue.js
index 77e5aeb..1122684 100644
--- a/assets/js/concise/Queue.js
+++ b/assets/js/concise/Queue.js
@@ -17,6 +17,7 @@
 		this.items = new Map();
 		this.subscribers = new Set();
 		this.loadFromStorage = false;
+		this.failedFetches = 0;
 
 		this.api = jvbSettings.api;
 		this.endpoint = 'queue';
@@ -801,6 +802,8 @@
 				return;
 			}
 		} catch (error) {
+			this.stopPolling();
+			this.updatePanel('synced');
 			console.error('Polling error:', error);
 		}
 
diff --git a/assets/js/min/crud.min.js b/assets/js/min/crud.min.js
index 98fb38a..9be9111 100644
--- a/assets/js/min/crud.min.js
+++ b/assets/js/min/crud.min.js
@@ -1 +1 @@
-(()=>{class e{constructor(){this.container=document.querySelector(".crud[data-content]:not([data-ignore])"),this.container&&(this.content=this.container.dataset.content,this.endpoint=this.container.dataset.endpoint??"content",this.singular=this.container.dataset.singular,this.plural=this.container.dataset.plural,this.queue=window.jvbQueue,this.a11y=window.jvbA11y,this.error=window.jvbError,this.populate=window.jvbPopulate,this.cache=new window.jvbCache(this.content),this.activeItem=null,this.isTimeline=!1,this.isPopulating=!1,this.changes=new Map,this.items=new Map,this.init())}init(){this.initElements(),this.initListeners(),this.defineTemplates();let e=this.initSettings();this.initStore(e),this.checkHideFilters(),this.initIntegrations(),this.initUploader(),this.initModals()}defineTemplates(){const e=window.jvbTemplates,t=this,s=(e,s,i)=>{e.dataset.itemId=i.id;let a=s.checkbox.closest(".preview");window.prefixInput(s.checkbox,`select-${i.id}`,a,!0),s.checkbox.value=i.id,s.checkbox.checked=t.selected.has(parseInt(i.id)),s.selectLabel&&(s.selectLabel.htmlFor=`select-${i.id}`),s.edit&&(s.edit.dataset.id=i.id),s.trash&&(s.trash.dataset.id=i.id)},i=function(e,t,s){let i=s?.fields?.post_thumbnail||s?.fields?.thumbnail;if(i){const e=s.images[i]??{};t.img.src=e.medium??"",t.img.alt=e.alt??s.fields.post_title??""}};e.define("gridView",{refs:{img:"img",checkbox:".select-item",selectLabel:"label.select-item-label",edit:'[data-action="edit"]',trash:'[data-action="trash"]'},setup({el:e,refs:t,manyRefs:a,data:l}){s(e,t,l),i(0,t,l)}}),e.define("listView",{refs:{img:"img",checkbox:".select-item",selectLabel:"label.select-item-label",edit:'[data-action="edit"]',trash:'[data-action="trash"]'},manyRefs:{attrs:"[data-attr]",fields:"[data-field]"},setup({el:e,refs:t,manyRefs:a,data:l}){s(e,t,l),i(0,t,l),a?.attrs?.forEach(e=>{const t=l[e.dataset.attr];t&&""!==t?e.textContent=t:e.remove()}),a?.fields?.forEach(e=>{const t=l.fields?.[e.dataset.field];t&&""!==t?"DIV"===e.tagName?e.innerHTML=t:e.textContent=t:e.remove()})}});let a={};this.isTimeline&&(a.sharedRow="tr.shared",a.point="tr.timeline-point"),e.define("tableView",{refs:{checkbox:".select-item",selectLabel:"label.select-item-label",...a},manyRefs:{inputs:"input,select,textarea",status:'input[name="post_status"]',selectors:'[data-type="selector"]',fields:"[data-field]"},setup({el:e,refs:i,manyRefs:a,data:l}){if(s(e,i,l),a?.inputs?.forEach(e=>{let t=e.closest("[data-field]");window.prefixInput(e,`${l.id}-`,t)}),a?.status?.forEach(e=>{e.value===l.status&&(e.checked=!0)}),t.isTimeline)i.sharedRow&&(i.sharedRow.querySelectorAll("input,select,textarea").forEach(e=>{let t=e.closest("[data-field]");window.prefixInput(e,`${l.id}-`,t)}),t.populate.populate(i.sharedRow,l),i.sharedRow.querySelectorAll('input[name="post_status"]').forEach(e=>{e.value===l.status&&(e.checked=!0)})),i.point&&l.fields?.timeline&&(Object.entries(l.fields.timeline).forEach(([s,a],n)=>{const o=i.point.cloneNode(!0);o.dataset.index=`${n}`,o.dataset.itemId=a.id,o.querySelectorAll("input,select,textarea").forEach(e=>{let t=e.closest("[data-field]");window.prefixInput(e,`${a.id}-`,t)}),t.populate.populate(o,{fields:a,images:l.images,taxonomies:l.taxonomies});const r=l.images?.[a.post_thumbnail];r&&o.querySelector(".field.upload")?.setAttribute("title",r["image-title"]??""),e.insertBefore(o,i.point)}),i.point.remove());else if(void 0!==t.ui.table.form?.dataset.edit)a?.inputs?.forEach(e=>{let t=e.closest("[data-field]");window.prefixInput(e,`${l.id}-`,t)}),a?.status?.forEach(e=>{e.value===l.status&&(e.checked=!0)}),t.populate.populate(e,l);else{const e=Object.hasOwn(l,"fields")?l.fields:l;a?.fields?.forEach(t=>{if(Object.hasOwn(e,t.dataset.field)&&""!==e[t.dataset.field]){let s=e[t.dataset.field],i=e.children[0];i&&(i.textContent="date"===t.dataset.field?window.formatTimeAgo(s):s)}})}a?.selectors?.forEach(e=>e.setAttribute("data-lazy",""))}}),e.define("emptyState"),e.define("bulkItem",{refs:{checkbox:"input",img:"img",label:"label"},setup({el:e,refs:t,manyRefs:s,data:i}){t.checkbox&&(t.checkbox.id=`bulk_${i.id}`,t.checkbox.value=i.id,t.checkbox.checked=!0,t.checkbox.name="selected[]");let a=i?.images[i?.fields?.post_thumnbail]??{};t.img&&Object.keys(a).length>0&&(t.img.src=a.medium??"",t.img.alt=a.alt??""),t.label&&(t.label.title=item.fields.post_title)}}),e.define("trashOptions"),e.define("notTrashOptions"),e.define("contentTable")}initElements(){this.allowedFilters=["status","orderby","order","search","date-filter","dateFrom","dateTo"],this.selectors={buttons:{create:".create-item",clearFilters:'[data-action="clear-filters"]'},views:{grid:'input[data-view="grid"]',list:'input[data-view="list"]',table:'input[data-view="table"]'},modals:{create:{modal:"dialog.create",form:"dialog.create form",h2:"dialog.create h2"},edit:{modal:"dialog.edit",form:"dialog.edit form",h2:"dialog.edit h2"},bulkEdit:{modal:"dialog.bulkEdit",selected:"dialog.bulkEdit .selected",h2:"dialog.bulkEdit h2 span",form:"dialog.bulkEdit form"},date:{modal:"dialog.date-range",start:"dialog.date-range .date-start",end:"dialog.date-range .date-end",month:"dialog.date-range .month-select"}},grid:`.${this.content}.item-grid`,table:{nav:"#vertical",form:"form.table",table:"form.table table",body:"form.table body",head:"form.table thead",foot:"form.table tfoot",selectedColumns:".all-filters .multi-select",columns:"thead th"},bulk:{action:".bulk-action-select",count:".bulk-controls .selected-count",control:".bulk-controls .bulk-actions",select:".bulk-controls select",selectAll:".select-all"},filters:{container:"details.all-filters",search:'.all-filters input[type="search"]',status:{all:'[name="status"]#all',publish:'[name="status"]#publish',draft:'[name="status"]#draft',trash:'[name="status"]#trash'},orderby:{date:'[name="orderby"]#date',alphabetical:'[name="orderby"]#alphabetical'},order:{asc:'[name="order"][value="asc"]',desc:'[name="order"][value="desc"]'},date:'[data-filter="date"]'},uploader:{details:"details.uploader",form:"details.uploader form",uploader:'details.uploader [data-field-type="upload"]'}},this.ui=window.uiFromSelectors(this.selectors);const e=document.querySelectorAll('[data-filter="taxonomies"]');e.length>0&&(this.ui.filters.taxonomies={},e.forEach(e=>{const t=e.dataset.taxonomy;this.ui.filters.taxonomies[t]=e,this.allowedFilters.push(`tax_${t}`)})),this.isTimeline=!!document.querySelector("[data-timeline]")}initUploader(){this.ui.uploader.form&&(this.uploadForm=this.forms.registerForm(this.ui.uploader.form).id??!1,window.jvbUploads.subscribe((e,t)=>{if("sent-to-queue"===e&&t.field.id===this.ui.uploader.uploader.dataset.uploader&&(this.uploadForm&&this.forms.store.delete(this.uploadForm),window.debouncer.schedule("crud-complete",()=>{this.store.clearCache()})),"sent-to-queue"===e&&t.field){const e=t.field.config.name,s=t.field.config.itemID;s&&e&&this.changes.has(s)&&delete this.changes.get(s)[e]}}))}initModals(){this.modals={};for(let[e,t]of Object.entries(this.ui.modals))t.modal&&(this.modals[e]=new window.jvbModal(t.modal),this.modals[e].subscribe((t,s)=>{if("modal-close"===t){const t=this.ui.modals[e].form.dataset.formId;t&&this.forms.clearForm(t),this.resetForm(this.ui.modals[e].form),"date"===e&&this.handleCustomDateSelection(),["edit","bulkEdit","create"].includes(e)&&window.debouncer.timeouts.has(`save-${this.content}`)&&this.scheduleSave(0)}}))}initStore(e){let t={...this.defaults,...e};const s=window.jvbStore.register(this.content,[{storeName:this.content,keyPath:"id",endpoint:this.endpoint??"content",headers:{"X-Action-Nonce":window.auth.getNonce("dash")},indexes:[{name:"id",keyPath:"id"},{name:"status",keyPath:"status"},{name:"date",keyPath:"date"},{name:"modified",keyPath:"modified"},{name:"title",keyPath:"title"}],isAuth:!0,filters:t,ignore:["content","user"],TTL:36e5,showLoading:!0},{storeName:"changes",keyPath:"id"}]);this.changesStore=s.changes,this.store=s[this.content],this.store.subscribe((e,t)=>{if("data-loaded"===e)this.render(),this.selectionHandler.collectItems()}),this.changesStore.subscribe((e,t)=>{if("data-ready"===e){let e=this.changesStore.getAll();e.length>0&&(e.forEach(e=>{this.changes.set(e.id,e)}),this.savePosts("",!1).then(()=>{}))}})}initIntegrations(){this.selected=new Set,this.selectionHandler=new window.jvbHandleSelection(this.container,{selectAll:{checkbox:"#select-all",label:".bulk-select label",span:".bulk-select label span"},wrapper:{wrapper:".wrap"},item:{idAttribute:"itemId"}}),this.selectionHandler.subscribe((e,t)=>{this.selected=new Set([...t.selectedItems].map(e=>parseInt(e))),this.ui.bulk.control.hidden=0===this.selected.size,this.ui.bulk.count.hidden=0===this.selected.size,this.ui.bulk.count.textContent=`${this.selected.size} ${this.plural} selected`}),this.forms=window.jvbForm,window.jvbUploads&&window.jvbUploads.subscribe((e,t)=>{"groups_uploaded"===e&&t.content===this.content&&this.handleGroupsUploaded(t)}),this.queue.subscribe((e,t)=>{if(["image_upload","video_upload","document_upload"].includes(t.type)&&"operation-status"===e&&"completed"===t.status&&this.store.clearCache(),"operation-status"===e&&"completed"===t.status&&"uploads/groups"===t.endpoint&&(t.result&&t.result.group_mappings&&(console.log("Handling group mapping from queue response"),this.handleGroupMappings(t.result.group_mappings)),this.store.clearCache()),"operation-status"===e&&"completed"===t.status&&"content_update"===t.type){if(this.store.clearCache(),!t.result||!t.result.success||!t.result.errors)return void console.warn("Content update completed but no results",t);if(Object.keys(t.result.success).length>0&&this.checkCompletedChanges(Object.entries(t.result.success)),Object.keys(t.result.errors).length>0)return void this.checkFailedChanges(Object.entries(t.result.errors));0===Object.keys(t.result.success).length&&(console.log(t.result.success),t.result.success.forEach(e=>this.changesStore.delete(e)),this.store.clearCache())}if("sent-to-server"===e&&"content_update"===t.type){if(t instanceof FormData)return;for(let[e,s]of Object.entries(t.posts))this.compareStored(e,s)}})}checkCompletedChanges(e){for(let[t,s]of e)this.compareStored(t,s)}compareStored(e,t){let s=this.changesStore.get(e);if(!s)return;for(let[e,i]of Object.entries(t))if(Object.hasOwn(s,e)){let t=window.getDifferences.map(s[e],i);t?s[e]=t:delete s[e]}let i=Object.hasOwn(s,"id"),a=Object.hasOwn(s,"content");i&&a&&2===Object.keys(s).length||(i||a)&&1===Object.keys(s).length||0===Object.keys(s).length?(this.changesStore.delete(e),this.store.clearCache()):this.changesStore.save(s)}checkFailedChanges(e){}initSettings(){this.defaults={content:this.content,user:window.auth.getUser(),page:1,status:"all",orderby:"date",order:"desc",search:""};let e={},t=this.container.dataset.view??"grid";this.view=this.cache.get("view")??t,this.view!==t&&(this.ui.views[this.view].checked=!0),this.status=this.cache.get("status")??this.defaults.status,this.status!==this.defaults.status&&(this.ui.filters.status[this.status].checked=!0,e.status=this.status),this.orderby=this.cache.get("orderby")??this.defaults.orderby,this.orderby!==this.defaults.orderby&&(this.ui.filters.orderby[this.orderby].checked=!0,e.orderBy=this.orderby),this.order=this.cache.get("order")??this.defaults.order,this.order!==this.defaults.order&&(this.ui.filters.order[this.order].checked=!0,e.order=this.order),this.ui.filters.taxonomies&&Object.entries(this.ui.filters.taxonomies).forEach(([t,s])=>{const i=`tax_${t}`,a=this.cache.get(i);a&&(s.value=a,e[i]=a)});let s=this.cache.get("tabNav")??"horizontal";this.ui.table.nav&&"vertical"===s&&(this.ui.table.nav.checked=!0);let i={showFilters:{element:this.ui.filters.container,default:"closed"},showUploader:{element:this.ui.uploader.details,default:"open"}};for(let[e,t]of Object.entries(i))if(t.element){let s=this.cache.get(e)??t.default;t.element.open="open"===s,t.element.addEventListener("toggle",()=>{this.cache.set(e,t.element.open?"open":"closed")})}return e}initListeners(){this.changeHandler=this.handleChange.bind(this),this.clickHandler=this.handleClick.bind(this),this.inputHandler=this.handleInput.bind(this),this.submitHandler=this.handleModalSubmit.bind(this),document.addEventListener("change",this.changeHandler),document.addEventListener("click",this.clickHandler),this.ui.filters.search&&this.ui.filters.search.addEventListener("input",this.inputHandler);for(let[e,t]of Object.entries(this.ui.modals))t.form&&t.form.addEventListener("submit",this.submitHandler)}handleModalSubmit(e){e.preventDefault();const t=e.target.closest("dialog");if(!t)return;if(t.classList.contains("create"))return void this.handleCreateSubmit(t);this.plural;this.scheduleSave(0),this.modals.edit.handleClose()}async handleCreateSubmit(e){e.dataset.itemId;this.changes.size>0&&(this.cancelBackup(),await this.handleBackup());const t=await this.changesStore.getAll();if(0===t.length)return;let s={};t.forEach(e=>{const{id:t,...i}=e;s[t]=i});let i=this.queue.addToQueue({endpoint:this.endpoint,headers:{"X-Action-Nonce":window.auth.getNonce("dash")},data:{posts:s},popup:`Creating your new ${this.singular}`,title:`Creating your new ${this.singular}`});if(!i)return;const a=e.querySelectorAll("[data-upload-field]");for(const e of a){const t=e.dataset.uploader;if(!t)continue;0!==window.jvbUploads.stores.uploads.filterByIndex({field:t}).length&&await window.jvbUploads.queueUploads("uploads",t,i)}}handleChange(e){const t=e.target.closest("[data-item-id]"),s=e.target.matches("[data-filter]"),i=e.target.matches(".bulk-action-select"),a=e.target.matches("[data-view]");if(t||s||i||a)if(this.isPopulating||!t||e.target.closest("[data-ignore], .select-item")){if(a)return this.items.clear(),void this.handleViewChange(e.target);if(i)this.handleBulkAction(e.target);else if(s)this.handleFilterChange(e.target);else if("table"===this.view){if(e.target.matches("details.multi-select"))return void this.toggleColumn(e.target.id,e.target.checked);e.target.matches(this.selectors.table.nav)&&(this.tabNav=e.target.checked,this.cache.set("tabNav",e.target.checked?"vertical":"horizontal"))}}else this.handleItemUpdate(e)}handleBulkAction(e){if(e.value.startsWith("tax-")){const t=e.options[e.selectedIndex],s=t.dataset.taxonomy,i=t.dataset.single,a=t.dataset.plural;return window.jvbSelector.openEmpty(s,i,a,e=>this.handleBulkTaxonomy(e)),void(e.value="")}switch(e.value){case"edit":this.openBulkEditModal();break;case"publish":case"trash":case"delete":this.setBulkStatus(e.value);break;case"draft":case"restore":this.setBulkStatus("draft")}}handleBulkTaxonomy(e){e.termIds.length&&this.selected.size&&(this.selected.forEach(t=>{const s=this.store.get(t);if(!s)return;const i=(s.taxonomies?.[e.taxonomy]||[]).map(e=>e.id),a=[...new Set([...i,...e.termIds])];this.updateItem(t,e.taxonomy,a)}),this.savePosts(`Adding ${e.terms.length} ${e.taxonomy} to ${this.selected.size} ${this.plural}...`).then(()=>{}),this.selectionHandler.clearSelection())}handleItemUpdate(e){let t=window.targetCheck(e,"[data-item-id]");if(!t)return;const s=e.target.closest('[data-field-type="repeater"], [data-field-type="tag-list"]');let i,a;if(s)i=s.dataset.field,a=this.forms.getFieldValue(s);else{let t=e.target.closest("[data-field]");i=t.dataset.field,a=this.forms.getFieldValue(e.target)}t.dataset.itemId.split(",").forEach(e=>{this.updateItem(e,i,a)})}updateItem(e,t,s){if(this.isPopulating)return;t.replace(`[${e}]`,"");const i=this.store.get(e);if(i){const a=i.fields?.[t]??i[t];if(null===window.getDifferences.map(a,s)){if(this.changes.has(e)){delete this.changes.get(e)[t];0===Object.keys(this.changes.get(e)).filter(e=>"id"!==e&&"content"!==e).length&&(this.changes.delete(e),this.changesStore.delete(e))}return}}this.changes.has(e)||this.changes.set(e,{id:e,content:this.content}),this.changes.get(e)[t]=s,this.scheduleBackup(),"number"!=typeof e&&String(e).includes("group")||this.scheduleSave()}scheduleBackup(){window.debouncer.schedule(`changes-${this.content}`,async()=>{this.changes.size>0&&await this.handleBackup()},2e3)}cancelBackup(){window.debouncer.cancel(`changes-${this.content}`)}async handleBackup(){const e=Array.from(this.changes.values());this.changes.clear();const t=e.map(e=>e.id),s=await Promise.all(t.map(e=>this.changesStore.get(e))),i=e.map((e,t)=>s[t]?window.deepMerge(s[t],e):e);await this.changesStore.saveMany(i)}scheduleSave(e=1e4){window.debouncer.schedule(`save-${this.content}`,async()=>{this.changes.size>0&&(this.cancelBackup(),await this.handleBackup()),await this.savePosts("",!1)},e)}handleFilterChange(e){let t=e.dataset.filter;return"date"===t&&"custom"===e.value?(e.value="",void this.modals.date.handleOpen()):"date"===t&&""!==e.value?(this.setFilter("date-filter",e.value),this.deleteFilter("dateFrom"),this.deleteFilter("dateTo"),void this.checkHideFilters()):("taxonomies"===t&&(t=`tax_${e.dataset.taxonomy}`),void this.setFilter(t,e.value))}checkHideFilters(){const e=this.store.filters,t=Object.entries(e).some(([e,t])=>!["content","user","page"].includes(e)&&(this.defaults[e]!==t&&""!==t&&null!==t));this.ui.buttons.clearFilters.hidden=!t}clearAllFilters(){let e=this.store.filters;this.store.clearFilters();for(let[t,s]of Object.entries(e))this.cache.remove(t),this.deleteFilter(t,s);this.a11y.announce("All filters cleared")}handleCustomDateSelection(){if(this.ui.modals.date.month&&this.ui.modals.date.month.value){const[e,t]=this.ui.modals.date.month.value.split("-"),s=`${e}-${t}-01`,i=new Date(e,parseInt(t),0).getDate(),a=`${e}-${t}-${String(i).padStart(2,"0")}`;this.setFilter("dateFrom",s),this.setFilter("dateTo",a),this.deleteFilter("date-filter"),this.ui.modals.date.month.value=""}else this.ui.modals.date.start&&this.ui.modals.date.start.value&&this.ui.modals.date.end&&this.ui.modals.date.end.value&&(this.setFilter("dateFrom",this.ui.modals.date.start.value),this.setFilter("dateTo",this.ui.modals.date.end.value),this.deleteFilter("date-filter"),this.ui.modals.date.start.value="",this.ui.modals.date.end.value="");this.checkHideFilters()}handleViewChange(e){this.view=e.dataset.view,this.cache.set("view",this.view),this.render()}handleClick(e){if(e.target.matches(".clear-search"))return void this.deleteFilter("search","");const t=e.target.closest("[data-action]");return t?(e.preventDefault(),void this.handleActionButton(t)):e.target.matches(".apply-date-filter")?(this.handleCustomDateSelection(),void this.modals.date.handleClose()):void((e.target.matches(this.selectors.buttons.create)||e.target.closest(this.selectors.buttons.create))&&this.openCreateModal())}openCreateModal(){this.forms.registerForm(this.ui.modals.create.form,{cache:!1}),this.ui.modals.create.modal.dataset.itemId=window.generateID("new"),this.modals.create.handleOpen()}handleActionButton(e){const t=e.dataset.id;switch(e.dataset.action){case"edit":this.openEditModal(t);break;case"delete":confirm("Delete this item? This cannot be undone")&&(this.updateItem(t,"post_status","delete"),window.fade(e.closest(".item"),!1),this.savePosts(`Permanently deleting ${this.singular}...`).then(()=>{}),this.store.delete(t));break;case"trash":"trash"===this.status?confirm("Delete this item? This cannot be undone")&&(this.updateItem(t,"post_status","delete"),window.fade(e.closest(".item"),!1),this.savePosts(`Permanently deleting ${this.singular}...`).then(()=>{}),this.store.delete(t)):(this.updateItem(t,"post_status","trash"),window.fade(e.closest(".item"),!1),this.savePosts(`Sending ${this.singular} to trash...`).then(()=>{}));break;case"bulk-edit":this.selected.size>0&&this.openBulkEditModal();break;case"bulk-delete":this.handleBulkDelete();break;case"refresh":this.store.clearCache(),this.store.fetch();break;case"clear-filters":this.clearAllFilters()}}handleBulkDelete(){let e="trash"===this.status;if(this.selected.size>0&&confirm(`${e?"Permanently delete":"Send"} ${this.selected.size} ${1===this.selected.size?this.singular:this.plural}${e?"":"to trash"}?`)){this.selected.forEach(t=>{this.store.delete(t),this.updateItem(t,"post_status",e?"delete":"trash")});let t=e?`Permanently deleting ${this.selected.size} ${1===this.selected.size?this.singular:this.plural}`:`Sending ${this.selected.size} ${1===this.selected.size?this.singular:this.plural} to trash`;this.savePosts(t).then(()=>{}),this.selectionHandler.clearSelection()}}handleInput(e){e.preventDefault(),e.stopPropagation();let t=e.target.value.trim(),s=`${this.content}-search`;0!==t.length?window.debouncer.schedule(s,()=>{this.a11y.announce(`Searching for "${t}"...`),this.store.setFilters({search:t,page:1})},300):this.deleteFilter("search","")}handleKeys(e){if(this.tabNav&&"Tab"===e.key){e.preventDefault();const t=e.target.closest("[data-field]"),s=e.target.closest("tr");if(!t||!s)return;const i=t.dataset.field,a=e.shiftKey;let l=this.findNextEditableRow(s,a);l||(l=this.wrapToRow(s,a)),l&&this.focusFieldInRow(l,i,a)}}findNextEditableRow(e,t=!1){let s=t?e.previousElementSibling:e.nextElementSibling;for(;s&&!this.isEditableRow(s);)s=t?s.previousElementSibling:s.nextElementSibling;return s}wrapToRow(e,t=!1){if(this.isTimeline){const s=e.closest("tbody");if(!s)return null;const i=Array.from(s.querySelectorAll("tr")).filter(e=>this.isEditableRow(e));return t?i[i.length-1]:i[0]}{if(!this.ui.table.body)return null;const e=Array.from(this.ui.table.body.querySelectorAll("tr")).filter(e=>this.isEditableRow(e));return t?e[e.length-1]:e[0]}}isEditableRow(e){return!e.closest("thead")&&!e.closest("tfoot")&&(this.isTimeline?e.classList.contains("shared")||e.classList.contains("timeline-point"):!!e.dataset.itemId)}focusFieldInRow(e,t,s=!1){const i=e.querySelector(`[data-field="${t}"]`);if(!i)return;const a=this.findFocusableInput(i);if(a){a.focus(),a.select&&"text"===a.type&&a.select();const e=s?"next":"previous";this.a11y?.announce(`Moved to ${t} in ${e} row`)}}findFocusableInput(e){const t=['input:not([type="hidden"]):not([disabled])',"textarea:not([disabled])","select:not([disabled])","button:not([disabled])"];for(const s of t){const t=e.querySelector(s);if(t)return t}return null}openEditModal(e){let t,s=this.store.get(parseInt(e));s&&(this.activeItem=s.id,this.ui.modals.edit.modal.dataset.itemId=e,this.ui.modals.edit.modal.dataset.content=this.content,Object.hasOwn(s.fields,"post_title")?t=s.fields.post_title:Object.hasOwn(s.fields,"name")&&(t=s.fields.name),this.ui.modals.edit.h2.textContent=`Editing ${""===t?this.singular:t}`,this.ui.modals.edit.form.dataset.formId=`edit-${e}`,this.modals.edit.handleOpen(),this.forms.registerForm(this.ui.modals.edit.form,{cache:!1,autoUpload:!0}),this.isPopulating=!0,this.populate.populate(this.ui.modals.edit.form,s),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.isPopulating=!1})}))}openBulkEditModal(){window.removeChildren(this.ui.modals.bulkEdit.selected),this.ui.modals.edit.form.reset(),window.chunkIt(this.selected,t=>{let s=this.store.get(parseInt(t));if(s)return e.push(s.id),window.jvbTemplates.create("bulkItem",s)},e=>this.ui.modals.bulkEdit.selected.append(e)).then(()=>{});let e=Array.from(this.selected).map(e=>this.store.get(parseInt(e))).filter(Boolean);this.ui.modals.bulkEdit.modal.dataset.itemId=e.join(","),this.ui.modals.bulkEdit.h2&&(this.ui.modals.bulkEdit.h2.textContent=this.selected.size),this.modals.bulkEdit.handleOpen(),this.forms.registerForm(this.ui.modals.bulkEdit.form,{cache:!1}),this.isPopulating=!0,this.populate.populate(this.ui.modals.edit.form,item),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.isPopulating=!1})})}async savePosts(e="",t=!1){this.changes.size>0&&(this.cancelBackup(),await this.handleBackup());let s=await this.changesStore.getAll();if(0===s.length)return;if(s=this.validateChanges(s),0===s.length)return;""===e&&(e=`Saving ${s.length} ${1===s.length?this.singular:this.plural}`);let i={},a=[];s.forEach(e=>{let t=e.id;const{id:s,...l}=e;i[t]=l,e.post_status&&this.shouldRemoveItemUI(e.post_status)&&a.push(t)}),a.length>0&&this.removeItems(a);let l={endpoint:this.endpoint,headers:{"X-Action-Nonce":window.auth.getNonce("dash")},data:{posts:i},delay:t,popup:"Saving changes",title:e};this.queue.addToQueue(l)}validateChanges(e){return e.reduce((e,t)=>{const{id:s,content:i,...a}=t,l=this.store.get(s);if(!l)return e.push(t),e;const n={id:s,content:i};let o=!1;for(const[e,t]of Object.entries(a)){const s=l.fields?.[e]??l[e];null!==window.getDifferences.map(s,t)&&(n[e]=t,o=!0)}return o?e.push(n):(this.changes.delete(s),this.changesStore.delete(s)),e},[])}setBulkStatus(e){if(!["publish","draft","trash","delete"].includes(e))return;let t,s=[];if(this.selected.forEach(t=>{s.push(t),this.updateItem(t,"post_status",e)}),"delete"===e)t="Deleting";else t=window.uppercaseFirst(e)+"ing";this.shouldRemoveItemUI(e)&&this.removeItems(s),this.selectionHandler.clearSelection(),this.savePosts(`${t} ${s.length} ${1===s.length?this.singular:this.plural}...`).then(()=>{})}render(){const e=this.store.getFiltered();if(0!==e.length){switch(this.view){case"grid":this.renderGrid(e);break;case"table":this.renderTable(e).then(()=>{});break;case"list":this.renderList(e)}this.updateUI()}else this.renderEmpty()}updateUI(){if(this.ui.bulk.action){let e=!1,t=this.ui.bulk.action.querySelector('[value="edit"]'),s=this.status;"trash"===s&&t?(window.removeChildren(this.ui.bulk.action),e=window.jvbTemplates.create("trashOptions")):"trash"===s||t||(window.removeChildren(this.ui.bulk.action),e=window.jvbTemplates.create("notTrashOptions")),e&&e.querySelectorAll("option").forEach((e,t)=>{0===t&&(e.checked=!0),this.ui.bulk.action.append(e)}),this.ui.bulk.action.value=""}this.selected.size>0&&this.selectionHandler.updateSelectionUI()}renderEmpty(){this.toggleTable(!1),window.removeChildren(this.ui.grid);const e=window.jvbTemplates.create("emptyState");e&&(this.ui.grid.append(e),this.a11y.announceItems(0,!1,!1))}toggleTable(e=!0){if(this.ui.table.selectedColumns&&(this.ui.table.selectedColumns.hidden=!e),e&&!this.ui.table.form){let e=window.jvbTemplates.create("contentTable");this.container.append(e),this.ui.table=window.uiFromSelectors(this.selectors.table),this.ui.table.columns=this.container.querySelectorAll(this.selectors.table.columns)}this.ui.table.form&&(this.ui.table.form.hidden=!e,e||this.forms.clearForm(this.ui.table.form.dataset.formId),this.ui.table.body&&window.removeChildren(this.ui.table.body)),this.keyHandler=this.handleKeys.bind(this),e?document.addEventListener("keydown",this.keyHandler):document.removeEventListener("keydown",this.keyHandler)}renderGrid(e){window.removeChildren(this.ui.grid),this.toggleTable(!1),this.ui.grid.classList.remove("list-view"),this.ui.grid.classList.add("grid-view"),window.chunkIt(e,e=>this.renderGridItem(e),e=>this.ui.grid.append(e)).then(()=>{})}renderList(e){window.removeChildren(this.ui.grid),this.toggleTable(!1),this.ui.grid.classList.remove("grid-view"),this.ui.grid.classList.add("list-view"),window.chunkIt(e,e=>this.renderListItem(e),e=>this.ui.grid.append(e)).then(()=>{})}async renderTable(e){this.toggleTable(),window.removeChildren(this.ui.grid),await window.chunkIt(e,e=>this.renderTableItem(e),e=>{this.ui.table.body?this.ui.table.body.append(e):this.ui.table.table.insertBefore(e,this.ui.table.foot)},5),requestAnimationFrame(()=>{window.jvbSelector?.scanExistingFields(this.ui.table.table)})}renderGridItem(e){let t=window.jvbTemplates.create("gridView",e);return this.items.set(e.id,t),t}renderListItem(e){let t=window.jvbTemplates.create("listView",e);return this.items.set(e.id,t),t}renderTableItem(e){let t=window.jvbTemplates.create("tableView",e);return this.items.set(e.id,t),t}toggleColumn(e,t){this.ui.table.table.querySelectorAll(`.${e}`).forEach(e=>{e.hidden=!t})}handleGroupsUploaded(e){const{posts:t,fieldId:s}=e;let i=window.jvbUploads,a=(i.fields.get(s),[]);t.forEach(e=>{const t={id:e.groupId,title:e.fields.post_title||`New ${this.singular}`,status:"draft",date:(new Date).toISOString(),modified:(new Date).toISOString(),thumbnail:null,icon:this.content,taxonomies:{},fields:e.fields,images:{}};e.images.forEach((e,s)=>{let a=e.upload_id;0===s&&(t.fields.post_thumbnail=e);let l=i.stores.uploads.get(a);l&&(t.images[a]={"image-alt-text":"","image-caption":"","image-title":l.fields.originalName,medium:i.createPreviewUrl(i.formatFile(l))})}),a.push(t)}),this.store.saveMany(a).then(()=>this.render()),this.a11y.announce(`${t.length} ${1===t.length?this.singular:this.plural} created. Waiting for server confirmation...`)}handleGroupMappings(e){for(const[t,s]of Object.entries(e)){let e={};this.changes.has(t)&&(e=this.changes.get(t),this.changes.delete(t));let i=this.changesStore.get(t)??{};(e.size>0||i.size>0)&&(e=window.deepMerge(i,e),this.changes.set(s,e),this.scheduleBackup())}}shouldRemoveItemUI(e){return"all"===this.status&&!["publish","draft"].includes(e)||e!==this.store.filters.status}removeItems(e){e.forEach(e=>{if(this.items.has(e)){let t=this.items.get(e);t&&window.fade(t,!1)}})}setFilters(e){for(let[t,s]of Object.entries(e)){if(!this.allowedFilters.includes(t)){delete e[t];continue}this.cache.set(t,s);let i=this.findFilterEl(t);this.setElValue(i,s)}this.store.setFilters(e)}setFilter(e,t){if(!this.allowedFilters.includes(e))return;this.cache.set(e,t),"status"===e&&(this.status=t),"orderby"===e&&(this.orderby=t),"order"===e&&(this.order=t);let s=this.findFilterEl(e,t);this.setElValue(s,t),this.store.setFilter(e,t)}deleteFilter(e,t){if(!this.allowedFilters.includes(e))return;if(Object.hasOwn(this.defaults,e))return void this.setFilter(e,this.defaults[e]);let s=this.findFilterEl(e,t);this.setElValue(s,!1),this.cache.remove(e),this.setFilter(e,"")}setElValue(e,t){if(e){if(!t)return["SELECT","TEXTAREA"].includes(e.tagName)&&(e.value=""),["text","search"].includes(e.type)&&(e.value=""),void("radio"===e.type&&(e.checked=!1));["SELECT","TEXTAREA"].includes(e.tagName)&&(e.value=t),["text","search"].includes(e.type)&&(e.value=t),"radio"===e.type&&(e.checked=!0)}}findFilterEl(e,t){if(["date-filter","dateFrom","dateTo"].includes(e)){switch(e){case"date-filter":e="month";break;case"dateFrom":e="start";break;case"dateTo":e="end"}return this.ui.modals.date[e]}if(e.includes("tax_")){const t=e.replace("tax_",""),s=this.ui.filters.taxonomies?.[t];return s||(console.warn("Taxonomy filter element not found:",t),null)}if(!Object.hasOwn(this.ui.filters,e))return console.warn("Filter el not found: ",e),!1;let s=this.ui.filters[e];if("object"==typeof s){if(!Object.hasOwn(this.ui.filters[e],t))return!1;s=this.ui.filters[e][t]}return s}resetForm(e){e.querySelectorAll('input[type="hidden"], input[type="text"], input[type="number"], input[type="email"], input[type="url"], textarea').forEach(e=>{e.value=""}),e.querySelectorAll('input[type="checkbox"], input[type="radio"]').forEach(e=>{e.checked=!1}),e.querySelectorAll("select").forEach(e=>{e.selectedIndex=0}),e.querySelectorAll(".selected-items").forEach(e=>{window.removeChildren(e)}),e.querySelectorAll(".item-grid.preview").forEach(e=>{window.removeChildren(e)})}destroy(){window.debouncer.cancel(`changes-${this.content}`),this.changes.size>0&&(this.changesStore.saveMany(this.changes).then(()=>{}),this.changes.clear()),this.timelineSortables&&(this.timelineSortables.forEach(e=>e.destroy()),this.timelineSortables=[]);for(let[e,t]of Object.entries(this.ui.modals))t.form&&t.form.removeEventListener("submit",this.submitHandler);document.removeEventListener("click",this.clickHandler),document.removeEventListener("change",this.changeHandler),this.ui.filters.search&&this.ui.filters.search.removeEventListener("input",this.handleInput)}}document.addEventListener("DOMContentLoaded",async function(){window.auth.subscribe(t=>{if("auth-loaded"===t){let t=document.querySelector("[data-content]");t&&!Object.hasOwn(t.dataset,"ignore")&&(window.crudManager=new e({content:t.dataset.content}))}})})})();
\ No newline at end of file
+(()=>{class e{constructor(){this.container=document.querySelector(".crud[data-content]:not([data-ignore])"),this.container&&(this.content=this.container.dataset.content,this.endpoint=this.container.dataset.endpoint??"content",this.singular=this.container.dataset.singular,this.plural=this.container.dataset.plural,this.queue=window.jvbQueue,this.a11y=window.jvbA11y,this.error=window.jvbError,this.populate=window.jvbPopulate,this.cache=new window.jvbCache(this.content),this.activeItem=null,this.isTimeline=!1,this.isPopulating=!1,this.changes=new Map,this.items=new Map,this.init())}init(){this.initElements(),this.initListeners(),this.defineTemplates();let e=this.initSettings();this.initStore(e),this.checkHideFilters(),this.initIntegrations(),this.initUploader(),this.initModals()}defineTemplates(){const e=window.jvbTemplates,t=this,s=(e,s,i)=>{e.dataset.itemId=i.id;let a=s.checkbox.closest(".preview");window.prefixInput(s.checkbox,`select-${i.id}`,a,!0),s.checkbox.value=i.id,s.checkbox.checked=t.selected.has(parseInt(i.id)),s.selectLabel&&(s.selectLabel.htmlFor=`select-${i.id}`),s.edit&&(s.edit.dataset.id=i.id),s.trash&&(s.trash.dataset.id=i.id)},i=function(e,t,s){let i=s?.fields?.post_thumbnail||s?.fields?.thumbnail;if(i){const e=s.images[i]??{};t.img.src=e.medium??"",t.img.alt=e.alt??s.fields.post_title??""}};e.define("gridView",{refs:{img:"img",checkbox:".select-item",selectLabel:"label.select-item-label",edit:'[data-action="edit"]',trash:'[data-action="trash"]'},setup({el:e,refs:t,manyRefs:a,data:l}){s(e,t,l),i(0,t,l)}}),e.define("listView",{refs:{img:"img",checkbox:".select-item",selectLabel:"label.select-item-label",edit:'[data-action="edit"]',trash:'[data-action="trash"]'},manyRefs:{attrs:"[data-attr]",fields:"[data-field]"},setup({el:e,refs:t,manyRefs:a,data:l}){s(e,t,l),i(0,t,l),a?.attrs?.forEach(e=>{const t=l[e.dataset.attr];t&&""!==t?e.textContent=t:e.remove()}),a?.fields?.forEach(e=>{const t=l.fields?.[e.dataset.field];t&&""!==t?"DIV"===e.tagName?e.innerHTML=t:e.textContent=t:e.remove()})}});let a={};this.isTimeline&&(a.sharedRow="tr.shared",a.point="tr.timeline-point"),e.define("tableView",{refs:{checkbox:".select-item",selectLabel:"label.select-item-label",...a},manyRefs:{inputs:"input,select,textarea",status:'input[name="post_status"]',selectors:'[data-type="selector"]',fields:"[data-field]"},setup({el:e,refs:i,manyRefs:a,data:l}){if(s(e,i,l),a?.inputs?.forEach(e=>{let t=e.closest("[data-field]");window.prefixInput(e,`${l.id}-`,t)}),a?.status?.forEach(e=>{e.value===l.status&&(e.checked=!0)}),t.isTimeline)i.sharedRow&&(i.sharedRow.querySelectorAll("input,select,textarea").forEach(e=>{let t=e.closest("[data-field]");window.prefixInput(e,`${l.id}-`,t)}),t.populate.populate(i.sharedRow,l),i.sharedRow.querySelectorAll('input[name="post_status"]').forEach(e=>{e.value===l.status&&(e.checked=!0)})),i.point&&l.fields?.timeline&&(Object.entries(l.fields.timeline).forEach(([s,a],n)=>{const o=i.point.cloneNode(!0);o.dataset.index=`${n}`,o.dataset.itemId=a.id,o.querySelectorAll("input,select,textarea").forEach(e=>{let t=e.closest("[data-field]");window.prefixInput(e,`${a.id}-`,t)}),t.populate.populate(o,{fields:a,images:l.images,taxonomies:l.taxonomies});const r=l.images?.[a.post_thumbnail];r&&o.querySelector(".field.upload")?.setAttribute("title",r["image-title"]??""),e.insertBefore(o,i.point)}),i.point.remove());else if(void 0!==t.ui.table.form?.dataset.edit)a?.inputs?.forEach(e=>{let t=e.closest("[data-field]");window.prefixInput(e,`${l.id}-`,t)}),a?.status?.forEach(e=>{e.value===l.status&&(e.checked=!0)}),t.populate.populate(e,l);else{const e=Object.hasOwn(l,"fields")?l.fields:l;a?.fields?.forEach(t=>{if(Object.hasOwn(e,t.dataset.field)&&""!==e[t.dataset.field]){let s=e[t.dataset.field],i=e.children[0];i&&(i.textContent="date"===t.dataset.field?window.formatTimeAgo(s):s)}})}a?.selectors?.forEach(e=>e.setAttribute("data-lazy",""))}}),e.define("emptyState"),e.define("bulkItem",{refs:{checkbox:"input",img:"img",label:"label"},setup({el:e,refs:t,manyRefs:s,data:i}){t.checkbox&&(t.checkbox.id=`bulk_${i.id}`,t.checkbox.value=i.id,t.checkbox.checked=!0,t.checkbox.name="selected[]");let a=i?.images[i?.fields?.post_thumnbail]??{};t.img&&Object.keys(a).length>0&&(t.img.src=a.medium??"",t.img.alt=a.alt??""),t.label&&(t.label.title=item.fields.post_title)}}),e.define("trashOptions"),e.define("notTrashOptions"),e.define("contentTable")}initElements(){this.allowedFilters=["status","orderby","order","search","date-filter","dateFrom","dateTo"],this.selectors={buttons:{create:".create-item",clearFilters:'[data-action="clear-filters"]'},views:{grid:'input[data-view="grid"]',list:'input[data-view="list"]',table:'input[data-view="table"]'},modals:{create:{modal:"dialog.create",form:"dialog.create form",h2:"dialog.create h2"},edit:{modal:"dialog.edit",form:"dialog.edit form",h2:"dialog.edit h2"},bulkEdit:{modal:"dialog.bulkEdit",selected:"dialog.bulkEdit .selected",h2:"dialog.bulkEdit h2 span",form:"dialog.bulkEdit form"},date:{modal:"dialog.date-range",start:"dialog.date-range .date-start",end:"dialog.date-range .date-end",month:"dialog.date-range .month-select"}},grid:`.${this.content}.item-grid`,table:{nav:"#vertical",form:"form.table",table:"form.table table",body:"form.table body",head:"form.table thead",foot:"form.table tfoot",selectedColumns:".all-filters .multi-select",columns:"thead th"},bulk:{action:".bulk-action-select",count:".bulk-controls .selected-count",control:".bulk-controls .bulk-actions",select:".bulk-controls select",selectAll:".select-all"},filters:{container:"details.all-filters",search:'.all-filters input[type="search"]',status:{all:'[name="status"]#all',publish:'[name="status"]#publish',draft:'[name="status"]#draft',trash:'[name="status"]#trash'},orderby:{date:'[name="orderby"]#date',alphabetical:'[name="orderby"]#alphabetical'},order:{asc:'[name="order"][value="asc"]',desc:'[name="order"][value="desc"]'},date:'[data-filter="date"]'},uploader:{details:"details.uploader",form:"details.uploader form",uploader:'details.uploader [data-field-type="upload"]'}},this.ui=window.uiFromSelectors(this.selectors);const e=document.querySelectorAll('[data-filter="taxonomies"]');e.length>0&&(this.ui.filters.taxonomies={},e.forEach(e=>{const t=e.dataset.taxonomy;this.ui.filters.taxonomies[t]=e,this.allowedFilters.push(`tax_${t}`)})),this.isTimeline=!!document.querySelector("[data-timeline]")}initUploader(){this.ui.uploader.form&&(this.uploadForm=this.forms.registerForm(this.ui.uploader.form).id??!1,window.jvbUploads.subscribe((e,t)=>{if("sent-to-queue"===e&&t.field.id===this.ui.uploader.uploader.dataset.uploader&&(this.uploadForm&&this.forms.store.delete(this.uploadForm),window.debouncer.schedule("crud-complete",()=>{this.store.clearCache()})),"sent-to-queue"===e&&t.field){const e=t.field.config.name,s=t.field.config.itemID;s&&e&&this.changes.has(s)&&delete this.changes.get(s)[e]}}))}initModals(){this.modals={};for(let[e,t]of Object.entries(this.ui.modals))t.modal&&(this.modals[e]=new window.jvbModal(t.modal),this.modals[e].subscribe((t,s)=>{if("modal-close"===t){const t=this.ui.modals[e].form.dataset.formId;t&&this.forms.clearForm(t),this.resetForm(this.ui.modals[e].form),"date"===e&&this.handleCustomDateSelection(),["edit","bulkEdit","create"].includes(e)&&window.debouncer.timeouts.has(`save-${this.content}`)&&this.scheduleSave(0)}}))}initStore(e){let t={...this.defaults,...e};const s=window.jvbStore.register(this.content,[{storeName:this.content,keyPath:"id",endpoint:this.endpoint??"content",headers:{"X-Action-Nonce":window.auth.getNonce("dash")},indexes:[{name:"id",keyPath:"id"},{name:"status",keyPath:"status"},{name:"date",keyPath:"date"},{name:"modified",keyPath:"modified"},{name:"title",keyPath:"title"}],isAuth:!0,filters:t,ignore:["content","user"],TTL:36e5,showLoading:!0},{storeName:"changes",keyPath:"id"}]);this.changesStore=s.changes,this.store=s[this.content],this.store.subscribe((e,t)=>{if("data-loaded"===e)this.render(),this.selectionHandler.collectItems()}),this.changesStore.subscribe((e,t)=>{if("data-ready"===e){let e=this.changesStore.getAll();e.length>0&&(e.forEach(e=>{this.changes.set(e.id,e)}),this.savePosts("",!1).then(()=>{}))}})}initIntegrations(){this.selected=new Set,this.selectionHandler=new window.jvbHandleSelection(this.container,{selectAll:{checkbox:"#select-all",label:".bulk-select label",span:".bulk-select label span"},wrapper:{wrapper:".wrap"},item:{idAttribute:"itemId"}}),this.selectionHandler.subscribe((e,t)=>{this.selected=new Set([...t.selectedItems].map(e=>parseInt(e))),this.ui.bulk.control.hidden=0===this.selected.size,this.ui.bulk.count.hidden=0===this.selected.size,this.ui.bulk.count.textContent=`${this.selected.size} ${this.plural} selected`}),this.forms=window.jvbForm,window.jvbUploads&&window.jvbUploads.subscribe((e,t)=>{"groups_uploaded"===e&&t.content===this.content&&this.handleGroupsUploaded(t)}),this.queue.subscribe((e,t)=>{if(["image_upload","video_upload","document_upload"].includes(t.type)&&"operation-status"===e&&"completed"===t.status&&this.store.clearCache(),"operation-status"===e&&"completed"===t.status&&"uploads/groups"===t.endpoint&&(t.result&&t.result.group_mappings&&(console.log("Handling group mapping from queue response"),this.handleGroupMappings(t.result.group_mappings)),this.store.clearCache()),"operation-status"===e&&"completed"===t.status&&"content_update"===t.type){if(this.store.clearCache(),!t.result||!t.result.success||!t.result.errors)return void console.warn("Content update completed but no results",t);if(Object.keys(t.result.success).length>0&&this.checkCompletedChanges(Object.entries(t.result.success)),Object.keys(t.result.errors).length>0)return void this.checkFailedChanges(Object.entries(t.result.errors));0===Object.keys(t.result.success).length&&(console.log(t.result.success),t.result.success.forEach(e=>this.changesStore.delete(e)),this.store.clearCache())}if("sent-to-server"===e&&"content_update"===t.type){if(t instanceof FormData)return;for(let[e,s]of Object.entries(t.posts))this.compareStored(e,s)}})}checkCompletedChanges(e){for(let[t,s]of e)this.compareStored(t,s)}compareStored(e,t){let s=this.changesStore.get(e);if(!s)return;for(let[e,i]of Object.entries(t))if(Object.hasOwn(s,e)){let t=window.getDifferences.map(s[e],i);t?s[e]=t:delete s[e]}let i=Object.hasOwn(s,"id"),a=Object.hasOwn(s,"content");i&&a&&2===Object.keys(s).length||(i||a)&&1===Object.keys(s).length||0===Object.keys(s).length?(this.changesStore.delete(e),this.store.clearCache()):this.changesStore.save(s)}checkFailedChanges(e){}initSettings(){this.defaults={content:this.content,user:window.auth.getUser(),page:1,status:"all",orderby:"date",order:"desc",search:""};let e={},t=this.container.dataset.view??"grid";this.view=this.cache.get("view")??t,this.view!==t&&(this.ui.views[this.view].checked=!0),this.status=this.cache.get("status")??this.defaults.status,this.status!==this.defaults.status&&(this.ui.filters.status[this.status].checked=!0,e.status=this.status),this.orderby=this.cache.get("orderby")??this.defaults.orderby,this.orderby!==this.defaults.orderby&&(this.ui.filters.orderby[this.orderby].checked=!0,e.orderBy=this.orderby),this.order=this.cache.get("order")??this.defaults.order,this.order!==this.defaults.order&&(this.ui.filters.order[this.order].checked=!0,e.order=this.order),this.ui.filters.taxonomies&&Object.entries(this.ui.filters.taxonomies).forEach(([t,s])=>{const i=`tax_${t}`,a=this.cache.get(i);a&&(s.value=a,e[i]=a)});let s=this.cache.get("tabNav")??"horizontal";this.ui.table.nav&&"vertical"===s&&(this.ui.table.nav.checked=!0);let i={showFilters:{element:this.ui.filters.container,default:"closed"},showUploader:{element:this.ui.uploader.details,default:"open"}};for(let[e,t]of Object.entries(i))if(t.element){let s=this.cache.get(e)??t.default;t.element.open="open"===s,t.element.addEventListener("toggle",()=>{this.cache.set(e,t.element.open?"open":"closed")})}return e}initListeners(){this.changeHandler=this.handleChange.bind(this),this.clickHandler=this.handleClick.bind(this),this.inputHandler=this.handleInput.bind(this),this.submitHandler=this.handleModalSubmit.bind(this),document.addEventListener("change",this.changeHandler),document.addEventListener("click",this.clickHandler),this.ui.filters.search&&this.ui.filters.search.addEventListener("input",this.inputHandler);for(let[e,t]of Object.entries(this.ui.modals))t.form&&t.form.addEventListener("submit",this.submitHandler)}handleModalSubmit(e){e.preventDefault();const t=e.target.closest("dialog");if(!t)return;if(t.classList.contains("create"))return void this.handleCreateSubmit(t);this.plural;this.scheduleSave(0),this.modals.edit.handleClose()}async handleCreateSubmit(e){e.dataset.itemId;this.changes.size>0&&(this.cancelBackup(),await this.handleBackup());const t=await this.changesStore.getAll();if(0===t.length)return;let s={};t.forEach(e=>{const{id:t,...i}=e;s[t]=i});let i=this.queue.addToQueue({endpoint:this.endpoint,headers:{"X-Action-Nonce":window.auth.getNonce("dash")},data:{posts:s},popup:`Creating your new ${this.singular}`,title:`Creating your new ${this.singular}`});if(!i)return;const a=e.querySelectorAll("[data-upload-field]");for(const e of a){const t=e.dataset.uploader;if(!t)continue;0!==window.jvbUploads.stores.uploads.filterByIndex({field:t}).length&&await window.jvbUploads.queueUploads("uploads",t,i)}}handleChange(e){const t=e.target.closest("[data-item-id]"),s=e.target.matches("[data-filter]"),i=e.target.matches(".bulk-action-select"),a=e.target.matches("[data-view]");if(t||s||i||a)if(this.isPopulating||!t||e.target.closest("[data-ignore], .select-item")){if(a)return this.items.clear(),void this.handleViewChange(e.target);if(i)this.handleBulkAction(e.target);else if(s)this.handleFilterChange(e.target);else if("table"===this.view){if(e.target.matches("details.multi-select"))return void this.toggleColumn(e.target.id,e.target.checked);e.target.matches(this.selectors.table.nav)&&(this.tabNav=e.target.checked,this.cache.set("tabNav",e.target.checked?"vertical":"horizontal"))}}else this.handleItemUpdate(e)}handleBulkAction(e){if(e.value.startsWith("tax-")){const t=e.options[e.selectedIndex],s=t.dataset.taxonomy,i=t.dataset.single,a=t.dataset.plural;return window.jvbSelector.openEmpty(s,i,a,e=>this.handleBulkTaxonomy(e)),void(e.value="")}switch(e.value){case"edit":this.openBulkEditModal();break;case"publish":case"trash":case"delete":this.setBulkStatus(e.value);break;case"draft":case"restore":this.setBulkStatus("draft")}}handleBulkTaxonomy(e){e.termIds.length&&this.selected.size&&(this.selected.forEach(t=>{const s=this.store.get(t);if(!s)return;const i=(s.taxonomies?.[e.taxonomy]||[]).map(e=>e.id),a=[...new Set([...i,...e.termIds])];this.updateItem(t,e.taxonomy,a)}),this.savePosts(`Adding ${e.terms.length} ${e.taxonomy} to ${this.selected.size} ${this.plural}...`).then(()=>{}),this.selectionHandler.clearSelection())}handleItemUpdate(e){let t=window.targetCheck(e,"[data-item-id]");if(!t)return;const s=e.target.closest('[data-field-type="repeater"], [data-field-type="tag-list"]');let i,a;if(s)i=s.dataset.field,a=this.forms.getFieldValue(s);else{let t=e.target.closest("[data-field]");i=t.dataset.field,a=this.forms.getFieldValue(e.target)}t.dataset.itemId.split(",").forEach(e=>{this.updateItem(e,i,a)})}updateItem(e,t,s){if(this.isPopulating)return;t.replace(`[${e}]`,"");const i=this.store.get(e);if(i){const a=i.fields?.[t]??i[t];if(null===window.getDifferences.map(a,s)){if(this.changes.has(e)){delete this.changes.get(e)[t];0===Object.keys(this.changes.get(e)).filter(e=>"id"!==e&&"content"!==e).length&&(this.changes.delete(e),this.changesStore.delete(e))}return}}this.changes.has(e)||this.changes.set(e,{id:e,content:this.content}),this.changes.get(e)[t]=s,this.scheduleBackup(),"number"!=typeof e&&String(e).includes("group")||this.scheduleSave()}scheduleBackup(){window.debouncer.schedule(`changes-${this.content}`,async()=>{this.changes.size>0&&await this.handleBackup()},2e3)}cancelBackup(){window.debouncer.cancel(`changes-${this.content}`)}async handleBackup(){const e=Array.from(this.changes.values());this.changes.clear();const t=e.map(e=>e.id),s=await Promise.all(t.map(e=>this.changesStore.get(e))),i=e.map((e,t)=>s[t]?window.deepMerge(s[t],e):e);await this.changesStore.saveMany(i)}scheduleSave(e=1e4){window.debouncer.schedule(`save-${this.content}`,async()=>{this.changes.size>0&&(this.cancelBackup(),await this.handleBackup()),await this.savePosts("",!1)},e)}handleFilterChange(e){let t=e.dataset.filter;return"date"===t&&"custom"===e.value?(e.value="",void this.modals.date.handleOpen()):"date"===t&&""!==e.value?(this.setFilter("date-filter",e.value),this.deleteFilter("dateFrom"),this.deleteFilter("dateTo"),void this.checkHideFilters()):("taxonomies"===t&&(t=`tax_${e.dataset.taxonomy}`),void this.setFilter(t,e.value))}checkHideFilters(){const e=this.store.filters,t=Object.entries(e).some(([e,t])=>!["content","user","page"].includes(e)&&(this.defaults[e]!==t&&""!==t&&null!==t));this.ui.buttons.clearFilters.hidden=!t}clearAllFilters(){let e=this.store.filters;this.store.clearFilters();for(let[t,s]of Object.entries(e))this.cache.remove(t),this.deleteFilter(t,s);this.a11y.announce("All filters cleared")}handleCustomDateSelection(){if(this.ui.modals.date.month&&this.ui.modals.date.month.value){const[e,t]=this.ui.modals.date.month.value.split("-"),s=`${e}-${t}-01`,i=new Date(e,parseInt(t),0).getDate(),a=`${e}-${t}-${String(i).padStart(2,"0")}`;this.setFilter("dateFrom",s),this.setFilter("dateTo",a),this.deleteFilter("date-filter"),this.ui.modals.date.month.value=""}else this.ui.modals.date.start&&this.ui.modals.date.start.value&&this.ui.modals.date.end&&this.ui.modals.date.end.value&&(this.setFilter("dateFrom",this.ui.modals.date.start.value),this.setFilter("dateTo",this.ui.modals.date.end.value),this.deleteFilter("date-filter"),this.ui.modals.date.start.value="",this.ui.modals.date.end.value="");this.checkHideFilters()}handleViewChange(e){this.view=e.dataset.view,this.cache.set("view",this.view),this.render()}handleClick(e){if(e.target.matches(".clear-search"))return void this.deleteFilter("search","");const t=e.target.closest("[data-action]");return t?(e.preventDefault(),void this.handleActionButton(t)):e.target.matches(".apply-date-filter")?(this.handleCustomDateSelection(),void this.modals.date.handleClose()):void((e.target.matches(this.selectors.buttons.create)||e.target.closest(this.selectors.buttons.create))&&this.openCreateModal())}openCreateModal(){this.forms.registerForm(this.ui.modals.create.form,{cache:!1}),this.ui.modals.create.modal.dataset.itemId=window.generateID("new"),this.modals.create.handleOpen()}handleActionButton(e){const t=e.dataset.id;switch(e.dataset.action){case"edit":this.openEditModal(t);break;case"delete":confirm("Delete this item? This cannot be undone")&&(this.updateItem(t,"post_status","delete"),window.fade(e.closest(".item"),!1),this.savePosts(`Permanently deleting ${this.singular}...`).then(()=>{}),this.store.delete(t));break;case"trash":"trash"===this.status?confirm("Delete this item? This cannot be undone")&&(this.updateItem(t,"post_status","delete"),window.fade(e.closest(".item"),!1),this.savePosts(`Permanently deleting ${this.singular}...`).then(()=>{}),this.store.delete(t)):(this.updateItem(t,"post_status","trash"),window.fade(e.closest(".item"),!1),this.savePosts(`Sending ${this.singular} to trash...`).then(()=>{}));break;case"bulk-edit":this.selected.size>0&&this.openBulkEditModal();break;case"bulk-delete":this.handleBulkDelete();break;case"refresh":this.store.clearCache(),this.store.fetch();break;case"clear-filters":this.clearAllFilters()}}handleBulkDelete(){let e="trash"===this.status;if(this.selected.size>0&&confirm(`${e?"Permanently delete":"Send"} ${this.selected.size} ${1===this.selected.size?this.singular:this.plural}${e?"":"to trash"}?`)){this.selected.forEach(t=>{this.store.delete(t),this.updateItem(t,"post_status",e?"delete":"trash")});let t=e?`Permanently deleting ${this.selected.size} ${1===this.selected.size?this.singular:this.plural}`:`Sending ${this.selected.size} ${1===this.selected.size?this.singular:this.plural} to trash`;this.savePosts(t).then(()=>{}),this.selectionHandler.clearSelection()}}handleInput(e){e.preventDefault(),e.stopPropagation();let t=e.target.value.trim(),s=`${this.content}-search`;0!==t.length?window.debouncer.schedule(s,()=>{this.a11y.announce(`Searching for "${t}"...`),this.store.setFilters({search:t,page:1})},300):this.deleteFilter("search","")}handleKeys(e){if(this.tabNav&&"Tab"===e.key){e.preventDefault();const t=e.target.closest("[data-field]"),s=e.target.closest("tr");if(!t||!s)return;const i=t.dataset.field,a=e.shiftKey;let l=this.findNextEditableRow(s,a);l||(l=this.wrapToRow(s,a)),l&&this.focusFieldInRow(l,i,a)}}findNextEditableRow(e,t=!1){let s=t?e.previousElementSibling:e.nextElementSibling;for(;s&&!this.isEditableRow(s);)s=t?s.previousElementSibling:s.nextElementSibling;return s}wrapToRow(e,t=!1){if(this.isTimeline){const s=e.closest("tbody");if(!s)return null;const i=Array.from(s.querySelectorAll("tr")).filter(e=>this.isEditableRow(e));return t?i[i.length-1]:i[0]}{if(!this.ui.table.body)return null;const e=Array.from(this.ui.table.body.querySelectorAll("tr")).filter(e=>this.isEditableRow(e));return t?e[e.length-1]:e[0]}}isEditableRow(e){return!e.closest("thead")&&!e.closest("tfoot")&&(this.isTimeline?e.classList.contains("shared")||e.classList.contains("timeline-point"):!!e.dataset.itemId)}focusFieldInRow(e,t,s=!1){const i=e.querySelector(`[data-field="${t}"]`);if(!i)return;const a=this.findFocusableInput(i);if(a){a.focus(),a.select&&"text"===a.type&&a.select();const e=s?"next":"previous";this.a11y?.announce(`Moved to ${t} in ${e} row`)}}findFocusableInput(e){const t=['input:not([type="hidden"]):not([disabled])',"textarea:not([disabled])","select:not([disabled])","button:not([disabled])"];for(const s of t){const t=e.querySelector(s);if(t)return t}return null}openEditModal(e){let t,s=this.store.get(parseInt(e));s&&(this.activeItem=s.id,this.ui.modals.edit.modal.dataset.itemId=e,this.ui.modals.edit.modal.dataset.content=this.content,Object.hasOwn(s.fields,"post_title")?t=s.fields.post_title:Object.hasOwn(s.fields,"name")&&(t=s.fields.name),this.ui.modals.edit.h2.textContent=`Editing ${""===t?this.singular:t}`,this.ui.modals.edit.form.dataset.formId=`edit-${e}`,this.isPopulating=!0,this.modals.edit.handleOpen(),this.forms.registerForm(this.ui.modals.edit.form,{cache:!1,autoUpload:!0}),this.populate.populate(this.ui.modals.edit.form,s),requestAnimationFrame(()=>{requestAnimationFrame(()=>{setTimeout(()=>{this.isPopulating=!1},50)})}))}openBulkEditModal(){window.removeChildren(this.ui.modals.bulkEdit.selected),this.ui.modals.edit.form.reset(),window.chunkIt(this.selected,t=>{let s=this.store.get(parseInt(t));if(s)return e.push(s.id),window.jvbTemplates.create("bulkItem",s)},e=>this.ui.modals.bulkEdit.selected.append(e)).then(()=>{});let e=Array.from(this.selected).map(e=>this.store.get(parseInt(e))).filter(Boolean);this.ui.modals.bulkEdit.modal.dataset.itemId=e.join(","),this.ui.modals.bulkEdit.h2&&(this.ui.modals.bulkEdit.h2.textContent=this.selected.size),this.modals.bulkEdit.handleOpen(),this.forms.registerForm(this.ui.modals.bulkEdit.form,{cache:!1}),this.isPopulating=!0,this.populate.populate(this.ui.modals.edit.form,item),requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.isPopulating=!1})})}async savePosts(e="",t=!1){this.changes.size>0&&(this.cancelBackup(),await this.handleBackup());let s=await this.changesStore.getAll();if(0===s.length)return;if(s=this.validateChanges(s),0===s.length)return;""===e&&(e=`Saving ${s.length} ${1===s.length?this.singular:this.plural}`);let i={},a=[];s.forEach(e=>{let t=e.id;const{id:s,...l}=e;i[t]=l,e.post_status&&this.shouldRemoveItemUI(e.post_status)&&a.push(t)}),a.length>0&&this.removeItems(a);let l={endpoint:this.endpoint,headers:{"X-Action-Nonce":window.auth.getNonce("dash")},data:{posts:i},delay:t,popup:"Saving changes",title:e};this.queue.addToQueue(l)}validateChanges(e){return e.reduce((e,t)=>{const{id:s,content:i,...a}=t,l=this.store.get(s);if(!l)return e.push(t),e;const n={id:s,content:i};let o=!1;for(const[e,t]of Object.entries(a)){const s=l.fields?.[e]??l[e];null!==window.getDifferences.map(s,t)&&(n[e]=t,o=!0)}return o?e.push(n):(this.changes.delete(s),this.changesStore.delete(s)),e},[])}setBulkStatus(e){if(!["publish","draft","trash","delete"].includes(e))return;let t,s=[];if(this.selected.forEach(t=>{s.push(t),this.updateItem(t,"post_status",e)}),"delete"===e)t="Deleting";else t=window.uppercaseFirst(e)+"ing";this.shouldRemoveItemUI(e)&&this.removeItems(s),this.selectionHandler.clearSelection(),this.savePosts(`${t} ${s.length} ${1===s.length?this.singular:this.plural}...`).then(()=>{})}render(){const e=this.store.getFiltered();if(0!==e.length){switch(this.view){case"grid":this.renderGrid(e);break;case"table":this.renderTable(e).then(()=>{});break;case"list":this.renderList(e)}this.updateUI()}else this.renderEmpty()}updateUI(){if(this.ui.bulk.action){let e=!1,t=this.ui.bulk.action.querySelector('[value="edit"]'),s=this.status;"trash"===s&&t?(window.removeChildren(this.ui.bulk.action),e=window.jvbTemplates.create("trashOptions")):"trash"===s||t||(window.removeChildren(this.ui.bulk.action),e=window.jvbTemplates.create("notTrashOptions")),e&&e.querySelectorAll("option").forEach((e,t)=>{0===t&&(e.checked=!0),this.ui.bulk.action.append(e)}),this.ui.bulk.action.value=""}this.selected.size>0&&this.selectionHandler.updateSelectionUI()}renderEmpty(){this.toggleTable(!1),window.removeChildren(this.ui.grid);const e=window.jvbTemplates.create("emptyState");e&&(this.ui.grid.append(e),this.a11y.announceItems(0,!1,!1))}toggleTable(e=!0){if(this.ui.table.selectedColumns&&(this.ui.table.selectedColumns.hidden=!e),e&&!this.ui.table.form){let e=window.jvbTemplates.create("contentTable");this.container.append(e),this.ui.table=window.uiFromSelectors(this.selectors.table),this.ui.table.columns=this.container.querySelectorAll(this.selectors.table.columns)}this.ui.table.form&&(this.ui.table.form.hidden=!e,e||this.forms.clearForm(this.ui.table.form.dataset.formId),this.ui.table.body&&window.removeChildren(this.ui.table.body)),this.keyHandler=this.handleKeys.bind(this),e?document.addEventListener("keydown",this.keyHandler):document.removeEventListener("keydown",this.keyHandler)}renderGrid(e){window.removeChildren(this.ui.grid),this.toggleTable(!1),this.ui.grid.classList.remove("list-view"),this.ui.grid.classList.add("grid-view"),window.chunkIt(e,e=>this.renderGridItem(e),e=>this.ui.grid.append(e)).then(()=>{})}renderList(e){window.removeChildren(this.ui.grid),this.toggleTable(!1),this.ui.grid.classList.remove("grid-view"),this.ui.grid.classList.add("list-view"),window.chunkIt(e,e=>this.renderListItem(e),e=>this.ui.grid.append(e)).then(()=>{})}async renderTable(e){this.toggleTable(),window.removeChildren(this.ui.grid),await window.chunkIt(e,e=>this.renderTableItem(e),e=>{this.ui.table.body?this.ui.table.body.append(e):this.ui.table.table.insertBefore(e,this.ui.table.foot)},5),requestAnimationFrame(()=>{window.jvbSelector?.scanExistingFields(this.ui.table.table)})}renderGridItem(e){let t=window.jvbTemplates.create("gridView",e);return this.items.set(e.id,t),t}renderListItem(e){let t=window.jvbTemplates.create("listView",e);return this.items.set(e.id,t),t}renderTableItem(e){let t=window.jvbTemplates.create("tableView",e);return this.items.set(e.id,t),t}toggleColumn(e,t){this.ui.table.table.querySelectorAll(`.${e}`).forEach(e=>{e.hidden=!t})}handleGroupsUploaded(e){const{posts:t,fieldId:s}=e;let i=window.jvbUploads,a=(i.fields.get(s),[]);t.forEach(e=>{const t={id:e.groupId,title:e.fields.post_title||`New ${this.singular}`,status:"draft",date:(new Date).toISOString(),modified:(new Date).toISOString(),thumbnail:null,icon:this.content,taxonomies:{},fields:e.fields,images:{}};e.images.forEach((e,s)=>{let a=e.upload_id;0===s&&(t.fields.post_thumbnail=e);let l=i.stores.uploads.get(a);l&&(t.images[a]={"image-alt-text":"","image-caption":"","image-title":l.fields.originalName,medium:i.createPreviewUrl(i.formatFile(l))})}),a.push(t)}),this.store.saveMany(a).then(()=>this.render()),this.a11y.announce(`${t.length} ${1===t.length?this.singular:this.plural} created. Waiting for server confirmation...`)}handleGroupMappings(e){for(const[t,s]of Object.entries(e)){let e={};this.changes.has(t)&&(e=this.changes.get(t),this.changes.delete(t));let i=this.changesStore.get(t)??{};(e.size>0||i.size>0)&&(e=window.deepMerge(i,e),this.changes.set(s,e),this.scheduleBackup())}}shouldRemoveItemUI(e){return"all"===this.status&&!["publish","draft"].includes(e)||e!==this.store.filters.status}removeItems(e){e.forEach(e=>{if(this.items.has(e)){let t=this.items.get(e);t&&window.fade(t,!1)}})}setFilters(e){for(let[t,s]of Object.entries(e)){if(!this.allowedFilters.includes(t)){delete e[t];continue}this.cache.set(t,s);let i=this.findFilterEl(t);this.setElValue(i,s)}this.store.setFilters(e)}setFilter(e,t){if(!this.allowedFilters.includes(e))return;this.cache.set(e,t),"status"===e&&(this.status=t),"orderby"===e&&(this.orderby=t),"order"===e&&(this.order=t);let s=this.findFilterEl(e,t);this.setElValue(s,t),this.store.setFilter(e,t)}deleteFilter(e,t){if(!this.allowedFilters.includes(e))return;if(Object.hasOwn(this.defaults,e))return void this.setFilter(e,this.defaults[e]);let s=this.findFilterEl(e,t);this.setElValue(s,!1),this.cache.remove(e),this.setFilter(e,"")}setElValue(e,t){if(e){if(!t)return["SELECT","TEXTAREA"].includes(e.tagName)&&(e.value=""),["text","search"].includes(e.type)&&(e.value=""),void("radio"===e.type&&(e.checked=!1));["SELECT","TEXTAREA"].includes(e.tagName)&&(e.value=t),["text","search"].includes(e.type)&&(e.value=t),"radio"===e.type&&(e.checked=!0)}}findFilterEl(e,t){if(["date-filter","dateFrom","dateTo"].includes(e)){switch(e){case"date-filter":e="month";break;case"dateFrom":e="start";break;case"dateTo":e="end"}return this.ui.modals.date[e]}if(e.includes("tax_")){const t=e.replace("tax_",""),s=this.ui.filters.taxonomies?.[t];return s||(console.warn("Taxonomy filter element not found:",t),null)}if(!Object.hasOwn(this.ui.filters,e))return console.warn("Filter el not found: ",e),!1;let s=this.ui.filters[e];if("object"==typeof s){if(!Object.hasOwn(this.ui.filters[e],t))return!1;s=this.ui.filters[e][t]}return s}resetForm(e){e.querySelectorAll('input[type="hidden"], input[type="text"], input[type="number"], input[type="email"], input[type="url"], textarea').forEach(e=>{e.value=""}),e.querySelectorAll('input[type="checkbox"], input[type="radio"]').forEach(e=>{e.checked=!1}),e.querySelectorAll("select").forEach(e=>{e.selectedIndex=0}),e.querySelectorAll(".selected-items").forEach(e=>{window.removeChildren(e)}),e.querySelectorAll(".item-grid.preview").forEach(e=>{window.removeChildren(e)})}destroy(){window.debouncer.cancel(`changes-${this.content}`),this.changes.size>0&&(this.changesStore.saveMany(this.changes).then(()=>{}),this.changes.clear()),this.timelineSortables&&(this.timelineSortables.forEach(e=>e.destroy()),this.timelineSortables=[]);for(let[e,t]of Object.entries(this.ui.modals))t.form&&t.form.removeEventListener("submit",this.submitHandler);document.removeEventListener("click",this.clickHandler),document.removeEventListener("change",this.changeHandler),this.ui.filters.search&&this.ui.filters.search.removeEventListener("input",this.handleInput)}}document.addEventListener("DOMContentLoaded",async function(){window.auth.subscribe(t=>{if("auth-loaded"===t){let t=document.querySelector("[data-content]");t&&!Object.hasOwn(t.dataset,"ignore")&&(window.crudManager=new e({content:t.dataset.content}))}})})})();
\ No newline at end of file
diff --git a/assets/js/min/gallery.min.js b/assets/js/min/gallery.min.js
index 2ecb486..82b3323 100644
--- a/assets/js/min/gallery.min.js
+++ b/assets/js/min/gallery.min.js
@@ -1 +1 @@
-(()=>{class e{constructor(){this.a11y=window.jvbA11y,this.index=0,this.images=[],this.zoom={scale:1,min:1,max:4,threshold:50,x:0,y:0,startX:0,startY:0,ease:.2,panning:!1},this.swipe=this.resetSwipe(),this.activePointers=new Map,this.lastTap=0,this.initElements(),this.initModal(),this.initListeners(),this.initSubscribers(),console.log("Gallery loaded...")}initElements(){this.elements={imageSelector:"img[data-gallery]",gallery:{modal:"dialog.gallery",wrap:".wrap",nextButton:".next",prevButton:".prev",image:".image",leftImage:".image-left",rightImage:".image-right",counter:".counter"}},this.ui=window.uiFromSelectors(this.elements)}initModal(){this.modal=new window.jvbModal(this.ui.gallery.modal,{openMessage:"Opened Gallery",closeMessage:"Closed Gallery"}),this.modal.subscribe(e=>{"modal-close"===e&&this.toggleGallery(!1)})}buildGalleryItems(e=null){let t=e?`[data-gallery="${e}"]`:this.elements.imageSelector;this.items=Array.from(document.querySelectorAll(t)).map((e,t)=>({id:e.dataset.id||t,srcset:e.srcset||e.src,sizes:e.sizes||"100vw",src:e.currentSrc||e.src,full:e.dataset.full||e.src,alt:e.alt||"",element:e}))}initListeners(){this.clickHandler=this.handleClick.bind(this),this.pointerDownHandler=this.onPointerDown.bind(this),this.pointerMoveHandler=this.onPointerMove.bind(this),this.pointerUpHandler=this.onPointerUp.bind(this),this.wheelHandler=this.onWheel.bind(this),this.keyHandler=this.handleKeys.bind(this),document.addEventListener("click",this.clickHandler)}handleClick(e){let t=window.targetCheck(e,this.elements.imageSelector);t&&!this.modal.isOpen?(e.preventDefault(),this.buildGalleryItems(t.dataset.gallery||null),this.index=this.items.findIndex(e=>e.element===t),this.toggleGallery(!0)):this.modal.isOpen&&(window.targetCheck(e,this.elements.gallery.nextButton)?(console.log("Next"),this.nextElement()):window.targetCheck(e,this.elements.gallery.prevButton)&&(console.log("Previous"),this.prevElement()))}handleKeys(e){if(this.modal.isOpen){switch(e.key){case"ArrowLeft":e.preventDefault(),this.prevElement();break;case"ArrowRight":e.preventDefault(),this.nextElement()}e.ctrlKey&&("+"!==e.key&&"="!==e.key||(e.preventDefault(),this.handleZoom(.2)),"-"===e.key&&(e.preventDefault(),this.handleZoom(-.2)),"0"===e.key&&(e.preventDefault(),this.resetZoom()))}}onPointerDown(e){e.preventDefault(),this.swipe.startX=e.clientX,this.swipe.startY=e.clientY,this.ui.gallery.image.setPointerCapture(e.pointerId),this.activePointers.set(e.pointerId,{x:e.clientX,y:e.clientY});const t=performance.now();if(t-this.lastTap<300&&1===this.activePointers.size)return this.zoom.scale>1?this.resetZoom():this.handleZoom(1,e.clientX,e.clientY),void(this.lastTap=0);if(this.lastTap=t,2===this.activePointers.size){const e=[...this.activePointers.values()];return this.pinchStartDist=Math.hypot(e[0].x-e[1].x,e[0].y-e[1].y),void(this.pinchStartScale=this.zoom.scale)}this.zoom.scale>1&&(this.zoom.panning=!0,this.zoom.startX=e.clientX-this.zoom.x,this.zoom.startY=e.clientY-this.zoom.y,this.ui.gallery.image.style.cursor="grabbing")}onPointerMove(e){if(this.activePointers.has(e.pointerId)){if(this.activePointers.set(e.pointerId,{x:e.clientX,y:e.clientY}),2===this.activePointers.size){const e=[...this.activePointers.values()],t=Math.hypot(e[0].x-e[1].x,e[0].y-e[1].y),i=this.pinchStartScale*(t/this.pinchStartDist)-this.zoom.scale,s=(e[0].x+e[1].x)/2,n=(e[0].y+e[1].y)/2;return void this.handleZoom(i,s,n)}this.zoom.panning&&(this.zoom.x=e.clientX-this.zoom.startX,this.zoom.y=e.clientY-this.zoom.startY,this.applyTransform())}}onPointerUp(e){const t=this.activePointers.get(e.pointerId);if(this.activePointers.delete(e.pointerId),this.activePointers.size<2&&(this.pinchStartDist=0),this.zoom.scale<=1&&!this.zoom.panning&&0===this.activePointers.size){const i=t?.x??e.clientX,s=t?.y??e.clientY,n=i-this.swipe.startX,o=s-this.swipe.startY;Math.abs(n)>this.zoom.threshold&&Math.abs(n)>Math.abs(o)&&(n>0?this.prevElement():this.nextElement())}0===this.activePointers.size&&(this.zoom.panning=!1,this.ui.gallery.image.style.cursor=this.zoom.scale>1?"grab":"default")}onWheel(e){if(!e.ctrlKey)return;e.preventDefault();const t=e.deltaY<0?.2:-.2;this.handleZoom(t,e.clientX,e.clientY)}handleZoom(e,t=null,i=null){const s=this.zoom.scale;let n=s+e;if(n=Math.min(this.zoom.max,Math.max(this.zoom.min,n)),n===s)return;const o=n/s;let l=this.ui.gallery.image.getBoundingClientRect();null!==t&&null!==i||(t=l.left+l.width/2,i=l.top+l.height/2);const r=t-l.left,a=i-l.top;this.zoom.x=(this.zoom.x-r)*o+r,this.zoom.y=(this.zoom.y-a)*o+a,this.zoom.scale=n,this.applyTransform(),this.notify("zoom",{scale:this.zoom.scale})}applyTransform(){this.clampPan();const e=this.ui.gallery.image;e.style.transform=`translate(${this.zoom.x}px, ${this.zoom.y}px) scale(${this.zoom.scale})`,e.style.cursor=this.zoom.scale>1?"grab":"default"}clampPan(){const e=this.ui.gallery.image,t=Math.max(0,(e.offsetWidth*this.zoom.scale-window.innerWidth)/2),i=Math.max(0,(e.offsetHeight*this.zoom.scale-window.innerHeight)/2);this.zoom.x=Math.max(-t,Math.min(t,this.zoom.x)),this.zoom.y=Math.max(-i,Math.min(i,this.zoom.y))}resetZoom(){this.zoom.scale=1,this.zoom.x=0,this.zoom.y=0,this.zoom.startX=0,this.zoom.startY=0,this.zoom.panning=!1,this.applyTransform()}resetSwipe(){return{startX:null,startY:null,endX:null,endY:null}}toggleGallery(e){e?(this.ui.gallery.image.draggable=!1,this.ui.gallery.image.style.userSelect="none",this.ui.gallery.image.addEventListener("pointerdown",this.pointerDownHandler),this.ui.gallery.image.addEventListener("pointermove",this.pointerMoveHandler),this.ui.gallery.image.addEventListener("pointerup",this.pointerUpHandler),this.ui.gallery.image.addEventListener("pointercancel",this.pointerUpHandler),window.addEventListener("wheel",this.wheelHandler,{passive:!1}),window.addEventListener("keydown",this.keyHandler),this.moveIntoView()):(this.ui.gallery.image.removeEventListener("pointerdown",this.pointerDownHandler),this.ui.gallery.image.removeEventListener("pointermove",this.pointerMoveHandler),this.ui.gallery.image.removeEventListener("pointerup",this.pointerUpHandler),this.ui.gallery.image.removeEventListener("pointercancel",this.pointerUpHandler),window.removeEventListener("wheel",this.wheelHandler),window.removeEventListener("keydown",this.keyHandler),this.resetZoom(),this.resetSwipe(),this.activePointers.clear(),this.lastTap=0),e&&!this.modal.isOpen&&this.modal.handleOpen()}moveIntoView(e=0){let t=this.index+e;t<0?t=this.items.length-1:t>=this.items.length?t=0:t===this.items.length-3&&this.notify("load-more"),this.index=t,this.updateDisplay(),this.preloadAdjacent(),this.a11y.announce(`Image ${this.index+1} of ${this.items.length}`)}nextElement(){this.resetZoom(),this.moveIntoView(1)}prevElement(){this.resetZoom(),this.moveIntoView(-1)}updateDisplay(){const e=this.items[this.index];if(!e)return;const t=this.ui.gallery.image;if(e.srcset&&(t.srcset=e.srcset,t.sizes=e.sizes),t.src=e.src,t.alt=e.alt,e.full&&e.full!==e.src){const i=new Image;i.onload=()=>{this.items[this.index]===e&&(t.src=e.full,t.removeAttribute("srcset"),t.removeAttribute("sizes"))},i.src=e.full}this.ui.gallery.counter.textContent=`${this.index+1} / ${this.items.length}`,this.ui.gallery.prevButton.disabled=this.items.length<=1,this.ui.gallery.nextButton.disabled=this.items.length<=1}preloadAdjacent(){[-1,1].forEach(e=>{const t=this.index+e;if(t>0&&t<this.items.length){const i=this.items[t];(e<0?this.ui.gallery.leftImage:this.ui.gallery.rightImage).src=i.full}})}initSubscribers(){this.subscribers=new Set}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(e,t={}){this.subscribers.forEach(i=>{try{i(e,t)}catch(e){console.error("Subscriber error:",e)}})}destroy(){this.subscribers.clear(),this.toggleGallery(!1),document.removeEventListener("click",this.clickHandler)}}document.addEventListener("DOMContentLoaded",function(){document.querySelector("dialog.gallery")&&(window.jvbGallery=new e)})})();
\ No newline at end of file
+(()=>{class e{constructor(){this.a11y=window.jvbA11y,this.index=0,this.images=[],this.zoom={scale:1,min:1,max:4,threshold:50,x:0,y:0,startX:0,startY:0,ease:.2,panning:!1},this.swipe=this.resetSwipe(),this.activePointers=new Map,this.lastTap=0,this.initElements(),this.initModal(),this.initListeners(),this.initSubscribers(),console.log("Gallery loaded...")}initElements(){this.elements={imageSelector:"img[data-gallery]",gallery:{modal:"dialog.gallery",wrap:".wrap",nextButton:".next",prevButton:".prev",image:".image",leftImage:".image-left",rightImage:".image-right",counter:".counter",caption:"details .item-info"}},this.ui=window.uiFromSelectors(this.elements)}initModal(){this.modal=new window.jvbModal(this.ui.gallery.modal,{openMessage:"Opened Gallery",closeMessage:"Closed Gallery"}),this.modal.subscribe(e=>{"modal-close"===e&&this.toggleGallery(!1)})}buildGalleryItems(e=null){let t=e?`[data-gallery="${e}"]`:this.elements.imageSelector;this.items=Array.from(document.querySelectorAll(t)).map((e,t)=>{let i=e.nextElementSibling&&"FIGCAPTION"===e.nextElementSibling.tagName?e.nextElementSibling.textContent:"";return{id:e.dataset.id||t,srcset:e.srcset||e.src,sizes:e.sizes||"100vw",src:e.currentSrc||e.src,full:e.dataset.full||e.src,alt:e.alt||"",element:e,caption:i}})}initListeners(){this.clickHandler=this.handleClick.bind(this),this.pointerDownHandler=this.onPointerDown.bind(this),this.pointerMoveHandler=this.onPointerMove.bind(this),this.pointerUpHandler=this.onPointerUp.bind(this),this.wheelHandler=this.onWheel.bind(this),this.keyHandler=this.handleKeys.bind(this),document.addEventListener("click",this.clickHandler)}handleClick(e){let t=window.targetCheck(e,this.elements.imageSelector);t&&!this.modal.isOpen?(e.preventDefault(),this.buildGalleryItems(t.dataset.gallery||null),this.index=this.items.findIndex(e=>e.element===t),this.toggleGallery(!0)):this.modal.isOpen&&(window.targetCheck(e,this.elements.gallery.nextButton)?(console.log("Next"),this.nextElement()):window.targetCheck(e,this.elements.gallery.prevButton)&&(console.log("Previous"),this.prevElement()))}handleKeys(e){if(this.modal.isOpen){switch(e.key){case"ArrowLeft":e.preventDefault(),this.prevElement();break;case"ArrowRight":e.preventDefault(),this.nextElement()}e.ctrlKey&&("+"!==e.key&&"="!==e.key||(e.preventDefault(),this.handleZoom(.2)),"-"===e.key&&(e.preventDefault(),this.handleZoom(-.2)),"0"===e.key&&(e.preventDefault(),this.resetZoom()))}}onPointerDown(e){e.preventDefault(),this.swipe.startX=e.clientX,this.swipe.startY=e.clientY,this.ui.gallery.image.setPointerCapture(e.pointerId),this.activePointers.set(e.pointerId,{x:e.clientX,y:e.clientY});const t=performance.now();if(t-this.lastTap<300&&1===this.activePointers.size)return this.zoom.scale>1?this.resetZoom():this.handleZoom(1,e.clientX,e.clientY),void(this.lastTap=0);if(this.lastTap=t,2===this.activePointers.size){const e=[...this.activePointers.values()];return this.pinchStartDist=Math.hypot(e[0].x-e[1].x,e[0].y-e[1].y),void(this.pinchStartScale=this.zoom.scale)}this.zoom.scale>1&&(this.zoom.panning=!0,this.zoom.startX=e.clientX-this.zoom.x,this.zoom.startY=e.clientY-this.zoom.y,this.ui.gallery.image.style.cursor="grabbing")}onPointerMove(e){if(this.activePointers.has(e.pointerId)){if(this.activePointers.set(e.pointerId,{x:e.clientX,y:e.clientY}),2===this.activePointers.size){const e=[...this.activePointers.values()],t=Math.hypot(e[0].x-e[1].x,e[0].y-e[1].y),i=this.pinchStartScale*(t/this.pinchStartDist)-this.zoom.scale,s=(e[0].x+e[1].x)/2,n=(e[0].y+e[1].y)/2;return void this.handleZoom(i,s,n)}this.zoom.panning&&(this.zoom.x=e.clientX-this.zoom.startX,this.zoom.y=e.clientY-this.zoom.startY,this.applyTransform())}}onPointerUp(e){const t=this.activePointers.get(e.pointerId);if(this.activePointers.delete(e.pointerId),this.activePointers.size<2&&(this.pinchStartDist=0),this.zoom.scale<=1&&!this.zoom.panning&&0===this.activePointers.size){const i=t?.x??e.clientX,s=t?.y??e.clientY,n=i-this.swipe.startX,o=s-this.swipe.startY;Math.abs(n)>this.zoom.threshold&&Math.abs(n)>Math.abs(o)&&(n>0?this.prevElement():this.nextElement())}0===this.activePointers.size&&(this.zoom.panning=!1,this.ui.gallery.image.style.cursor=this.zoom.scale>1?"grab":"default")}onWheel(e){if(!e.ctrlKey)return;e.preventDefault();const t=e.deltaY<0?.2:-.2;this.handleZoom(t,e.clientX,e.clientY)}handleZoom(e,t=null,i=null){const s=this.zoom.scale;let n=s+e;if(n=Math.min(this.zoom.max,Math.max(this.zoom.min,n)),n===s)return;const o=n/s;let l=this.ui.gallery.image.getBoundingClientRect();null!==t&&null!==i||(t=l.left+l.width/2,i=l.top+l.height/2);const a=t-l.left,r=i-l.top;this.zoom.x=(this.zoom.x-a)*o+a,this.zoom.y=(this.zoom.y-r)*o+r,this.zoom.scale=n,this.applyTransform(),this.notify("zoom",{scale:this.zoom.scale})}applyTransform(){this.clampPan();const e=this.ui.gallery.image;e.style.transform=`translate(${this.zoom.x}px, ${this.zoom.y}px) scale(${this.zoom.scale})`,e.style.cursor=this.zoom.scale>1?"grab":"default"}clampPan(){const e=this.ui.gallery.image,t=Math.max(0,(e.offsetWidth*this.zoom.scale-window.innerWidth)/2),i=Math.max(0,(e.offsetHeight*this.zoom.scale-window.innerHeight)/2);this.zoom.x=Math.max(-t,Math.min(t,this.zoom.x)),this.zoom.y=Math.max(-i,Math.min(i,this.zoom.y))}resetZoom(){this.zoom.scale=1,this.zoom.x=0,this.zoom.y=0,this.zoom.startX=0,this.zoom.startY=0,this.zoom.panning=!1,this.applyTransform()}resetSwipe(){return{startX:null,startY:null,endX:null,endY:null}}toggleGallery(e){e?(this.ui.gallery.image.draggable=!1,this.ui.gallery.image.style.userSelect="none",this.ui.gallery.image.addEventListener("pointerdown",this.pointerDownHandler),this.ui.gallery.image.addEventListener("pointermove",this.pointerMoveHandler),this.ui.gallery.image.addEventListener("pointerup",this.pointerUpHandler),this.ui.gallery.image.addEventListener("pointercancel",this.pointerUpHandler),window.addEventListener("wheel",this.wheelHandler,{passive:!1}),window.addEventListener("keydown",this.keyHandler),this.moveIntoView()):(this.ui.gallery.image.removeEventListener("pointerdown",this.pointerDownHandler),this.ui.gallery.image.removeEventListener("pointermove",this.pointerMoveHandler),this.ui.gallery.image.removeEventListener("pointerup",this.pointerUpHandler),this.ui.gallery.image.removeEventListener("pointercancel",this.pointerUpHandler),window.removeEventListener("wheel",this.wheelHandler),window.removeEventListener("keydown",this.keyHandler),this.resetZoom(),this.resetSwipe(),this.activePointers.clear(),this.lastTap=0),e&&!this.modal.isOpen&&this.modal.handleOpen()}moveIntoView(e=0){let t=this.index+e;t<0?t=this.items.length-1:t>=this.items.length?t=0:t===this.items.length-3&&this.notify("load-more"),this.index=t,this.updateDisplay(),this.preloadAdjacent(),this.a11y.announce(`Image ${this.index+1} of ${this.items.length}`)}nextElement(){this.resetZoom(),this.moveIntoView(1)}prevElement(){this.resetZoom(),this.moveIntoView(-1)}updateDisplay(){const e=this.items[this.index];if(!e)return;const t=this.ui.gallery.image;if(e.srcset&&(t.srcset=e.srcset,t.sizes=e.sizes),t.src=e.src,t.alt=e.alt,this.ui.gallery.caption.textContent=e.caption,e.full&&e.full!==e.src){const i=new Image;i.onload=()=>{this.items[this.index]===e&&(t.src=e.full,t.removeAttribute("srcset"),t.removeAttribute("sizes"))},i.src=e.full}this.ui.gallery.counter.textContent=`${this.index+1} / ${this.items.length}`,this.ui.gallery.prevButton.disabled=this.items.length<=1,this.ui.gallery.nextButton.disabled=this.items.length<=1}preloadAdjacent(){[-1,1].forEach(e=>{const t=this.index+e;if(t>0&&t<this.items.length){const i=this.items[t];(e<0?this.ui.gallery.leftImage:this.ui.gallery.rightImage).src=i.full}})}initSubscribers(){this.subscribers=new Set}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(e,t={}){this.subscribers.forEach(i=>{try{i(e,t)}catch(e){console.error("Subscriber error:",e)}})}destroy(){this.subscribers.clear(),this.toggleGallery(!1),document.removeEventListener("click",this.clickHandler)}}document.addEventListener("DOMContentLoaded",function(){document.querySelector("dialog.gallery")&&(window.jvbGallery=new e)})})();
\ No newline at end of file
diff --git a/assets/js/min/populate.min.js b/assets/js/min/populate.min.js
index 0833cb8..51a896d 100644
--- a/assets/js/min/populate.min.js
+++ b/assets/js/min/populate.min.js
@@ -1 +1 @@
-(()=>{class e{constructor(){this.templates=window.jvbTemplates,this.formHelper=window.jvbForm,this.defineTemplates(),this.data=null,this.form=null}populate(e,t={}){if(this.data=t,this.mergeRootData(),this.form=e,this.formHelper||(this.formHelper=window.jvbForm),this.formHelper){if(Object.hasOwn(this.data,"fields")&&0!==Object.keys(this.data.fields).length)for(let[t,i]of Object.entries(this.data.fields)){let a=e.querySelector(`[data-field="${t}"]`);a&&this.populateField(a,t,i)}}else requestAnimationFrame(()=>{this.populate(e,t)})}mergeRootData(){["status","date","modified"].forEach(e=>{this.data.fields[`post_${e}`]=this.data[e]})}populateField(e,t,i){let a=this.formHelper.getFieldType(e);if(!a||this.isEmptyValue(t)||this.isEmptyValue(i))return;const l={repeater:this.populateRepeater.bind(this),"tag-list":this.populateTagList.bind(this),group:this.populateGroup.bind(this),location:this.populateLocation.bind(this),selector:this.populateTaxonomy.bind(this),user:this.populateUser.bind(this),upload:this.populateUpload.bind(this),gallery:this.populateUpload.bind(this),image:this.populateUpload.bind(this),set:this.populateMultiValue.bind(this),checkbox:this.populateMultiValue.bind(this),select:this.populateSingleValue.bind(this),radio:this.populateSingleValue.bind(this),"true-false":this.populateBoolean.bind(this),"toggle-text":this.populateBoolean.bind(this),date:this.populateDate.bind(this),time:this.populateDate.bind(this),datetime:this.populateDate.bind(this),number:this.populateNumber.bind(this),textarea:this.populateTextarea.bind(this),quantity:this.populateNumber.bind(this)};Object.hasOwn(l,a)?l[a](e,t,i):this.populateText(e,t,i)}populateRepeater(e,t,i){if(!i||!Array.isArray(i))return;const a=e.querySelector(".repeater-items");let l=e.querySelector("template")?.className??!1;a&&l&&(window.removeChildren(a),i.forEach((t,i)=>{const o={...t,index:i,repeater:e},r=this.templates.create(l,o);if(!r)return;a.append(r);const s=this.formHelper.getForm(r);s&&this.formHelper.initializeFields(r,s);for(let[e,i]of Object.entries(t)){let t=r.querySelector(`[data-field="${e}"]`);t&&this.populateField(t,e,i)}}))}populateTagList(e,t,i){if(!i||!Array.isArray(i))return;const a=e.querySelector(".tag-items");let l=e.querySelector("template")?.className??!1;a&&l&&(window.removeChildren(a),i.forEach((i,o)=>{const r=this.templates.create(l,{label:this.getTagLabel(i,e.dataset.tagFormat??"first_field"),fieldName:t,...i});r&&(r.querySelectorAll('input[type="hidden"]').forEach(e=>{const t=e.dataset.field;t&&void 0!==i[t]&&(e.value=i[t])}),a.append(r))}))}getTagLabel(e,t){const i=Object.values(e).filter(e=>!this.isEmptyValue(e));switch(t){case"first_field":return i[0]??"New Item";case"all_fields":return i.join(", ")||"New Item";default:if(t.includes("{")){let i=t;for(const[t,a]of Object.entries(e))i=i.replace(`{${t}}`,a);return i}return e[t]??i[0]??"New Item"}}populateGroup(e,t,i){if(i&&"object"==typeof i)for(let[t,a]of Object.entries(i)){let i=e.querySelector(`[data-field="${t}"]`);i&&this.populateField(i,t,a)}}populateLocation(e,t,i){["address","lat","lng","street","city","province","postal_code","country"].forEach(t=>{if(Object.hasOwn(i,t)){let a=e.querySelector(`[data-location-field="${t}"]`);a&&(a.value=String(i[t]||""))}})}populateTaxonomy(e,t,i){let a=this.splitIDs(i);if(0===a.length)return;const l=e.querySelector(`input[type="hidden"][name="${t}"]`);l&&(l.value=a.join(","),window.jvbSelector&&requestAnimationFrame(()=>{window.jvbSelector.updateFieldFromInput(l)}))}populateUser(e,t,i){this.populateTaxonomy(e,t,i)}populateUpload(e,t,i){if(e.dataset.subtype&&"timeline"===e.dataset.subtype)return void this.populateTimelineGallery(e,t,i);if(this.isEmptyValue(i))return;const a=this.splitIDs(i);if(0===a.length)return;const l=e.querySelector('input[type="hidden"]');l&&(l.value=a.join(","));const o=e.querySelector(".item-grid");e.querySelector(".progress")?.remove(),o&&(window.removeChildren(o),a.forEach(e=>{let t=this.data.images[e]??{};t.field={config:{showMeta:!0}},t.id=e,o.append(this.templates.create("uploadItem",t))})),this.populateUploadMeta(e,t,i)}populateUploadMeta(e,t,i){const a=e.querySelector('[data-field="image_data"]');if(!a)return;let l=this.data.images[i]??!1;if(!l)return;a.dataset.attachmentId=l.id,a.setAttribute("data-ignore","");const o=["image-title","image-alt-text","image-caption"];for(const e of o){const t=a.querySelector(`[data-field="${e}"] input, [data-field="${e}"] textarea`);t&&""!==l[e]&&(t.value=window.decodeHTMLEntities(l[e]))}}populateTimelineGallery(e,t,i){if(!i||!Array.isArray(i)||0===i.length)return;let a=e.querySelector(".item-grid");if(a){window.removeChildren(a),e.querySelector(".progress")?.remove();for(let e of i){let t=this.templates.create("timelineItem",e);t&&a.append(t)}}}populateMultiValue(e,t,i){if("string"==typeof i)try{i=JSON.parse(i)}catch(e){i=i.split(",").map(e=>e.trim())}Array.isArray(i)||(i=[String(i)]);let a=e.querySelector(`select[name="${t}"]`);if(a&&a.multiple)for(let e of a.options)e.selected=i.includes(e.value);else e.querySelectorAll(`input[type="checkbox"][name="${t}[]"], input[type="checkbox"][name="${t}"]`).forEach(e=>{e.checked=i.includes(e.value)})}populateSingleValue(e,t,i){i=String(i||"");let a=e.querySelector(`select[name="${t}"]`);if(a)return void(a.value=i);let l=e.querySelector(`input[type="radio"][value="${i}"], input[type="checkbox"][value="${i}"]`)||e.querySelector(`[name="${t}"][value="${i}"]`);l&&(l.checked=!0)}populateBoolean(e,t,i){const a=e.querySelector(`[name="${t}"], input[type="checkbox"]`);a&&(a.checked=Boolean(i))}populateDate(e,t,i){const a=e.querySelector(`[name="${t}"], input`);if(a){"object"==typeof i&&Object.hasOwn(i,"date")&&(i=i.date);try{const e=new Date(i);if(!isNaN(e.getTime()))switch(a.type){case"date":a.value=e.toISOString().split("T")[0];break;case"time":a.value=e.toTimeString().slice(0,5);break;case"datetime-local":a.value=e.toISOString().slice(0,16);break;default:a.value=i}}catch(e){a.value=i}}}populateNumber(e,t,i){const a=e.querySelector(`[name="${t}"], input[type="number"]`);a&&(a.value=Number(i)||0)}populateTextarea(e,t,i){let a=e.querySelector("textarea[data-editor], textarea");if(this.populateText(e,t,i),a?.dataset.editor){const t=e.querySelector(".ql-editor");t?t.innerHTML=i:a.dispatchEvent(new Event("change",{bubbles:!0}))}}populateText(e,t,i){let a=e.querySelector(`[name="${t}"]`)||e.querySelector("textarea[data-editor]")||e.querySelector('input:not([type="hidden"]):not([type="file"]), textarea, select');a&&(a.value=window.decodeHTMLEntities(i??""))}getFormHelper(){window.requestAnimationFrame(()=>{this.formHelper=window.jvbForm})}splitIDs(e){return String(e).split(",").map(e=>parseInt(e.trim())).filter(e=>!isNaN(e)&&e>0)}isEmptyValue(e){return null==e||""===e||(!(!Array.isArray(e)||0!==e.length)||"object"==typeof e&&0===Object.keys(e).length)}defineTemplates(){const e=this.templates,t=this;e.define("timelineItem",{refs:{select:'[name="select-item"]',video:"video",file:".select-item span",img:"img",details:'[data-field="image_data"] details',imgAlt:'[data-field="image-alt-text"]',imgTitle:'[data-field="image-title"]',imgDesc:'[data-field="image-caption"]'},manyRefs:{fields:".field"},setup({el:e,refs:i,manyRefs:a,data:l}){if(e.dataset.itemId=l.id,i.select){let e=i.select.closest(".preview");window.prefixInput(i.select,`${l.id}-`,e)}i.video&&i.video.remove(),i.file&&i.file.remove();let o=t.data.images[l.post_thumbnail]??!1;if(i.img&&o&&(i.img.src=o.medium||o.small||o.large||"",i.img.title=o.large.split("/").pop()??"",i.img.alt=o["image-alt-text"]??""),i.details){let e=t.data.images[l.post_thumbnail];i.details.setAttribute("data-ignore",""),i.details.dataset.attachmentId=l.post_thumbnail;let a=i.imgAlt.querySelector("input"),o=i.imgTitle.querySelector("input"),r=i.imgDesc.querySelector("textarea");window.prefixInput(a,`[${l.post_thumbnail}]`,i.imgAlt,!1,!0),window.prefixInput(o,`[${l.post_thumbnail}]`,i.imgTitle,!1,!0),window.prefixInput(r,`[${l.post_thumbnail}]`,i.imgDesc,!1,!0),Object.hasOwn(e,"image-alt-text")&&i.imgAlt&&(a.value=window.decodeHTMLEntities(e["image-alt-text"])),(Object.hasOwn(e,"image-title")||Object.hasOwn(l,"file"))&&i.imgTitle&&(o.value=window.decodeHTMLEntities(e["image-title"]||l.file.name)),Object.hasOwn(e,"image-caption")&&i.imgDesc&&(r.value=window.decodeHTMLEntities(e["image-caption"]))}if(a.fields)for(let e of a.fields){if(e.closest("[data-ignore]"))continue;if("group"===e.dataset.fieldType)continue;if("post_thumbnail"===e.dataset.field){e.remove();continue}let i=e.dataset.field;const a=e.querySelector('input:not([type="file"]), textarea, select');a&&window.prefixInput(a,`[${l.id}]`,e,!1,!0);let o=l[i]??"";t.isEmptyValue(o)||t.populateField(e,i,o)}}})}}document.addEventListener("DOMContentLoaded",function(){window.auth.subscribe(t=>{"auth-loaded"===t&&(window.jvbPopulate=new e)})})})();
\ No newline at end of file
+(()=>{class e{constructor(){this.templates=window.jvbTemplates,this.formHelper=window.jvbForm,this.defineTemplates(),this.data=null,this.form=null}populate(e,t={}){if(this.data=t,this.mergeRootData(),this.form=e,this.formHelper||(this.formHelper=window.jvbForm),this.formHelper){if(Object.hasOwn(this.data,"fields")&&0!==Object.keys(this.data.fields).length)for(let[t,i]of Object.entries(this.data.fields)){let a=e.querySelector(`[data-field="${t}"]`);a&&this.populateField(a,t,i)}}else requestAnimationFrame(()=>{this.populate(e,t)})}mergeRootData(){["status","date","modified"].forEach(e=>{this.data.fields[`post_${e}`]=this.data[e]})}populateField(e,t,i){let a=this.formHelper.getFieldType(e);if(!a||this.isEmptyValue(t))return;const l={repeater:this.populateRepeater.bind(this),"tag-list":this.populateTagList.bind(this),group:this.populateGroup.bind(this),location:this.populateLocation.bind(this),selector:this.populateTaxonomy.bind(this),user:this.populateUser.bind(this),upload:this.populateUpload.bind(this),gallery:this.populateUpload.bind(this),image:this.populateUpload.bind(this),set:this.populateMultiValue.bind(this),checkbox:this.populateMultiValue.bind(this),select:this.populateSingleValue.bind(this),radio:this.populateSingleValue.bind(this),"true-false":this.populateBoolean.bind(this),"toggle-text":this.populateBoolean.bind(this),date:this.populateDate.bind(this),time:this.populateDate.bind(this),datetime:this.populateDate.bind(this),number:this.populateNumber.bind(this),textarea:this.populateTextarea.bind(this),quantity:this.populateNumber.bind(this)};Object.hasOwn(l,a)?l[a](e,t,i):this.populateText(e,t,i)}populateRepeater(e,t,i){const a=e.querySelector(".repeater-items");let l=e.querySelector("template")?.className??!1;if(a&&l){if("string"==typeof i)try{i=JSON.parse(i)}catch(e){i=[]}i&&!Array.isArray(i)&&"object"==typeof i&&(i=Object.values(i)),i&&Array.isArray(i)&&0!==i.length?(window.removeChildren(a),i.forEach((t,i)=>{const o={...t,index:i,repeater:e},r=this.templates.create(l,o);if(!r)return;a.append(r);const s=this.formHelper.getForm(r);s&&this.formHelper.initializeFields(r,s);for(let[e,i]of Object.entries(t)){let t=r.querySelector(`[data-field="${e}"]`);t&&this.populateField(t,e,i)}})):window.removeChildren(a)}}populateTagList(e,t,i){const a=e.querySelector(".tag-items");let l=e.querySelector("template")?.className??!1;if(a&&l){if("string"==typeof i)try{i=JSON.parse(i)}catch(e){i=[]}i&&!Array.isArray(i)&&"object"==typeof i&&(i=Object.values(i)),i&&Array.isArray(i)&&0!==i.length?(window.removeChildren(a),i.forEach((i,o)=>{const r=this.templates.create(l,{label:this.getTagLabel(i,e.dataset.tagFormat??"first_field"),fieldName:t,...i});r&&(r.querySelectorAll('input[type="hidden"]').forEach(e=>{const t=e.dataset.field;t&&void 0!==i[t]&&(e.value=i[t])}),a.append(r))})):window.removeChildren(a)}}getTagLabel(e,t){const i=Object.values(e).filter(e=>!this.isEmptyValue(e));switch(t){case"first_field":return i[0]??"New Item";case"all_fields":return i.join(", ")||"New Item";default:if(t.includes("{")){let i=t;for(const[t,a]of Object.entries(e))i=i.replace(`{${t}}`,a);return i}return e[t]??i[0]??"New Item"}}populateGroup(e,t,i){if(i&&"object"==typeof i)for(let[t,a]of Object.entries(i)){let i=e.querySelector(`[data-field="${t}"]`);i&&this.populateField(i,t,a)}}populateLocation(e,t,i){["address","lat","lng","street","city","province","postal_code","country"].forEach(t=>{if(Object.hasOwn(i,t)){let a=e.querySelector(`[data-location-field="${t}"]`);a&&(a.value=String(i[t]||""))}})}populateTaxonomy(e,t,i){let a=this.splitIDs(i);const l=e.querySelector(`input[type="hidden"][name="${t}"]`);l&&(l.value=a.join(","),window.jvbSelector&&requestAnimationFrame(()=>{window.jvbSelector.updateFieldFromInput(l)}))}populateUser(e,t,i){this.populateTaxonomy(e,t,i)}populateUpload(e,t,i){if(e.dataset.subtype&&"timeline"===e.dataset.subtype)return void this.populateTimelineGallery(e,t,i);const a=this.splitIDs(i);if(0===a.length)return;const l=e.querySelector('input[type="hidden"]');l&&(l.value=a.join(","));const o=e.querySelector(".item-grid");e.querySelector(".progress")?.remove(),o&&(window.removeChildren(o),a.forEach(e=>{let t=this.data.images[e]??{};t.field={config:{showMeta:!0}},t.id=e,o.append(this.templates.create("uploadItem",t))})),this.populateUploadMeta(e,t,i)}populateUploadMeta(e,t,i){const a=e.querySelector('[data-field="image_data"]');if(!a)return;let l=this.data.images[i]??!1;if(!l)return;a.dataset.attachmentId=l.id,a.setAttribute("data-ignore","");const o=["image-title","image-alt-text","image-caption"];for(const e of o){const t=a.querySelector(`[data-field="${e}"] input, [data-field="${e}"] textarea`);t&&""!==l[e]&&(t.value=window.decodeHTMLEntities(l[e]))}}populateTimelineGallery(e,t,i){if(!i||!Array.isArray(i)||0===i.length)return;let a=e.querySelector(".item-grid");if(a){window.removeChildren(a),e.querySelector(".progress")?.remove();for(let e of i){let t=this.templates.create("timelineItem",e);t&&a.append(t)}}}populateMultiValue(e,t,i){if("string"==typeof i)try{i=JSON.parse(i)}catch(e){i=i.split(",").map(e=>e.trim())}Array.isArray(i)||(i=[String(i)]);let a=e.querySelector(`select[name="${t}"]`);if(a&&a.multiple)for(let e of a.options)e.selected=i.includes(e.value);else e.querySelectorAll(`input[type="checkbox"][name="${t}[]"], input[type="checkbox"][name="${t}"]`).forEach(e=>{e.checked=i.includes(e.value)})}populateSingleValue(e,t,i){i=String(i||"");let a=e.querySelector(`select[name="${t}"]`);if(a)return void(a.value=i);let l=e.querySelector(`input[type="radio"][value="${i}"], input[type="checkbox"][value="${i}"]`)||e.querySelector(`[name="${t}"][value="${i}"]`);l&&(l.checked=!0)}populateBoolean(e,t,i){const a=e.querySelector(`[name="${t}"], input[type="checkbox"]`);a&&(a.checked=Boolean(i))}populateDate(e,t,i){const a=e.querySelector(`[name="${t}"], input`);if(a){"object"==typeof i&&Object.hasOwn(i,"date")&&(i=i.date);try{const e=new Date(i);if(!isNaN(e.getTime()))switch(a.type){case"date":a.value=e.toISOString().split("T")[0];break;case"time":a.value=e.toTimeString().slice(0,5);break;case"datetime-local":a.value=e.toISOString().slice(0,16);break;default:a.value=i}}catch(e){a.value=i}}}populateNumber(e,t,i){const a=e.querySelector(`[name="${t}"], input[type="number"]`);a&&(a.value=Number(i)||0)}populateTextarea(e,t,i){let a=e.querySelector("textarea[data-editor], textarea");if(this.populateText(e,t,i),a?.dataset.editor){const t=e.querySelector(".ql-editor");t?t.innerHTML=i:a.dispatchEvent(new Event("change",{bubbles:!0}))}}populateText(e,t,i){let a=e.querySelector(`[name="${t}"]`)||e.querySelector("textarea[data-editor]")||e.querySelector('input:not([type="hidden"]):not([type="file"]), textarea, select');a&&(a.value=window.decodeHTMLEntities(i??""))}getFormHelper(){window.requestAnimationFrame(()=>{this.formHelper=window.jvbForm})}splitIDs(e){return String(e).split(",").map(e=>parseInt(e.trim())).filter(e=>!isNaN(e)&&e>0)}isEmptyValue(e){return null==e||""===e||(!(!Array.isArray(e)||0!==e.length)||"object"==typeof e&&0===Object.keys(e).length)}defineTemplates(){const e=this.templates,t=this;e.define("timelineItem",{refs:{select:'[name="select-item"]',video:"video",file:".select-item span",img:"img",details:'[data-field="image_data"] details',imgAlt:'[data-field="image-alt-text"]',imgTitle:'[data-field="image-title"]',imgDesc:'[data-field="image-caption"]'},manyRefs:{fields:".field"},setup({el:e,refs:i,manyRefs:a,data:l}){if(e.dataset.itemId=l.id,i.select){let e=i.select.closest(".preview");window.prefixInput(i.select,`${l.id}-`,e)}i.video&&i.video.remove(),i.file&&i.file.remove();let o=t.data.images[l.post_thumbnail]??!1;if(i.img&&o&&(i.img.src=o.medium||o.small||o.large||"",i.img.title=o.large.split("/").pop()??"",i.img.alt=o["image-alt-text"]??""),i.details){let e=t.data.images[l.post_thumbnail];i.details.setAttribute("data-ignore",""),i.details.dataset.attachmentId=l.post_thumbnail;let a=i.imgAlt.querySelector("input"),o=i.imgTitle.querySelector("input"),r=i.imgDesc.querySelector("textarea");window.prefixInput(a,`[${l.post_thumbnail}]`,i.imgAlt,!1,!0),window.prefixInput(o,`[${l.post_thumbnail}]`,i.imgTitle,!1,!0),window.prefixInput(r,`[${l.post_thumbnail}]`,i.imgDesc,!1,!0),Object.hasOwn(e,"image-alt-text")&&i.imgAlt&&(a.value=window.decodeHTMLEntities(e["image-alt-text"])),(Object.hasOwn(e,"image-title")||Object.hasOwn(l,"file"))&&i.imgTitle&&(o.value=window.decodeHTMLEntities(e["image-title"]||l.file.name)),Object.hasOwn(e,"image-caption")&&i.imgDesc&&(r.value=window.decodeHTMLEntities(e["image-caption"]))}if(a.fields)for(let e of a.fields){if(e.closest("[data-ignore]"))continue;if("group"===e.dataset.fieldType)continue;if("post_thumbnail"===e.dataset.field){e.remove();continue}let i=e.dataset.field;const a=e.querySelector('input:not([type="file"]), textarea, select');a&&window.prefixInput(a,`[${l.id}]`,e,!1,!0);let o=l[i]??"";t.isEmptyValue(o)||t.populateField(e,i,o)}}})}}document.addEventListener("DOMContentLoaded",function(){window.auth.subscribe(t=>{"auth-loaded"===t&&(window.jvbPopulate=new e)})})})();
\ No newline at end of file
diff --git a/assets/js/min/queue.min.js b/assets/js/min/queue.min.js
index 9c39699..08dbcb7 100644
--- a/assets/js/min/queue.min.js
+++ b/assets/js/min/queue.min.js
@@ -1 +1 @@
-(()=>{class e{constructor(){this.a11y=window.jvbA11y,this.error=window.jvbError,this.user=window.auth.getUser(),this.user&&(this.canUpdateUI=!0,this.isProcessing=!1,this.isPolling=!1,this.queue=new Map,this.items=new Map,this.subscribers=new Set,this.loadFromStorage=!1,this.api=jvbSettings.api,this.endpoint="queue",this.init())}init(){this.headers={"X-WP-Nonce":window.auth.getNonce()},this.initElements(),this.initListeners(),this.initStore(),this.canUpdateUI&&this.ui.panel&&(this.popup=window.jvbPopup.registerPopup({popup:this.ui.panel,toggle:this.ui.toggle.button,name:"Queue Panel"})),this.defineTemplates()}initElements(){this.panelStatuses=["syncing","synced","pending","offline"],this.statuses=["queued","localProcessing","uploading","pending","processing","completed","failed","failed_permanent"],this.pendingStatuses=["queued","localProcessing","uploading"],this.workingStatuses=["pending","processing"],this.completedStatuses=["completed","failed","failed_permanent"],this.icons={queued:"arrows-clockwise",localProcessing:"arrows-clockwise",uploading:"syncing",pending:"cloud",processing:"syncing",completed:"cloud-check",failed:"cloud-warning",failed_permanent:"cloud-warning"},this.selectors={panel:"aside#queue",toggle:{button:"button.qtoggle",indicator:".qtoggle .indicator",count:".qtoggle .count"},refresh:{button:"#queue .m-actions .refresh",countdown:"#queue .m-actions .refresh .countdown"},popup:{popup:"#queue .popup",message:"#queue .popup span"},items:{container:"#queue .qitems"},actions:{retry:"#queue .retry-all",clear:"#queue .dismiss-all"},filters:{filter:"#queue [data-filter]",all:{label:'#queue [for="qfilter-all"]',radio:'#queue [data-filter="all"]',count:'#queue [data-filter="all"] .count'},queued:{label:'#queue [for="qfilter-queued"]',input:'#queue [data-filter="queued"]',count:'#queue [for="qfilter-queued"] .count'},localProcessing:{label:'#queue [for="qfilter-localProcessing"]',input:'#queue [data-filter="localProcessing"]',count:'#queue [for="qfilter-localProcessing"] .count'},uploading:{label:'#queue [for="qfilter-uploading"]',input:'#queue [data-filter="uploading"]',count:'#queue [for="qfilter-uploading"] .count'},pending:{label:'#queue [for="qfilter-pending"]',input:'#queue [data-filter="pending"]',count:'#queue [for="qfilter-pending"] .count'},processing:{label:'#queue [for="qfilter-processing"]',input:'#queue [data-filter="processing"]',count:'#queue [for="qfilter-processing"] .count'},completed:{label:'#queue [for="qfilter-completed"]',input:'#queue [data-filter="completed"]',count:'#queue [for="qfilter-completed"] .count'},failed:{label:'#queue [for="qfilter-failed"]',input:'#queue [data-filter="failed"]',count:'#queue [for="qfilter-failed"] .count'}},item:{type:".type",status:".status",details:".info .details",icon:".status .icon",startedAt:".started time",completed:{wrap:".completed",label:".completed span",time:".completed time"},progress:{progress:".progress",fill:".progress .fill",details:".progress .details",icon:".progress .icon"},actions:{cancel:"button.cancel",retry:"button.retry",refresh:"button.refresh",dismiss:"button.dismiss"}}},this.ui=window.uiFromSelectors(this.selectors),this.ui.panel||(this.canUpdateUI=!1)}defineTemplates(){const e=window.jvbTemplates;e.define("emptyState"),e.define("queueItem",{setup({el:e,refs:t,manyRefs:s,data:i}){e.dataset.id=i.id}})}initListeners(){this.activityListeners=null,this.clickHandler=this.handleClick.bind(this),this.onlineHandler=this.handleOnline.bind(this),this.offlineHandler=this.handleOffline.bind(this),this.unloadHandler=this.handleBeforeUnload.bind(this),this.visibilityHandler=this.handleVisibilityChange.bind(this),document.addEventListener("click",this.clickHandler),window.addEventListener("online",this.onlineHandler),window.addEventListener("offline",this.offlineHandler),document.addEventListener("visibilitychange",this.visibilityHandler)}handleOnline(){this.updatePanel("synced"),this.getQueueByStatus(this.pendingStatuses).length>0&&this.processQueue()}handleOffline(){this.updatePanel("offline")}handleVisibilityChange(e){this.isPolling&&document.hidden?this.stopPolling():this.maybeStartPolling()}handleBeforeUnload(e){if(!this.ui.panel)return;return this.getQueueByStatus(this.pendingStatuses).length>0?(e.preventDefault(),e.returnValue="",""):void 0}handleClick(e){if(!window.targetCheck(e,this.selectors.panel+", "+this.selectors.toggle.button))return;if(window.targetCheck(e,this.selectors.refresh.button))return this.ui.refresh.button.classList.add("fetching"),this.store.clearCache(),this.store.clearFilters(),void this.store.fetch().finally(()=>{this.ui.refresh.button.classList.remove("fetching")});if(window.targetCheck(e,this.selectors.actions.refresh))return void this.handleRefresh(opId);if(window.targetCheck(e,this.selectors.actions.clear))return void this.opActions("completed","dismiss").then(()=>{});if(window.targetCheck(e,this.selectors.actions.retry))return void this.opActions("failed","retry").then(()=>{});const t=window.targetCheck(e,"[data-action]");if(t){const e=t.closest("[data-id]")?.dataset.id;return void(e&&this.opActions(e,t.dataset.action))}const s=window.targetCheck(e,this.selectors.filters.filter);s&&this.setFilter(s.dataset.filter)}setFilter(e){Object.values(this.ui.filters).forEach(t=>{t.input?.dataset.filter===e&&(t.input.checked=!0)}),"all"===e?this.store.clearFilters():this.store.setFilter("status",e)}trackActivity(){if(!this.activityListeners){const e=["mousedown","mousemove","keypress","scroll","touchstart"];this.activityListeners=e.map(e=>{const t=()=>this.resetActivityTimer();return document.addEventListener(e,t,{passive:!0}),{event:e,handler:t}})}this.resetActivityTimer()}resetActivityTimer(){this.activityTimer&&clearTimeout(this.activityTimer),this.activityTimer=setTimeout(()=>{this.processQueue()},1750)}stopActivityTracking(){this.activityTimer&&(clearTimeout(this.activityTimer),this.activityTimer=null),this.activityListeners&&(this.activityListeners.forEach(({event:e,handler:t})=>{document.removeEventListener(e,t)}),this.activityListeners=null)}initStore(){if(!this.user)return;const e=window.jvbStore.register("queue",{storeName:"queue",keyPath:"id",endpoint:this.endpoint,TTL:1/0,isAuth:!0,indexes:[{name:"status",keyPath:"status"},{name:"type",keyPath:"type"}],filters:{user:window.auth.getUser()},showLoading:!1});this.store=e.queue,this.store.subscribe((e,t)=>{switch(e){case"data-loaded":this.store.getAll().forEach(e=>{const t=this.queue.get(e.id),s=this.mapServerOperation(e);this.queue.set(s.id,s),t&&t.status!==s.status&&this.notify("operation-status",s)}),this.maybeStartPolling(),this.updateUI();break;case"items-save":this.maybeStartPolling(),this.updateUI();break;case"item-saved":t.item&&(this.queue.set(t.item.id,t.item),t.previousItem?.status!==t.item.status&&this.notify("operation-status",t.item)),this.maybeStartPolling()}})}handleRefresh(e){const t=this.getQueue(e);if(!t)return;let s=null;if(s={content_update:t.data?.posts?Object.values(t.data.posts)[0]?.content:null,batch_creation:t.data?.content,image_upload:"uploads",video_upload:"uploads",document_upload:"uploads"}[t.type],s&&window.jvbStore){if(window.jvbStore.stores.get(s)){window.jvbStore.clearCache(s),window.jvbStore.fetch(s);const t=this.items.get(e)?.ui?.actions?.refresh;if(t){const e=t.querySelector("span").textContent;t.querySelector("span").textContent="Refreshed!",t.disabled=!0,setTimeout(()=>{t.querySelector("span").textContent=e,t.disabled=!1},2e3)}}}else confirm("Refresh the page to see changes?")&&window.location.reload()}addToQueue(e){const t={id:`u${this.user}_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,endpoint:null,method:"POST",headers:{},data:{},delay:!1,canMerge:!0,popup:"Saving changes...",title:"Operation",status:"queued",timestamp:Date.now(),created_at:(new Date).toISOString(),retries:0,user:this.user,...e};if(t.headers={...this.headers,...t.headers},!t.endpoint||!t.data)return null;if(t.popup&&this.ui.popup?.message&&(this.ui.popup.message.textContent=t.popup,this.ui.popup.popup.hidden=!1,setTimeout(()=>this.ui.popup.popup.hidden=!0,2e3)),!t.delay)return this.queue.set(t.id,t),this.processOperation(t).then(()=>{}),this.store.clearCache(),this.maybeStartPolling(),this.toggleQueue(),t.id;const s=Array.from(this.getAllQueue()).filter(e=>"queued"===e.status&&e.endpoint===t.endpoint&&e.canMerge);if(s.length>0){const e=s[0];return e.data=window.deepMerge(e.data,t.data),e.timestamp=Date.now(),this.setQueue(e),this.updateOperationStatus(e.id,e.status),this.updateUI(),this.trackActivity(),e.id}return this.store.clearCache(),this.setQueue(t),this.updateOperationStatus(t.id,t.status),this.updateUI(),this.trackActivity(),t.id}async opActions(e,t){if(this.statuses.includes(e)?e=this.getQueueByStatus(e).map(e=>e.id):"string"==typeof e&&(e=[e]),0===e.length)return;if(!["cancel","dismiss","retry"].includes(t))return;const s=["cancel","dismiss"].includes(t);s&&e.forEach(e=>{this.removeOperationUI(e)});try{const i=await window.auth.fetch(`${this.api}${this.endpoint}`,{method:"POST",headers:{"Content-Type":"application/json",...this.headers},body:JSON.stringify({action:t,ids:Array.isArray(e)?e:[e],user:this.user})});if(!i.ok)throw new Error(`${t} failed: ${i.status}`);const n=await i.json();if(!n.success)throw new Error(n.message||`${t} operation failed`);return e.forEach(e=>{let i=this.getQueue(e);if(i&&this.notify(`${t}-operation`,i),s)this.clearQueue(e);else{let t=this.getQueue(e);t.status="queued",this.setQueue(t),this.updateOperationStatus(t.id,t.status)}}),"retry"===t&&this.trackActivity(),this.updateUI(),n}catch(s){return await window.jvbError.log(s,{component:"Queue",operation:"performQueueAction",action:t,operationIds:e,itemCount:e.length},()=>this.opActions(e,t)),{success:!1,error:s.message}}}async processQueue(){if(this.isProcessing)return;const e=this.getQueueByStatus("queued");if(0===e.length)return void this.stopActivityTracking();this.setProcessing();for(const t of e)await this.processOperation(t);this.setProcessing(!1);0===this.getQueueByStatus("queued").length?this.stopActivityTracking():this.trackActivity(),this.toggleQueue(this.maybeStartPolling())}async processOperation(e){try{this.queue.has(e.id)||this.queue.set(e.id,e);let t,s,i=!1;if(e.data?._isFormData&&!e.data instanceof FormData&&(i=!0,e.data=await this.store.objectToFormData(e.data)),this.updateOperationStatus(e.id,"uploading"),e.data instanceof FormData?(e.data.append("id",e.id),e.data.append("user",window.auth.getUser()),t=e.data,s=e.data):(s={...e.data,id:e.id,user:window.auth.getUser()},t=JSON.stringify(s),e.headers["Content-Type"]="application/json"),"unknown"===e.endpoint||null==t)return;const n=await window.auth.fetch(`${this.api}${e.endpoint}`,{method:e.method,headers:e.headers,body:t});console.log("Sending request with data: ",s);const r=await n.json();if(i&&(e.data={}),console.log("Result: ",r),!n.ok||!r.success)throw new Error(r.message||`HTTP ${n.status}`);this.notify("sent-to-server",s),r.id&&e.id!==r.id?e=await this.handleServerMerge(e,r):(e.status=r.status??"pending",e.serverData=r,this.updateOperationStatus(e.id,e.status)),this.a11y.announce(`${e.title} sent to server for processing`),this.setQueue(e)}catch(t){console.error("Operation failed: ",t),e.retries++,e.lastError=t.message,e.retries>=3?e.status="failed_permanent":e.status="failed",this.updateOperationStatus(e.id,e.status),this.setQueue(e)}}async handleServerMerge(e,t){const s=this.getQueue(t.id);return s?(e.status=t.status||"pending",e.serverData=t,this.mergeOp(s,e)):(this.clearQueue(e.id),this.setQueue(t),t)}mergeOp(e,t){return e.data=window.deepMerge(e.data,t.data),e.status=t.status,Object.hasOwn(t,"serverData")&&(e.serverData=t.serverData),this.updateOperationStatus(e.id,e.status),this.removeOperationUI(t.id),this.clearQueue(t.id),e}sortByDate(e){return e.sort((e,t)=>(e.updated_at??e.timestamp??0)-(t.updated_at??t.timestamp??0))}sortOperations(e){const t={processing:0,uploading:1,pending:2,queued:3,localProcessing:4,failed:5,completed:6,failed_permanent:7};return e.sort((e,s)=>{const i=(t[e.status]??99)-(t[s.status]??99);if(0!==i)return i;const n=e.updated_at??e.timestamp??0,r=s.updated_at??s.timestamp??0;return new Date(r)-new Date(n)})}getAllQueue(){let e=new Set,t=[...Array.from(this.queue.values())];return this.loadFromStorage||(this.loadFromStorage=!0,t=[...t,...Array.from(this.store.data.values())],t=t.filter(t=>{const s=e.has(t.id);return e.add(t.id),!s})),this.sortOperations(t)}getQueueByStatus(e){return"string"==typeof e&&(e=[e]),this.getAllQueue().filter(t=>e.includes(t.status))}updateOperationStatus(e,t){let s=this.getQueue(e);s&&(this.statuses.includes(t)?(s.status=t,this.notify("operation-status",s),this.setQueue(s)):console.log("Invalid status: ",t))}setQueue(e){this.store.save(e),this.queue.set(e.id,e)}getQueue(e){return this.queue.has(e)?this.queue.get(e):this.store.get(e)}clearQueue(e){this.queue.delete(e),this.store.delete(e)}maybeStartPolling(){return this.getQueueByStatus([...this.pendingStatuses,...this.workingStatuses]).length>0?(this.startPolling(),!0):(this.updatePanel("synced"),!1)}startPolling(){this.isPolling||(this.isPolling=!0,this.updatePanel("pending"),this.runPollCycle())}async runPollCycle(){if(this.isPolling){try{if(this.ui.refresh.button.classList.add("fetching"),this.store.clearCache(),429===(await this.store.fetch()).status)return console.log("Too many requests. Waiting 30 seconds"),this.stopPolling(),void this.startCountdown(30,()=>this.runPollCycle());if(this.ui.refresh.button.classList.remove("fetching"),!this.maybeStartPolling())return this.stopPolling(),void this.updatePanel("synced")}catch(e){console.error("Polling error:",e)}this.startCountdown(5,()=>this.runPollCycle())}}startCountdown(e,t){this.ui.refresh.countdown?(this.ui.refresh.countdown.classList.add("counting"),this.ui.refresh.countdown.textContent=e,this.countdownTimer=setInterval(()=>{--e>0?this.ui.refresh.countdown.textContent=e:(this.stopCountdown(),t&&t())},1e3)):console.warn("Countdown element not found")}stopPolling(){this.isPolling&&(this.isPolling=!1,this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=null),this.stopCountdown())}stopCountdown(){this.countdownTimer&&(clearInterval(this.countdownTimer),this.countdownTimer=null),this.ui.refresh.countdown.classList.remove("counting"),this.ui.refresh.countdown.textContent=""}updateUI(){this.canUpdateUI&&window.debouncer.schedule("queue-ui",this.handleUpdateUI.bind(this))}handleUpdateUI(){const e=this.getAllQueue();this.ui.actions.retry.disabled=0===e.filter(e=>"failed"===e.status).length,this.ui.actions.clear.disabled=0===e.filter(e=>"completed"===e.status).length;let t=e.filter(e=>[...this.pendingStatuses,...this.workingStatuses].includes(e.status));t=t.length,this.ui.toggle.count.hidden=0===t,this.ui.toggle.count.textContent=t;for(let t of this.statuses){if("failed_permanent"===t)continue;let s=e.filter(e=>e.status===t).length;this.ui.filters[t].label.hidden=0===s,this.ui.filters[t].input.dataset.count=`${s}`,this.ui.filters[t].count.textContent=s>0?s:""}this.renderOperations()}renderOperations(){if(!this.ui.items.container)return;const e=this.store.filters?.status??"all",t="all"===e?this.getAllQueue():this.getQueueByStatus(e),s=this.sortOperations(t);if(0===s.length){window.removeChildren(this.ui.items.container);const e=window.jvbTemplates.create("emptyQueue");return this.ui.items.container.append(e),void this.a11y.announce("No items in queue")}this.ui.items.container.querySelector(".empty-group")?.remove();const i=new Set(s.map(e=>e.id));this.items.forEach((e,t)=>{i.has(t)||(e.element?.remove(),this.items.delete(t))}),s.forEach((e,t)=>{let s=this.items.get(e.id);s||(s=this.createOperationElement(e)),s?.element&&(this.updateOperationUI(e.id),this.ui.items.container.append(s.element))})}createOperationElement(e){const t=window.jvbTemplates.create("queueItem",e),s={element:t,ui:window.uiFromSelectors(this.selectors.item,t)};return this.items.set(e.id,s),s}updateOperationUI(e){let t=this.items.has(e)?this.items.get(e):this.createOperationElement(e);if(!t)return;let s=this.getQueue(e),i=t.element;i.classList.remove(...this.statuses),i.classList.add(s.status);let n=this.getProgress(s);t.ui.type&&t.ui.type.textContent!==s.title&&(t.ui.type.textContent=s.title),t.ui.status&&(t.ui.status.title=this.statusLabel(s.status)),t.ui.icon&&(t.ui.icon.className=`icon icon-${this.icons[s.status]}`),t.ui.details&&(t.ui.details.textContent=this.itemMessage(s)),t.ui.startedAt&&(t.ui.startedAt.setAttribute("datetime",s.created_at),t.ui.startedAt.textContent=window.formatTimeAgo(s.created_at));s.status;const r="completed"===s.status&&(s.completed_at||s.updated_at);if(t.ui.completed.wrap.hidden=!r,r){const e=s.completed_at??s.updated_at;t.ui.completed.label.textContent="Completed: ",t.ui.completed.time.setAttribute("datetime",e),t.ui.completed.time.textContent=window.formatTimeAgo(e)}window.showProgress(t.ui.progress,n,100,this.statusLabel(s.status)),t.ui.actions.cancel&&(t.ui.actions.cancel.hidden=this.completedStatuses.includes(s.status)),t.ui.actions.retry&&(s.retries>=3&&(t.ui.actions.retry.disabled=!0),t.ui.actions.retry.hidden="failed"!==s.status),t.ui.actions.dismiss&&(t.ui.actions.dismiss.hidden=this.pendingStatuses.includes(s.status)),t.ui.actions.refresh&&(t.ui.actions.refresh.hidden="completed"!==s.status)}getProgress(e){if(void 0!==e.progress_percentage)return e.progress_percentage;if(void 0!==e.progress)return e.progress;if(!this.statuses.includes(e.status))return 0;return{queued:10,uploading:25,pending:40,processing:70,completed:100,failed:0,failed_permanent:0}[e.status]??0}removeOperationUI(e){let t=this.items.get(e);t&&window.fade(t.element,!1)}updatePanel(e="syncing"){this.ui.panel&&this.panelStatuses.includes(e)&&(this.ui.panel.classList.remove(...this.panelStatuses),this.ui.panel.classList.add(e))}statusLabel(e){if(!this.statuses.includes(e))return"";return{queued:"Queued",localProcessing:"Processing locally",uploading:"Uploading",pending:"Waiting on server",processing:"Processing",completed:"Completed",failed:"Failed",failed_permanent:"Failed permanently",merged:"Merged"}[e]}itemMessage(e){if(Object.hasOwn(e,"message")&&""!==e.message)return e.message;if(Object.hasOwn(e,"error_message")&&e.error_message)return e.error_message;switch(e.status){case"queued":return"Waiting to send...";case"uploading":return"Sending to server...";case"pending":return e.position?`Position ${e.position} in queue`:"In server queue";case"processing":if(e.count&&void 0!==e.progress_count){const t=e.progress_count,s=e.count;return`Processing ${t}/${s} items (${Math.round(t/s*100)}%)`}return void 0!==e.progress_percentage?`${e.progress_percentage}% complete`:"Processing...";case"completed":return"Successfully completed. Refresh to see changes.";case"merged":return e.merged_into?`Merged with another operation (${e.merged_into.substring(0,8)}...)`:"Merged with another operation";case"failed":return`Failed: ${e.lastError||"Unknown error"} (Retry ${e.retries}/2)`;case"failed_permanent":return`Failed: ${e.lastError||"Unknown error"}`;default:return""}}toggleQueue(e=!0){this.ui.panel&&(this.ui.panel.hidden=!e,this.ui.toggle.button.hidden=!e)}setProcessing(e=!0){this.isProcessing=e,this.ui.toggle.button.classList.toggle("saving",e)}mapServerOperation(e){const t=this.queue.get(e.id);if(t&&t.endpoint){const s={...t,...e,endpoint:t.endpoint,method:t.method,headers:t.headers,progress_percentage:e.progress_percentage,progress_count:e.progress_count,count:e.count};e.merged_into&&this.handleMergedOperation(s)}const s=e.type?e.type.replace("_update","").replace("_","/"):"unknown",i={...e,endpoint:s,method:"POST",headers:{...this.headers}};return e.merged_into&&this.handleMergedOperation(i),i}handleMergedOperation(e){e.merged_into&&(console.log(`[Queue] Operation ${e.id} merged into ${e.merged_into}`),setTimeout(()=>{this.clearQueue(e.id),this.removeOperationFromUI(e.id)},3e3))}subscribe(e){if(this.subscribers)return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(e,t){this.subscribers.forEach(s=>s(e,t))}destroy(){this.isPolling&&this.stopPolling(),this.stopActivityTracking(),document.removeEventListener("click",this.clickHandler),this.subscribers.clear()}}document.addEventListener("DOMContentLoaded",async function(){window.auth.subscribe(t=>{"auth-loaded"===t&&(window.jvbQueue=new e)})})})();
\ No newline at end of file
+(()=>{class e{constructor(){this.a11y=window.jvbA11y,this.error=window.jvbError,this.user=window.auth.getUser(),this.user&&(this.canUpdateUI=!0,this.isProcessing=!1,this.isPolling=!1,this.queue=new Map,this.items=new Map,this.subscribers=new Set,this.loadFromStorage=!1,this.failedFetches=0,this.api=jvbSettings.api,this.endpoint="queue",this.init())}init(){this.headers={"X-WP-Nonce":window.auth.getNonce()},this.initElements(),this.initListeners(),this.initStore(),this.canUpdateUI&&this.ui.panel&&(this.popup=window.jvbPopup.registerPopup({popup:this.ui.panel,toggle:this.ui.toggle.button,name:"Queue Panel"})),this.defineTemplates()}initElements(){this.panelStatuses=["syncing","synced","pending","offline"],this.statuses=["queued","localProcessing","uploading","pending","processing","completed","failed","failed_permanent"],this.pendingStatuses=["queued","localProcessing","uploading"],this.workingStatuses=["pending","processing"],this.completedStatuses=["completed","failed","failed_permanent"],this.icons={queued:"arrows-clockwise",localProcessing:"arrows-clockwise",uploading:"syncing",pending:"cloud",processing:"syncing",completed:"cloud-check",failed:"cloud-warning",failed_permanent:"cloud-warning"},this.selectors={panel:"aside#queue",toggle:{button:"button.qtoggle",indicator:".qtoggle .indicator",count:".qtoggle .count"},refresh:{button:"#queue .m-actions .refresh",countdown:"#queue .m-actions .refresh .countdown"},popup:{popup:"#queue .popup",message:"#queue .popup span"},items:{container:"#queue .qitems"},actions:{retry:"#queue .retry-all",clear:"#queue .dismiss-all"},filters:{filter:"#queue [data-filter]",all:{label:'#queue [for="qfilter-all"]',radio:'#queue [data-filter="all"]',count:'#queue [data-filter="all"] .count'},queued:{label:'#queue [for="qfilter-queued"]',input:'#queue [data-filter="queued"]',count:'#queue [for="qfilter-queued"] .count'},localProcessing:{label:'#queue [for="qfilter-localProcessing"]',input:'#queue [data-filter="localProcessing"]',count:'#queue [for="qfilter-localProcessing"] .count'},uploading:{label:'#queue [for="qfilter-uploading"]',input:'#queue [data-filter="uploading"]',count:'#queue [for="qfilter-uploading"] .count'},pending:{label:'#queue [for="qfilter-pending"]',input:'#queue [data-filter="pending"]',count:'#queue [for="qfilter-pending"] .count'},processing:{label:'#queue [for="qfilter-processing"]',input:'#queue [data-filter="processing"]',count:'#queue [for="qfilter-processing"] .count'},completed:{label:'#queue [for="qfilter-completed"]',input:'#queue [data-filter="completed"]',count:'#queue [for="qfilter-completed"] .count'},failed:{label:'#queue [for="qfilter-failed"]',input:'#queue [data-filter="failed"]',count:'#queue [for="qfilter-failed"] .count'}},item:{type:".type",status:".status",details:".info .details",icon:".status .icon",startedAt:".started time",completed:{wrap:".completed",label:".completed span",time:".completed time"},progress:{progress:".progress",fill:".progress .fill",details:".progress .details",icon:".progress .icon"},actions:{cancel:"button.cancel",retry:"button.retry",refresh:"button.refresh",dismiss:"button.dismiss"}}},this.ui=window.uiFromSelectors(this.selectors),this.ui.panel||(this.canUpdateUI=!1)}defineTemplates(){const e=window.jvbTemplates;e.define("emptyState"),e.define("queueItem",{setup({el:e,refs:t,manyRefs:s,data:i}){e.dataset.id=i.id}})}initListeners(){this.activityListeners=null,this.clickHandler=this.handleClick.bind(this),this.onlineHandler=this.handleOnline.bind(this),this.offlineHandler=this.handleOffline.bind(this),this.unloadHandler=this.handleBeforeUnload.bind(this),this.visibilityHandler=this.handleVisibilityChange.bind(this),document.addEventListener("click",this.clickHandler),window.addEventListener("online",this.onlineHandler),window.addEventListener("offline",this.offlineHandler),document.addEventListener("visibilitychange",this.visibilityHandler)}handleOnline(){this.updatePanel("synced"),this.getQueueByStatus(this.pendingStatuses).length>0&&this.processQueue()}handleOffline(){this.updatePanel("offline")}handleVisibilityChange(e){this.isPolling&&document.hidden?this.stopPolling():this.maybeStartPolling()}handleBeforeUnload(e){if(!this.ui.panel)return;return this.getQueueByStatus(this.pendingStatuses).length>0?(e.preventDefault(),e.returnValue="",""):void 0}handleClick(e){if(!window.targetCheck(e,this.selectors.panel+", "+this.selectors.toggle.button))return;if(window.targetCheck(e,this.selectors.refresh.button))return this.ui.refresh.button.classList.add("fetching"),this.store.clearCache(),this.store.clearFilters(),void this.store.fetch().finally(()=>{this.ui.refresh.button.classList.remove("fetching")});if(window.targetCheck(e,this.selectors.actions.refresh))return void this.handleRefresh(opId);if(window.targetCheck(e,this.selectors.actions.clear))return void this.opActions("completed","dismiss").then(()=>{});if(window.targetCheck(e,this.selectors.actions.retry))return void this.opActions("failed","retry").then(()=>{});const t=window.targetCheck(e,"[data-action]");if(t){const e=t.closest("[data-id]")?.dataset.id;return void(e&&this.opActions(e,t.dataset.action))}const s=window.targetCheck(e,this.selectors.filters.filter);s&&this.setFilter(s.dataset.filter)}setFilter(e){Object.values(this.ui.filters).forEach(t=>{t.input?.dataset.filter===e&&(t.input.checked=!0)}),"all"===e?this.store.clearFilters():this.store.setFilter("status",e)}trackActivity(){if(!this.activityListeners){const e=["mousedown","mousemove","keypress","scroll","touchstart"];this.activityListeners=e.map(e=>{const t=()=>this.resetActivityTimer();return document.addEventListener(e,t,{passive:!0}),{event:e,handler:t}})}this.resetActivityTimer()}resetActivityTimer(){this.activityTimer&&clearTimeout(this.activityTimer),this.activityTimer=setTimeout(()=>{this.processQueue()},1750)}stopActivityTracking(){this.activityTimer&&(clearTimeout(this.activityTimer),this.activityTimer=null),this.activityListeners&&(this.activityListeners.forEach(({event:e,handler:t})=>{document.removeEventListener(e,t)}),this.activityListeners=null)}initStore(){if(!this.user)return;const e=window.jvbStore.register("queue",{storeName:"queue",keyPath:"id",endpoint:this.endpoint,TTL:1/0,isAuth:!0,indexes:[{name:"status",keyPath:"status"},{name:"type",keyPath:"type"}],filters:{user:window.auth.getUser()},showLoading:!1});this.store=e.queue,this.store.subscribe((e,t)=>{switch(e){case"data-loaded":this.store.getAll().forEach(e=>{const t=this.queue.get(e.id),s=this.mapServerOperation(e);this.queue.set(s.id,s),t&&t.status!==s.status&&this.notify("operation-status",s)}),this.maybeStartPolling(),this.updateUI();break;case"items-save":this.maybeStartPolling(),this.updateUI();break;case"item-saved":t.item&&(this.queue.set(t.item.id,t.item),t.previousItem?.status!==t.item.status&&this.notify("operation-status",t.item)),this.maybeStartPolling()}})}handleRefresh(e){const t=this.getQueue(e);if(!t)return;let s=null;if(s={content_update:t.data?.posts?Object.values(t.data.posts)[0]?.content:null,batch_creation:t.data?.content,image_upload:"uploads",video_upload:"uploads",document_upload:"uploads"}[t.type],s&&window.jvbStore){if(window.jvbStore.stores.get(s)){window.jvbStore.clearCache(s),window.jvbStore.fetch(s);const t=this.items.get(e)?.ui?.actions?.refresh;if(t){const e=t.querySelector("span").textContent;t.querySelector("span").textContent="Refreshed!",t.disabled=!0,setTimeout(()=>{t.querySelector("span").textContent=e,t.disabled=!1},2e3)}}}else confirm("Refresh the page to see changes?")&&window.location.reload()}addToQueue(e){const t={id:`u${this.user}_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,endpoint:null,method:"POST",headers:{},data:{},delay:!1,canMerge:!0,popup:"Saving changes...",title:"Operation",status:"queued",timestamp:Date.now(),created_at:(new Date).toISOString(),retries:0,user:this.user,...e};if(t.headers={...this.headers,...t.headers},!t.endpoint||!t.data)return null;if(t.popup&&this.ui.popup?.message&&(this.ui.popup.message.textContent=t.popup,this.ui.popup.popup.hidden=!1,setTimeout(()=>this.ui.popup.popup.hidden=!0,2e3)),!t.delay)return this.queue.set(t.id,t),this.processOperation(t).then(()=>{}),this.store.clearCache(),this.maybeStartPolling(),this.toggleQueue(),t.id;const s=Array.from(this.getAllQueue()).filter(e=>"queued"===e.status&&e.endpoint===t.endpoint&&e.canMerge);if(s.length>0){const e=s[0];return e.data=window.deepMerge(e.data,t.data),e.timestamp=Date.now(),this.setQueue(e),this.updateOperationStatus(e.id,e.status),this.updateUI(),this.trackActivity(),e.id}return this.store.clearCache(),this.setQueue(t),this.updateOperationStatus(t.id,t.status),this.updateUI(),this.trackActivity(),t.id}async opActions(e,t){if(this.statuses.includes(e)?e=this.getQueueByStatus(e).map(e=>e.id):"string"==typeof e&&(e=[e]),0===e.length)return;if(!["cancel","dismiss","retry"].includes(t))return;const s=["cancel","dismiss"].includes(t);s&&e.forEach(e=>{this.removeOperationUI(e)});try{const i=await window.auth.fetch(`${this.api}${this.endpoint}`,{method:"POST",headers:{"Content-Type":"application/json",...this.headers},body:JSON.stringify({action:t,ids:Array.isArray(e)?e:[e],user:this.user})});if(!i.ok)throw new Error(`${t} failed: ${i.status}`);const n=await i.json();if(!n.success)throw new Error(n.message||`${t} operation failed`);return e.forEach(e=>{let i=this.getQueue(e);if(i&&this.notify(`${t}-operation`,i),s)this.clearQueue(e);else{let t=this.getQueue(e);t.status="queued",this.setQueue(t),this.updateOperationStatus(t.id,t.status)}}),"retry"===t&&this.trackActivity(),this.updateUI(),n}catch(s){return await window.jvbError.log(s,{component:"Queue",operation:"performQueueAction",action:t,operationIds:e,itemCount:e.length},()=>this.opActions(e,t)),{success:!1,error:s.message}}}async processQueue(){if(this.isProcessing)return;const e=this.getQueueByStatus("queued");if(0===e.length)return void this.stopActivityTracking();this.setProcessing();for(const t of e)await this.processOperation(t);this.setProcessing(!1);0===this.getQueueByStatus("queued").length?this.stopActivityTracking():this.trackActivity(),this.toggleQueue(this.maybeStartPolling())}async processOperation(e){try{this.queue.has(e.id)||this.queue.set(e.id,e);let t,s,i=!1;if(e.data?._isFormData&&!e.data instanceof FormData&&(i=!0,e.data=await this.store.objectToFormData(e.data)),this.updateOperationStatus(e.id,"uploading"),e.data instanceof FormData?(e.data.append("id",e.id),e.data.append("user",window.auth.getUser()),t=e.data,s=e.data):(s={...e.data,id:e.id,user:window.auth.getUser()},t=JSON.stringify(s),e.headers["Content-Type"]="application/json"),"unknown"===e.endpoint||null==t)return;const n=await window.auth.fetch(`${this.api}${e.endpoint}`,{method:e.method,headers:e.headers,body:t});console.log("Sending request with data: ",s);const r=await n.json();if(i&&(e.data={}),console.log("Result: ",r),!n.ok||!r.success)throw new Error(r.message||`HTTP ${n.status}`);this.notify("sent-to-server",s),r.id&&e.id!==r.id?e=await this.handleServerMerge(e,r):(e.status=r.status??"pending",e.serverData=r,this.updateOperationStatus(e.id,e.status)),this.a11y.announce(`${e.title} sent to server for processing`),this.setQueue(e)}catch(t){console.error("Operation failed: ",t),e.retries++,e.lastError=t.message,e.retries>=3?e.status="failed_permanent":e.status="failed",this.updateOperationStatus(e.id,e.status),this.setQueue(e)}}async handleServerMerge(e,t){const s=this.getQueue(t.id);return s?(e.status=t.status||"pending",e.serverData=t,this.mergeOp(s,e)):(this.clearQueue(e.id),this.setQueue(t),t)}mergeOp(e,t){return e.data=window.deepMerge(e.data,t.data),e.status=t.status,Object.hasOwn(t,"serverData")&&(e.serverData=t.serverData),this.updateOperationStatus(e.id,e.status),this.removeOperationUI(t.id),this.clearQueue(t.id),e}sortByDate(e){return e.sort((e,t)=>(e.updated_at??e.timestamp??0)-(t.updated_at??t.timestamp??0))}sortOperations(e){const t={processing:0,uploading:1,pending:2,queued:3,localProcessing:4,failed:5,completed:6,failed_permanent:7};return e.sort((e,s)=>{const i=(t[e.status]??99)-(t[s.status]??99);if(0!==i)return i;const n=e.updated_at??e.timestamp??0,r=s.updated_at??s.timestamp??0;return new Date(r)-new Date(n)})}getAllQueue(){let e=new Set,t=[...Array.from(this.queue.values())];return this.loadFromStorage||(this.loadFromStorage=!0,t=[...t,...Array.from(this.store.data.values())],t=t.filter(t=>{const s=e.has(t.id);return e.add(t.id),!s})),this.sortOperations(t)}getQueueByStatus(e){return"string"==typeof e&&(e=[e]),this.getAllQueue().filter(t=>e.includes(t.status))}updateOperationStatus(e,t){let s=this.getQueue(e);s&&(this.statuses.includes(t)?(s.status=t,this.notify("operation-status",s),this.setQueue(s)):console.log("Invalid status: ",t))}setQueue(e){this.store.save(e),this.queue.set(e.id,e)}getQueue(e){return this.queue.has(e)?this.queue.get(e):this.store.get(e)}clearQueue(e){this.queue.delete(e),this.store.delete(e)}maybeStartPolling(){return this.getQueueByStatus([...this.pendingStatuses,...this.workingStatuses]).length>0?(this.startPolling(),!0):(this.updatePanel("synced"),!1)}startPolling(){this.isPolling||(this.isPolling=!0,this.updatePanel("pending"),this.runPollCycle())}async runPollCycle(){if(this.isPolling){try{if(this.ui.refresh.button.classList.add("fetching"),this.store.clearCache(),429===(await this.store.fetch()).status)return console.log("Too many requests. Waiting 30 seconds"),this.stopPolling(),void this.startCountdown(30,()=>this.runPollCycle());if(this.ui.refresh.button.classList.remove("fetching"),!this.maybeStartPolling())return this.stopPolling(),void this.updatePanel("synced")}catch(e){this.stopPolling(),this.updatePanel("synced"),console.error("Polling error:",e)}this.startCountdown(5,()=>this.runPollCycle())}}startCountdown(e,t){this.ui.refresh.countdown?(this.ui.refresh.countdown.classList.add("counting"),this.ui.refresh.countdown.textContent=e,this.countdownTimer=setInterval(()=>{--e>0?this.ui.refresh.countdown.textContent=e:(this.stopCountdown(),t&&t())},1e3)):console.warn("Countdown element not found")}stopPolling(){this.isPolling&&(this.isPolling=!1,this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=null),this.stopCountdown())}stopCountdown(){this.countdownTimer&&(clearInterval(this.countdownTimer),this.countdownTimer=null),this.ui.refresh.countdown.classList.remove("counting"),this.ui.refresh.countdown.textContent=""}updateUI(){this.canUpdateUI&&window.debouncer.schedule("queue-ui",this.handleUpdateUI.bind(this))}handleUpdateUI(){const e=this.getAllQueue();this.ui.actions.retry.disabled=0===e.filter(e=>"failed"===e.status).length,this.ui.actions.clear.disabled=0===e.filter(e=>"completed"===e.status).length;let t=e.filter(e=>[...this.pendingStatuses,...this.workingStatuses].includes(e.status));t=t.length,this.ui.toggle.count.hidden=0===t,this.ui.toggle.count.textContent=t;for(let t of this.statuses){if("failed_permanent"===t)continue;let s=e.filter(e=>e.status===t).length;this.ui.filters[t].label.hidden=0===s,this.ui.filters[t].input.dataset.count=`${s}`,this.ui.filters[t].count.textContent=s>0?s:""}this.renderOperations()}renderOperations(){if(!this.ui.items.container)return;const e=this.store.filters?.status??"all",t="all"===e?this.getAllQueue():this.getQueueByStatus(e),s=this.sortOperations(t);if(0===s.length){window.removeChildren(this.ui.items.container);const e=window.jvbTemplates.create("emptyQueue");return this.ui.items.container.append(e),void this.a11y.announce("No items in queue")}this.ui.items.container.querySelector(".empty-group")?.remove();const i=new Set(s.map(e=>e.id));this.items.forEach((e,t)=>{i.has(t)||(e.element?.remove(),this.items.delete(t))}),s.forEach((e,t)=>{let s=this.items.get(e.id);s||(s=this.createOperationElement(e)),s?.element&&(this.updateOperationUI(e.id),this.ui.items.container.append(s.element))})}createOperationElement(e){const t=window.jvbTemplates.create("queueItem",e),s={element:t,ui:window.uiFromSelectors(this.selectors.item,t)};return this.items.set(e.id,s),s}updateOperationUI(e){let t=this.items.has(e)?this.items.get(e):this.createOperationElement(e);if(!t)return;let s=this.getQueue(e),i=t.element;i.classList.remove(...this.statuses),i.classList.add(s.status);let n=this.getProgress(s);t.ui.type&&t.ui.type.textContent!==s.title&&(t.ui.type.textContent=s.title),t.ui.status&&(t.ui.status.title=this.statusLabel(s.status)),t.ui.icon&&(t.ui.icon.className=`icon icon-${this.icons[s.status]}`),t.ui.details&&(t.ui.details.textContent=this.itemMessage(s)),t.ui.startedAt&&(t.ui.startedAt.setAttribute("datetime",s.created_at),t.ui.startedAt.textContent=window.formatTimeAgo(s.created_at));s.status;const r="completed"===s.status&&(s.completed_at||s.updated_at);if(t.ui.completed.wrap.hidden=!r,r){const e=s.completed_at??s.updated_at;t.ui.completed.label.textContent="Completed: ",t.ui.completed.time.setAttribute("datetime",e),t.ui.completed.time.textContent=window.formatTimeAgo(e)}window.showProgress(t.ui.progress,n,100,this.statusLabel(s.status)),t.ui.actions.cancel&&(t.ui.actions.cancel.hidden=this.completedStatuses.includes(s.status)),t.ui.actions.retry&&(s.retries>=3&&(t.ui.actions.retry.disabled=!0),t.ui.actions.retry.hidden="failed"!==s.status),t.ui.actions.dismiss&&(t.ui.actions.dismiss.hidden=this.pendingStatuses.includes(s.status)),t.ui.actions.refresh&&(t.ui.actions.refresh.hidden="completed"!==s.status)}getProgress(e){if(void 0!==e.progress_percentage)return e.progress_percentage;if(void 0!==e.progress)return e.progress;if(!this.statuses.includes(e.status))return 0;return{queued:10,uploading:25,pending:40,processing:70,completed:100,failed:0,failed_permanent:0}[e.status]??0}removeOperationUI(e){let t=this.items.get(e);t&&window.fade(t.element,!1)}updatePanel(e="syncing"){this.ui.panel&&this.panelStatuses.includes(e)&&(this.ui.panel.classList.remove(...this.panelStatuses),this.ui.panel.classList.add(e))}statusLabel(e){if(!this.statuses.includes(e))return"";return{queued:"Queued",localProcessing:"Processing locally",uploading:"Uploading",pending:"Waiting on server",processing:"Processing",completed:"Completed",failed:"Failed",failed_permanent:"Failed permanently",merged:"Merged"}[e]}itemMessage(e){if(Object.hasOwn(e,"message")&&""!==e.message)return e.message;if(Object.hasOwn(e,"error_message")&&e.error_message)return e.error_message;switch(e.status){case"queued":return"Waiting to send...";case"uploading":return"Sending to server...";case"pending":return e.position?`Position ${e.position} in queue`:"In server queue";case"processing":if(e.count&&void 0!==e.progress_count){const t=e.progress_count,s=e.count;return`Processing ${t}/${s} items (${Math.round(t/s*100)}%)`}return void 0!==e.progress_percentage?`${e.progress_percentage}% complete`:"Processing...";case"completed":return"Successfully completed. Refresh to see changes.";case"merged":return e.merged_into?`Merged with another operation (${e.merged_into.substring(0,8)}...)`:"Merged with another operation";case"failed":return`Failed: ${e.lastError||"Unknown error"} (Retry ${e.retries}/2)`;case"failed_permanent":return`Failed: ${e.lastError||"Unknown error"}`;default:return""}}toggleQueue(e=!0){this.ui.panel&&(this.ui.panel.hidden=!e,this.ui.toggle.button.hidden=!e)}setProcessing(e=!0){this.isProcessing=e,this.ui.toggle.button.classList.toggle("saving",e)}mapServerOperation(e){const t=this.queue.get(e.id);if(t&&t.endpoint){const s={...t,...e,endpoint:t.endpoint,method:t.method,headers:t.headers,progress_percentage:e.progress_percentage,progress_count:e.progress_count,count:e.count};e.merged_into&&this.handleMergedOperation(s)}const s=e.type?e.type.replace("_update","").replace("_","/"):"unknown",i={...e,endpoint:s,method:"POST",headers:{...this.headers}};return e.merged_into&&this.handleMergedOperation(i),i}handleMergedOperation(e){e.merged_into&&(console.log(`[Queue] Operation ${e.id} merged into ${e.merged_into}`),setTimeout(()=>{this.clearQueue(e.id),this.removeOperationFromUI(e.id)},3e3))}subscribe(e){if(this.subscribers)return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(e,t){this.subscribers.forEach(s=>s(e,t))}destroy(){this.isPolling&&this.stopPolling(),this.stopActivityTracking(),document.removeEventListener("click",this.clickHandler),this.subscribers.clear()}}document.addEventListener("DOMContentLoaded",async function(){window.auth.subscribe(t=>{"auth-loaded"===t&&(window.jvbQueue=new e)})})})();
\ No newline at end of file
diff --git a/build/drawer-menu/index-rtl.css b/build/drawer-menu/index-rtl.css
index 8b13789..d315337 100644
--- a/build/drawer-menu/index-rtl.css
+++ b/build/drawer-menu/index-rtl.css
@@ -1 +1,4 @@
+/*!****************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/drawer-menu/editor.scss ***!
+  \****************************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/drawer-menu/index.asset.php b/build/drawer-menu/index.asset.php
index 46c7e8a..69e4b46 100644
--- a/build/drawer-menu/index.asset.php
+++ b/build/drawer-menu/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components'), 'version' => '483555faf4d69fc14935');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components'), 'version' => '65376817f33306cc5678');
diff --git a/build/drawer-menu/index.css b/build/drawer-menu/index.css
index 8b13789..d315337 100644
--- a/build/drawer-menu/index.css
+++ b/build/drawer-menu/index.css
@@ -1 +1,4 @@
+/*!****************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/drawer-menu/editor.scss ***!
+  \****************************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/drawer-menu/index.js b/build/drawer-menu/index.js
index 3379cd2..00008f0 100644
--- a/build/drawer-menu/index.js
+++ b/build/drawer-menu/index.js
@@ -1 +1,345 @@
-(()=>{"use strict";var e,r={582(){const e=window.wp.blocks,r=window.wp.blockEditor,n=window.wp.components,o=window.ReactJSXRuntime;(0,e.registerBlockType)("jvb/drawer-menu",{edit:function({attributes:e,setAttributes:t}){const{menuId:l,collapsed:s}=e,i=(0,r.useBlockProps)();return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(r.InspectorControls,{children:(0,o.jsxs)(n.PanelBody,{title:"Drawer Settings",children:[(0,o.jsx)(n.TextControl,{label:"Menu ID",value:l,onChange:e=>t({menuId:e}),help:"PHP-generated menu identifier"}),(0,o.jsx)(n.ToggleControl,{label:"Start Collapsed",checked:s,onChange:e=>t({collapsed:e})})]})}),(0,o.jsx)("div",{...i,children:(0,o.jsxs)("div",{className:"drawer-menu-preview",children:[(0,o.jsxs)("p",{children:["Drawer Menu: ",l||"Not configured"]}),(0,o.jsxs)("p",{children:["State: ",s?"Collapsed":"Expanded"]})]})})]})},save:function(){return null}})}},n={};function o(e){var t=n[e];if(void 0!==t)return t.exports;var l=n[e]={exports:{}};return r[e](l,l.exports,o),l.exports}o.m=r,e=[],o.O=(r,n,t,l)=>{if(!n){var s=1/0;for(c=0;c<e.length;c++){for(var[n,t,l]=e[c],i=!0,a=0;a<n.length;a++)(!1&l||s>=l)&&Object.keys(o.O).every(e=>o.O[e](n[a]))?n.splice(a--,1):(i=!1,l<s&&(s=l));if(i){e.splice(c--,1);var d=t();void 0!==d&&(r=d)}}return r}l=l||0;for(var c=e.length;c>0&&e[c-1][2]>l;c--)e[c]=e[c-1];e[c]=[n,t,l]},o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),(()=>{var e={121:0,397:0};o.O.j=r=>0===e[r];var r=(r,n)=>{var t,l,[s,i,a]=n,d=0;if(s.some(r=>0!==e[r])){for(t in i)o.o(i,t)&&(o.m[t]=i[t]);if(a)var c=a(o)}for(r&&r(n);d<s.length;d++)l=s[d],o.o(e,l)&&e[l]&&e[l][0](),e[l]=0;return o.O(c)},n=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];n.forEach(r.bind(null,0)),n.push=r.bind(null,n.push.bind(n))})();var t=o.O(void 0,[397],()=>o(582));t=o.O(t)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/drawer-menu/edit.js"
+/*!*********************************!*\
+  !*** ./src/drawer-menu/edit.js ***!
+  \*********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__);
+
+
+
+function Edit({
+  attributes,
+  setAttributes
+}) {
+  const {
+    menuId,
+    collapsed
+  } = attributes;
+  const blockProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__.useBlockProps)();
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.Fragment, {
+    children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__.InspectorControls, {
+      children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, {
+        title: "Drawer Settings",
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.TextControl, {
+          label: "Menu ID",
+          value: menuId,
+          onChange: value => setAttributes({
+            menuId: value
+          }),
+          help: "PHP-generated menu identifier"
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.ToggleControl, {
+          label: "Start Collapsed",
+          checked: collapsed,
+          onChange: value => setAttributes({
+            collapsed: value
+          })
+        })]
+      })
+    }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.jsx)("div", {
+      ...blockProps,
+      children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxs)("div", {
+        className: "drawer-menu-preview",
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxs)("p", {
+          children: ["Drawer Menu: ", menuId || 'Not configured']
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_2__.jsxs)("p", {
+          children: ["State: ", collapsed ? 'Collapsed' : 'Expanded']
+        })]
+      })
+    })]
+  });
+}
+
+/***/ },
+
+/***/ "./src/drawer-menu/index.js"
+/*!**********************************!*\
+  !*** ./src/drawer-menu/index.js ***!
+  \**********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./edit */ "./src/drawer-menu/edit.js");
+/* harmony import */ var _save__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./save */ "./src/drawer-menu/save.js");
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./style.scss */ "./src/drawer-menu/style.scss");
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./editor.scss */ "./src/drawer-menu/editor.scss");
+
+
+
+
+
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)('jvb/drawer-menu', {
+  edit: _edit__WEBPACK_IMPORTED_MODULE_1__["default"],
+  save: _save__WEBPACK_IMPORTED_MODULE_2__["default"]
+});
+
+/***/ },
+
+/***/ "./src/drawer-menu/save.js"
+/*!*********************************!*\
+  !*** ./src/drawer-menu/save.js ***!
+  \*********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ save)
+/* harmony export */ });
+function save() {
+  return null; // Server-side rendered
+}
+
+/***/ },
+
+/***/ "./src/drawer-menu/editor.scss"
+/*!*************************************!*\
+  !*** ./src/drawer-menu/editor.scss ***!
+  \*************************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "./src/drawer-menu/style.scss"
+/*!************************************!*\
+  !*** ./src/drawer-menu/style.scss ***!
+  \************************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/components"
+/*!************************************!*\
+  !*** external ["wp","components"] ***!
+  \************************************/
+(module) {
+
+module.exports = window["wp"]["components"];
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"drawer-menu/index": 0,
+/******/ 			"drawer-menu/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["drawer-menu/style-index"], () => (__webpack_require__("./src/drawer-menu/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/drawer-menu/index.js.map b/build/drawer-menu/index.js.map
new file mode 100644
index 0000000..009c48d
--- /dev/null
+++ b/build/drawer-menu/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"drawer-menu/index.js","mappings":";;;;;;;;;;;;;;;;;;;;AAA2E;AACG;AAAA;AAE/D,SAASW,IAAIA,CAAC;EAAEC,UAAU;EAAEC;AAAc,CAAC,EAAE;EAC3D,MAAM;IAAEC,MAAM;IAAEC;EAAU,CAAC,GAAGH,UAAU;EACxC,MAAMI,UAAU,GAAGhB,sEAAa,CAAC,CAAC;EAElC,oBACCQ,uDAAA,CAAAE,uDAAA;IAAAO,QAAA,gBACCX,sDAAA,CAACL,sEAAiB;MAAAgB,QAAA,eACjBT,uDAAA,CAACN,4DAAS;QAACgB,KAAK,EAAC,iBAAiB;QAAAD,QAAA,gBACjCX,sDAAA,CAACF,8DAAW;UACXe,KAAK,EAAC,SAAS;UACfC,KAAK,EAAEN,MAAO;UACdO,QAAQ,EAAGD,KAAK,IAAKP,aAAa,CAAC;YAAEC,MAAM,EAAEM;UAAM,CAAC,CAAE;UACtDE,IAAI,EAAC;QAA+B,CACpC,CAAC,eACFhB,sDAAA,CAACH,gEAAa;UACbgB,KAAK,EAAC,iBAAiB;UACvBI,OAAO,EAAER,SAAU;UACnBM,QAAQ,EAAGD,KAAK,IAAKP,aAAa,CAAC;YAAEE,SAAS,EAAEK;UAAM,CAAC;QAAE,CACzD,CAAC;MAAA,CACQ;IAAC,CACM,CAAC,eACpBd,sDAAA;MAAA,GAASU,UAAU;MAAAC,QAAA,eAClBT,uDAAA;QAAKgB,SAAS,EAAC,qBAAqB;QAAAP,QAAA,gBACnCT,uDAAA;UAAAS,QAAA,GAAG,eAAa,EAACH,MAAM,IAAI,gBAAgB;QAAA,CAAI,CAAC,eAChDN,uDAAA;UAAAS,QAAA,GAAG,SAAO,EAACF,SAAS,GAAG,WAAW,GAAG,UAAU;QAAA,CAAI,CAAC;MAAA,CAChD;IAAC,CACF,CAAC;EAAA,CACL,CAAC;AAEL,C;;;;;;;;;;;;;;;;;AChCsD;AAC5B;AACA;AACJ;AACC;AAEvBU,oEAAiB,CAAC,iBAAiB,EAAE;EACpCC,IAAI;EACJC,IAAIA,+CAAAA;AACL,CAAC,CAAC,C;;;;;;;;;;;;;;ACTa,SAASA,IAAIA,CAAA,EAAG;EAC9B,OAAO,IAAI,CAAC,CAAC;AACd,C;;;;;;;;;;;ACFA;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA,2C;;;;;;;;;;ACAA,6C;;;;;;;;;;ACAA,wC;;;;;;;;;;ACAA,4C;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WC/BA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G;;;;;UEjDA;UACA;UACA;UACA;UACA","sources":["webpack://jvb/./src/drawer-menu/edit.js","webpack://jvb/./src/drawer-menu/index.js","webpack://jvb/./src/drawer-menu/save.js","webpack://jvb/./src/drawer-menu/editor.scss","webpack://jvb/./src/drawer-menu/style.scss?537e","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"components\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["import { useBlockProps, InspectorControls } from '@wordpress/block-editor';\r\nimport { PanelBody, ToggleControl, TextControl } from '@wordpress/components';\r\n\r\nexport default function Edit({ attributes, setAttributes }) {\r\n\tconst { menuId, collapsed } = attributes;\r\n\tconst blockProps = useBlockProps();\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<InspectorControls>\r\n\t\t\t\t<PanelBody title=\"Drawer Settings\">\r\n\t\t\t\t\t<TextControl\r\n\t\t\t\t\t\tlabel=\"Menu ID\"\r\n\t\t\t\t\t\tvalue={menuId}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ menuId: value })}\r\n\t\t\t\t\t\thelp=\"PHP-generated menu identifier\"\r\n\t\t\t\t\t/>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel=\"Start Collapsed\"\r\n\t\t\t\t\t\tchecked={collapsed}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ collapsed: value })}\r\n\t\t\t\t\t/>\r\n\t\t\t\t</PanelBody>\r\n\t\t\t</InspectorControls>\r\n\t\t\t<div {...blockProps}>\r\n\t\t\t\t<div className=\"drawer-menu-preview\">\r\n\t\t\t\t\t<p>Drawer Menu: {menuId || 'Not configured'}</p>\r\n\t\t\t\t\t<p>State: {collapsed ? 'Collapsed' : 'Expanded'}</p>\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\t\t</>\r\n\t);\r\n}\r\n","import { registerBlockType } from '@wordpress/blocks';\r\nimport edit from './edit';\r\nimport save from './save';\r\nimport './style.scss';\r\nimport './editor.scss';\r\n\r\nregisterBlockType('jvb/drawer-menu', {\r\n\tedit,\r\n\tsave,\r\n});\r\n","export default function save() {\r\n\treturn null; // Server-side rendered\r\n}\r\n","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"components\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"drawer-menu/index\": 0,\n\t\"drawer-menu/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"drawer-menu/style-index\"], () => (__webpack_require__(\"./src/drawer-menu/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["useBlockProps","InspectorControls","PanelBody","ToggleControl","TextControl","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","Edit","attributes","setAttributes","menuId","collapsed","blockProps","children","title","label","value","onChange","help","checked","className","registerBlockType","edit","save"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/drawer-menu/render.php b/build/drawer-menu/render.php
index d2fe96c..b3d9bbc 100644
--- a/build/drawer-menu/render.php
+++ b/build/drawer-menu/render.php
@@ -1,41 +1 @@
 <?php
-
-use JVBase\managers\Cache;
-use JVBase\ui\Navigation;
-
-$menu_id = $attributes['menuId'] ?? '';
-$collapsed = $attributes['collapsed'] ?? true;
-
-// You'd populate this from options, a filter, or however you store menu data
-$menu_items = apply_filters('jvbDrawerItems', [], $menu_id);
-
-if (empty($menu_items) || empty($menu_id)) {
-	return '<p>Please configure the drawer menu in block settings.</p>';
-}
-
-$cache = Cache::for('drawer');
-if (JVB_TESTING) {
-	$cache->flush();
-}
-
-if (!is_front_page()) {
-	$menu_items[] = [
-		'text'	=> 'Home',
-		'url'	=> home_url(),
-		'icon'	=> 'house-simple',
-	];
-}
-$items = array_map(function($item) { return $item['text'];}, $menu_items);
-
-$key = $cache->generateKey($items);
-$menu =  $cache->remember($key,
-function () use ($menu_items, $menu_id, $collapsed) {
-	$menu = new Navigation($menu_id);
-	$menu->asDrawer($collapsed)->populateFromArray($menu_items);
-	return $menu->render();
-});
-
-global $wp;
-
-$current = home_url($wp->request.'/');
-echo str_replace($current.'"', $current.'" class="current" aria-current="page"', $menu);
diff --git a/build/drawer-menu/style-index-rtl.css b/build/drawer-menu/style-index-rtl.css
index a917d2d..8fe8c4e 100644
--- a/build/drawer-menu/style-index-rtl.css
+++ b/build/drawer-menu/style-index-rtl.css
@@ -1 +1,89 @@
-nav.drawer{bottom:0;max-height:100vh;overflow:hidden auto;position:fixed;left:0;transition:var(--trans-size);width:var(--btn);z-index:var(--z-5);--dir:column-reverse;background-color:rgb(var(--base));border-right:1px solid rgb(var(--base-200));box-shadow:rgba(var(--base),var(--op-4)) var(--shdw-left);height:auto;--w:var(--chip_)}nav.drawer .section-title,nav.drawer .title{display:none}nav.drawer ul .icon{min-width:var(--chip_)}nav.drawer .a,nav.drawer a{gap:.5rem;height:var(--chipchip);justify-content:center;padding:0 .5rem;width:100%}nav.drawer .toggle{aspect-ratio:unset;width:100%}nav.drawer .toggle .icon{transform:rotate(0);transition:var(--trans-transform)}nav.drawer.open{width:240px}nav.drawer.open .section-title,nav.drawer.open .title{display:block}nav.drawer.open .toggle .icon{transform:rotate(-180deg)}nav.drawer.open .a,nav.drawer.open a{justify-content:flex-start}nav.drawer ul{--dir:column;--gap:0;--height:auto;margin:0;overflow:hidden;padding:0}nav.drawer li,nav.drawer ul{height:auto;width:100%}nav.drawer .row{width:100%}nav.drawer .menu-section{border-bottom:1px solid rgb(var(--contrast-200))}nav.drawer .section-title{font-size:var(--small);font-weight:700;opacity:.6;padding:.5rem var(--px);text-transform:uppercase}.main-actions .buttons.buttons{left:calc(var(--btn_) + .5rem)}nav.on-this-page.on-this-page.on-this-page{max-width:calc(100vw - var(--btn_))!important}
+/*!***************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/drawer-menu/style.scss ***!
+  \***************************************************************************************************************************************************************************************************************************************************/
+nav.drawer {
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  max-height: 100vh;
+  overflow: hidden auto;
+  width: var(--btn);
+  z-index: var(--z-5);
+  transition: var(--trans-size);
+  --dir: column-reverse;
+  background-color: rgb(var(--base));
+  border-right: 1px solid rgb(var(--base-200));
+  box-shadow: rgba(var(--base), var(--op-4)) var(--shdw-left);
+  height: auto;
+  --w: var(--chip_);
+}
+nav.drawer .title,
+nav.drawer .section-title {
+  display: none;
+}
+nav.drawer ul .icon {
+  min-width: var(--chip_);
+}
+nav.drawer a,
+nav.drawer .a {
+  height: var(--chipchip);
+  padding: 0 0.5rem;
+  width: 100%;
+  gap: 0.5rem;
+  justify-content: center;
+}
+nav.drawer .toggle {
+  width: 100%;
+  aspect-ratio: unset;
+}
+nav.drawer .toggle .icon {
+  transform: rotate(0);
+  transition: var(--trans-transform);
+}
+nav.drawer.open {
+  width: 240px;
+}
+nav.drawer.open .title,
+nav.drawer.open .section-title {
+  display: block;
+}
+nav.drawer.open .toggle .icon {
+  transform: rotate(-180deg);
+}
+nav.drawer.open a,
+nav.drawer.open .a {
+  justify-content: flex-start;
+}
+nav.drawer ul {
+  --dir: column;
+  --gap: 0;
+  --height: auto;
+  padding: 0;
+  margin: 0;
+  height: auto;
+  width: 100%;
+  overflow: hidden;
+}
+nav.drawer li {
+  height: auto;
+  width: 100%;
+}
+nav.drawer .row {
+  width: 100%;
+}
+nav.drawer .menu-section {
+  border-bottom: 1px solid rgb(var(--contrast-200));
+}
+nav.drawer .section-title {
+  padding: 0.5rem var(--px);
+  font-size: var(--small);
+  text-transform: uppercase;
+  opacity: 0.6;
+  font-weight: bold;
+}
+.main-actions .buttons.buttons {
+  left: calc(var(--btn_) + 0.5rem);
+}
+nav.on-this-page.on-this-page.on-this-page {
+  width: calc(100vw - var(--btn)) !important;
+}
diff --git a/build/drawer-menu/style-index.css b/build/drawer-menu/style-index.css
index fd861f9..a207881 100644
--- a/build/drawer-menu/style-index.css
+++ b/build/drawer-menu/style-index.css
@@ -1 +1,91 @@
-nav.drawer{bottom:0;max-height:100vh;overflow:hidden auto;position:fixed;right:0;transition:var(--trans-size);width:var(--btn);z-index:var(--z-5);--dir:column-reverse;background-color:rgb(var(--base));border-left:1px solid rgb(var(--base-200));box-shadow:rgba(var(--base),var(--op-4)) var(--shdw-left);height:auto;--w:var(--chip_)}nav.drawer .section-title,nav.drawer .title{display:none}nav.drawer ul .icon{min-width:var(--chip_)}nav.drawer .a,nav.drawer a{gap:.5rem;height:var(--chipchip);justify-content:center;padding:0 .5rem;width:100%}nav.drawer .toggle{aspect-ratio:unset;width:100%}nav.drawer .toggle .icon{transform:rotate(0);transition:var(--trans-transform)}nav.drawer.open{width:240px}nav.drawer.open .section-title,nav.drawer.open .title{display:block}nav.drawer.open .toggle .icon{transform:rotate(180deg)}nav.drawer.open .a,nav.drawer.open a{justify-content:flex-start}nav.drawer ul{--dir:column;--gap:0;--height:auto;margin:0;overflow:hidden;padding:0}nav.drawer li,nav.drawer ul{height:auto;width:100%}nav.drawer .row{width:100%}nav.drawer .menu-section{border-bottom:1px solid rgb(var(--contrast-200))}nav.drawer .section-title{font-size:var(--small);font-weight:700;opacity:.6;padding:.5rem var(--px);text-transform:uppercase}.main-actions .buttons.buttons{right:calc(var(--btn_) + .5rem)}nav.on-this-page.on-this-page.on-this-page{max-width:calc(100vw - var(--btn_))!important}
+/*!***************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/drawer-menu/style.scss ***!
+  \***************************************************************************************************************************************************************************************************************************************************/
+nav.drawer {
+  position: fixed;
+  right: 0;
+  bottom: 0;
+  max-height: 100vh;
+  overflow: hidden auto;
+  width: var(--btn);
+  z-index: var(--z-5);
+  transition: var(--trans-size);
+  --dir: column-reverse;
+  background-color: rgb(var(--base));
+  border-left: 1px solid rgb(var(--base-200));
+  box-shadow: rgba(var(--base), var(--op-4)) var(--shdw-left);
+  height: auto;
+  --w: var(--chip_);
+}
+nav.drawer .title,
+nav.drawer .section-title {
+  display: none;
+}
+nav.drawer ul .icon {
+  min-width: var(--chip_);
+}
+nav.drawer a,
+nav.drawer .a {
+  height: var(--chipchip);
+  padding: 0 0.5rem;
+  width: 100%;
+  gap: 0.5rem;
+  justify-content: center;
+}
+nav.drawer .toggle {
+  width: 100%;
+  aspect-ratio: unset;
+}
+nav.drawer .toggle .icon {
+  transform: rotate(0);
+  transition: var(--trans-transform);
+}
+nav.drawer.open {
+  width: 240px;
+}
+nav.drawer.open .title,
+nav.drawer.open .section-title {
+  display: block;
+}
+nav.drawer.open .toggle .icon {
+  transform: rotate(180deg);
+}
+nav.drawer.open a,
+nav.drawer.open .a {
+  justify-content: flex-start;
+}
+nav.drawer ul {
+  --dir: column;
+  --gap: 0;
+  --height: auto;
+  padding: 0;
+  margin: 0;
+  height: auto;
+  width: 100%;
+  overflow: hidden;
+}
+nav.drawer li {
+  height: auto;
+  width: 100%;
+}
+nav.drawer .row {
+  width: 100%;
+}
+nav.drawer .menu-section {
+  border-bottom: 1px solid rgb(var(--contrast-200));
+}
+nav.drawer .section-title {
+  padding: 0.5rem var(--px);
+  font-size: var(--small);
+  text-transform: uppercase;
+  opacity: 0.6;
+  font-weight: bold;
+}
+.main-actions .buttons.buttons {
+  right: calc(var(--btn_) + 0.5rem);
+}
+nav.on-this-page.on-this-page.on-this-page {
+  width: calc(100vw - var(--btn)) !important;
+}
+
+/*# sourceMappingURL=style-index.css.map*/
\ No newline at end of file
diff --git a/build/drawer-menu/style-index.css.map b/build/drawer-menu/style-index.css.map
new file mode 100644
index 0000000..6dfa5f2
--- /dev/null
+++ b/build/drawer-menu/style-index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"drawer-menu/style-index.css","mappings":";;;AAAA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AACD;AACC;;EAEC;AACF;AACC;EACC;AACF;AAEC;;EAEC;EACA;EACA;EACA;EACA;AAAF;AAGC;EACC;EACA;AADF;AAEE;EACC;EACA;AAAH;AAGC;EACC;AADF;AAEE;;EAEC;AAAH;AAGE;EACC;AADH;AAIE;;EAEC;AAFH;AAMC;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AAJF;AAMC;EACC;EACA;AAJF;AAQC;EACC;AANF;AASC;EACC;AAPF;AASC;EACC;EACA;EACA;EACA;EACA;AAPF;AAYA;EACC;AATD;AAYA;EACC;AATD,C","sources":["webpack://jvb/./src/drawer-menu/style.scss"],"sourcesContent":["nav.drawer {\r\n\tposition: fixed;\r\n\tright: 0;\r\n\tbottom: 0;\r\n\tmax-height: 100vh;\r\n\toverflow: hidden auto;\r\n\twidth: var(--btn);\r\n\tz-index: var(--z-5);\r\n\ttransition: var(--trans-size);\r\n\t--dir: column-reverse;\r\n\tbackground-color: rgb(var(--base));\r\n\tborder-left: 1px solid rgb(var(--base-200));\r\n\tbox-shadow:rgba(var(--base), var(--op-4)) var(--shdw-left);\r\n\theight: auto;\r\n\t--w: var(--chip_);\r\n\r\n\t.title,\r\n\t.section-title {\r\n\t\tdisplay: none;\r\n\t}\r\n\tul .icon {\r\n\t\tmin-width: var(--chip_);\r\n\t}\r\n\r\n\ta,\r\n\t.a {\r\n\t\theight: var(--chipchip);\r\n\t\tpadding: 0 .5rem;\r\n\t\twidth: 100%;\r\n\t\tgap: .5rem;\r\n\t\tjustify-content: center;\r\n\t}\r\n\r\n\t.toggle {\r\n\t\twidth: 100%;\r\n\t\taspect-ratio: unset;\r\n\t\t.icon {\r\n\t\t\ttransform: rotate(0);\r\n\t\t\ttransition: var(--trans-transform);\r\n\t\t}\r\n\t}\r\n\t&.open {\r\n\t\twidth: 240px;\r\n\t\t.title,\r\n\t\t.section-title {\r\n\t\t\tdisplay: block;\r\n\t\t}\r\n\r\n\t\t.toggle .icon {\r\n\t\t\ttransform: rotate(180deg);\r\n\t\t}\r\n\r\n\t\ta,\r\n\t\t.a {\r\n\t\t\tjustify-content: flex-start;\r\n\t\t}\r\n\t}\r\n\r\n\tul {\r\n\t\t--dir: column;\r\n\t\t--gap: 0;\r\n\t\t--height: auto;\r\n\t\tpadding: 0;\r\n\t\tmargin: 0;\r\n\t\theight: auto;\r\n\t\twidth:100%;\r\n\t\toverflow: hidden;\r\n\t}\r\n\tli {\r\n\t\theight: auto;\r\n\t\twidth: 100%;\r\n\t}\r\n\r\n\r\n\t.row {\r\n\t\twidth: 100%;\r\n\t}\r\n\r\n\t.menu-section {\r\n\t\tborder-bottom: 1px solid rgb(var(--contrast-200));\r\n\t}\r\n\t.section-title {\r\n\t\tpadding: 0.5rem var(--px);\r\n\t\tfont-size: var(--small);\r\n\t\ttext-transform: uppercase;\r\n\t\topacity: 0.6;\r\n\t\tfont-weight: bold;\r\n\t}\r\n\r\n}\r\n\r\n.main-actions .buttons.buttons {\r\n\tright: calc(var(--btn_) + .5rem);\r\n}\r\n\r\nnav.on-this-page.on-this-page.on-this-page {\r\n\twidth: calc(100vw - var(--btn))!important;\r\n}\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/faq/index-rtl.css b/build/faq/index-rtl.css
index 2b0a857..5d54b8f 100644
--- a/build/faq/index-rtl.css
+++ b/build/faq/index-rtl.css
@@ -1 +1,84 @@
-.faq-block-editor{background:#f9f9f9;border:2px dashed #ccc;border-radius:8px;padding:2rem}.faq-block-editor .faq-block-preview{text-align:center}.faq-block-editor .faq-block-preview h3{font-size:1.25rem;font-weight:600;margin:0 0 .5rem}.faq-block-editor .faq-block-preview>p{color:#666;margin:0 0 1.5rem}.faq-block-editor .faq-block-preview .faq-sections-preview{background:#fff;border-radius:4px;margin-top:1.5rem;padding:1rem;text-align:right}.faq-block-editor .faq-block-preview .faq-sections-preview strong{display:block;margin-bottom:.5rem}.faq-block-editor .faq-block-preview .faq-sections-preview ol{margin:0;padding-right:1.5rem}.faq-block-editor .faq-block-preview .faq-sections-preview ol li{margin:.25rem 0;padding:.25rem 0}.faq-section-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem}.faq-section-item{align-items:center;background:#fff;border:1px solid #ddd;border-radius:4px;display:flex;gap:.5rem;padding:.5rem .75rem;transition:background .15s ease}.faq-section-item:hover{background:#f9f9f9}.faq-section-controls{display:flex;flex-shrink:0;gap:.25rem}.faq-section-button{height:30px!important;min-width:30px!important;padding:4px!important}.faq-section-button:disabled{cursor:not-allowed;opacity:.3}.faq-section-name{flex:1;font-weight:500;padding-right:.5rem}.components-panel__body .components-notice{margin:1rem 0}
+/*!********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/faq/editor.scss ***!
+  \********************************************************************************************************************************************************************************************************************************************/
+/**
+ * FAQ Block - Editor Styles
+ */
+.faq-block-editor {
+  padding: 2rem;
+  border: 2px dashed #ccc;
+  border-radius: 8px;
+  background: #f9f9f9;
+}
+.faq-block-editor .faq-block-preview {
+  text-align: center;
+}
+.faq-block-editor .faq-block-preview h3 {
+  margin: 0 0 0.5rem;
+  font-size: 1.25rem;
+  font-weight: 600;
+}
+.faq-block-editor .faq-block-preview > p {
+  margin: 0 0 1.5rem;
+  color: #666;
+}
+.faq-block-editor .faq-block-preview .faq-sections-preview {
+  margin-top: 1.5rem;
+  text-align: right;
+  background: white;
+  padding: 1rem;
+  border-radius: 4px;
+}
+.faq-block-editor .faq-block-preview .faq-sections-preview strong {
+  display: block;
+  margin-bottom: 0.5rem;
+}
+.faq-block-editor .faq-block-preview .faq-sections-preview ol {
+  margin: 0;
+  padding-right: 1.5rem;
+}
+.faq-block-editor .faq-block-preview .faq-sections-preview ol li {
+  margin: 0.25rem 0;
+  padding: 0.25rem 0;
+}
+.faq-section-list {
+  display: flex;
+  flex-direction: column;
+  gap: 0.5rem;
+  margin-top: 0.5rem;
+}
+.faq-section-item {
+  display: flex;
+  align-items: center;
+  gap: 0.5rem;
+  padding: 0.5rem 0.75rem;
+  background: white;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  transition: background 150ms ease;
+}
+.faq-section-item:hover {
+  background: #f9f9f9;
+}
+.faq-section-controls {
+  display: flex;
+  gap: 0.25rem;
+  flex-shrink: 0;
+}
+.faq-section-button {
+  min-width: 30px !important;
+  padding: 4px !important;
+  height: 30px !important;
+}
+.faq-section-button:disabled {
+  opacity: 0.3;
+  cursor: not-allowed;
+}
+.faq-section-name {
+  flex: 1;
+  font-weight: 500;
+  padding-right: 0.5rem;
+}
+.components-panel__body .components-notice {
+  margin: 1rem 0;
+}
diff --git a/build/faq/index.asset.php b/build/faq/index.asset.php
index c462b08..89d33d2 100644
--- a/build/faq/index.asset.php
+++ b/build/faq/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '4f3282194e1c2db371a3');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '48d21a70dd8a090baee8');
diff --git a/build/faq/index.css b/build/faq/index.css
index 61a5670..51a6abd 100644
--- a/build/faq/index.css
+++ b/build/faq/index.css
@@ -1 +1,86 @@
-.faq-block-editor{background:#f9f9f9;border:2px dashed #ccc;border-radius:8px;padding:2rem}.faq-block-editor .faq-block-preview{text-align:center}.faq-block-editor .faq-block-preview h3{font-size:1.25rem;font-weight:600;margin:0 0 .5rem}.faq-block-editor .faq-block-preview>p{color:#666;margin:0 0 1.5rem}.faq-block-editor .faq-block-preview .faq-sections-preview{background:#fff;border-radius:4px;margin-top:1.5rem;padding:1rem;text-align:left}.faq-block-editor .faq-block-preview .faq-sections-preview strong{display:block;margin-bottom:.5rem}.faq-block-editor .faq-block-preview .faq-sections-preview ol{margin:0;padding-left:1.5rem}.faq-block-editor .faq-block-preview .faq-sections-preview ol li{margin:.25rem 0;padding:.25rem 0}.faq-section-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.5rem}.faq-section-item{align-items:center;background:#fff;border:1px solid #ddd;border-radius:4px;display:flex;gap:.5rem;padding:.5rem .75rem;transition:background .15s ease}.faq-section-item:hover{background:#f9f9f9}.faq-section-controls{display:flex;flex-shrink:0;gap:.25rem}.faq-section-button{height:30px!important;min-width:30px!important;padding:4px!important}.faq-section-button:disabled{cursor:not-allowed;opacity:.3}.faq-section-name{flex:1;font-weight:500;padding-left:.5rem}.components-panel__body .components-notice{margin:1rem 0}
+/*!********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/faq/editor.scss ***!
+  \********************************************************************************************************************************************************************************************************************************************/
+/**
+ * FAQ Block - Editor Styles
+ */
+.faq-block-editor {
+  padding: 2rem;
+  border: 2px dashed #ccc;
+  border-radius: 8px;
+  background: #f9f9f9;
+}
+.faq-block-editor .faq-block-preview {
+  text-align: center;
+}
+.faq-block-editor .faq-block-preview h3 {
+  margin: 0 0 0.5rem;
+  font-size: 1.25rem;
+  font-weight: 600;
+}
+.faq-block-editor .faq-block-preview > p {
+  margin: 0 0 1.5rem;
+  color: #666;
+}
+.faq-block-editor .faq-block-preview .faq-sections-preview {
+  margin-top: 1.5rem;
+  text-align: left;
+  background: white;
+  padding: 1rem;
+  border-radius: 4px;
+}
+.faq-block-editor .faq-block-preview .faq-sections-preview strong {
+  display: block;
+  margin-bottom: 0.5rem;
+}
+.faq-block-editor .faq-block-preview .faq-sections-preview ol {
+  margin: 0;
+  padding-left: 1.5rem;
+}
+.faq-block-editor .faq-block-preview .faq-sections-preview ol li {
+  margin: 0.25rem 0;
+  padding: 0.25rem 0;
+}
+.faq-section-list {
+  display: flex;
+  flex-direction: column;
+  gap: 0.5rem;
+  margin-top: 0.5rem;
+}
+.faq-section-item {
+  display: flex;
+  align-items: center;
+  gap: 0.5rem;
+  padding: 0.5rem 0.75rem;
+  background: white;
+  border: 1px solid #ddd;
+  border-radius: 4px;
+  transition: background 150ms ease;
+}
+.faq-section-item:hover {
+  background: #f9f9f9;
+}
+.faq-section-controls {
+  display: flex;
+  gap: 0.25rem;
+  flex-shrink: 0;
+}
+.faq-section-button {
+  min-width: 30px !important;
+  padding: 4px !important;
+  height: 30px !important;
+}
+.faq-section-button:disabled {
+  opacity: 0.3;
+  cursor: not-allowed;
+}
+.faq-section-name {
+  flex: 1;
+  font-weight: 500;
+  padding-left: 0.5rem;
+}
+.components-panel__body .components-notice {
+  margin: 1rem 0;
+}
+
+/*# sourceMappingURL=index.css.map*/
\ No newline at end of file
diff --git a/build/faq/index.css.map b/build/faq/index.css.map
new file mode 100644
index 0000000..6045d9c
--- /dev/null
+++ b/build/faq/index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"faq/index.css","mappings":";;;AAAA;;EAAA;AAIA;EACC;EACA;EACA;EACA;AAAD;AAEC;EACC;AAAF;AAEE;EACC;EACA;EACA;AAAH;AAGE;EACC;EACA;AADH;AAIE;EACC;EACA;EACA;EACA;EACA;AAFH;AAIG;EACC;EACA;AAFJ;AAKG;EACC;EACA;AAHJ;AAKI;EACC;EACA;AAHL;AAWA;EACC;EACA;EACA;EACA;AARD;AAWA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AARD;AAUC;EACC;AARF;AAYA;EACC;EACA;EACA;AATD;AAYA;EACC;EACA;EACA;AATD;AAWC;EACC;EACA;AATF;AAaA;EACC;EACA;EACA;AAVD;AAcA;EACC;AAXD,C","sources":["webpack://jvb/./src/faq/editor.scss"],"sourcesContent":["/**\r\n * FAQ Block - Editor Styles\r\n */\r\n\r\n.faq-block-editor {\r\n\tpadding: 2rem;\r\n\tborder: 2px dashed #ccc;\r\n\tborder-radius: 8px;\r\n\tbackground: #f9f9f9;\r\n\r\n\t.faq-block-preview {\r\n\t\ttext-align: center;\r\n\r\n\t\th3 {\r\n\t\t\tmargin: 0 0 0.5rem;\r\n\t\t\tfont-size: 1.25rem;\r\n\t\t\tfont-weight: 600;\r\n\t\t}\r\n\r\n\t\t> p {\r\n\t\t\tmargin: 0 0 1.5rem;\r\n\t\t\tcolor: #666;\r\n\t\t}\r\n\r\n\t\t.faq-sections-preview {\r\n\t\t\tmargin-top: 1.5rem;\r\n\t\t\ttext-align: left;\r\n\t\t\tbackground: white;\r\n\t\t\tpadding: 1rem;\r\n\t\t\tborder-radius: 4px;\r\n\r\n\t\t\tstrong {\r\n\t\t\t\tdisplay: block;\r\n\t\t\t\tmargin-bottom: 0.5rem;\r\n\t\t\t}\r\n\r\n\t\t\tol {\r\n\t\t\t\tmargin: 0;\r\n\t\t\t\tpadding-left: 1.5rem;\r\n\r\n\t\t\t\tli {\r\n\t\t\t\t\tmargin: 0.25rem 0;\r\n\t\t\t\t\tpadding: 0.25rem 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\n// Inspector Controls\r\n.faq-section-list {\r\n\tdisplay: flex;\r\n\tflex-direction: column;\r\n\tgap: 0.5rem;\r\n\tmargin-top: 0.5rem;\r\n}\r\n\r\n.faq-section-item {\r\n\tdisplay: flex;\r\n\talign-items: center;\r\n\tgap: 0.5rem;\r\n\tpadding: 0.5rem 0.75rem;\r\n\tbackground: white;\r\n\tborder: 1px solid #ddd;\r\n\tborder-radius: 4px;\r\n\ttransition: background 150ms ease;\r\n\r\n\t&:hover {\r\n\t\tbackground: #f9f9f9;\r\n\t}\r\n}\r\n\r\n.faq-section-controls {\r\n\tdisplay: flex;\r\n\tgap: 0.25rem;\r\n\tflex-shrink: 0;\r\n}\r\n\r\n.faq-section-button {\r\n\tmin-width: 30px !important;\r\n\tpadding: 4px !important;\r\n\theight: 30px !important;\r\n\r\n\t&:disabled {\r\n\t\topacity: 0.3;\r\n\t\tcursor: not-allowed;\r\n\t}\r\n}\r\n\r\n.faq-section-name {\r\n\tflex: 1;\r\n\tfont-weight: 500;\r\n\tpadding-left: 0.5rem;\r\n}\r\n\r\n// Notice adjustments\r\n.components-panel__body .components-notice {\r\n\tmargin: 1rem 0;\r\n}\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/faq/index.js b/build/faq/index.js
index 4c54c25..e94f3e8 100644
--- a/build/faq/index.js
+++ b/build/faq/index.js
@@ -1 +1,479 @@
-(()=>{"use strict";var e,s={604(){const e=window.wp.blocks,s=window.wp.blockEditor,n=window.wp.components,i=window.wp.i18n,o=window.wp.element,t=window.ReactJSXRuntime;(0,e.registerBlockType)("jvb/faq",{edit:function({attributes:e,setAttributes:l}){const{sectionOrder:a,showSectionTitles:c,collapseByDefault:r}=e,[d,h]=(0,o.useState)([]),p=window.jvbFaq?.sections||[];(0,o.useEffect)(()=>{if(p.length)if(0===a.length){const e=p.map(e=>({id:e.id,name:e.name}));h(e),l({sectionOrder:e.map(e=>e.id)})}else{const e=[],s=new Set(a);a.forEach(s=>{const n=p.find(e=>e.id===s);n&&e.push({id:n.id,name:n.name})}),p.forEach(n=>{s.has(n.id)||e.push({id:n.id,name:n.name})}),h(e)}},[p,a]);const b=(e,s)=>{const n=[...d],i="up"===s?e-1:e+1;i<0||i>=n.length||([n[e],n[i]]=[n[i],n[e]],h(n),l({sectionOrder:n.map(e=>e.id)}))},v=(0,s.useBlockProps)({className:"faq-block-editor"});return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsxs)(s.InspectorControls,{children:[(0,t.jsxs)(n.PanelBody,{title:(0,i.__)("FAQ Settings","jvb"),initialOpen:!0,children:[(0,t.jsx)(n.ToggleControl,{label:(0,i.__)("Show Section Titles","jvb"),checked:c,onChange:e=>l({showSectionTitles:e}),help:(0,i.__)("Display section names as headings","jvb")}),(0,t.jsx)(n.ToggleControl,{label:(0,i.__)("Collapse by Default","jvb"),checked:r,onChange:e=>l({collapseByDefault:e}),help:(0,i.__)("Questions start collapsed and expand on click","jvb")})]}),(0,t.jsxs)(n.PanelBody,{title:(0,i.__)("Section Order","jvb"),initialOpen:!1,children:[(0,t.jsx)("p",{className:"components-base-control__help",children:(0,i.__)("Use the arrow buttons to reorder sections","jvb")}),d.length>0?(0,t.jsx)("div",{className:"faq-section-list",children:d.map((e,s)=>(0,t.jsxs)("div",{className:"faq-section-item",children:[(0,t.jsxs)("div",{className:"faq-section-controls",children:[(0,t.jsx)(n.Button,{icon:"arrow-up-alt2",label:(0,i.__)("Move up","jvb"),disabled:0===s,onClick:()=>b(s,"up"),className:"faq-section-button"}),(0,t.jsx)(n.Button,{icon:"arrow-down-alt2",label:(0,i.__)("Move down","jvb"),disabled:s===d.length-1,onClick:()=>b(s,"down"),className:"faq-section-button"})]}),(0,t.jsx)("span",{className:"faq-section-name",children:e.name})]},e.id))}):(0,t.jsx)(n.Notice,{status:"info",isDismissible:!1,children:(0,i.__)("No sections found. Create sections in the FAQ taxonomy.","jvb")})]})]}),(0,t.jsx)("div",{...v,children:(0,t.jsxs)("div",{className:"faq-block-preview",children:[(0,t.jsx)("h3",{children:(0,i.__)("FAQ Block","jvb")}),(0,t.jsx)("p",{children:(0,i.__)("This block will display FAQs organized by sections.","jvb")}),d.length>0?(0,t.jsxs)("div",{className:"faq-sections-preview",children:[(0,t.jsx)("strong",{children:(0,i.__)("Section Order:","jvb")}),(0,t.jsx)("ol",{children:d.map(e=>(0,t.jsx)("li",{children:e.name},e.id))})]}):(0,t.jsx)(n.Notice,{status:"warning",isDismissible:!1,children:(0,i.__)("No sections available. Create sections in the FAQ taxonomy.","jvb")})]})})]})},save:()=>null})}},n={};function i(e){var o=n[e];if(void 0!==o)return o.exports;var t=n[e]={exports:{}};return s[e](t,t.exports,i),t.exports}i.m=s,e=[],i.O=(s,n,o,t)=>{if(!n){var l=1/0;for(d=0;d<e.length;d++){for(var[n,o,t]=e[d],a=!0,c=0;c<n.length;c++)(!1&t||l>=t)&&Object.keys(i.O).every(e=>i.O[e](n[c]))?n.splice(c--,1):(a=!1,t<l&&(l=t));if(a){e.splice(d--,1);var r=o();void 0!==r&&(s=r)}}return s}t=t||0;for(var d=e.length;d>0&&e[d-1][2]>t;d--)e[d]=e[d-1];e[d]=[n,o,t]},i.o=(e,s)=>Object.prototype.hasOwnProperty.call(e,s),(()=>{var e={456:0,656:0};i.O.j=s=>0===e[s];var s=(s,n)=>{var o,t,[l,a,c]=n,r=0;if(l.some(s=>0!==e[s])){for(o in a)i.o(a,o)&&(i.m[o]=a[o]);if(c)var d=c(i)}for(s&&s(n);r<l.length;r++)t=l[r],i.o(e,t)&&e[t]&&e[t][0](),e[t]=0;return i.O(d)},n=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];n.forEach(s.bind(null,0)),n.push=s.bind(null,n.push.bind(n))})();var o=i.O(void 0,[656],()=>i(604));o=i.O(o)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/faq/edit.js"
+/*!*************************!*\
+  !*** ./src/faq/edit.js ***!
+  \*************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__);
+/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
+/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_3__);
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./editor.scss */ "./src/faq/editor.scss");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__);
+
+
+
+
+
+
+function Edit({
+  attributes,
+  setAttributes
+}) {
+  const {
+    sectionOrder,
+    showSectionTitles,
+    collapseByDefault
+  } = attributes;
+  const [sections, setSections] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_3__.useState)([]);
+
+  // Get sections from localized script
+  const allSections = window.jvbFaq?.sections || [];
+
+  // Initialize sections with proper ordering
+  (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_3__.useEffect)(() => {
+    if (!allSections.length) return;
+    if (sectionOrder.length === 0) {
+      // First time - use default order
+      const orderedSections = allSections.map(section => ({
+        id: section.id,
+        name: section.name
+      }));
+      setSections(orderedSections);
+      setAttributes({
+        sectionOrder: orderedSections.map(s => s.id)
+      });
+    } else {
+      // Use saved order, add any new sections at the end
+      const orderedSections = [];
+      const existingIds = new Set(sectionOrder);
+
+      // Add sections in saved order
+      sectionOrder.forEach(id => {
+        const section = allSections.find(s => s.id === id);
+        if (section) {
+          orderedSections.push({
+            id: section.id,
+            name: section.name
+          });
+        }
+      });
+
+      // Add any new sections that weren't in the saved order
+      allSections.forEach(section => {
+        if (!existingIds.has(section.id)) {
+          orderedSections.push({
+            id: section.id,
+            name: section.name
+          });
+        }
+      });
+      setSections(orderedSections);
+    }
+  }, [allSections, sectionOrder]);
+  const moveSection = (index, direction) => {
+    const newSections = [...sections];
+    const newIndex = direction === 'up' ? index - 1 : index + 1;
+    if (newIndex < 0 || newIndex >= newSections.length) return;
+
+    // Swap sections
+    [newSections[index], newSections[newIndex]] = [newSections[newIndex], newSections[index]];
+    setSections(newSections);
+    setAttributes({
+      sectionOrder: newSections.map(s => s.id)
+    });
+  };
+  const blockProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__.useBlockProps)({
+    className: 'faq-block-editor'
+  });
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.Fragment, {
+    children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__.InspectorControls, {
+      children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, {
+        title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('FAQ Settings', 'jvb'),
+        initialOpen: true,
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Show Section Titles', 'jvb'),
+          checked: showSectionTitles,
+          onChange: value => setAttributes({
+            showSectionTitles: value
+          }),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Display section names as headings', 'jvb')
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Collapse by Default', 'jvb'),
+          checked: collapseByDefault,
+          onChange: value => setAttributes({
+            collapseByDefault: value
+          }),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Questions start collapsed and expand on click', 'jvb')
+        })]
+      }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, {
+        title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Section Order', 'jvb'),
+        initialOpen: false,
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+          className: "components-base-control__help",
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Use the arrow buttons to reorder sections', 'jvb')
+        }), sections.length > 0 ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+          className: "faq-section-list",
+          children: sections.map((section, index) => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+            className: "faq-section-item",
+            children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+              className: "faq-section-controls",
+              children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Button, {
+                icon: "arrow-up-alt2",
+                label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Move up', 'jvb'),
+                disabled: index === 0,
+                onClick: () => moveSection(index, 'up'),
+                className: "faq-section-button"
+              }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Button, {
+                icon: "arrow-down-alt2",
+                label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Move down', 'jvb'),
+                disabled: index === sections.length - 1,
+                onClick: () => moveSection(index, 'down'),
+                className: "faq-section-button"
+              })]
+            }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("span", {
+              className: "faq-section-name",
+              children: section.name
+            })]
+          }, section.id))
+        }) : /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Notice, {
+          status: "info",
+          isDismissible: false,
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('No sections found. Create sections in the FAQ taxonomy.', 'jvb')
+        })]
+      })]
+    }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+      ...blockProps,
+      children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+        className: "faq-block-preview",
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("h3", {
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('FAQ Block', 'jvb')
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('This block will display FAQs organized by sections.', 'jvb')
+        }), sections.length > 0 ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+          className: "faq-sections-preview",
+          children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("strong", {
+            children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Section Order:', 'jvb')
+          }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("ol", {
+            children: sections.map(section => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("li", {
+              children: section.name
+            }, section.id))
+          })]
+        }) : /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.Notice, {
+          status: "warning",
+          isDismissible: false,
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('No sections available. Create sections in the FAQ taxonomy.', 'jvb')
+        })]
+      })
+    })]
+  });
+}
+
+/***/ },
+
+/***/ "./src/faq/index.js"
+/*!**************************!*\
+  !*** ./src/faq/index.js ***!
+  \**************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./edit */ "./src/faq/edit.js");
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./style.scss */ "./src/faq/style.scss");
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./editor.scss */ "./src/faq/editor.scss");
+/* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./block.json */ "./src/faq/block.json");
+
+
+
+
+
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)(_block_json__WEBPACK_IMPORTED_MODULE_4__.name, {
+  edit: _edit__WEBPACK_IMPORTED_MODULE_1__["default"],
+  // No save function - dynamic block rendered on server
+  save: () => null
+});
+
+/***/ },
+
+/***/ "./src/faq/editor.scss"
+/*!*****************************!*\
+  !*** ./src/faq/editor.scss ***!
+  \*****************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "./src/faq/style.scss"
+/*!****************************!*\
+  !*** ./src/faq/style.scss ***!
+  \****************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/components"
+/*!************************************!*\
+  !*** external ["wp","components"] ***!
+  \************************************/
+(module) {
+
+module.exports = window["wp"]["components"];
+
+/***/ },
+
+/***/ "@wordpress/element"
+/*!*********************************!*\
+  !*** external ["wp","element"] ***!
+  \*********************************/
+(module) {
+
+module.exports = window["wp"]["element"];
+
+/***/ },
+
+/***/ "@wordpress/i18n"
+/*!******************************!*\
+  !*** external ["wp","i18n"] ***!
+  \******************************/
+(module) {
+
+module.exports = window["wp"]["i18n"];
+
+/***/ },
+
+/***/ "./src/faq/block.json"
+/*!****************************!*\
+  !*** ./src/faq/block.json ***!
+  \****************************/
+(module) {
+
+module.exports = /*#__PURE__*/JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/faq","title":"FAQ Block","category":"jvb","icon":"info","description":"Display FAQs organized by sections with customizable ordering","keywords":["faq","questions","help"],"version":"1.0.0","textdomain":"jvb","attributes":{"sectionOrder":{"type":"array","default":[]},"showSectionTitles":{"type":"boolean","default":true},"collapseByDefault":{"type":"boolean","default":false}},"supports":{"align":["wide","full"],"html":false},"editorScript":"file:./index.js","editorStyle":"file:./index.css","style":"file:./style-index.css","viewScript":"file:./view.js"}');
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"faq/index": 0,
+/******/ 			"faq/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["faq/style-index"], () => (__webpack_require__("./src/faq/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/faq/index.js.map b/build/faq/index.js.map
new file mode 100644
index 0000000..fb1458a
--- /dev/null
+++ b/build/faq/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"faq/index.js","mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAA2E;AACM;AAC5C;AACoB;AAClC;AAAA;AAER,SAASe,IAAIA,CAAC;EAAEC,UAAU;EAAEC;AAAc,CAAC,EAAE;EAC3D,MAAM;IAAEC,YAAY;IAAEC,iBAAiB;IAAEC;EAAkB,CAAC,GAAGJ,UAAU;EACzE,MAAM,CAACK,QAAQ,EAAEC,WAAW,CAAC,GAAGf,4DAAQ,CAAC,EAAE,CAAC;;EAE5C;EACA,MAAMgB,WAAW,GAAGC,MAAM,CAACC,MAAM,EAAEJ,QAAQ,IAAI,EAAE;;EAEjD;EACAb,6DAAS,CAAC,MAAM;IACf,IAAI,CAACe,WAAW,CAACG,MAAM,EAAE;IAEzB,IAAIR,YAAY,CAACQ,MAAM,KAAK,CAAC,EAAE;MAC9B;MACA,MAAMC,eAAe,GAAGJ,WAAW,CAACK,GAAG,CAACC,OAAO,KAAK;QACnDC,EAAE,EAAED,OAAO,CAACC,EAAE;QACdC,IAAI,EAAEF,OAAO,CAACE;MACf,CAAC,CAAC,CAAC;MACHT,WAAW,CAACK,eAAe,CAAC;MAC5BV,aAAa,CAAC;QAAEC,YAAY,EAAES,eAAe,CAACC,GAAG,CAACI,CAAC,IAAIA,CAAC,CAACF,EAAE;MAAE,CAAC,CAAC;IAChE,CAAC,MAAM;MACN;MACA,MAAMH,eAAe,GAAG,EAAE;MAC1B,MAAMM,WAAW,GAAG,IAAIC,GAAG,CAAChB,YAAY,CAAC;;MAEzC;MACAA,YAAY,CAACiB,OAAO,CAACL,EAAE,IAAI;QAC1B,MAAMD,OAAO,GAAGN,WAAW,CAACa,IAAI,CAACJ,CAAC,IAAIA,CAAC,CAACF,EAAE,KAAKA,EAAE,CAAC;QAClD,IAAID,OAAO,EAAE;UACZF,eAAe,CAACU,IAAI,CAAC;YAAEP,EAAE,EAAED,OAAO,CAACC,EAAE;YAAEC,IAAI,EAAEF,OAAO,CAACE;UAAK,CAAC,CAAC;QAC7D;MACD,CAAC,CAAC;;MAEF;MACAR,WAAW,CAACY,OAAO,CAACN,OAAO,IAAI;QAC9B,IAAI,CAACI,WAAW,CAACK,GAAG,CAACT,OAAO,CAACC,EAAE,CAAC,EAAE;UACjCH,eAAe,CAACU,IAAI,CAAC;YAAEP,EAAE,EAAED,OAAO,CAACC,EAAE;YAAEC,IAAI,EAAEF,OAAO,CAACE;UAAK,CAAC,CAAC;QAC7D;MACD,CAAC,CAAC;MAEFT,WAAW,CAACK,eAAe,CAAC;IAC7B;EACD,CAAC,EAAE,CAACJ,WAAW,EAAEL,YAAY,CAAC,CAAC;EAE/B,MAAMqB,WAAW,GAAGA,CAACC,KAAK,EAAEC,SAAS,KAAK;IACzC,MAAMC,WAAW,GAAG,CAAC,GAAGrB,QAAQ,CAAC;IACjC,MAAMsB,QAAQ,GAAGF,SAAS,KAAK,IAAI,GAAGD,KAAK,GAAG,CAAC,GAAGA,KAAK,GAAG,CAAC;IAE3D,IAAIG,QAAQ,GAAG,CAAC,IAAIA,QAAQ,IAAID,WAAW,CAAChB,MAAM,EAAE;;IAEpD;IACA,CAACgB,WAAW,CAACF,KAAK,CAAC,EAAEE,WAAW,CAACC,QAAQ,CAAC,CAAC,GAAG,CAACD,WAAW,CAACC,QAAQ,CAAC,EAAED,WAAW,CAACF,KAAK,CAAC,CAAC;IAEzFlB,WAAW,CAACoB,WAAW,CAAC;IACxBzB,aAAa,CAAC;MAAEC,YAAY,EAAEwB,WAAW,CAACd,GAAG,CAACI,CAAC,IAAIA,CAAC,CAACF,EAAE;IAAE,CAAC,CAAC;EAC5D,CAAC;EAED,MAAMc,UAAU,GAAG5C,sEAAa,CAAC;IAChC6C,SAAS,EAAE;EACZ,CAAC,CAAC;EAEF,oBACCjC,uDAAA,CAAAE,uDAAA;IAAAgC,QAAA,gBACClC,uDAAA,CAACX,sEAAiB;MAAA6C,QAAA,gBACjBlC,uDAAA,CAACV,4DAAS;QAAC6C,KAAK,EAAEzC,mDAAE,CAAC,cAAc,EAAE,KAAK,CAAE;QAAC0C,WAAW,EAAE,IAAK;QAAAF,QAAA,gBAC9DpC,sDAAA,CAACP,gEAAa;UACb8C,KAAK,EAAE3C,mDAAE,CAAC,qBAAqB,EAAE,KAAK,CAAE;UACxC4C,OAAO,EAAE/B,iBAAkB;UAC3BgC,QAAQ,EAAGC,KAAK,IAAKnC,aAAa,CAAC;YAAEE,iBAAiB,EAAEiC;UAAM,CAAC,CAAE;UACjEC,IAAI,EAAE/C,mDAAE,CAAC,mCAAmC,EAAE,KAAK;QAAE,CACrD,CAAC,eACFI,sDAAA,CAACP,gEAAa;UACb8C,KAAK,EAAE3C,mDAAE,CAAC,qBAAqB,EAAE,KAAK,CAAE;UACxC4C,OAAO,EAAE9B,iBAAkB;UAC3B+B,QAAQ,EAAGC,KAAK,IAAKnC,aAAa,CAAC;YAAEG,iBAAiB,EAAEgC;UAAM,CAAC,CAAE;UACjEC,IAAI,EAAE/C,mDAAE,CAAC,+CAA+C,EAAE,KAAK;QAAE,CACjE,CAAC;MAAA,CACQ,CAAC,eAEZM,uDAAA,CAACV,4DAAS;QAAC6C,KAAK,EAAEzC,mDAAE,CAAC,eAAe,EAAE,KAAK,CAAE;QAAC0C,WAAW,EAAE,KAAM;QAAAF,QAAA,gBAChEpC,sDAAA;UAAGmC,SAAS,EAAC,+BAA+B;UAAAC,QAAA,EAC1CxC,mDAAE,CAAC,2CAA2C,EAAE,KAAK;QAAC,CACrD,CAAC,EACHe,QAAQ,CAACK,MAAM,GAAG,CAAC,gBACnBhB,sDAAA;UAAKmC,SAAS,EAAC,kBAAkB;UAAAC,QAAA,EAC/BzB,QAAQ,CAACO,GAAG,CAAC,CAACC,OAAO,EAAEW,KAAK,kBAC5B5B,uDAAA;YAAsBiC,SAAS,EAAC,kBAAkB;YAAAC,QAAA,gBACjDlC,uDAAA;cAAKiC,SAAS,EAAC,sBAAsB;cAAAC,QAAA,gBACpCpC,sDAAA,CAACL,yDAAM;gBACNiD,IAAI,EAAC,eAAe;gBACpBL,KAAK,EAAE3C,mDAAE,CAAC,SAAS,EAAE,KAAK,CAAE;gBAC5BiD,QAAQ,EAAEf,KAAK,KAAK,CAAE;gBACtBgB,OAAO,EAAEA,CAAA,KAAMjB,WAAW,CAACC,KAAK,EAAE,IAAI,CAAE;gBACxCK,SAAS,EAAC;cAAoB,CAC9B,CAAC,eACFnC,sDAAA,CAACL,yDAAM;gBACNiD,IAAI,EAAC,iBAAiB;gBACtBL,KAAK,EAAE3C,mDAAE,CAAC,WAAW,EAAE,KAAK,CAAE;gBAC9BiD,QAAQ,EAAEf,KAAK,KAAKnB,QAAQ,CAACK,MAAM,GAAG,CAAE;gBACxC8B,OAAO,EAAEA,CAAA,KAAMjB,WAAW,CAACC,KAAK,EAAE,MAAM,CAAE;gBAC1CK,SAAS,EAAC;cAAoB,CAC9B,CAAC;YAAA,CACE,CAAC,eACNnC,sDAAA;cAAMmC,SAAS,EAAC,kBAAkB;cAAAC,QAAA,EAAEjB,OAAO,CAACE;YAAI,CAAO,CAAC;UAAA,GAjB/CF,OAAO,CAACC,EAkBb,CACL;QAAC,CACE,CAAC,gBAENpB,sDAAA,CAACN,yDAAM;UAACqD,MAAM,EAAC,MAAM;UAACC,aAAa,EAAE,KAAM;UAAAZ,QAAA,EACzCxC,mDAAE,CAAC,yDAAyD,EAAE,KAAK;QAAC,CAC9D,CACR;MAAA,CACS,CAAC;IAAA,CACM,CAAC,eAEpBI,sDAAA;MAAA,GAASkC,UAAU;MAAAE,QAAA,eAClBlC,uDAAA;QAAKiC,SAAS,EAAC,mBAAmB;QAAAC,QAAA,gBACjCpC,sDAAA;UAAAoC,QAAA,EAAKxC,mDAAE,CAAC,WAAW,EAAE,KAAK;QAAC,CAAK,CAAC,eACjCI,sDAAA;UAAAoC,QAAA,EACExC,mDAAE,CAAC,qDAAqD,EAAE,KAAK;QAAC,CAC/D,CAAC,EACHe,QAAQ,CAACK,MAAM,GAAG,CAAC,gBACnBd,uDAAA;UAAKiC,SAAS,EAAC,sBAAsB;UAAAC,QAAA,gBACpCpC,sDAAA;YAAAoC,QAAA,EAASxC,mDAAE,CAAC,gBAAgB,EAAE,KAAK;UAAC,CAAS,CAAC,eAC9CI,sDAAA;YAAAoC,QAAA,EACEzB,QAAQ,CAACO,GAAG,CAAEC,OAAO,iBACrBnB,sDAAA;cAAAoC,QAAA,EAAsBjB,OAAO,CAACE;YAAI,GAAzBF,OAAO,CAACC,EAAsB,CACvC;UAAC,CACC,CAAC;QAAA,CACD,CAAC,gBAENpB,sDAAA,CAACN,yDAAM;UAACqD,MAAM,EAAC,SAAS;UAACC,aAAa,EAAE,KAAM;UAAAZ,QAAA,EAC5CxC,mDAAE,CAAC,6DAA6D,EAAE,KAAK;QAAC,CAClE,CACR;MAAA,CACG;IAAC,CACF,CAAC;EAAA,CACL,CAAC;AAEL,C;;;;;;;;;;;;;;;;;AChJsD;AAC5B;AACJ;AACC;AACa;AAEpCqD,oEAAiB,CAACC,6CAAa,EAAE;EAChCC,IAAI,EAAE9C,6CAAI;EACV;EACA+C,IAAI,EAAEA,CAAA,KAAM;AACb,CAAC,CAAC,C;;;;;;;;;;;ACVF;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA,2C;;;;;;;;;;ACAA,6C;;;;;;;;;;ACAA,wC;;;;;;;;;;ACAA,4C;;;;;;;;;;ACAA,yC;;;;;;;;;;ACAA,sC;;;;;;;;;;;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WC/BA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G;;;;;UEjDA;UACA;UACA;UACA;UACA","sources":["webpack://jvb/./src/faq/edit.js","webpack://jvb/./src/faq/index.js","webpack://jvb/./src/faq/editor.scss?435f","webpack://jvb/./src/faq/style.scss?4bc3","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"components\"]","webpack://jvb/external window [\"wp\",\"element\"]","webpack://jvb/external window [\"wp\",\"i18n\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["import { useBlockProps, InspectorControls } from '@wordpress/block-editor';\r\nimport { PanelBody, ToggleControl, Notice, Button } from '@wordpress/components';\r\nimport { __ } from '@wordpress/i18n';\r\nimport { useState, useEffect } from '@wordpress/element';\r\nimport './editor.scss';\r\n\r\nexport default function Edit({ attributes, setAttributes }) {\r\n\tconst { sectionOrder, showSectionTitles, collapseByDefault } = attributes;\r\n\tconst [sections, setSections] = useState([]);\r\n\r\n\t// Get sections from localized script\r\n\tconst allSections = window.jvbFaq?.sections || [];\r\n\r\n\t// Initialize sections with proper ordering\r\n\tuseEffect(() => {\r\n\t\tif (!allSections.length) return;\r\n\r\n\t\tif (sectionOrder.length === 0) {\r\n\t\t\t// First time - use default order\r\n\t\t\tconst orderedSections = allSections.map(section => ({\r\n\t\t\t\tid: section.id,\r\n\t\t\t\tname: section.name,\r\n\t\t\t}));\r\n\t\t\tsetSections(orderedSections);\r\n\t\t\tsetAttributes({ sectionOrder: orderedSections.map(s => s.id) });\r\n\t\t} else {\r\n\t\t\t// Use saved order, add any new sections at the end\r\n\t\t\tconst orderedSections = [];\r\n\t\t\tconst existingIds = new Set(sectionOrder);\r\n\r\n\t\t\t// Add sections in saved order\r\n\t\t\tsectionOrder.forEach(id => {\r\n\t\t\t\tconst section = allSections.find(s => s.id === id);\r\n\t\t\t\tif (section) {\r\n\t\t\t\t\torderedSections.push({ id: section.id, name: section.name });\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\t// Add any new sections that weren't in the saved order\r\n\t\t\tallSections.forEach(section => {\r\n\t\t\t\tif (!existingIds.has(section.id)) {\r\n\t\t\t\t\torderedSections.push({ id: section.id, name: section.name });\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tsetSections(orderedSections);\r\n\t\t}\r\n\t}, [allSections, sectionOrder]);\r\n\r\n\tconst moveSection = (index, direction) => {\r\n\t\tconst newSections = [...sections];\r\n\t\tconst newIndex = direction === 'up' ? index - 1 : index + 1;\r\n\r\n\t\tif (newIndex < 0 || newIndex >= newSections.length) return;\r\n\r\n\t\t// Swap sections\r\n\t\t[newSections[index], newSections[newIndex]] = [newSections[newIndex], newSections[index]];\r\n\r\n\t\tsetSections(newSections);\r\n\t\tsetAttributes({ sectionOrder: newSections.map(s => s.id) });\r\n\t};\r\n\r\n\tconst blockProps = useBlockProps({\r\n\t\tclassName: 'faq-block-editor',\r\n\t});\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<InspectorControls>\r\n\t\t\t\t<PanelBody title={__('FAQ Settings', 'jvb')} initialOpen={true}>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Show Section Titles', 'jvb')}\r\n\t\t\t\t\t\tchecked={showSectionTitles}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ showSectionTitles: value })}\r\n\t\t\t\t\t\thelp={__('Display section names as headings', 'jvb')}\r\n\t\t\t\t\t/>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Collapse by Default', 'jvb')}\r\n\t\t\t\t\t\tchecked={collapseByDefault}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ collapseByDefault: value })}\r\n\t\t\t\t\t\thelp={__('Questions start collapsed and expand on click', 'jvb')}\r\n\t\t\t\t\t/>\r\n\t\t\t\t</PanelBody>\r\n\r\n\t\t\t\t<PanelBody title={__('Section Order', 'jvb')} initialOpen={false}>\r\n\t\t\t\t\t<p className=\"components-base-control__help\">\r\n\t\t\t\t\t\t{__('Use the arrow buttons to reorder sections', 'jvb')}\r\n\t\t\t\t\t</p>\r\n\t\t\t\t\t{sections.length > 0 ? (\r\n\t\t\t\t\t\t<div className=\"faq-section-list\">\r\n\t\t\t\t\t\t\t{sections.map((section, index) => (\r\n\t\t\t\t\t\t\t\t<div key={section.id} className=\"faq-section-item\">\r\n\t\t\t\t\t\t\t\t\t<div className=\"faq-section-controls\">\r\n\t\t\t\t\t\t\t\t\t\t<Button\r\n\t\t\t\t\t\t\t\t\t\t\ticon=\"arrow-up-alt2\"\r\n\t\t\t\t\t\t\t\t\t\t\tlabel={__('Move up', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t\t\tdisabled={index === 0}\r\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => moveSection(index, 'up')}\r\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"faq-section-button\"\r\n\t\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t\t<Button\r\n\t\t\t\t\t\t\t\t\t\t\ticon=\"arrow-down-alt2\"\r\n\t\t\t\t\t\t\t\t\t\t\tlabel={__('Move down', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t\t\tdisabled={index === sections.length - 1}\r\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => moveSection(index, 'down')}\r\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"faq-section-button\"\r\n\t\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t\t\t\t<span className=\"faq-section-name\">{section.name}</span>\r\n\t\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t\t))}\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t) : (\r\n\t\t\t\t\t\t<Notice status=\"info\" isDismissible={false}>\r\n\t\t\t\t\t\t\t{__('No sections found. Create sections in the FAQ taxonomy.', 'jvb')}\r\n\t\t\t\t\t\t</Notice>\r\n\t\t\t\t\t)}\r\n\t\t\t\t</PanelBody>\r\n\t\t\t</InspectorControls>\r\n\r\n\t\t\t<div {...blockProps}>\r\n\t\t\t\t<div className=\"faq-block-preview\">\r\n\t\t\t\t\t<h3>{__('FAQ Block', 'jvb')}</h3>\r\n\t\t\t\t\t<p>\r\n\t\t\t\t\t\t{__('This block will display FAQs organized by sections.', 'jvb')}\r\n\t\t\t\t\t</p>\r\n\t\t\t\t\t{sections.length > 0 ? (\r\n\t\t\t\t\t\t<div className=\"faq-sections-preview\">\r\n\t\t\t\t\t\t\t<strong>{__('Section Order:', 'jvb')}</strong>\r\n\t\t\t\t\t\t\t<ol>\r\n\t\t\t\t\t\t\t\t{sections.map((section) => (\r\n\t\t\t\t\t\t\t\t\t<li key={section.id}>{section.name}</li>\r\n\t\t\t\t\t\t\t\t))}\r\n\t\t\t\t\t\t\t</ol>\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t) : (\r\n\t\t\t\t\t\t<Notice status=\"warning\" isDismissible={false}>\r\n\t\t\t\t\t\t\t{__('No sections available. Create sections in the FAQ taxonomy.', 'jvb')}\r\n\t\t\t\t\t\t</Notice>\r\n\t\t\t\t\t)}\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\t\t</>\r\n\t);\r\n}\r\n","import { registerBlockType } from '@wordpress/blocks';\r\nimport Edit from './edit';\r\nimport './style.scss';\r\nimport './editor.scss';\r\nimport metadata from './block.json';\r\n\r\nregisterBlockType(metadata.name, {\r\n\tedit: Edit,\r\n\t// No save function - dynamic block rendered on server\r\n\tsave: () => null,\r\n});\r\n","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"components\"];","module.exports = window[\"wp\"][\"element\"];","module.exports = window[\"wp\"][\"i18n\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"faq/index\": 0,\n\t\"faq/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"faq/style-index\"], () => (__webpack_require__(\"./src/faq/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["useBlockProps","InspectorControls","PanelBody","ToggleControl","Notice","Button","__","useState","useEffect","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","Edit","attributes","setAttributes","sectionOrder","showSectionTitles","collapseByDefault","sections","setSections","allSections","window","jvbFaq","length","orderedSections","map","section","id","name","s","existingIds","Set","forEach","find","push","has","moveSection","index","direction","newSections","newIndex","blockProps","className","children","title","initialOpen","label","checked","onChange","value","help","icon","disabled","onClick","status","isDismissible","registerBlockType","metadata","edit","save"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/faq/style-index-rtl.css b/build/faq/style-index-rtl.css
index 9f59a7f..64930b4 100644
--- a/build/faq/style-index-rtl.css
+++ b/build/faq/style-index-rtl.css
@@ -1 +1,77 @@
-nav#faq{background-color:rgb(var(--base-100));border-radius:var(--radius-outer);display:block;height:-moz-max-content;height:max-content;padding:1.5rem;touch-action:auto}nav#faq ol{counter-reset:faq;display:block;height:-moz-fit-content;height:fit-content;list-style:decimal-leading-zero}nav#faq ol li{counter-increment:faq;width:-moz-max-content;width:max-content}nav#faq ol li:before{content:counter(faq);display:block;font-family:var(--heading);font-weight:var(--fw-h-bold)}nav#faq h2{font-size:var(--txt-large);right:0;margin:.5rem 0}nav#faq a{padding:.5rem}.faq-block{max-width:none;padding-bottom:3rem;width:100%}.faq-block>*{margin:1rem auto;max-width:var(--wide)}.faq-block h2{margin:5rem 0 1.5rem}.faq-block h3{margin:0;text-transform:none}.faq-block :target{background-color:rgb(var(--base));outline:none}.faq-block :target h2{background-color:rgb(var(--base));border-radius:var(--radius-outer);padding:1rem 1.5rem}.faq-block details{margin:1rem auto;max-width:var(--content);padding:.75rem}.faq-block details+details{margin-top:3rem}.faq-block details .button{display:flex;height:-moz-fit-content;height:fit-content;margin-right:auto}
+/*!*******************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/faq/style.scss ***!
+  \*******************************************************************************************************************************************************************************************************************************************/
+nav#faq {
+  height: -moz-max-content;
+  height: max-content;
+  display: block;
+  background-color: rgb(var(--base-100));
+  border-radius: var(--radius-outer);
+  padding: 1.5rem;
+  touch-action: auto;
+}
+nav#faq ol {
+  list-style: decimal-leading-zero;
+  height: -moz-fit-content;
+  height: fit-content;
+  display: block;
+  counter-reset: faq;
+}
+nav#faq ol li {
+  counter-increment: faq;
+  width: -moz-max-content;
+  width: max-content;
+}
+nav#faq ol li::before {
+  content: counter(faq);
+  display: block;
+  font-family: var(--heading);
+  font-weight: var(--fw-h-bold);
+}
+nav#faq h2 {
+  right: 0;
+  font-size: var(--txt-large);
+  margin: 0.5rem 0 0.5rem;
+}
+nav#faq a {
+  padding: 0.5rem;
+}
+.faq-block {
+  padding-bottom: 3rem;
+  max-width: none;
+  width: 100%;
+}
+.faq-block > * {
+  max-width: var(--wide);
+  margin: 1rem auto;
+}
+.faq-block h2 {
+  margin: 5rem 0 1.5rem;
+}
+.faq-block h3 {
+  margin: 0;
+  text-transform: none;
+}
+.faq-block :target {
+  background-color: rgb(var(--base));
+  outline: none;
+}
+.faq-block :target h2 {
+  background-color: rgb(var(--base));
+  padding: 1rem 1.5rem;
+  border-radius: var(--radius-outer);
+}
+.faq-block details {
+  max-width: var(--content);
+  margin: 1rem auto;
+  padding: 0.75rem;
+}
+.faq-block details + details {
+  margin-top: 3rem;
+}
+.faq-block details .button {
+  height: -moz-fit-content;
+  height: fit-content;
+  display: flex;
+  margin-right: auto;
+}
diff --git a/build/faq/style-index.css b/build/faq/style-index.css
index f166ad3..f7c189a 100644
--- a/build/faq/style-index.css
+++ b/build/faq/style-index.css
@@ -1 +1,79 @@
-nav#faq{background-color:rgb(var(--base-100));border-radius:var(--radius-outer);display:block;height:-moz-max-content;height:max-content;padding:1.5rem;touch-action:auto}nav#faq ol{counter-reset:faq;display:block;height:-moz-fit-content;height:fit-content;list-style:decimal-leading-zero}nav#faq ol li{counter-increment:faq;width:-moz-max-content;width:max-content}nav#faq ol li:before{content:counter(faq);display:block;font-family:var(--heading);font-weight:var(--fw-h-bold)}nav#faq h2{font-size:var(--txt-large);left:0;margin:.5rem 0}nav#faq a{padding:.5rem}.faq-block{max-width:none;padding-bottom:3rem;width:100%}.faq-block>*{margin:1rem auto;max-width:var(--wide)}.faq-block h2{margin:5rem 0 1.5rem}.faq-block h3{margin:0;text-transform:none}.faq-block :target{background-color:rgb(var(--base));outline:none}.faq-block :target h2{background-color:rgb(var(--base));border-radius:var(--radius-outer);padding:1rem 1.5rem}.faq-block details{margin:1rem auto;max-width:var(--content);padding:.75rem}.faq-block details+details{margin-top:3rem}.faq-block details .button{display:flex;height:-moz-fit-content;height:fit-content;margin-left:auto}
+/*!*******************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/faq/style.scss ***!
+  \*******************************************************************************************************************************************************************************************************************************************/
+nav#faq {
+  height: -moz-max-content;
+  height: max-content;
+  display: block;
+  background-color: rgb(var(--base-100));
+  border-radius: var(--radius-outer);
+  padding: 1.5rem;
+  touch-action: auto;
+}
+nav#faq ol {
+  list-style: decimal-leading-zero;
+  height: -moz-fit-content;
+  height: fit-content;
+  display: block;
+  counter-reset: faq;
+}
+nav#faq ol li {
+  counter-increment: faq;
+  width: -moz-max-content;
+  width: max-content;
+}
+nav#faq ol li::before {
+  content: counter(faq);
+  display: block;
+  font-family: var(--heading);
+  font-weight: var(--fw-h-bold);
+}
+nav#faq h2 {
+  left: 0;
+  font-size: var(--txt-large);
+  margin: 0.5rem 0 0.5rem;
+}
+nav#faq a {
+  padding: 0.5rem;
+}
+.faq-block {
+  padding-bottom: 3rem;
+  max-width: none;
+  width: 100%;
+}
+.faq-block > * {
+  max-width: var(--wide);
+  margin: 1rem auto;
+}
+.faq-block h2 {
+  margin: 5rem 0 1.5rem;
+}
+.faq-block h3 {
+  margin: 0;
+  text-transform: none;
+}
+.faq-block :target {
+  background-color: rgb(var(--base));
+  outline: none;
+}
+.faq-block :target h2 {
+  background-color: rgb(var(--base));
+  padding: 1rem 1.5rem;
+  border-radius: var(--radius-outer);
+}
+.faq-block details {
+  max-width: var(--content);
+  margin: 1rem auto;
+  padding: 0.75rem;
+}
+.faq-block details + details {
+  margin-top: 3rem;
+}
+.faq-block details .button {
+  height: -moz-fit-content;
+  height: fit-content;
+  display: flex;
+  margin-left: auto;
+}
+
+/*# sourceMappingURL=style-index.css.map*/
\ No newline at end of file
diff --git a/build/faq/style-index.css.map b/build/faq/style-index.css.map
new file mode 100644
index 0000000..abda510
--- /dev/null
+++ b/build/faq/style-index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"faq/style-index.css","mappings":";;;AAAA;EACC;EAAA;EACA;EACA;EACA;EACA;EACA;AACD;AAAC;EACC;EACA;EAAA;EACA;EACA;AAEF;AADE;EACC;EACA;EAAA;AAGH;AAFG;EACC;EACA;EACA;EACA;AAIJ;AAAC;EACC;EACA;EACA;AAEF;AAAC;EACC;AAEF;AAEA;EACC;EACA;EACA;AACD;AAAC;EACC;EACA;AAEF;AAAC;EACC;AAEF;AAAC;EACC;EACA;AAEF;AAAC;EACC;EACA;AAEF;AAAE;EACC;EACA;EACA;AAEH;AACC;EACC;EACA;EACA;AACF;AACC;EACC;AACF;AACC;EACC;EAAA;EACA;EACA;AACF,C","sources":["webpack://jvb/./src/faq/style.scss"],"sourcesContent":["nav#faq {\r\n\theight: max-content;\r\n\tdisplay: block;\r\n\tbackground-color: rgb(var(--base-100));\r\n\tborder-radius: var(--radius-outer);\r\n\tpadding: 1.5rem;\r\n\ttouch-action: auto;\r\n\tol {\r\n\t\tlist-style: decimal-leading-zero;\r\n\t\theight: fit-content;\r\n\t\tdisplay: block;\r\n\t\tcounter-reset: faq;\r\n\t\tli {\r\n\t\t\tcounter-increment: faq;\r\n\t\t\twidth: max-content;\r\n\t\t\t&::before {\r\n\t\t\t\tcontent: counter(faq);\r\n\t\t\t\tdisplay: block;\r\n\t\t\t\tfont-family: var(--heading);\r\n\t\t\t\tfont-weight: var(--fw-h-bold);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\th2 {\r\n\t\tleft: 0;\r\n\t\tfont-size: var(--txt-large);\r\n\t\tmargin: .5rem 0 .5rem;\r\n\t}\r\n\ta {\r\n\t\tpadding: .5rem;\r\n\t}\r\n}\r\n\r\n.faq-block {\r\n\tpadding-bottom: 3rem;\r\n\tmax-width: none;\r\n\twidth: 100%;\r\n\t> * {\r\n\t\tmax-width: var(--wide);\r\n\t\tmargin: 1rem auto;\r\n\t}\r\n\th2 {\r\n\t\tmargin: 5rem 0 1.5rem;\r\n\t}\r\n\th3 {\r\n\t\tmargin: 0;\r\n\t\ttext-transform: none;\r\n\t}\r\n\t:target {\r\n\t\tbackground-color: rgb(var(--base));\r\n\t\toutline: none;\r\n\r\n\t\th2 {\r\n\t\t\tbackground-color: rgb(var(--base));\r\n\t\t\tpadding: 1rem 1.5rem;\r\n\t\t\tborder-radius: var(--radius-outer);\r\n\t\t}\r\n\t}\r\n\tdetails {\r\n\t\tmax-width: var(--content);\r\n\t\tmargin: 1rem auto;\r\n\t\tpadding: .75rem;\r\n\t}\r\n\tdetails + details {\r\n\t\tmargin-top: 3rem;\r\n\t}\r\n\tdetails .button {\r\n\t\theight: fit-content;\r\n\t\tdisplay: flex;\r\n\t\tmargin-left: auto;\r\n\t}\r\n}\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/faq/view.asset.php b/build/faq/view.asset.php
index 198caa8..a3a804e 100644
--- a/build/faq/view.asset.php
+++ b/build/faq/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => 'd8ed72030ab0be236a6c');
+<?php return array('dependencies' => array(), 'version' => 'b2708d109babb049c10a');
diff --git a/build/faq/view.js b/build/faq/view.js
index b521928..4d5ee84 100644
--- a/build/faq/view.js
+++ b/build/faq/view.js
@@ -1 +1,83 @@
-document.addEventListener("DOMContentLoaded",()=>{if(document.querySelectorAll(".faq-block").forEach(e=>{e.querySelectorAll(".faq-item").forEach(e=>{const t=e.querySelector(".faq-item__question"),i=e.querySelector(".faq-item__answer");t&&i&&(t.addEventListener("click",()=>{const o="true"===t.getAttribute("aria-expanded");t.setAttribute("aria-expanded",!o),o?(i.style.height=i.scrollHeight+"px",i.offsetHeight,i.style.height="0",setTimeout(()=>{i.style.display="none",i.style.height=""},300),e.classList.remove("faq-item--expanded")):(i.style.display="block",i.style.height="0",i.offsetHeight,i.style.height=i.scrollHeight+"px",setTimeout(()=>{i.style.height="auto"},300),e.classList.add("faq-item--expanded"))}),t.addEventListener("keydown",e=>{" "!==e.key&&"Enter"!==e.key||(e.preventDefault(),t.click())}))})}),window.location.hash){const e=window.location.hash.substring(1),t=document.querySelector(`[data-faq-id="${e}"]`);if(t){const e=t.querySelector(".faq-item__question");"true"===e.getAttribute("aria-expanded")||e.click(),setTimeout(()=>{t.scrollIntoView({behavior:"smooth",block:"center"})},350)}}});
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/*!*************************!*\
+  !*** ./src/faq/view.js ***!
+  \*************************/
+/**
+ * FAQ Block - Frontend Interactions
+ * Handles accordion functionality for FAQ items
+ */
+
+document.addEventListener('DOMContentLoaded', () => {
+  const faqBlocks = document.querySelectorAll('.faq-block');
+  faqBlocks.forEach(block => {
+    const faqItems = block.querySelectorAll('.faq-item');
+    faqItems.forEach(item => {
+      const button = item.querySelector('.faq-item__question');
+      const answer = item.querySelector('.faq-item__answer');
+      if (!button || !answer) return;
+      button.addEventListener('click', () => {
+        const isExpanded = button.getAttribute('aria-expanded') === 'true';
+
+        // Toggle this item
+        button.setAttribute('aria-expanded', !isExpanded);
+        if (isExpanded) {
+          // Collapse
+          answer.style.height = answer.scrollHeight + 'px';
+          // Force reflow
+          answer.offsetHeight;
+          answer.style.height = '0';
+          setTimeout(() => {
+            answer.style.display = 'none';
+            answer.style.height = '';
+          }, 300);
+          item.classList.remove('faq-item--expanded');
+        } else {
+          // Expand
+          answer.style.display = 'block';
+          answer.style.height = '0';
+          // Force reflow
+          answer.offsetHeight;
+          answer.style.height = answer.scrollHeight + 'px';
+          setTimeout(() => {
+            answer.style.height = 'auto';
+          }, 300);
+          item.classList.add('faq-item--expanded');
+        }
+      });
+
+      // Handle keyboard navigation
+      button.addEventListener('keydown', e => {
+        // Space or Enter triggers the button
+        if (e.key === ' ' || e.key === 'Enter') {
+          e.preventDefault();
+          button.click();
+        }
+      });
+    });
+  });
+
+  // Optional: Add URL hash navigation
+  // If URL has #faq-123, open that specific FAQ
+  if (window.location.hash) {
+    const hash = window.location.hash.substring(1);
+    const targetItem = document.querySelector(`[data-faq-id="${hash}"]`);
+    if (targetItem) {
+      const button = targetItem.querySelector('.faq-item__question');
+      const isExpanded = button.getAttribute('aria-expanded') === 'true';
+      if (!isExpanded) {
+        button.click();
+      }
+
+      // Scroll to item after a short delay
+      setTimeout(() => {
+        targetItem.scrollIntoView({
+          behavior: 'smooth',
+          block: 'center'
+        });
+      }, 350);
+    }
+  }
+});
+/******/ })()
+;
+//# sourceMappingURL=view.js.map
\ No newline at end of file
diff --git a/build/faq/view.js.map b/build/faq/view.js.map
new file mode 100644
index 0000000..9fb4dc4
--- /dev/null
+++ b/build/faq/view.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"faq/view.js","mappings":"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","sources":["webpack://jvb/./src/faq/view.js"],"sourcesContent":["/**\r\n * FAQ Block - Frontend Interactions\r\n * Handles accordion functionality for FAQ items\r\n */\r\n\r\ndocument.addEventListener('DOMContentLoaded', () => {\r\n\tconst faqBlocks = document.querySelectorAll('.faq-block');\r\n\r\n\tfaqBlocks.forEach((block) => {\r\n\t\tconst faqItems = block.querySelectorAll('.faq-item');\r\n\r\n\t\tfaqItems.forEach((item) => {\r\n\t\t\tconst button = item.querySelector('.faq-item__question');\r\n\t\t\tconst answer = item.querySelector('.faq-item__answer');\r\n\r\n\t\t\tif (!button || !answer) return;\r\n\r\n\t\t\tbutton.addEventListener('click', () => {\r\n\t\t\t\tconst isExpanded = button.getAttribute('aria-expanded') === 'true';\r\n\r\n\t\t\t\t// Toggle this item\r\n\t\t\t\tbutton.setAttribute('aria-expanded', !isExpanded);\r\n\r\n\t\t\t\tif (isExpanded) {\r\n\t\t\t\t\t// Collapse\r\n\t\t\t\t\tanswer.style.height = answer.scrollHeight + 'px';\r\n\t\t\t\t\t// Force reflow\r\n\t\t\t\t\tanswer.offsetHeight;\r\n\t\t\t\t\tanswer.style.height = '0';\r\n\r\n\t\t\t\t\tsetTimeout(() => {\r\n\t\t\t\t\t\tanswer.style.display = 'none';\r\n\t\t\t\t\t\tanswer.style.height = '';\r\n\t\t\t\t\t}, 300);\r\n\r\n\t\t\t\t\titem.classList.remove('faq-item--expanded');\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Expand\r\n\t\t\t\t\tanswer.style.display = 'block';\r\n\t\t\t\t\tanswer.style.height = '0';\r\n\t\t\t\t\t// Force reflow\r\n\t\t\t\t\tanswer.offsetHeight;\r\n\t\t\t\t\tanswer.style.height = answer.scrollHeight + 'px';\r\n\r\n\t\t\t\t\tsetTimeout(() => {\r\n\t\t\t\t\t\tanswer.style.height = 'auto';\r\n\t\t\t\t\t}, 300);\r\n\r\n\t\t\t\t\titem.classList.add('faq-item--expanded');\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\t// Handle keyboard navigation\r\n\t\t\tbutton.addEventListener('keydown', (e) => {\r\n\t\t\t\t// Space or Enter triggers the button\r\n\t\t\t\tif (e.key === ' ' || e.key === 'Enter') {\r\n\t\t\t\t\te.preventDefault();\r\n\t\t\t\t\tbutton.click();\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t});\r\n\t});\r\n\r\n\t// Optional: Add URL hash navigation\r\n\t// If URL has #faq-123, open that specific FAQ\r\n\tif (window.location.hash) {\r\n\t\tconst hash = window.location.hash.substring(1);\r\n\t\tconst targetItem = document.querySelector(`[data-faq-id=\"${hash}\"]`);\r\n\r\n\t\tif (targetItem) {\r\n\t\t\tconst button = targetItem.querySelector('.faq-item__question');\r\n\t\t\tconst isExpanded = button.getAttribute('aria-expanded') === 'true';\r\n\r\n\t\t\tif (!isExpanded) {\r\n\t\t\t\tbutton.click();\r\n\t\t\t}\r\n\r\n\t\t\t// Scroll to item after a short delay\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\ttargetItem.scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n\t\t\t}, 350);\r\n\t\t}\r\n\t}\r\n});\r\n"],"names":["document","addEventListener","faqBlocks","querySelectorAll","forEach","block","faqItems","item","button","querySelector","answer","isExpanded","getAttribute","setAttribute","style","height","scrollHeight","offsetHeight","setTimeout","display","classList","remove","add","e","key","preventDefault","click","window","location","hash","substring","targetItem","scrollIntoView","behavior"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/feed/index.asset.php b/build/feed/index.asset.php
index 3c481c5..76857a2 100644
--- a/build/feed/index.asset.php
+++ b/build/feed/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '33aeda6042c7c1cebcc0');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => 'fe0e82dbe0767c5155b9');
diff --git a/build/feed/index.js b/build/feed/index.js
index 69200f8..68d9753 100644
--- a/build/feed/index.js
+++ b/build/feed/index.js
@@ -1 +1,602 @@
-(()=>{"use strict";var e,t={111(e,t,n){const o=window.wp.blocks,l=window.wp.element,i=window.wp.blockEditor,r=window.wp.components,s=window.wp.apiFetch;var c=n.n(s);const a=window.wp.i18n,d=window.ReactJSXRuntime;(0,o.registerBlockType)("jvb/feed",{edit:function({attributes:e,setAttributes:t}){const[n,o]=(0,l.useState)(null),[s,h]=(0,l.useState)(!0),[p,j]=(0,l.useState)(null),x=(0,i.useBlockProps)({className:"feed-block-editor"});(0,l.useEffect)(()=>{c()({path:"/jvb/v1/feed/types",headers:{"If-Modified-Since":localStorage.getItem("feed_types_modified")}}).then(n=>{if(o(n),h(!1),!e.contentTypes&&!e.inheritQuery){const e=Object.keys(n)[0];e&&t({contentTypes:[e]})}}).catch(e=>{console.error("Error loading feed types:",e),j(e.message),h(!1)})},[e.inheritQuery]);const y=(n,o)=>{const l=e.contentTypes||[],i=o?[...l,n]:l.filter(e=>e!==n);t({contentTypes:i})},b=(e,t)=>`${t.plural} (${t.type})`,g=n?{content:Object.entries(n).filter(([e,t])=>"content"===t.type),taxonomy:Object.entries(n).filter(([e,t])=>"taxonomy"===t.type)}:{content:[],taxonomy:[]};return(0,d.jsxs)("div",{...x,children:[(0,d.jsxs)(i.InspectorControls,{children:[(0,d.jsxs)(r.PanelBody,{title:(0,a.__)("Feed Settings","jvb"),initialOpen:!0,children:[(0,d.jsx)(r.ToggleControl,{label:(0,a.__)("Inherit from Page Context","jvb"),help:e.inheritQuery?(0,a.__)("Feed will adapt to the current page (profile, taxonomy, etc.)","jvb"):(0,a.__)("Manually select content types to display","jvb"),checked:e.inheritQuery,onChange:e=>t({inheritQuery:e})}),!e.inheritQuery&&(0,d.jsxs)(d.Fragment,{children:[s&&(0,d.jsxs)("div",{style:{textAlign:"center",padding:"20px"},children:[(0,d.jsx)(r.Spinner,{}),(0,d.jsx)("p",{children:(0,a.__)("Loading feed types...","jvb")})]}),p&&(0,d.jsxs)(r.Notice,{status:"error",isDismissible:!1,children:[(0,a.__)("Error loading feed types: ","jvb")," ",p]}),!s&&!p&&n&&(0,d.jsxs)(d.Fragment,{children:[g.content.length>0&&(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)("h4",{children:(0,a.__)("Content Types","jvb")}),g.content.map(([t,n])=>(0,d.jsx)(r.CheckboxControl,{label:b(0,n),checked:e.contentTypes?.includes(t)||!1,onChange:e=>y(t,e),help:n.taxonomies?.length>0?`Filters: ${n.taxonomies.join(", ")}`:null},t))]}),g.taxonomy.length>0&&(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)("h4",{style:{marginTop:"20px"},children:(0,a.__)("Content Taxonomies","jvb")}),(0,d.jsx)("p",{style:{fontSize:"12px",color:"#757575"},children:(0,a.__)("These are collections that group other content","jvb")}),g.taxonomy.map(([t,n])=>(0,d.jsx)(r.CheckboxControl,{label:b(0,n),checked:e.contentTypes?.includes(t)||!1,onChange:e=>y(t,e),help:n.for_content?.length>0?`Contains: ${n.for_content.join(", ")}`:null},t))]}),!e.contentTypes?.length&&(0,d.jsx)(r.Notice,{status:"warning",isDismissible:!1,children:(0,a.__)("Please select at least one content type","jvb")})]})]})]}),(0,d.jsx)(r.PanelBody,{title:(0,a.__)("Display Settings","jvb"),initialOpen:!1,children:(0,d.jsx)(r.ToggleControl,{label:(0,a.__)("Show Gallery View","jvb"),help:(0,a.__)("Enable lightbox for images","jvb"),checked:e.enableGallery||!1,onChange:e=>t({enableGallery:e})})})]}),(0,d.jsxs)("div",{className:"feed-block-placeholder",children:[(0,d.jsx)("div",{className:"feed-block-icon",children:(0,d.jsxs)("svg",{width:"48",height:"48",viewBox:"0 0 24 24",fill:"none",children:[(0,d.jsx)("rect",{x:"3",y:"3",width:"7",height:"7",fill:"currentColor",opacity:"0.3"}),(0,d.jsx)("rect",{x:"13",y:"3",width:"7",height:"7",fill:"currentColor",opacity:"0.3"}),(0,d.jsx)("rect",{x:"3",y:"13",width:"7",height:"7",fill:"currentColor",opacity:"0.3"}),(0,d.jsx)("rect",{x:"13",y:"13",width:"7",height:"7",fill:"currentColor",opacity:"0.3"})]})}),(0,d.jsx)("h3",{children:(0,a.__)("Feed Block","jvb")}),e.inheritQuery?(0,d.jsx)("p",{className:"feed-block-description",children:(0,a.__)("📍 Inheriting from page context","jvb")}):(0,d.jsx)("div",{className:"feed-block-description",children:e.contentTypes?.length>0?(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)("p",{children:(0,d.jsx)("strong",{children:(0,a.__)("Showing:","jvb")})}),(0,d.jsx)("ul",{style:{listStyle:"none",padding:"0",margin:"8px 0"},children:e.contentTypes.map(e=>{const t=n?.[e];return(0,d.jsxs)("li",{style:{padding:"4px 0",color:"#2271b1"},children:["✓ ",t?.plural||e]},e)})})]}):(0,d.jsx)("p",{style:{color:"#d63638"},children:(0,a.__)("⚠️  No content types selected","jvb")})}),(0,d.jsx)("p",{className:"feed-block-note",children:(0,a.__)("Feed will be displayed on the frontend","jvb")})]})]})},save:function(){return null}})}},n={};function o(e){var l=n[e];if(void 0!==l)return l.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,o),i.exports}o.m=t,e=[],o.O=(t,n,l,i)=>{if(!n){var r=1/0;for(d=0;d<e.length;d++){for(var[n,l,i]=e[d],s=!0,c=0;c<n.length;c++)(!1&i||r>=i)&&Object.keys(o.O).every(e=>o.O[e](n[c]))?n.splice(c--,1):(s=!1,i<r&&(r=i));if(s){e.splice(d--,1);var a=l();void 0!==a&&(t=a)}}return t}i=i||0;for(var d=e.length;d>0&&e[d-1][2]>i;d--)e[d]=e[d-1];e[d]=[n,l,i]},o.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return o.d(t,{a:t}),t},o.d=(e,t)=>{for(var n in t)o.o(t,n)&&!o.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={814:0,138:0};o.O.j=t=>0===e[t];var t=(t,n)=>{var l,i,[r,s,c]=n,a=0;if(r.some(t=>0!==e[t])){for(l in s)o.o(s,l)&&(o.m[l]=s[l]);if(c)var d=c(o)}for(t&&t(n);a<r.length;a++)i=r[a],o.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return o.O(d)},n=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})();var l=o.O(void 0,[138],()=>o(111));l=o.O(l)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/feed/edit.js"
+/*!**************************!*\
+  !*** ./src/feed/edit.js ***!
+  \**************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
+/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__);
+/* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/api-fetch */ "@wordpress/api-fetch");
+/* harmony import */ var _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_3__);
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__);
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__);
+/**
+ * Feed Block - Edit Component
+ * Fetches available feed types from /jvb/v1/feed/types
+ * Allows configuration of content types and inherit query setting
+ */
+
+
+
+
+
+
+
+function Edit({
+  attributes,
+  setAttributes
+}) {
+  const [feedTypes, setFeedTypes] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.useState)(null);
+  const [loading, setLoading] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.useState)(true);
+  const [error, setError] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.useState)(null);
+  const blockProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.useBlockProps)({
+    className: 'feed-block-editor'
+  });
+
+  /**
+   * Fetch available feed types on component mount
+   */
+  (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
+    _wordpress_api_fetch__WEBPACK_IMPORTED_MODULE_3___default()({
+      path: '/jvb/v1/feed/types',
+      headers: {
+        'If-Modified-Since': localStorage.getItem('feed_types_modified')
+      }
+    }).then(types => {
+      setFeedTypes(types);
+      setLoading(false);
+
+      // Store Last-Modified for future requests
+      // (apiFetch doesn't expose response headers easily,
+      // but the server will handle 304s)
+
+      // Initialize contentTypes if not set and not inheriting
+      if (!attributes.contentTypes && !attributes.inheritQuery) {
+        const firstType = Object.keys(types)[0];
+        if (firstType) {
+          setAttributes({
+            contentTypes: [firstType]
+          });
+        }
+      }
+    }).catch(err => {
+      console.error('Error loading feed types:', err);
+      setError(err.message);
+      setLoading(false);
+    });
+  }, [attributes.inheritQuery]);
+
+  /**
+   * Toggle a content type in the selection
+   */
+  const toggleContentType = (slug, checked) => {
+    const currentTypes = attributes.contentTypes || [];
+    const newTypes = checked ? [...currentTypes, slug] : currentTypes.filter(t => t !== slug);
+    setAttributes({
+      contentTypes: newTypes
+    });
+  };
+
+  /**
+   * Get friendly label for content type
+   */
+  const getTypeLabel = (slug, config) => {
+    return `${config.plural} (${config.type})`;
+  };
+
+  /**
+   * Group types by category for better UX
+   */
+  const groupedTypes = feedTypes ? {
+    content: Object.entries(feedTypes).filter(([_, config]) => config.type === 'content'),
+    taxonomy: Object.entries(feedTypes).filter(([_, config]) => config.type === 'taxonomy')
+  } : {
+    content: [],
+    taxonomy: []
+  };
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+    ...blockProps,
+    children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.InspectorControls, {
+      children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.PanelBody, {
+        title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Feed Settings', 'jvb'),
+        initialOpen: true,
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Inherit from Page Context', 'jvb'),
+          help: attributes.inheritQuery ? (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Feed will adapt to the current page (profile, taxonomy, etc.)', 'jvb') : (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Manually select content types to display', 'jvb'),
+          checked: attributes.inheritQuery,
+          onChange: value => setAttributes({
+            inheritQuery: value
+          })
+        }), !attributes.inheritQuery && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.Fragment, {
+          children: [loading && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+            style: {
+              textAlign: 'center',
+              padding: '20px'
+            },
+            children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.Spinner, {}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+              children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Loading feed types...', 'jvb')
+            })]
+          }), error && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.Notice, {
+            status: "error",
+            isDismissible: false,
+            children: [(0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Error loading feed types: ', 'jvb'), " ", error]
+          }), !loading && !error && feedTypes && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.Fragment, {
+            children: [groupedTypes.content.length > 0 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.Fragment, {
+              children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("h4", {
+                children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Content Types', 'jvb')
+              }), groupedTypes.content.map(([slug, config]) => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.CheckboxControl, {
+                label: getTypeLabel(slug, config),
+                checked: attributes.contentTypes?.includes(slug) || false,
+                onChange: checked => toggleContentType(slug, checked),
+                help: config.taxonomies?.length > 0 ? `Filters: ${config.taxonomies.join(', ')}` : null
+              }, slug))]
+            }), groupedTypes.taxonomy.length > 0 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.Fragment, {
+              children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("h4", {
+                style: {
+                  marginTop: '20px'
+                },
+                children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Content Taxonomies', 'jvb')
+              }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+                style: {
+                  fontSize: '12px',
+                  color: '#757575'
+                },
+                children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('These are collections that group other content', 'jvb')
+              }), groupedTypes.taxonomy.map(([slug, config]) => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.CheckboxControl, {
+                label: getTypeLabel(slug, config),
+                checked: attributes.contentTypes?.includes(slug) || false,
+                onChange: checked => toggleContentType(slug, checked),
+                help: config.for_content?.length > 0 ? `Contains: ${config.for_content.join(', ')}` : null
+              }, slug))]
+            }), !attributes.contentTypes?.length && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.Notice, {
+              status: "warning",
+              isDismissible: false,
+              children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Please select at least one content type', 'jvb')
+            })]
+          })]
+        })]
+      }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.PanelBody, {
+        title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Display Settings', 'jvb'),
+        initialOpen: false,
+        children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Show Gallery View', 'jvb'),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Enable lightbox for images', 'jvb'),
+          checked: attributes.enableGallery || false,
+          onChange: value => setAttributes({
+            enableGallery: value
+          })
+        })
+      })]
+    }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+      className: "feed-block-placeholder",
+      children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+        className: "feed-block-icon",
+        children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("svg", {
+          width: "48",
+          height: "48",
+          viewBox: "0 0 24 24",
+          fill: "none",
+          children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("rect", {
+            x: "3",
+            y: "3",
+            width: "7",
+            height: "7",
+            fill: "currentColor",
+            opacity: "0.3"
+          }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("rect", {
+            x: "13",
+            y: "3",
+            width: "7",
+            height: "7",
+            fill: "currentColor",
+            opacity: "0.3"
+          }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("rect", {
+            x: "3",
+            y: "13",
+            width: "7",
+            height: "7",
+            fill: "currentColor",
+            opacity: "0.3"
+          }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("rect", {
+            x: "13",
+            y: "13",
+            width: "7",
+            height: "7",
+            fill: "currentColor",
+            opacity: "0.3"
+          })]
+        })
+      }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("h3", {
+        children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Feed Block', 'jvb')
+      }), attributes.inheritQuery ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+        className: "feed-block-description",
+        children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('📍 Inheriting from page context', 'jvb')
+      }) : /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+        className: "feed-block-description",
+        children: attributes.contentTypes?.length > 0 ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.Fragment, {
+          children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+            children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("strong", {
+              children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Showing:', 'jvb')
+            })
+          }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("ul", {
+            style: {
+              listStyle: 'none',
+              padding: '0',
+              margin: '8px 0'
+            },
+            children: attributes.contentTypes.map(type => {
+              const config = feedTypes?.[type];
+              return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("li", {
+                style: {
+                  padding: '4px 0',
+                  color: '#2271b1'
+                },
+                children: ["\u2713 ", config?.plural || type]
+              }, type);
+            })
+          })]
+        }) : /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+          style: {
+            color: '#d63638'
+          },
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('⚠️  No content types selected', 'jvb')
+        })
+      }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+        className: "feed-block-note",
+        children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_4__.__)('Feed will be displayed on the frontend', 'jvb')
+      })]
+    })]
+  });
+}
+
+/***/ },
+
+/***/ "./src/feed/index.js"
+/*!***************************!*\
+  !*** ./src/feed/index.js ***!
+  \***************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./style.scss */ "./src/feed/style.scss");
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./edit */ "./src/feed/edit.js");
+/* harmony import */ var _save__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./save */ "./src/feed/save.js");
+/* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./block.json */ "./src/feed/block.json");
+/**
+ * Registers a new block provided a unique name and an object defining its behavior.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+
+
+/**
+ * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
+ * All files containing `style` keyword are bundled together. The code used
+ * gets applied both to the front of your site and to the editor.
+ *
+ * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
+ */
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+/**
+ * Every block starts by registering a new block type definition.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)(_block_json__WEBPACK_IMPORTED_MODULE_4__.name, {
+  /**
+   * @see ./edit.js
+   */
+  edit: _edit__WEBPACK_IMPORTED_MODULE_2__["default"],
+  /**
+   * @see ./save.js
+   */
+  save: _save__WEBPACK_IMPORTED_MODULE_3__["default"]
+});
+
+/***/ },
+
+/***/ "./src/feed/save.js"
+/*!**************************!*\
+  !*** ./src/feed/save.js ***!
+  \**************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ save)
+/* harmony export */ });
+function save() {
+  return null; // Dynamic block rendered by PHP
+}
+
+/***/ },
+
+/***/ "./src/feed/style.scss"
+/*!*****************************!*\
+  !*** ./src/feed/style.scss ***!
+  \*****************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/api-fetch"
+/*!**********************************!*\
+  !*** external ["wp","apiFetch"] ***!
+  \**********************************/
+(module) {
+
+module.exports = window["wp"]["apiFetch"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/components"
+/*!************************************!*\
+  !*** external ["wp","components"] ***!
+  \************************************/
+(module) {
+
+module.exports = window["wp"]["components"];
+
+/***/ },
+
+/***/ "@wordpress/element"
+/*!*********************************!*\
+  !*** external ["wp","element"] ***!
+  \*********************************/
+(module) {
+
+module.exports = window["wp"]["element"];
+
+/***/ },
+
+/***/ "@wordpress/i18n"
+/*!******************************!*\
+  !*** external ["wp","i18n"] ***!
+  \******************************/
+(module) {
+
+module.exports = window["wp"]["i18n"];
+
+/***/ },
+
+/***/ "./src/feed/block.json"
+/*!*****************************!*\
+  !*** ./src/feed/block.json ***!
+  \*****************************/
+(module) {
+
+module.exports = /*#__PURE__*/JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/feed","title":"Feed","category":"jvb","icon":"grid-view","description":"Displays a filterable feed of registered content types","keywords":["feed","grid"],"version":"0.9.0","textdomain":"jvb","supports":{"html":false,"align":["wide","full"]},"attributes":{"title":{"type":"string","default":"Your Scene"},"inheritQuery":{"type":"boolean","default":false},"contentTypes":{"type":"array","default":["tattoo","artwork","artist"],"items":{"type":"string"}},"itemsPerPage":{"type":"number","default":36},"defaultOrder":{"type":"string","default":"date_desc"}},"selectors":{"root":".feed-block"},"styles":[{"name":"default","label":"Default","isDefault":true},{"name":"other","label":"Other"}],"example":{"attributes":{"message":"This is a notice!"}},"editorScript":"file:./index.js","editorStyle":"file:./index.css","style":"file:./style-index.css","viewScript":"file:./view.js"}');
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"feed/index": 0,
+/******/ 			"feed/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["feed/style-index"], () => (__webpack_require__("./src/feed/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/feed/index.js.map b/build/feed/index.js.map
new file mode 100644
index 0000000..e07c9e9
--- /dev/null
+++ b/build/feed/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"feed/index.js","mappings":"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AgF,oEAAiB,CAAEE,6CAAa,EAAE;EAC9B;AACJ;AACA;EACIE,IAAI,EAAE7E,6CAAI;EAEV;AACJ;AACA;EACI0E,IAAIA,+CAAAA;AACR,CAAE,CAAC,C;;;;;;;;;;;;;;ACtCY,SAASA,IAAIA,CAAA,EAAG;EAC3B,OAAO,IAAI,CAAC,CAAC;AACjB,C;;;;;;;;;;;ACFA;;;;;;;;;;;ACAA,2C;;;;;;;;;;ACAA,0C;;;;;;;;;;ACAA,6C;;;;;;;;;;ACAA,wC;;;;;;;;;;ACAA,4C;;;;;;;;;;ACAA,yC;;;;;;;;;;ACAA,sC;;;;;;;;;;;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WC/BA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G;;;;;UEjDA;UACA;UACA;UACA;UACA","sources":["webpack://jvb/./src/feed/edit.js","webpack://jvb/./src/feed/index.js","webpack://jvb/./src/feed/save.js","webpack://jvb/./src/feed/style.scss?8efb","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"apiFetch\"]","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"components\"]","webpack://jvb/external window [\"wp\",\"element\"]","webpack://jvb/external window [\"wp\",\"i18n\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["/**\r\n * Feed Block - Edit Component\r\n * Fetches available feed types from /jvb/v1/feed/types\r\n * Allows configuration of content types and inherit query setting\r\n */\r\n\r\nimport { useEffect, useState } from '@wordpress/element';\r\nimport { useBlockProps, InspectorControls } from '@wordpress/block-editor';\r\nimport {\r\n\tPanelBody,\r\n\tCheckboxControl,\r\n\tToggleControl,\r\n\tSpinner,\r\n\tNotice\r\n} from '@wordpress/components';\r\nimport apiFetch from '@wordpress/api-fetch';\r\nimport { __ } from '@wordpress/i18n';\r\n\r\nexport default function Edit({ attributes, setAttributes }) {\r\n\tconst [feedTypes, setFeedTypes] = useState(null);\r\n\tconst [loading, setLoading] = useState(true);\r\n\tconst [error, setError] = useState(null);\r\n\r\n\tconst blockProps = useBlockProps({\r\n\t\tclassName: 'feed-block-editor'\r\n\t});\r\n\r\n\t/**\r\n\t * Fetch available feed types on component mount\r\n\t */\r\n\tuseEffect(() => {\r\n\t\tapiFetch({\r\n\t\t\tpath: '/jvb/v1/feed/types',\r\n\t\t\theaders: {\r\n\t\t\t\t'If-Modified-Since': localStorage.getItem('feed_types_modified'),\r\n\t\t\t}\r\n\t\t})\r\n\t\t\t.then(types => {\r\n\t\t\t\tsetFeedTypes(types);\r\n\t\t\t\tsetLoading(false);\r\n\r\n\t\t\t\t// Store Last-Modified for future requests\r\n\t\t\t\t// (apiFetch doesn't expose response headers easily,\r\n\t\t\t\t// but the server will handle 304s)\r\n\r\n\t\t\t\t// Initialize contentTypes if not set and not inheriting\r\n\t\t\t\tif (!attributes.contentTypes && !attributes.inheritQuery) {\r\n\t\t\t\t\tconst firstType = Object.keys(types)[0];\r\n\t\t\t\t\tif (firstType) {\r\n\t\t\t\t\t\tsetAttributes({ contentTypes: [firstType] });\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t\t.catch(err => {\r\n\t\t\t\tconsole.error('Error loading feed types:', err);\r\n\t\t\t\tsetError(err.message);\r\n\t\t\t\tsetLoading(false);\r\n\t\t\t});\r\n\t}, [attributes.inheritQuery]);\r\n\r\n\t/**\r\n\t * Toggle a content type in the selection\r\n\t */\r\n\tconst toggleContentType = (slug, checked) => {\r\n\t\tconst currentTypes = attributes.contentTypes || [];\r\n\r\n\t\tconst newTypes = checked\r\n\t\t\t? [...currentTypes, slug]\r\n\t\t\t: currentTypes.filter(t => t !== slug);\r\n\r\n\t\tsetAttributes({ contentTypes: newTypes });\r\n\t};\r\n\r\n\t/**\r\n\t * Get friendly label for content type\r\n\t */\r\n\tconst getTypeLabel = (slug, config) => {\r\n\t\treturn `${config.plural} (${config.type})`;\r\n\t};\r\n\r\n\t/**\r\n\t * Group types by category for better UX\r\n\t */\r\n\tconst groupedTypes = feedTypes ? {\r\n\t\tcontent: Object.entries(feedTypes)\r\n\t\t\t.filter(([_, config]) => config.type === 'content'),\r\n\t\ttaxonomy: Object.entries(feedTypes)\r\n\t\t\t.filter(([_, config]) => config.type === 'taxonomy')\r\n\t} : { content: [], taxonomy: [] };\r\n\r\n\treturn (\r\n\t\t<div {...blockProps}>\r\n\t\t\t<InspectorControls>\r\n\t\t\t\t<PanelBody\r\n\t\t\t\t\ttitle={__('Feed Settings', 'jvb')}\r\n\t\t\t\t\tinitialOpen={true}\r\n\t\t\t\t>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Inherit from Page Context', 'jvb')}\r\n\t\t\t\t\t\thelp={\r\n\t\t\t\t\t\t\tattributes.inheritQuery\r\n\t\t\t\t\t\t\t\t? __('Feed will adapt to the current page (profile, taxonomy, etc.)', 'jvb')\r\n\t\t\t\t\t\t\t\t: __('Manually select content types to display', 'jvb')\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tchecked={attributes.inheritQuery}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ inheritQuery: value })}\r\n\t\t\t\t\t/>\r\n\r\n\t\t\t\t\t{!attributes.inheritQuery && (\r\n\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t{loading && (\r\n\t\t\t\t\t\t\t\t<div style={{ textAlign: 'center', padding: '20px' }}>\r\n\t\t\t\t\t\t\t\t\t<Spinner />\r\n\t\t\t\t\t\t\t\t\t<p>{__('Loading feed types...', 'jvb')}</p>\r\n\t\t\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t\t)}\r\n\r\n\t\t\t\t\t\t\t{error && (\r\n\t\t\t\t\t\t\t\t<Notice status=\"error\" isDismissible={false}>\r\n\t\t\t\t\t\t\t\t\t{__('Error loading feed types: ', 'jvb')} {error}\r\n\t\t\t\t\t\t\t\t</Notice>\r\n\t\t\t\t\t\t\t)}\r\n\r\n\t\t\t\t\t\t\t{!loading && !error && feedTypes && (\r\n\t\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t\t{groupedTypes.content.length > 0 && (\r\n\t\t\t\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t\t\t\t<h4>{__('Content Types', 'jvb')}</h4>\r\n\t\t\t\t\t\t\t\t\t\t\t{groupedTypes.content.map(([slug, config]) => (\r\n\t\t\t\t\t\t\t\t\t\t\t\t<CheckboxControl\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={slug}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tlabel={getTypeLabel(slug, config)}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tchecked={\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tattributes.contentTypes?.includes(slug) || false\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tonChange={(checked) =>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttoggleContentType(slug, checked)\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\thelp={\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconfig.taxonomies?.length > 0\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? `Filters: ${config.taxonomies.join(', ')}`\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t\t\t))}\r\n\t\t\t\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t\t\t\t)}\r\n\r\n\t\t\t\t\t\t\t\t\t{groupedTypes.taxonomy.length > 0 && (\r\n\t\t\t\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t\t\t\t<h4 style={{ marginTop: '20px' }}>\r\n\t\t\t\t\t\t\t\t\t\t\t\t{__('Content Taxonomies', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t\t\t</h4>\r\n\t\t\t\t\t\t\t\t\t\t\t<p style={{ fontSize: '12px', color: '#757575' }}>\r\n\t\t\t\t\t\t\t\t\t\t\t\t{__('These are collections that group other content', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t\t\t</p>\r\n\t\t\t\t\t\t\t\t\t\t\t{groupedTypes.taxonomy.map(([slug, config]) => (\r\n\t\t\t\t\t\t\t\t\t\t\t\t<CheckboxControl\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tkey={slug}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tlabel={getTypeLabel(slug, config)}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tchecked={\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tattributes.contentTypes?.includes(slug) || false\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\tonChange={(checked) =>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ttoggleContentType(slug, checked)\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\t\t\thelp={\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tconfig.for_content?.length > 0\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t? `Contains: ${config.for_content.join(', ')}`\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t: null\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t\t\t))}\r\n\t\t\t\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t\t\t\t)}\r\n\r\n\t\t\t\t\t\t\t\t\t{!attributes.contentTypes?.length && (\r\n\t\t\t\t\t\t\t\t\t\t<Notice status=\"warning\" isDismissible={false}>\r\n\t\t\t\t\t\t\t\t\t\t\t{__('Please select at least one content type', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t\t</Notice>\r\n\t\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t</>\r\n\t\t\t\t\t)}\r\n\t\t\t\t</PanelBody>\r\n\r\n\t\t\t\t<PanelBody\r\n\t\t\t\t\ttitle={__('Display Settings', 'jvb')}\r\n\t\t\t\t\tinitialOpen={false}\r\n\t\t\t\t>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Show Gallery View', 'jvb')}\r\n\t\t\t\t\t\thelp={__('Enable lightbox for images', 'jvb')}\r\n\t\t\t\t\t\tchecked={attributes.enableGallery || false}\r\n\t\t\t\t\t\tonChange={(value) =>\r\n\t\t\t\t\t\t\tsetAttributes({ enableGallery: value })\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t/>\r\n\t\t\t\t</PanelBody>\r\n\t\t\t</InspectorControls>\r\n\r\n\t\t\t<div className=\"feed-block-placeholder\">\r\n\t\t\t\t<div className=\"feed-block-icon\">\r\n\t\t\t\t\t<svg width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n\t\t\t\t\t\t<rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" fill=\"currentColor\" opacity=\"0.3\" />\r\n\t\t\t\t\t\t<rect x=\"13\" y=\"3\" width=\"7\" height=\"7\" fill=\"currentColor\" opacity=\"0.3\" />\r\n\t\t\t\t\t\t<rect x=\"3\" y=\"13\" width=\"7\" height=\"7\" fill=\"currentColor\" opacity=\"0.3\" />\r\n\t\t\t\t\t\t<rect x=\"13\" y=\"13\" width=\"7\" height=\"7\" fill=\"currentColor\" opacity=\"0.3\" />\r\n\t\t\t\t\t</svg>\r\n\t\t\t\t</div>\r\n\r\n\t\t\t\t<h3>{__('Feed Block', 'jvb')}</h3>\r\n\r\n\t\t\t\t{attributes.inheritQuery ? (\r\n\t\t\t\t\t<p className=\"feed-block-description\">\r\n\t\t\t\t\t\t{__('📍 Inheriting from page context', 'jvb')}\r\n\t\t\t\t\t</p>\r\n\t\t\t\t) : (\r\n\t\t\t\t\t<div className=\"feed-block-description\">\r\n\t\t\t\t\t\t{attributes.contentTypes?.length > 0 ? (\r\n\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t<p><strong>{__('Showing:', 'jvb')}</strong></p>\r\n\t\t\t\t\t\t\t\t<ul style={{\r\n\t\t\t\t\t\t\t\t\tlistStyle: 'none',\r\n\t\t\t\t\t\t\t\t\tpadding: '0',\r\n\t\t\t\t\t\t\t\t\tmargin: '8px 0'\r\n\t\t\t\t\t\t\t\t}}>\r\n\t\t\t\t\t\t\t\t\t{attributes.contentTypes.map(type => {\r\n\t\t\t\t\t\t\t\t\t\tconst config = feedTypes?.[type];\r\n\t\t\t\t\t\t\t\t\t\treturn (\r\n\t\t\t\t\t\t\t\t\t\t\t<li key={type} style={{\r\n\t\t\t\t\t\t\t\t\t\t\t\tpadding: '4px 0',\r\n\t\t\t\t\t\t\t\t\t\t\t\tcolor: '#2271b1'\r\n\t\t\t\t\t\t\t\t\t\t\t}}>\r\n\t\t\t\t\t\t\t\t\t\t\t\t✓ {config?.plural || type}\r\n\t\t\t\t\t\t\t\t\t\t\t</li>\r\n\t\t\t\t\t\t\t\t\t\t);\r\n\t\t\t\t\t\t\t\t\t})}\r\n\t\t\t\t\t\t\t\t</ul>\r\n\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t) : (\r\n\t\t\t\t\t\t\t<p style={{ color: '#d63638' }}>\r\n\t\t\t\t\t\t\t\t{__('⚠️  No content types selected', 'jvb')}\r\n\t\t\t\t\t\t\t</p>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t</div>\r\n\t\t\t\t)}\r\n\r\n\t\t\t\t<p className=\"feed-block-note\">\r\n\t\t\t\t\t{__('Feed will be displayed on the frontend', 'jvb')}\r\n\t\t\t\t</p>\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t);\r\n}\r\n","/**\r\n * Registers a new block provided a unique name and an object defining its behavior.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nimport { registerBlockType } from '@wordpress/blocks';\r\n\r\n/**\r\n * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.\r\n * All files containing `style` keyword are bundled together. The code used\r\n * gets applied both to the front of your site and to the editor.\r\n *\r\n * @see https://www.npmjs.com/package/@wordpress/scripts#using-css\r\n */\r\nimport './style.scss';\r\n\r\n/**\r\n * Internal dependencies\r\n */\r\nimport Edit from './edit';\r\nimport save from './save';\r\nimport metadata from './block.json';\r\n\r\n/**\r\n * Every block starts by registering a new block type definition.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nregisterBlockType( metadata.name, {\r\n    /**\r\n     * @see ./edit.js\r\n     */\r\n    edit: Edit,\r\n\r\n    /**\r\n     * @see ./save.js\r\n     */\r\n    save,\r\n} );\r\n","export default function save() {\r\n    return null; // Dynamic block rendered by PHP\r\n}\r\n","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"apiFetch\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"components\"];","module.exports = window[\"wp\"][\"element\"];","module.exports = window[\"wp\"][\"i18n\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"feed/index\": 0,\n\t\"feed/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"feed/style-index\"], () => (__webpack_require__(\"./src/feed/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["useEffect","useState","useBlockProps","InspectorControls","PanelBody","CheckboxControl","ToggleControl","Spinner","Notice","apiFetch","__","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","Edit","attributes","setAttributes","feedTypes","setFeedTypes","loading","setLoading","error","setError","blockProps","className","path","headers","localStorage","getItem","then","types","contentTypes","inheritQuery","firstType","Object","keys","catch","err","console","message","toggleContentType","slug","checked","currentTypes","newTypes","filter","t","getTypeLabel","config","plural","type","groupedTypes","content","entries","_","taxonomy","children","title","initialOpen","label","help","onChange","value","style","textAlign","padding","status","isDismissible","length","map","includes","taxonomies","join","marginTop","fontSize","color","for_content","enableGallery","width","height","viewBox","fill","x","y","opacity","listStyle","margin","registerBlockType","save","metadata","name","edit"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/feed/style-index-rtl.css b/build/feed/style-index-rtl.css
index 8f39c7d..19de821 100644
--- a/build/feed/style-index-rtl.css
+++ b/build/feed/style-index-rtl.css
@@ -1 +1,264 @@
-.feed-block{grid-column:full}.feed-block .placeholder{align-items:center;aspect-ratio:1;background:rgb(var(--base));border:1rem solid rgb(var(--base-50));border-radius:1rem;display:flex;justify-content:center;--w:50%;color:rgb(var(--base-200))}.feed-block .placeholder i.icon{animation:dance 2.5s ease-in-out infinite}.feed-block .item-grid{max-width:var(--full)}.feed-block .item-grid:has([data-timeline]){grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}.feed-block .item{background:rgb(var(--base-50));box-shadow:rgba(var(--base),var(--op-2)) var(--shdw);height:-moz-fit-content;height:fit-content;overflow:hidden;padding:0}.feed-block .item h3{font-size:var(--txt-medium);margin:0}.feed-block .item details{padding:0;position:relative;width:100%;z-index:var(--z-2)}.feed-block .item details summary{backdrop-filter:blur(5px);background-color:rgba(var(--base),var(--op-2));right:0;position:absolute;top:calc(var(--chip_)*-1);width:100%}.feed-block .item details summary:hover{background-color:rgba(var(--action-0),var(--op-45))}.feed-block .item details[open]{padding:.25rem .5rem}.feed-block .item img:hover{opacity:.8}.feed-block .item[data-timeline] .images{aspect-ratio:3/2;padding:0 0 1rem}.feed-block .item[data-timeline] .images span{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast));padding:.25rem .5rem;position:absolute;width:50%}.feed-block .item[data-timeline] .images span:first-of-type{bottom:0;left:50%;text-align:left}.feed-block .item[data-timeline] .images span:last-of-type{right:50%;top:0}.feed-block .item[data-timeline] .images img{width:50%}.feed-block .item[data-timeline] .images img:first-of-type{border-left:2px solid rgb(var(--action-0))}.feed-block .item a:after,.feed-block .item a:before{display:none}.feed-block .item label{font-weight:400;text-transform:none;--w:1.5em}.all-filters{font-size:var(--txt-x-small)}.all-filters[open]{border:2px solid rgb(var(--action-0));border-radius:0 0 var(--radius-outer) var(--radius-outer);padding:0}.all-filters summary{width:100%}.all-filters summary:hover,.all-filters[open] summary{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast))}.all-filters summary:hover:after,.all-filters[open] summary:after{background-color:rgb(var(--action-contrast))}.all-filters>.row.row{padding:0 .75rem 2rem;width:var(--content)}.all-filters>.row.row.search{padding-bottom:0}.all-filters>.row.row{position:relative}.all-filters>.row.row>.label,.all-filters>.row.row>.row>.label{font-family:var(--heading);font-weight:var(--fw-h-bold);text-transform:uppercase}.all-filters>.row.row>.label{width:20%}.all-filters>.row.row>.row>.label{white-space:nowrap}.all-filters .btn+label,.all-filters button{min-height:var(--chipchip);padding:0;width:var(--chipchip)}.all-filters .btn+label .label,.all-filters .row:has(>.btn:not(:checked)+label:hover) :checked+label .label,.all-filters button .label{bottom:-2rem;opacity:0;position:absolute;white-space:nowrap;width:-moz-max-content;width:max-content;z-index:var(--z-4)}.all-filters .btn+label:hover .label,.all-filters .btn:checked+label .label,.all-filters button:hover .label{opacity:1}.all-filters .search.row,.all-filters .view.row{display:none}.search-container:not(.open) .clear-search,.search-container:not(.open) input[type=search]{padding:0;transform:scaleX(0);transform-origin:right;transition:transform var(--trans-base),width var(--trans-base),padding var(--trans-base);width:0}.search-container button{padding:.5rem}.search-container .icon{--w:1.5rem}.search-container.open .clear-search,.search-container.open input[type=search]{transform:scaleX(1);transform-origin:right;transition:transform var(--trans-base),width var(--trans-base),padding var(--trans-base)}.all-filters>.search,.search-container,input[type=search]{width:100%}.toggle-text input+label{border:1px dashed transparent;color:var(--contrast)!important;cursor:pointer;font-weight:400;padding:.25rem .5rem;position:relative;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.toggle-text input+label:after,.toggle-text input+label:before{display:none!important}.toggle-text input+label .text{margin:0;position:relative;--gap:0;border:1px solid rgb(var(--action-50));border-radius:var(--radius);color:rgb(var(--action-50));font-weight:700;padding:2px 4px;width:-moz-fit-content;width:fit-content}.toggle-text input+label .off{--mid:-100%}.toggle-text input+label .on{--mid:100%}.toggle-text input+label .off,.toggle-text input+label .on{transition:var(--trans-transform),opacity var(--trans-base)}.toggle-text input+label .off,.toggle-text input:checked+label .on{max-width:100%;opacity:1;transform:translateZ(0)}.toggle-text input+label .on,.toggle-text input:checked+label .off{max-width:0;opacity:0;transform:translate3d(0,var(--mid),0)}.toggle-text:hover label{border-color:rgb(var(--action-200))}.toggle-text:hover .text{background-color:rgb(var(--action-50));border-color:rgb(var(--action-50));color:rgb(var(--action-contrast))}
+/*!********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/feed/style.scss ***!
+  \********************************************************************************************************************************************************************************************************************************************/
+/***** START FRESH *****/
+.feed-block {
+  grid-column: full;
+}
+.feed-block .placeholder {
+  aspect-ratio: 1;
+  background: rgb(var(--base));
+  border: 1rem solid rgb(var(--base-50));
+  border-radius: 1rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  --w: 50%;
+  color: rgb(var(--base-200));
+}
+.feed-block .placeholder i.icon {
+  animation: dance 2.5s ease-in-out infinite;
+}
+.feed-block .item-grid {
+  max-width: var(--full);
+}
+.feed-block .item-grid:has([data-timeline]) {
+  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+}
+.feed-block .item {
+  overflow: hidden;
+  background: rgb(var(--base-50));
+  box-shadow: rgba(var(--base), var(--op-2)) var(--shdw);
+  height: -moz-fit-content;
+  height: fit-content;
+  padding: 0;
+}
+.feed-block .item h3 {
+  margin: 0;
+  font-size: var(--txt-medium);
+}
+.feed-block .item details {
+  z-index: var(--z-2);
+  width: 100%;
+  position: relative;
+  padding: 0;
+}
+.feed-block .item details summary {
+  position: absolute;
+  top: calc(var(--chip_) * -1);
+  right: 0;
+  width: 100%;
+  background-color: rgba(var(--base), var(--op-2));
+  backdrop-filter: blur(5px);
+}
+.feed-block .item details summary:hover {
+  background-color: rgba(var(--action-0), var(--op-45));
+}
+.feed-block .item details[open] {
+  padding: 0.25rem 0.5rem;
+}
+.feed-block .item img:hover {
+  opacity: 0.8;
+}
+.feed-block .item[data-timeline] .images {
+  aspect-ratio: 3/2;
+  padding: 0 0 1rem;
+}
+.feed-block .item[data-timeline] .images span {
+  width: 50%;
+  position: absolute;
+  background-color: rgb(var(--action-0));
+  color: rgb(var(--action-contrast));
+  padding: 0.25rem 0.5rem;
+}
+.feed-block .item[data-timeline] .images span:first-of-type {
+  bottom: 0;
+  left: 50%;
+  text-align: left;
+}
+.feed-block .item[data-timeline] .images span:last-of-type {
+  top: 0;
+  right: 50%;
+}
+.feed-block .item[data-timeline] .images img {
+  width: 50%;
+}
+.feed-block .item[data-timeline] .images img:first-of-type {
+  border-left: 2px solid rgb(var(--action-0));
+}
+.feed-block .item a::before, .feed-block .item a::after {
+  display: none;
+}
+.feed-block .item label {
+  font-weight: normal;
+  text-transform: none;
+  --w: 1.5em;
+}
+.feed-block .all-filters summary {
+  display: flex;
+  justify-content: space-between;
+}
+.all-filters {
+  font-size: var(--txt-x-small);
+}
+.all-filters[open] {
+  border: 2px solid rgb(var(--action-0));
+  padding: 0;
+  border-radius: 0 0 var(--radius-outer) var(--radius-outer);
+}
+.all-filters summary {
+  width: 100%;
+}
+.all-filters[open] summary,
+.all-filters summary:hover {
+  background-color: rgb(var(--action-0));
+  color: rgb(var(--action-contrast));
+}
+.all-filters[open] summary::after,
+.all-filters summary:hover::after {
+  background-color: rgb(var(--action-contrast));
+}
+.all-filters > .row.row {
+  padding: 0 0.75rem 2rem;
+  width: var(--content);
+}
+.all-filters > .row.row.search {
+  padding-bottom: 0;
+}
+.all-filters > .row.row {
+  position: relative;
+}
+.all-filters > .row.row > .label,
+.all-filters > .row.row > .row > .label {
+  font-family: var(--heading);
+  font-weight: var(--fw-h-bold);
+  text-transform: uppercase;
+}
+.all-filters > .row.row > .label {
+  width: 20%;
+}
+.all-filters > .row.row > .row > .label {
+  white-space: nowrap;
+}
+.all-filters button,
+.all-filters .btn + label {
+  width: var(--chipchip);
+  min-height: var(--chipchip);
+  padding: 0;
+}
+.all-filters button .label,
+.all-filters .row:has(> .btn:not(:checked) + label:hover) :checked + label .label,
+.all-filters .btn + label .label {
+  position: absolute;
+  bottom: -2rem;
+  width: -moz-max-content;
+  width: max-content;
+  white-space: nowrap;
+  opacity: 0;
+  z-index: var(--z-4);
+}
+.all-filters button:hover .label,
+.all-filters .btn:checked + label .label,
+.all-filters .btn + label:hover .label {
+  opacity: 1;
+}
+.all-filters .search.row,
+.all-filters .view.row {
+  display: none;
+}
+.all-filters .ordering {
+  padding: 2rem 0 0.75rem 0;
+}
+.all-filters .ordering > .row label {
+  position: unset;
+}
+.all-filters .ordering .row .label {
+  top: -1rem;
+  color: rgb(var(--contrast));
+}
+.all-filters .ordering .row.orderby .label {
+  right: 0;
+}
+.all-filters .ordering .row.order-direction .label {
+  left: 0;
+}
+.search-container:not(.open) input[type=search],
+.search-container:not(.open) .clear-search {
+  transform: scaleX(0);
+  transform-origin: right;
+  width: 0;
+  padding: 0;
+  transition: transform var(--trans-base), width var(--trans-base), padding var(--trans-base);
+}
+.search-container button {
+  padding: 0.5rem;
+}
+.search-container .icon {
+  --w: 1.5rem;
+}
+.search-container.open input[type=search],
+.search-container.open .clear-search {
+  transform: scaleX(1);
+  transform-origin: right;
+  transition: transform var(--trans-base), width var(--trans-base), padding var(--trans-base);
+}
+.all-filters > .search,
+input[type=search],
+.search-container {
+  width: 100%;
+}
+.toggle-text input + label {
+  font-weight: normal;
+  color: var(--contrast) !important;
+  text-transform: none;
+  cursor: pointer;
+  position: relative;
+  padding: 0.25rem 0.5rem;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  user-select: none;
+  border: 1px dashed transparent;
+}
+.toggle-text input + label::before, .toggle-text input + label::after {
+  display: none !important;
+}
+.toggle-text input + label .text {
+  position: relative;
+  margin: 0;
+  --gap: 0;
+  font-weight: bold;
+  width: -moz-fit-content;
+  width: fit-content;
+  padding: 2px 4px;
+  border: 1px solid rgb(var(--action-50));
+  border-radius: var(--radius);
+  color: rgb(var(--action-50));
+}
+.toggle-text input + label .off {
+  --mid: -100%;
+}
+.toggle-text input + label .on {
+  --mid: 100%;
+}
+.toggle-text input + label .off,
+.toggle-text input + label .on {
+  transition: var(--trans-transform), opacity var(--trans-base);
+}
+.toggle-text input + label .off, .toggle-text input:checked + label .on {
+  opacity: 1;
+  max-width: 100%;
+  transform: translate3d(0, 0, 0);
+}
+.toggle-text input + label .on, .toggle-text input:checked + label .off {
+  opacity: 0;
+  max-width: 0;
+  transform: translate3d(0, var(--mid), 0);
+}
+.toggle-text:hover label {
+  border-color: rgb(var(--action-200));
+}
+.toggle-text:hover .text {
+  background-color: rgb(var(--action-50));
+  color: rgb(var(--action-contrast));
+  border-color: rgb(var(--action-50));
+}
diff --git a/build/feed/style-index.css b/build/feed/style-index.css
index d68b275..d13fce2 100644
--- a/build/feed/style-index.css
+++ b/build/feed/style-index.css
@@ -1 +1,266 @@
-.feed-block{grid-column:full}.feed-block .placeholder{align-items:center;aspect-ratio:1;background:rgb(var(--base));border:1rem solid rgb(var(--base-50));border-radius:1rem;display:flex;justify-content:center;--w:50%;color:rgb(var(--base-200))}.feed-block .placeholder i.icon{animation:dance 2.5s ease-in-out infinite}.feed-block .item-grid{max-width:var(--full)}.feed-block .item-grid:has([data-timeline]){grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}.feed-block .item{background:rgb(var(--base-50));box-shadow:rgba(var(--base),var(--op-2)) var(--shdw);height:-moz-fit-content;height:fit-content;overflow:hidden;padding:0}.feed-block .item h3{font-size:var(--txt-medium);margin:0}.feed-block .item details{padding:0;position:relative;width:100%;z-index:var(--z-2)}.feed-block .item details summary{backdrop-filter:blur(5px);background-color:rgba(var(--base),var(--op-2));left:0;position:absolute;top:calc(var(--chip_)*-1);width:100%}.feed-block .item details summary:hover{background-color:rgba(var(--action-0),var(--op-45))}.feed-block .item details[open]{padding:.25rem .5rem}.feed-block .item img:hover{opacity:.8}.feed-block .item[data-timeline] .images{aspect-ratio:3/2;padding:0 0 1rem}.feed-block .item[data-timeline] .images span{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast));padding:.25rem .5rem;position:absolute;width:50%}.feed-block .item[data-timeline] .images span:first-of-type{bottom:0;right:50%;text-align:right}.feed-block .item[data-timeline] .images span:last-of-type{left:50%;top:0}.feed-block .item[data-timeline] .images img{width:50%}.feed-block .item[data-timeline] .images img:first-of-type{border-right:2px solid rgb(var(--action-0))}.feed-block .item a:after,.feed-block .item a:before{display:none}.feed-block .item label{font-weight:400;text-transform:none;--w:1.5em}.all-filters{font-size:var(--txt-x-small)}.all-filters[open]{border:2px solid rgb(var(--action-0));border-radius:0 0 var(--radius-outer) var(--radius-outer);padding:0}.all-filters summary{width:100%}.all-filters summary:hover,.all-filters[open] summary{background-color:rgb(var(--action-0));color:rgb(var(--action-contrast))}.all-filters summary:hover:after,.all-filters[open] summary:after{background-color:rgb(var(--action-contrast))}.all-filters>.row.row{padding:0 .75rem 2rem;width:var(--content)}.all-filters>.row.row.search{padding-bottom:0}.all-filters>.row.row{position:relative}.all-filters>.row.row>.label,.all-filters>.row.row>.row>.label{font-family:var(--heading);font-weight:var(--fw-h-bold);text-transform:uppercase}.all-filters>.row.row>.label{width:20%}.all-filters>.row.row>.row>.label{white-space:nowrap}.all-filters .btn+label,.all-filters button{min-height:var(--chipchip);padding:0;width:var(--chipchip)}.all-filters .btn+label .label,.all-filters .row:has(>.btn:not(:checked)+label:hover) :checked+label .label,.all-filters button .label{bottom:-2rem;opacity:0;position:absolute;white-space:nowrap;width:-moz-max-content;width:max-content;z-index:var(--z-4)}.all-filters .btn+label:hover .label,.all-filters .btn:checked+label .label,.all-filters button:hover .label{opacity:1}.all-filters .search.row,.all-filters .view.row{display:none}.search-container:not(.open) .clear-search,.search-container:not(.open) input[type=search]{padding:0;transform:scaleX(0);transform-origin:left;transition:transform var(--trans-base),width var(--trans-base),padding var(--trans-base);width:0}.search-container button{padding:.5rem}.search-container .icon{--w:1.5rem}.search-container.open .clear-search,.search-container.open input[type=search]{transform:scaleX(1);transform-origin:left;transition:transform var(--trans-base),width var(--trans-base),padding var(--trans-base)}.all-filters>.search,.search-container,input[type=search]{width:100%}.toggle-text input+label{border:1px dashed transparent;color:var(--contrast)!important;cursor:pointer;font-weight:400;padding:.25rem .5rem;position:relative;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.toggle-text input+label:after,.toggle-text input+label:before{display:none!important}.toggle-text input+label .text{margin:0;position:relative;--gap:0;border:1px solid rgb(var(--action-50));border-radius:var(--radius);color:rgb(var(--action-50));font-weight:700;padding:2px 4px;width:-moz-fit-content;width:fit-content}.toggle-text input+label .off{--mid:-100%}.toggle-text input+label .on{--mid:100%}.toggle-text input+label .off,.toggle-text input+label .on{transition:var(--trans-transform),opacity var(--trans-base)}.toggle-text input+label .off,.toggle-text input:checked+label .on{max-width:100%;opacity:1;transform:translateZ(0)}.toggle-text input+label .on,.toggle-text input:checked+label .off{max-width:0;opacity:0;transform:translate3d(0,var(--mid),0)}.toggle-text:hover label{border-color:rgb(var(--action-200))}.toggle-text:hover .text{background-color:rgb(var(--action-50));border-color:rgb(var(--action-50));color:rgb(var(--action-contrast))}
+/*!********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/feed/style.scss ***!
+  \********************************************************************************************************************************************************************************************************************************************/
+/***** START FRESH *****/
+.feed-block {
+  grid-column: full;
+}
+.feed-block .placeholder {
+  aspect-ratio: 1;
+  background: rgb(var(--base));
+  border: 1rem solid rgb(var(--base-50));
+  border-radius: 1rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  --w: 50%;
+  color: rgb(var(--base-200));
+}
+.feed-block .placeholder i.icon {
+  animation: dance 2.5s ease-in-out infinite;
+}
+.feed-block .item-grid {
+  max-width: var(--full);
+}
+.feed-block .item-grid:has([data-timeline]) {
+  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+}
+.feed-block .item {
+  overflow: hidden;
+  background: rgb(var(--base-50));
+  box-shadow: rgba(var(--base), var(--op-2)) var(--shdw);
+  height: -moz-fit-content;
+  height: fit-content;
+  padding: 0;
+}
+.feed-block .item h3 {
+  margin: 0;
+  font-size: var(--txt-medium);
+}
+.feed-block .item details {
+  z-index: var(--z-2);
+  width: 100%;
+  position: relative;
+  padding: 0;
+}
+.feed-block .item details summary {
+  position: absolute;
+  top: calc(var(--chip_) * -1);
+  left: 0;
+  width: 100%;
+  background-color: rgba(var(--base), var(--op-2));
+  backdrop-filter: blur(5px);
+}
+.feed-block .item details summary:hover {
+  background-color: rgba(var(--action-0), var(--op-45));
+}
+.feed-block .item details[open] {
+  padding: 0.25rem 0.5rem;
+}
+.feed-block .item img:hover {
+  opacity: 0.8;
+}
+.feed-block .item[data-timeline] .images {
+  aspect-ratio: 3/2;
+  padding: 0 0 1rem;
+}
+.feed-block .item[data-timeline] .images span {
+  width: 50%;
+  position: absolute;
+  background-color: rgb(var(--action-0));
+  color: rgb(var(--action-contrast));
+  padding: 0.25rem 0.5rem;
+}
+.feed-block .item[data-timeline] .images span:first-of-type {
+  bottom: 0;
+  right: 50%;
+  text-align: right;
+}
+.feed-block .item[data-timeline] .images span:last-of-type {
+  top: 0;
+  left: 50%;
+}
+.feed-block .item[data-timeline] .images img {
+  width: 50%;
+}
+.feed-block .item[data-timeline] .images img:first-of-type {
+  border-right: 2px solid rgb(var(--action-0));
+}
+.feed-block .item a::before, .feed-block .item a::after {
+  display: none;
+}
+.feed-block .item label {
+  font-weight: normal;
+  text-transform: none;
+  --w: 1.5em;
+}
+.feed-block .all-filters summary {
+  display: flex;
+  justify-content: space-between;
+}
+.all-filters {
+  font-size: var(--txt-x-small);
+}
+.all-filters[open] {
+  border: 2px solid rgb(var(--action-0));
+  padding: 0;
+  border-radius: 0 0 var(--radius-outer) var(--radius-outer);
+}
+.all-filters summary {
+  width: 100%;
+}
+.all-filters[open] summary,
+.all-filters summary:hover {
+  background-color: rgb(var(--action-0));
+  color: rgb(var(--action-contrast));
+}
+.all-filters[open] summary::after,
+.all-filters summary:hover::after {
+  background-color: rgb(var(--action-contrast));
+}
+.all-filters > .row.row {
+  padding: 0 0.75rem 2rem;
+  width: var(--content);
+}
+.all-filters > .row.row.search {
+  padding-bottom: 0;
+}
+.all-filters > .row.row {
+  position: relative;
+}
+.all-filters > .row.row > .label,
+.all-filters > .row.row > .row > .label {
+  font-family: var(--heading);
+  font-weight: var(--fw-h-bold);
+  text-transform: uppercase;
+}
+.all-filters > .row.row > .label {
+  width: 20%;
+}
+.all-filters > .row.row > .row > .label {
+  white-space: nowrap;
+}
+.all-filters button,
+.all-filters .btn + label {
+  width: var(--chipchip);
+  min-height: var(--chipchip);
+  padding: 0;
+}
+.all-filters button .label,
+.all-filters .row:has(> .btn:not(:checked) + label:hover) :checked + label .label,
+.all-filters .btn + label .label {
+  position: absolute;
+  bottom: -2rem;
+  width: -moz-max-content;
+  width: max-content;
+  white-space: nowrap;
+  opacity: 0;
+  z-index: var(--z-4);
+}
+.all-filters button:hover .label,
+.all-filters .btn:checked + label .label,
+.all-filters .btn + label:hover .label {
+  opacity: 1;
+}
+.all-filters .search.row,
+.all-filters .view.row {
+  display: none;
+}
+.all-filters .ordering {
+  padding: 2rem 0 0.75rem 0;
+}
+.all-filters .ordering > .row label {
+  position: unset;
+}
+.all-filters .ordering .row .label {
+  top: -1rem;
+  color: rgb(var(--contrast));
+}
+.all-filters .ordering .row.orderby .label {
+  left: 0;
+}
+.all-filters .ordering .row.order-direction .label {
+  right: 0;
+}
+.search-container:not(.open) input[type=search],
+.search-container:not(.open) .clear-search {
+  transform: scaleX(0);
+  transform-origin: left;
+  width: 0;
+  padding: 0;
+  transition: transform var(--trans-base), width var(--trans-base), padding var(--trans-base);
+}
+.search-container button {
+  padding: 0.5rem;
+}
+.search-container .icon {
+  --w: 1.5rem;
+}
+.search-container.open input[type=search],
+.search-container.open .clear-search {
+  transform: scaleX(1);
+  transform-origin: left;
+  transition: transform var(--trans-base), width var(--trans-base), padding var(--trans-base);
+}
+.all-filters > .search,
+input[type=search],
+.search-container {
+  width: 100%;
+}
+.toggle-text input + label {
+  font-weight: normal;
+  color: var(--contrast) !important;
+  text-transform: none;
+  cursor: pointer;
+  position: relative;
+  padding: 0.25rem 0.5rem;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  user-select: none;
+  border: 1px dashed transparent;
+}
+.toggle-text input + label::before, .toggle-text input + label::after {
+  display: none !important;
+}
+.toggle-text input + label .text {
+  position: relative;
+  margin: 0;
+  --gap: 0;
+  font-weight: bold;
+  width: -moz-fit-content;
+  width: fit-content;
+  padding: 2px 4px;
+  border: 1px solid rgb(var(--action-50));
+  border-radius: var(--radius);
+  color: rgb(var(--action-50));
+}
+.toggle-text input + label .off {
+  --mid: -100%;
+}
+.toggle-text input + label .on {
+  --mid: 100%;
+}
+.toggle-text input + label .off,
+.toggle-text input + label .on {
+  transition: var(--trans-transform), opacity var(--trans-base);
+}
+.toggle-text input + label .off, .toggle-text input:checked + label .on {
+  opacity: 1;
+  max-width: 100%;
+  transform: translate3d(0, 0, 0);
+}
+.toggle-text input + label .on, .toggle-text input:checked + label .off {
+  opacity: 0;
+  max-width: 0;
+  transform: translate3d(0, var(--mid), 0);
+}
+.toggle-text:hover label {
+  border-color: rgb(var(--action-200));
+}
+.toggle-text:hover .text {
+  background-color: rgb(var(--action-50));
+  color: rgb(var(--action-contrast));
+  border-color: rgb(var(--action-50));
+}
+
+/*# sourceMappingURL=style-index.css.map*/
\ No newline at end of file
diff --git a/build/feed/style-index.css.map b/build/feed/style-index.css.map
new file mode 100644
index 0000000..d65a9c3
--- /dev/null
+++ b/build/feed/style-index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"feed/style-index.css","mappings":";;;AA8/BA;AACA;EACC;AA7/BD;AA+/BC;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AA7/BF;AA8/BE;EACC;AA5/BH;AAggCC;EACC;AA9/BF;AAggCE;EACC;AA9/BH;AAkgCC;EACC;EACA;EACA;EACA;EAAA;EACA;AAhgCF;AAkgCE;EACC;EACA;AAhgCH;AAmgCE;EACC;EACA;EACA;EACA;AAjgCH;AAmgCG;EACC;EACA;EACA;EACA;EACA;EACA;AAjgCJ;AAmgCI;EACC;AAjgCL;AAqgCG;EACC;AAngCJ;AAwgCG;EACC;AAtgCJ;AA2gCG;EACC;EACA;AAzgCJ;AA2gCI;EACC;EACA;EACA;EACA;EACA;AAzgCL;AA2gCK;EACC;EACA;EACA;AAzgCN;AA2gCK;EACC;EACA;AAzgCN;AAqhCI;EACC;AAnhCL;AAohCK;EACC;AAlhCN;AAyhCG;EAEC;AAxhCJ;AA2hCE;EACC;EACA;EACA;AAzhCH;AA4hCC;EACC;EACA;AA1hCF;AA6hCA;EACC;AA1hCD;AA4hCC;EACC;EACA;EACA;AA1hCF;AA6hCC;EACC;AA3hCF;AA8hCC;;EAEC;EACA;AA5hCF;AA6hCE;;EACC;AA1hCH;AA8hCC;EACC;EACA;AA5hCF;AA8hCE;EACC;AA5hCH;AAuhCC;EAOC;AA3hCF;AA6hCE;;EAEC;EACA;EACA;AA3hCH;AA6hCE;EACC;AA3hCH;AA6hCE;EACC;AA3hCH;AA+hCC;;EAEC;EACA;EACA;AA7hCF;AAgiCC;;;EAGC;EACA;EACA;EAAA;EACA;EACA;EACA;AA9hCF;AAiiCC;;;EAGC;AA/hCF;AAkiCC;;EAEC;AAhiCF;AAkiCC;EACC;AAhiCF;AAkiCC;EACC;AAhiCF;AAoiCE;EACC;EACA;AAliCH;AAoiCE;EACC;AAliCH;AAoiCE;EACC;AAliCH;AAwiCA;;EAEC;EACA;EACA;EACA;EACA;AAriCD;AAuiCA;EACC;AApiCD;AAsiCA;EACC;AAniCD;AAqiCA;;EAEC;EACA;EACA;AAliCD;AAoiCA;;;EAGC;AAjiCD;AAuiCE;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;AApiCH;AAsiCG;EAEC;AAriCJ;AAwiCG;EACC;EACA;EACA;EACA;EACA;EAAA;EACA;EACA;EACA;EACA;AAtiCJ;AAyiCG;EACC;AAviCJ;AAyiCG;EACC;AAviCJ;AAyiCG;;EAEC;AAviCJ;AA2iCG;EAEA;EACA;EACA;AA1iCH;AA4iCG;EAEA;EACA;EACA;AA3iCH;AAijCE;EACC;AA/iCH;AAijCE;EACC;EACA;EACA;AA/iCH,C","sources":["webpack://jvb/./src/feed/style.scss"],"sourcesContent":["//.feed-block {\r\n//\tmax-width: var(--full);\r\n//\tmargin: 0 auto;\r\n//\r\n//\t&:target {\r\n//\t\tscroll-snap-margin-top: 5rem;\r\n//\t\tscroll-margin-top: 5rem;\r\n//\t\toutline: 0;\r\n//\t\tborder-radius: 0;\r\n//\t\tpadding: 0;\r\n//\r\n//\t\t.feed-item {\r\n//\t\t\toutline: double var(--pink-0);\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//.loading .feed-block {\r\n//\topacity: .7;\r\n//}\r\n//\r\n//.label {\r\n//\tdisplay: flex;\r\n//\talign-items: center;\r\n//\tgap: .25rem;\r\n//\tfont-size: .9rem;\r\n//\ta:hover {\r\n//\t\tcolor: var(--pink-0);\r\n//\t}\r\n//}\r\n//\r\n///** Filters Form **/\r\n//.feed-filters {\r\n//\tmargin: 2rem 0;\r\n//\tposition: sticky;\r\n//\ttop: 3rem;\r\n//\tz-index: 15;\r\n//\tbackground: rgba(var(--base),var(--op-6));\r\n//\tpadding: .25rem 3rem;\r\n//\tdetails[open] summary {\r\n//\t\tbackground-color: var(--overlay);\r\n//\t}\r\n//\tsummary {\r\n//\t\tjustify-content: flex-start;\r\n//\r\n//\t\t> * {\r\n//\t\t\torder: 3;\r\n//\t\t}\r\n//\t\t.label {\r\n//\t\t\torder: 1;\r\n//\t\t}\r\n//\t\t.filter-label {\r\n//\t\t\torder: 2;\r\n//\t\t}\r\n//\t\t&::after {\r\n//\t\t\torder: 4;\r\n//\t\t}\r\n//\t\t#favourites + label {\r\n//\t\t\tmargin-left: auto;\r\n//\t\t}\r\n//\t\t#favourites + label:hover,\r\n//\t\t#favourites:checked + label {\r\n//\t\t\tborder-color: var(--pink-0);\r\n//\t\t\tbackground-color: var(--pink-0);\r\n//\t\t\tcolor: var(--white);\r\n//\r\n//\t\t}\r\n//\t\t#favourites:checked + label {\r\n//\t\t\tanimation: pop 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tdetails[open],\r\n//\tsummary:hover {\r\n//\t\tbackground-color: rgba(var(--base),var(--op-6));\r\n//\t}\r\n//\r\n//\t&:has(#favourites) {\r\n//\t\tsummary::after {\r\n//\t\t\tmargin-left: 1rem;\r\n//\t\t}\r\n//\t}\r\n//}\r\n//summary > * {\r\n//\torder: 3;\r\n//}\r\n//summary .label {\r\n//\torder: 1;\r\n//}\r\n//.filter-label {\r\n//\tdisplay: inline-block;\r\n//\tvertical-align: middle;\r\n//\theight: 1.3em;\r\n//\torder: 2;\r\n//\tmargin: 0;\r\n//\tpadding: 0;\r\n//\r\n//\tli {\r\n//\t\tlist-style: none;\r\n//\t\theight: 0;\r\n//\t\toverflow: hidden;\r\n//\t\t&.active {\r\n//\t\t\theight: 100%;\r\n//\t\t}\r\n//\t}\r\n//}\r\n//.filter-group {\r\n//\tdisplay: flex;\r\n//\talign-items: center;\r\n//\tgap: .5rem;\r\n//\tflex-wrap: wrap;\r\n//\tlabel {\r\n//\t\tfont-weight: 100;\r\n//\t}\r\n//\t&:has(.order-by) {\r\n//\t\tjustify-content: space-between;\r\n//\t}\r\n//\t.order-by,\r\n//\t.order-direction {\r\n//\t\tdisplay: flex;\r\n//\t\tflex-wrap: wrap;\r\n//\t\tgap: .5rem;\r\n//\t\tflex: 1;\r\n//\t\tjustify-content: flex-start;\r\n//\t\t.label {\r\n//\t\t\twidth: 100%;\r\n//\t\t}\r\n//\r\n//\t\tlabel:has(.label) {\r\n//\t\t\tpadding: 0 .35rem;\r\n//\t\t\tgap: .5rem;\r\n//\t\t\t.label {\r\n//\t\t\t\tfont-size: 1rem;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//}\r\n//.filter-group >.label {\r\n//\twidth: 100%;\r\n//}\r\n//\r\n///**\r\n//Feed Grid\r\n// */\r\n//.feed-grid {\r\n//\tdisplay: grid;\r\n//\tgrid-template-columns: repeat(auto-fit, minmax(250px, 1fr));\r\n//\tgap: .5rem;\r\n//\tmargin-bottom: 2rem;\r\n//\tpadding: 0 4rem;\r\n//\t--delay: 0s;\r\n//\t--increase: .1s;\r\n//}\r\n//.feed-empty-state {\r\n//\tgrid-column: 1/-1;\r\n//\ttext-align: center;\r\n//\tpadding: 2rem;\r\n//\tbackground: rgb(var(--base-100));\r\n//\tborder-radius: var(--radius);\r\n//\tmargin: 0 auto;\r\n//\tmax-width: 600px;\r\n//}\r\n///**\r\n//Placeholders\r\n// */\r\n//.placeholder {\r\n//\taspect-ratio: 1;\r\n//\tbackground: rgb(var(--base));\r\n//\tborder: 1rem solid rgb(var(--base-50));\r\n//\tborder-radius: 1rem;\r\n//\tdisplay: flex;\r\n//\tjustify-content: center;\r\n//\talign-items: center;\r\n//\r\n//\t.icon {\r\n//\t\t--w: 50%;\r\n//\t\tcolor: rgb(var(--base-200));\r\n//\t\tanimation: dance 2.5s ease-in-out infinite;\r\n//\r\n//\t}\r\n//}\r\n//\r\n///**\r\n//Feed Items\r\n// */\r\n//.feed-item {\r\n//\tposition: relative;\r\n//\tborder-radius: 0.5rem;\r\n//\toverflow: hidden;\r\n//\tbackground: rgb(var(--base-50));\r\n//\tbox-shadow: 0 2px 4px rgba(0,0,0,0.1);\r\n//\topacity: 0;\r\n//\ttransition: opacity var(--trans-base) var(--delay);\r\n//\theight: fit-content;\r\n//\tpadding: 0;\r\n//\r\n//\timg {\r\n//\t\topacity: .7;\r\n//\t\tfilter: grayscale(.5) sepia(.3) blur(7px);\r\n//\t}\r\n//\t&[data-loaded=true] {\r\n//\t\timg {\r\n//\t\t\topacity: 1;\r\n//\t\t\tfilter: none;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\ta {\r\n//\t\t&::before,\r\n//\t\t&::after {\r\n//\t\t\tdisplay: none;\r\n//\t\t}\r\n//\t}\r\n//\tdetails a {\r\n//\t\tfont-size: clamp(1rem, 0.9306rem + 0.2222vw, 1.125rem);\r\n//\t}\r\n//\r\n//\t&[data-loaded] {\r\n//\t\topacity: 1;\r\n//\t\t+ [data-loaded] {\r\n//\t\t\t--delay: var(--delay) + var(--increase);\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t&.highlighted {\r\n//\t\tbox-shadow: 0 0 0 4px #FF0080, 0 8px 16px rgba(0, 0, 0, 0.1);\r\n//\t\tanimation: highlight-puls 2s ease-in-out;\r\n//\t}\r\n//\t&[open],\r\n//\t&:hover {\r\n//\t\t.handle {\r\n//\t\t\tbackground-color: var(--overlay-pink-medium);\r\n//\t\t\tbackdrop-filter: blur(5px);\r\n//\t\t}\r\n//\t}\r\n//\tsummary {\r\n//\t\twidth: calc(100% - 1rem);\r\n//\t\theight: 100%;\r\n//\t\taspect-ratio: 1;\r\n//\t\t.handle {\r\n//\t\t\tposition: absolute;\r\n//\t\t\tbottom: 0;\r\n//\t\t\tleft: 0;\r\n//\t\t\tright: 0;\r\n//\t\t\tbackground-color: rgba(var(--base),var(--op-3));\r\n//\t\t\tbackdrop-filter: blur(5px);\r\n//\t\t\tborder-radius: var(--radius);\r\n//\t\t\tz-index: 1;\r\n//\t\t\tpadding: .25rem .25rem .25rem 1.1rem;\r\n//\t\t}\r\n//\t\t&::after {\r\n//\t\t\tz-index: 11;\r\n//\t\t\tposition: absolute;\r\n//\t\t\tbottom: .35rem;\r\n//\t\t\tright: .7rem;\r\n//\t\t\twidth: 1.5rem;\r\n//\t\t\theight: 1.5rem;\r\n//\t\t\tcursor: pointer;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tlabel {\r\n//\t\tfont-weight: normal;\r\n//\t\ttext-transform: none;\r\n//\t\t.icon {\r\n//\t\t\t--w: 1.5em;\r\n//\t\t}\r\n//\t}\r\n//}\r\n///**\r\n//Load More Button\r\n// */\r\n//.load-more {\r\n//\topacity: 1;\r\n//\tmargin: 1rem auto;\r\n//\twidth: 66.666%;\r\n//\tdisplay: flex;\r\n//\talign-items: center;\r\n//\tgap: .5rem;\r\n//\tpadding: .75rem 1.5rem;\r\n//\tbackground: rgb(var(--base));\r\n//\tcolor: rgb(var(--contrast));\r\n//\tborder-radius: 4px;\r\n//\tfont-size: var(--txt-medium);\r\n//\ttransition: all var(--trans-base);\r\n//\tborder: 2px solid transparent;\r\n//\t&[hidden] {\r\n//\t\topacity: 0;\r\n//\t\ttransition: all var(--trans-base);\r\n//\t}\r\n//\t&:hover {\r\n//\t\tbackground: var(--pink-50);\r\n//\t\tborder-color: rgb(var(--contrast));\r\n//\t\tcolor: var(--white);\r\n//\t}\r\n//}\r\n///**\r\n//favourite button\r\n// */\r\n//button.favourite {\r\n//\tposition: absolute;\r\n//\ttop: .5rem;\r\n//\tright: .5rem;\r\n//\tz-index: 10;\r\n//\tbackground: rgba(var(--base),var(--op-4));\r\n//\tborder-radius: 50%;\r\n//\tbox-shadow: rgba(var(--base),var(--op-45)) var(--shdw-subtle);\r\n//\tborder: none;\r\n//\twidth: 2rem;\r\n//\theight: 2rem;\r\n//\tdisplay: flex;\r\n//\tjustify-content: center;\r\n//\talign-items: center;\r\n//\tbackdrop-filter: blur(5px);\r\n//\ttransition: all var(--trans-base);\r\n//\r\n//\t&:hover {\r\n//\t\ttransform: scale(1.1);\r\n//\t\tcolor: var(--pink-0);\r\n//\t\tbackground: rgb(var(--base));\r\n//\t\tbox-shadow: 0 4px 8px rgba(0,0,0,0.15);\r\n//\t}\r\n//\r\n//\t&.favourited {\r\n//\t\tanimation: pop 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);\r\n//\t}\r\n//}\r\n//\r\n//\r\n///** Images **/\r\n//.feed-image {\r\n//\tdisplay: block;\r\n//\taspect-ratio: 1;\r\n//\toverflow: hidden;\r\n//\twidth: 100%;\r\n//\theight: 100%;\r\n//}\r\n//.feed-images {\r\n//\twidth: 100%;\r\n//\theight: 100%;\r\n//\t&.multi {\r\n//\t\tdisplay :grid;\r\n//\t\tgrid-template-columns: repeat(3, 1fr);\r\n//\t\tgrid-auto-rows: 1fr;\r\n//\t\tgap: 4px;\r\n//\r\n//\t\t> a {\r\n//\t\t\twidth: 100%;\r\n//\t\t\theight: 100%;\r\n//\t\t\taspect-ratio: 1;\r\n//\t\t}\r\n//\t\t.feed-image {\r\n//\t\t\tgrid-row: span 2;\r\n//\t\t\tgrid-column: span 2;\r\n//\t\t}\r\n//\t}\r\n//\timg {\r\n//\t\twidth: 100%;\r\n//\t\theight: 100%;\r\n//\t\tobject-fit: cover;\r\n//\t\ttransition: transform var(--trans-t) var(--trans-fn);\r\n//\t}\r\n//\ta:hover img {\r\n//\t\ttransform: scale(1.05);\r\n//\t}\r\n//}\r\n//\r\n//.feed-item {\r\n//\t&:nth-of-type(4n+2) .multi .feed-image {\r\n//\t\tgrid-column: 2 / span 2;\r\n//\t\tgrid-row: 1 / span 2;\r\n//\t}\r\n//\t&:nth-of-type(4n+3) .multi .feed-image {\r\n//\t\tgrid-row: 2 / span 2;\r\n//\t\tgrid-column: 1 / span 2;\r\n//\t}\r\n//\t&:nth-of-type(4n+4) .multi .feed-image {\r\n//\t\tgrid-column: 2 / span 2;\r\n//\t\tgrid-row: 2 / span 2;\r\n//\t}\r\n//}\r\n//\r\n///** Item Information **/\r\n//.item-info {\r\n//\tpadding: .25rem;\r\n//\tborder-left: 1px solid rgb(var(--base-200));\r\n//\t>div + div {\r\n//\t\tmargin-top: .5em;\r\n//\t\tposition: relative;\r\n//\r\n//\t\t&::before {\r\n//\t\t\tcontent: '';\r\n//\t\t\tdisplay: block;\r\n//\t\t\tposition: absolute;\r\n//\t\t\ttop: -.3em;\r\n//\t\t\tleft: -.25rem;\r\n//\t\t\twidth: 66.6%;\r\n//\t\t\tborder-bottom: 1px solid rgb(var(--base-200));\r\n//\t\t}\r\n//\t}\r\n//\th3 {\r\n//\t\tmargin: 0 0 .5em 0!important;\r\n//\t\tfont-size: 1.1rem;\r\n//\t\tfont-family: var(--body);\r\n//\t\tfont-weight: var(--fw-b);\r\n//\t}\r\n//\tspan {\r\n//\t\ttext-transform: uppercase;\r\n//\t\tdisplay: flex;\r\n//\t\talign-items: center;\r\n//\t}\r\n//\t.icon {\r\n//\t\t--w: 1.1em;\r\n//\t\tmargin-right: .5em;\r\n//\t\tdisplay: inline-block;\r\n//\t\tvertical-align: middle;\r\n//\t}\r\n//}\r\n//.item-list {\r\n//\tul {\r\n//\t\tmargin: 0;\r\n//\t\tpadding: .5em 0;\r\n//\t\tdisplay: flex;\r\n//\t\tflex-wrap: wrap;\r\n//\t\tgap: .5rem;\r\n//\t\tli {\r\n//\t\t\tlist-style: none;\r\n//\t\t}\r\n//\t}\r\n//\ta {\r\n//\t\tbackground-color: var(--pink-0);\r\n//\t\tborder: 1px solid transparent;\r\n//\t\tborder-radius: 4px;\r\n//\t\tcolor: var(--light-0);\r\n//\t\tpadding: .25em;\r\n//\t\tline-height: .8;\r\n//\t\t&:visited {\r\n//\t\t\tbackground-color: var(--pink-100);\r\n//\t\t\tcolor: var(--white);\r\n//\t\t}\r\n//\t\t&:visited:hover,\r\n//\t\t&:visited:focus,\r\n//\t\t&:hover,\r\n//\t\t&:focus {\r\n//\t\t\tbackground-color: transparent;\r\n//\t\t\tborder-color: rgb(var(--contrast));\r\n//\t\t\tcolor: rgb(var(--contrast));\r\n//\t\t}\r\n//\t}\r\n//}\r\n///**\r\n//Loading\r\n// */\r\n//.loading {\r\n//\topacity: .7;\r\n//}\r\n//\r\n//.loading-overlay {\r\n//\tposition: fixed;\r\n//\ttop: 0;\r\n//\tleft: 0;\r\n//\tright: 0;\r\n//\tbottom: 0;\r\n//\tbackground-color: rgba(var(--base),var(--op-4));\r\n//\tdisplay: flex;\r\n//\talign-items: center;\r\n//\tjustify-content: center;\r\n//\ttransition: opacity 0.3s ease, visibility 0.3s ease;\r\n//\tz-index: 9999;\r\n//\topacity: 0;\r\n//\tvisibility: hidden;\r\n//}\r\n//.loading .loading-overlay {\r\n//\topacity: 1;\r\n//\tvisibility: visible;\r\n//\r\n//\t&::after {\r\n//\t\tcontent: '';\r\n//\t\tposition: absolute;\r\n//\t\tz-index: -1;\r\n//\t\tinset: 0;\r\n//\t\tbackground: linear-gradient(\r\n//\t\t\t\t90deg,\r\n//\t\t\t\tvar(--shimmer)\r\n//\t\t);\r\n//\t\tanimation: shimmer 3s ease-in-out infinite;\r\n//\t}\r\n//\r\n//\t.wrapper {\r\n//\t\tbackground-color: rgba(var(--base),var(--op-6));\r\n//\t\tpadding: 2rem;\r\n//\t\tborder-radius: var(--radius);\r\n//\t\ttext-align: center;\r\n//\t\tmax-width: 90%;\r\n//\t\twidth: 400px;\r\n//\t\theight: 300px;\r\n//\t\tz-index: 5;\r\n//\t\tdisplay: flex;\r\n//\t\tjustify-content: center;\r\n//\t\talign-items: center;\r\n//\t\tposition: relative;\r\n//\r\n//\t\t.spinner {\r\n//\t\t\t--h: 150px;\r\n//\t\t\t--w: calc(var(--h) * 2);\r\n//\t\t\tborder-top: 5px solid var(--pink-0);\r\n//\t\t\tborder-radius: 50%;\r\n//\t\t\tposition: absolute;\r\n//\t\t\twidth: var(--w);\r\n//\t\t\theight: var(--w);\r\n//\t\t\ttop: calc(50% - var(--h));\r\n//\t\t\tleft: calc(50% - var(--h));\r\n//\t\t\topacity: .5;\r\n//\t\t\tz-index: 0;\r\n//\t\t\tanimation: spin 1s var(--trans-t) infinite;\r\n//\t\t}\r\n//\t\tdiv.icon {\r\n//\t\t\theight: 50px;\r\n//\t\t\twidth: 50px;\r\n//\r\n//\t\t\t.icon {\r\n//\t\t\t\t--w: 100%;\r\n//\t\t\t\tsvg {\r\n//\t\t\t\t\tanimation: dance 2s ease-in-out infinite;\r\n//\t\t\t\t\ttransition: color 0.3s ease;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\t.status {\r\n//\t\t\theight: 200px;\r\n//\t\t\twidth: 100%;\r\n//\t\t\tz-index: 5;\r\n//\t\t\tdisplay: flex;\r\n//\t\t\tflex-direction: column;\r\n//\t\t\talign-items: center;\r\n//\r\n//\t\t\th3 {\r\n//\t\t\t\tmargin: 1.5rem 0 .25rem!important;\r\n//\t\t\t\tcolor: rgb(var(--contrast-200));\r\n//\t\t\t}\r\n//\t\t\t.message {\r\n//\t\t\t\tmargin: 0;\r\n//\t\t\t\tmax-width: 275px;\r\n//\t\t\t\tcolor: rgb(var(--contrast-100));\r\n//\t\t\t\tfont-size: var(--txt-x-small);\r\n//\t\t\t\tanimation: flicker 2s infinite;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//\r\n///* Animations */\r\n//@keyframes highlight {\r\n//\t0%, 100% {\r\n//\t\tbox-shadow: none;\r\n//\t}\r\n//\t50% {\r\n//\t\tbox-shadow: 0 0 0 4px var(--pink-0);\r\n//\t}\r\n//}\r\n//\r\n//@keyframes pop {\r\n//\t0% { transform: scale(1); }\r\n//\t50% { transform: scale(1.3); }\r\n//\t75% { transform: scale(0.9); }\r\n//\t100% { transform: scale(1); }\r\n//}\r\n//\r\n//@keyframes bubble {\r\n//\t50%  { box-shadow: 19px 0 0 3px, 38px 0 0 7px, 57px 0 0 3px }\r\n//\t100% { box-shadow: 19px 0 0 0, 38px 0 0 3px, 57px 0 0 7px }\r\n//}\r\n//@keyframes highlight-pulse {\r\n//\t0%, 100% { box-shadow: 0 0 0 4px #FF0080, 0 8px 16px rgba(0, 0, 0, 0.1); }\r\n//\t50% { box-shadow: 0 0 0 8px #FF0080, 0 12px 24px rgba(0, 0, 0, 0.15); }\r\n//}\r\n//\r\n//@keyframes spin {\r\n//\tto { transform: rotate(360deg); }\r\n//}\r\n//\r\n//@keyframes shimmer {\r\n//\t0% { transform: translateX(-100%); }\r\n//\t50%, 100% { transform: translateX(100%); }\r\n//}\r\n//@keyframes dance {\r\n//\t0%, 100% { transform: rotate(-5deg) scale(1);}\r\n//\t50% { transform: rotate(5deg) scale(1.1); }\r\n//}\r\n//@keyframes flicker {\r\n//\t0% { opacity: 0.6; }\r\n//\t50% { opacity: 1; }\r\n//\t100% { opacity: 0.6; }\r\n//}\r\n//\r\n//\r\n///**\r\n//Accessibility\r\n// */\r\n//\r\n///* Keyboard navigable feed items */\r\n//.feed-item[tabindex=\"0\"] {\r\n//\tposition: relative;\r\n//}\r\n//\r\n//.feed-item[tabindex=\"0\"]::after {\r\n//\tcontent: '';\r\n//\tposition: absolute;\r\n//\ttop: 0;\r\n//\tleft: 0;\r\n//\tright: 0;\r\n//\tbottom: 0;\r\n//\tpointer-events: none;\r\n//\tborder: 2px solid transparent;\r\n//\ttransition: border-color 0.2s ease;\r\n//}\r\n//\r\n//.feed-item[tabindex=\"0\"]:focus::after {\r\n//\tborder-color: #FF0080;\r\n//}\r\n//\r\n//\r\n//.feed-block .item {\r\n//\tsummary {\r\n//\t\ta {\r\n//\t\t\tbackground-color: rgb(var(--action-0));\r\n//\t\t\tdisplay: flex;\r\n//\t\t\tgap: .25rem;\r\n//\t\t\tflex-wrap: nowrap;\r\n//\t\t\taspect-ratio: 1;\r\n//\t\t\tposition: relative;\r\n//\t\t}\r\n//\t\timg {\r\n//\t\t\twidth: 50%;\r\n//\t\t\theight: 100%;\r\n//\t\t\tobject-fit: cover;\r\n//\t\t}\r\n//\r\n//\t}\r\n//}\r\n\r\n//\r\n//.feed-block {\r\n//\tgrid-column: full;\r\n//\t.filters {\r\n//\t\tpadding: 1rem 0;\r\n//\t\tmax-width:var(--wide);\r\n//\t\tmargin: 0 auto;\r\n//\r\n//\t\t.remove-term.remove-term {\r\n//\t\t\twidth: max-content;\r\n//\t\t\theight: max-content\r\n//\t\t}\r\n//\t}\r\n//\t.filter-group {\r\n//\t\tposition: relative;\r\n//\t\tpadding: 2rem 0;\r\n//\t\t.label {\r\n//\t\t\tposition: absolute;\r\n//\t\t\tleft: 0;\r\n//\t\t}\r\n//\t\t> .label {\r\n//\t\t\ttop: 0;\r\n//\t\t}\r\n//\t\t.btn + label {\r\n//\t\t\twidth: auto;\r\n//\t\t}\r\n//\t\t[type=radio] {\r\n//\t\t\tposition:absolute;\r\n//\t\t\tleft: var(--offScreen);\r\n//\t\t}\r\n//\t\tbutton, label {\r\n//\t\t\tposition: relative;\r\n//\t\t\tpadding: .5rem;\r\n//\t\t\theight: max-content;\r\n//\t\t\t&:hover {\r\n//\t\t\t\tcolor: var(--action-contrast);\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\tbutton:hover .label,\r\n//\t\t:checked + label .label,\r\n//\t\tlabel:hover .label {\r\n//\t\t\topacity: 1;\r\n//\t\t\tvisibility: visible;\r\n//\t\t}\r\n//\t\t&:has(label:hover) :checked + label .label,\r\n//\t\tbutton .label,\r\n//\t\tlabel .label {\r\n//\t\t\t--height: max-content;\r\n//\t\t\topacity: 0;\r\n//\t\t\tvisibility: hidden;\r\n//\t\t\tbottom: -2rem;\r\n//\t\t\twidth: max-content;\r\n//\t\t\twhite-space: nowrap;\r\n//\t\t\tfont-weight: var(--fw-b);\r\n//\t\t}\r\n//\r\n//\r\n//\t}\r\n//\th3 {\r\n//\t\tmargin: 0 0 .25rem;\r\n//\t\tfont-size: var(--medium);\r\n//\t}\r\n//}\r\n///** PLACEHOLDERS **/\r\n//.placeholder {\r\n//\taspect-ratio: 1;\r\n//\tbackground: rgb(var(--base));\r\n//\tborder: 1rem solid rgb(var(--base-50));\r\n//\tborder-radius: 1rem;\r\n//\tdisplay: flex;\r\n//\tjustify-content: center;\r\n//\talign-items: center;\r\n//\r\n//\ti.icon {\r\n//\t\t--w: 50%;\r\n//\t\tcolor: rgb(var(--base-200));\r\n//\t\tanimation: dance 2.5s ease-in-out infinite;\r\n//\t}\r\n//}\r\n//\r\n//.item-grid {\r\n//\tpadding: 0 var(--chip);\r\n//\tmax-width: 100%;\r\n//}\r\n///** FEED ITEM **/\r\n//.feed.item {\r\n//\tposition: relative;\r\n//\tborder-radius: 0.5rem;\r\n//\toverflow: hidden;\r\n//\tbackground: rgb(var(--base-50));\r\n//\tbox-shadow: 0 2px 4px rgba(0,0,0,0.1);\r\n//\theight: fit-content;\r\n//\tpadding: 0;\r\n//\tdetails {\r\n//\t\tz-index: var(--z-2);\r\n//\t\twidth: 100%;\r\n//\t\tposition: relative;\r\n//\t\tpadding: 0;\r\n//\t\tsummary {\r\n//\t\t\tposition:absolute;\r\n//\t\t\ttop: -3rem;\r\n//\t\t\tleft:0;\r\n//\t\t\twidth: 100%;\r\n//\t\t\tbackground-color: rgba(var(--base),var(--op-2));\r\n//\t\t\tbackdrop-filter: blur(5px);\r\n//\t\t\t&:hover {\r\n//\t\t\t\tbackground-color: rgba(var(--action-0),var(--op-45));\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\t&[open] {\r\n//\t\t\tpadding: .25rem .5rem;\r\n//\t\t\tsummary .icon {\r\n//\t\t\t\topacity: 0;\r\n//\t\t\t}\r\n//\t\t}\r\n//\r\n//\t}\r\n//\r\n//\timg {\r\n//\t\tobject-fit: cover;\r\n//\t\twidth: 100%;\r\n//\t\theight: 100%;\r\n//\t\t//opacity: .7;\r\n//\t\t//filter: grayscale(.5) sepia(.3);\r\n//\t\t&:hover {\r\n//\t\t\topacity: .8;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\t&[data-timeline] {\r\n//\t\t.images {\r\n//\t\t\taspect-ratio: 3/2;\r\n//\t\t\tpadding: 0 0 1rem;\r\n//\t\t\tspan {\r\n//\t\t\t\twidth: 50%;\r\n//\t\t\t\tposition: absolute;\r\n//\t\t\t\tbackground-color: rgb(var(--action-0));\r\n//\t\t\t\tcolor: var(--action-contrast);\r\n//\t\t\t\tpadding: .25rem .5rem;\r\n//\t\t\t\t&:first-of-type {\r\n//\t\t\t\t\tbottom: 0;\r\n//\t\t\t\t\tright: 50%;\r\n//\t\t\t\t\ttext-align: right;\r\n//\t\t\t\t}\r\n//\t\t\t\t&:last-of-type {\r\n//\t\t\t\t\ttop: 0;\r\n//\t\t\t\t\tleft: 50%;\r\n//\t\t\t\t}\r\n//\t\t\t}\r\n//\t\t\t> a {\r\n//\t\t\t\tposition: relative;\r\n//\t\t\t\tdisplay: flex;\r\n//\t\t\t\tflex-wrap: nowrap;\r\n//\t\t\t\twidth: 100%;\r\n//\t\t\t\theight: 100%;\r\n//\t\t\t}\r\n//\t\t}\r\n//\t\timg {\r\n//\t\t\twidth: 50%;\r\n//\t\t\tobject-fit: cover;\r\n//\t\t\theight: 100%;\r\n//\t\t\t&:first-of-type {\r\n//\t\t\t\tborder-right: 1px solid rgb(var(--action-0));\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\r\n//\r\n//\ta {\r\n//\t\t&::before,\r\n//\t\t&::after {\r\n//\t\t\tdisplay: none;\r\n//\t\t}\r\n//\t}\r\n//\r\n//\tlabel {\r\n//\t\tfont-weight: normal;\r\n//\t\ttext-transform: none;\r\n//\t\t.icon {\r\n//\t\t\t--w: 1.5em;\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//\r\n//.item-grid:has([data-timeline]) {\r\n//\tgrid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\r\n//}\r\n//\r\n//.items-wrap [type=radio],\r\n//.items-wrap [type=checkbox] {\r\n//\tposition: absolute;\r\n//\topacity: 0;\r\n//\tleft: -200vw;\r\n//}\r\n//\r\n//.items-wrap [type=radio] + label,\r\n//.items-wrap [type=checkbox] + label {\r\n//\tposition: relative;\r\n//\tcursor: pointer;\r\n//}\r\n//\r\n//.items-wrap [type=radio] + label:hover,\r\n//.items-wrap [type=checkbox] + label:hover {\r\n//\tcolor: rgb(var(--action-0));\r\n//}\r\n//\r\n//.items-wrap [type=radio] + label::before,\r\n//.items-wrap [type=checkbox] + label::before,\r\n//.items-wrap [type=radio] + label::after,\r\n//.items-wrap [type=checkbox] + label::after {\r\n//\tcontent: '';\r\n//\tposition: absolute;\r\n//\ttop: 50%;\r\n//}\r\n//\r\n//.items-wrap [type=radio] + label::after,\r\n//.items-wrap [type=checkbox] + label::after {\r\n//\tleft: 5px;\r\n//\ttransform: translateY(-70%) rotate(45deg);\r\n//\twidth: 5px;\r\n//\theight: 10px;\r\n//\tborder: solid var(--light-0);\r\n//\tborder-width: 0 2px 2px 0;\r\n//\tdisplay: none;\r\n//}\r\n//\r\n//.items-wrap [type=radio] + label::before,\r\n//.items-wrap [type=checkbox] + label::before {\r\n//\tleft: 0;\r\n//\ttransform: translateY(-50%);\r\n//\twidth: 1rem;\r\n//\theight: 1rem;\r\n//\tborder: 2px solid rgb(var(--contrast-200));\r\n//\tbackground-color: rgb(var(--base));\r\n//\tborder-radius: var(--radius);\r\n//}\r\n//\r\n//.items-wrap [type=radio]:hover + label::before,\r\n//.items-wrap [type=checkbox]:hover + label::before {\r\n//\tborder-color: rgb(var(--action-200));\r\n//}\r\n//\r\n//.items-wrap [type=radio]:checked + label::before,\r\n//.items-wrap [type=checkbox]:checked + label::before{\r\n//\tbackground-color: rgb(var(--action-0));\r\n//\tborder-color: rgb(var(--action-100));\r\n//}\r\n//\r\n//.items-wrap [type=radio]:checked + label::before {\r\n//\tborder-radius: 50%;\r\n//}\r\n//\r\n//.items-wrap [type=checkbox]:checked + label::after {\r\n//\tdisplay: block;\r\n//\tleft: 5px;\r\n//\ttop: 50%;\r\n//\ttransform: translateY(-70%) rotate(45deg);\r\n//\twidth: .35rem;\r\n//\theight: .66rem;\r\n//\tborder: solid var(--light-0);\r\n//\tborder-width: 0 2px 2px 0;\r\n//}\r\n//\r\n//.items-wrap :disabled + label {\r\n//\tcursor: not-allowed;\r\n//\tbackground-color: rgb(var(--base-50));\r\n//\tcolor: rgb(var(--base-200));\r\n//\tborder-color: rgb(var(--base-200));\r\n//}\r\n//\r\n//.items-wrap :disabled + label:hover {\r\n//\tbackground-color: rgb(var(--base-50));\r\n//\tcolor: rgb(var(--base-200));\r\n//\tborder-color: rgb(var(--base-200));\r\n//}\r\n//\r\n//.items-wrap :disabled + label::before {\r\n//\tborder-color: rgb(var(--base-200));\r\n//}\r\n//\r\n//#jvb-selector .items-wrap [type=radio] + label,\r\n//#jvb-selector .items-wrap [type=checkbox] + label{\r\n//\tflex: 1;\r\n//\tpadding-left: 2rem!important;\r\n//\ttransform-origin: top center;\r\n//\twill-change: transform;\r\n//}\r\n//\r\n//.feed-block + footer {\r\n//\tgrid-column: full;\r\n//\tpadding: 0!important;\r\n//\tmargin: 0;\r\n//\tbackground-color: rgb(var(--base-50));\r\n//\tz-index: 0;\r\n//\tdisplay: flex;\r\n//\tjustify-content: flex-end;\r\n//\tbutton {\r\n//\t\twidth: max-content;\r\n//\t\tmargin-left: auto;\r\n//\t\tpadding: .35rem .25rem;\r\n//\t\t--w: 1.3em!important;\r\n//\t\tflex-wrap: nowrap;\r\n//\t\tjustify-content:flex-start;\r\n//\t\ttransition: var(--trans-size);\r\n//\t\tfont-size: var(--txt-x-small);\r\n//\t\tmin-height: 0;\r\n//\t\tspan {\r\n//\t\t\tdisplay: none;\r\n//\t\t\twhite-space: nowrap;\r\n//\t\t}\r\n//\t\t&:focus span,\r\n//\t\t&:hover span {\r\n//\t\t\tdisplay: block;\r\n//\t\t}\r\n//\t}\r\n//}\r\n//\r\n//\r\n//\r\n//.search-container:not(.open) input[type=search],\r\n//.search-container:not(.open) .clear-search {\r\n//\ttransform: scaleX(0);\r\n//\ttransform-origin: left;\r\n//\twidth: 0;\r\n//\tpadding: 0;\r\n//\ttransition: transform var(--trans-base), width var(--trans-base), padding var(--trans-base);\r\n//}\r\n//.search-container button {\r\n//\tpadding: .5rem;\r\n//}\r\n//.search-container .icon {\r\n//\t--w: 1.5rem;\r\n//}\r\n//.search-container.open input[type=search],\r\n//.search-container.open .clear-search {\r\n//\ttransform: scaleX(1);\r\n//\ttransform-origin: left;\r\n//\ttransition: transform var(--trans-base), width var(--trans-base), padding var(--trans-base);\r\n//}\r\n//.all-filters > .search,\r\n//input[type=search],\r\n//.search-container {\r\n//\twidth: 100%;\r\n//}\r\n//\r\n//\r\n//.all-filters {\r\n//\tbutton .label,\r\n//\t.row:has(label:hover),\r\n//\t.btn:checked + label .label {\r\n//\t\t--height: max-content;\r\n//\t\tbottom: -2rem;\r\n//\t\tfont-weight: var(--fw-b);\r\n//\t\topacity: 0;\r\n//\t\tvisibility: hidden;\r\n//\t\twhite-space: nowrap;\r\n//\t\twidth: -moz-max-content;\r\n//\t\twidth: max-content;\r\n//\t}\r\n//\tsummary {\r\n//\t\twidth: 100%;\r\n//\t\t&:hover {\r\n//\t\t\tbackground-color: rgb(var(--action-0));\r\n//\t\t\tcolor: rgb(var(--action-contrast));\r\n//\t\t\t&::after {\r\n//\t\t\t\tbackground-color: rgb(var(--action-contrast));\r\n//\t\t\t}\r\n//\t\t}\r\n//\t}\r\n//\t> .row {\r\n//\t\twidth: 100%;\r\n//\t\tmargin: 0;\r\n//\t\t.label {\r\n//\t\t\twidth: 20%;\r\n//\t\t}\r\n//\t}\r\n//}\r\n\r\n\r\n/***** START FRESH *****/\r\n.feed-block {\r\n\tgrid-column: full;\r\n\r\n\t.placeholder {\r\n\t\taspect-ratio: 1;\r\n\t\tbackground: rgb(var(--base));\r\n\t\tborder: 1rem solid rgb(var(--base-50));\r\n\t\tborder-radius: 1rem;\r\n\t\tdisplay: flex;\r\n\t\tjustify-content: center;\r\n\t\talign-items: center;\r\n\t\t--w: 50%;\r\n\t\tcolor: rgb(var(--base-200));\r\n\t\ti.icon {\r\n\t\t\tanimation: dance 2.5s ease-in-out infinite;\r\n\t\t}\r\n\t}\r\n\r\n\t.item-grid {\r\n\t\tmax-width: var(--full);\r\n\r\n\t\t&:has([data-timeline]) {\r\n\t\t\tgrid-template-columns: repeat(auto-fill, minmax(250px, 1fr));\r\n\t\t}\r\n\t}\r\n\r\n\t.item {\r\n\t\toverflow: hidden;\r\n\t\tbackground: rgb(var(--base-50));\r\n\t\tbox-shadow: rgba(var(--base), var(--op-2)) var(--shdw);\r\n\t\theight: fit-content;\r\n\t\tpadding: 0;\r\n\r\n\t\th3 {\r\n\t\t\tmargin: 0;\r\n\t\t\tfont-size: var(--txt-medium);\r\n\t\t}\r\n\r\n\t\tdetails {\r\n\t\t\tz-index: var(--z-2);\r\n\t\t\twidth: 100%;\r\n\t\t\tposition: relative;\r\n\t\t\tpadding: 0;\r\n\r\n\t\t\tsummary {\r\n\t\t\t\tposition: absolute;\r\n\t\t\t\ttop: calc(var(--chip_) * -1);\r\n\t\t\t\tleft: 0;\r\n\t\t\t\twidth: 100%;\r\n\t\t\t\tbackground-color: rgba(var(--base), var(--op-2));\r\n\t\t\t\tbackdrop-filter: blur(5px);\r\n\r\n\t\t\t\t&:hover {\r\n\t\t\t\t\tbackground-color: rgba(var(--action-0), var(--op-45));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t&[open] {\r\n\t\t\t\tpadding: .25rem .5rem;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\timg {\r\n\t\t\t&:hover {\r\n\t\t\t\topacity: .8;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t&[data-timeline] {\r\n\t\t\t.images {\r\n\t\t\t\taspect-ratio: 3/2;\r\n\t\t\t\tpadding: 0 0 1rem;\r\n\r\n\t\t\t\tspan {\r\n\t\t\t\t\twidth: 50%;\r\n\t\t\t\t\tposition: absolute;\r\n\t\t\t\t\tbackground-color: rgb(var(--action-0));\r\n\t\t\t\t\tcolor: rgb(var(--action-contrast));\r\n\t\t\t\t\tpadding: .25rem .5rem;\r\n\r\n\t\t\t\t\t&:first-of-type {\r\n\t\t\t\t\t\tbottom: 0;\r\n\t\t\t\t\t\tright: 50%;\r\n\t\t\t\t\t\ttext-align: right;\r\n\t\t\t\t\t}\r\n\t\t\t\t\t&:last-of-type {\r\n\t\t\t\t\t\ttop: 0;\r\n\t\t\t\t\t\tleft: 50%;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\t//> a {\r\n\t\t\t\t//\tposition: relative;\r\n\t\t\t\t//\tdisplay: flex;\r\n\t\t\t\t//\tflex-wrap: nowrap;\r\n\t\t\t\t//\twidth: 100%;\r\n\t\t\t\t//\theight: 100%;\r\n\t\t\t\t//}\r\n\r\n\t\t\t\timg {\r\n\t\t\t\t\twidth: 50%;\r\n\t\t\t\t\t&:first-of-type {\r\n\t\t\t\t\t\tborder-right: 2px solid rgb(var(--action-0));\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\ta {\r\n\t\t\t&::before,\r\n\t\t\t&::after {\r\n\t\t\t\tdisplay: none;\r\n\t\t\t}\r\n\t\t}\r\n\t\tlabel {\r\n\t\t\tfont-weight: normal;\r\n\t\t\ttext-transform: none;\r\n\t\t\t--w: 1.5em;\r\n\t\t}\r\n\t}\r\n\t.all-filters summary {\r\n\t\tdisplay: flex;\r\n\t\tjustify-content: space-between;\r\n\t}\r\n}\r\n.all-filters {\r\n\tfont-size: var(--txt-x-small);\r\n\r\n\t&[open] {\r\n\t\tborder: 2px solid rgb(var(--action-0));\r\n\t\tpadding: 0;\r\n\t\tborder-radius: 0 0 var(--radius-outer) var(--radius-outer);\r\n\t}\r\n\r\n\tsummary {\r\n\t\twidth: 100%;\r\n\t}\r\n\r\n\t&[open] summary,\r\n\tsummary:hover {\r\n\t\tbackground-color: rgb(var(--action-0));\r\n\t\tcolor: rgb(var(--action-contrast));\r\n\t\t&::after {\r\n\t\t\tbackground-color: rgb(var(--action-contrast));\r\n\t\t}\r\n\t}\r\n\r\n\t>.row.row {\r\n\t\tpadding: 0 .75rem 2rem;\r\n\t\twidth: var(--content);\r\n\r\n\t\t&.search {\r\n\t\t\tpadding-bottom: 0;\r\n\t\t}\r\n\t\tposition: relative;\r\n\r\n\t\t> .label,\r\n\t\t> .row > .label {\r\n\t\t\tfont-family: var(--heading);\r\n\t\t\tfont-weight: var(--fw-h-bold);\r\n\t\t\ttext-transform: uppercase;\r\n\t\t}\r\n\t\t> .label {\r\n\t\t\twidth: 20%;\r\n\t\t}\r\n\t\t>.row > .label {\r\n\t\t\twhite-space: nowrap;\r\n\t\t}\r\n\t}\r\n\r\n\tbutton,\r\n\t.btn + label {\r\n\t\twidth: var(--chipchip);\r\n\t\tmin-height: var(--chipchip);\r\n\t\tpadding: 0;\r\n\t}\r\n\r\n\tbutton .label,\r\n\t.row:has(> .btn:not(:checked) + label:hover) :checked + label .label,\r\n\t.btn + label .label {\r\n\t\tposition: absolute;\r\n\t\tbottom: -2rem;\r\n\t\twidth: max-content;\r\n\t\twhite-space: nowrap;\r\n\t\topacity: 0;\r\n\t\tz-index: var(--z-4);\r\n\t}\r\n\r\n\tbutton:hover .label,\r\n\t.btn:checked + label .label,\r\n\t.btn + label:hover .label {\r\n\t\topacity: 1;\r\n\t}\r\n\r\n\t.search.row,\r\n\t.view.row {\r\n\t\tdisplay: none;\r\n\t}\r\n\t.ordering {\r\n\t\tpadding: 2rem 0 .75rem 0;\r\n\t}\r\n\t.ordering > .row label {\r\n\t\tposition: unset;\r\n\t}\r\n\t.ordering .row {\r\n\r\n\t\t.label {\r\n\t\t\ttop: -1rem;\r\n\t\t\tcolor: rgb(var(--contrast));\r\n\t\t}\r\n\t\t&.orderby .label {\r\n\t\t\tleft: 0;\r\n\t\t}\r\n\t\t&.order-direction .label {\r\n\t\t\tright: 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n\r\n.search-container:not(.open) input[type=search],\r\n.search-container:not(.open) .clear-search {\r\n\ttransform: scaleX(0);\r\n\ttransform-origin: left;\r\n\twidth: 0;\r\n\tpadding: 0;\r\n\ttransition: transform var(--trans-base), width var(--trans-base), padding var(--trans-base);\r\n}\r\n.search-container button {\r\n\tpadding: .5rem;\r\n}\r\n.search-container .icon {\r\n\t--w: 1.5rem;\r\n}\r\n.search-container.open input[type=search],\r\n.search-container.open .clear-search {\r\n\ttransform: scaleX(1);\r\n\ttransform-origin: left;\r\n\ttransition: transform var(--trans-base), width var(--trans-base), padding var(--trans-base);\r\n}\r\n.all-filters > .search,\r\ninput[type=search],\r\n.search-container {\r\n\twidth: 100%;\r\n}\r\n\r\n\r\n.toggle-text {\r\n\tinput {\r\n\t\t+ label {\r\n\t\t\tfont-weight: normal;\r\n\t\t\tcolor: var(--contrast)!important;\r\n\t\t\ttext-transform: none;\r\n\t\t\tcursor: pointer;\r\n\t\t\tposition: relative;\r\n\t\t\tpadding: .25rem .5rem;\r\n\t\t\t-webkit-user-select: none;\r\n\t\t\t-moz-user-select: none;\r\n\t\t\t-ms-user-select: none;\r\n\t\t\tuser-select: none;\r\n\t\t\tborder: 1px dashed transparent;\r\n\r\n\t\t\t&::before,\r\n\t\t\t&::after {\r\n\t\t\t\tdisplay: none!important;\r\n\t\t\t}\r\n\r\n\t\t\t.text {\r\n\t\t\t\tposition: relative;\r\n\t\t\t\tmargin: 0;\r\n\t\t\t\t--gap: 0;\r\n\t\t\t\tfont-weight: bold;\r\n\t\t\t\twidth: fit-content;\r\n\t\t\t\tpadding: 2px 4px;\r\n\t\t\t\tborder: 1px solid rgb(var(--action-50));\r\n\t\t\t\tborder-radius: var(--radius);\r\n\t\t\t\tcolor: rgb(var(--action-50));\r\n\t\t\t}\r\n\r\n\t\t\t.off {\r\n\t\t\t\t--mid: -100%;\r\n\t\t\t}\r\n\t\t\t.on {\r\n\t\t\t\t--mid: 100%;\r\n\t\t\t}\r\n\t\t\t.off,\r\n\t\t\t.on {\r\n\t\t\t\ttransition: var(--trans-transform), opacity var(--trans-base);\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t\t + label .off,\r\n\t\t&:checked + label .on {\r\n\t\t\topacity: 1;\r\n\t\t\tmax-width: 100%;\r\n\t\t\ttransform: translate3d(0,0,0);\r\n\t\t}\r\n\t\t + label .on,\r\n\t\t&:checked + label .off {\r\n\t\t\topacity: 0;\r\n\t\t\tmax-width: 0;\r\n\t\t\ttransform: translate3d(0,var(--mid),0);\r\n\t\t}\r\n\t}\r\n\r\n\r\n\t&:hover {\r\n\t\tlabel {\r\n\t\t\tborder-color: rgb(var(--action-200));\r\n\t\t}\r\n\t\t.text {\r\n\t\t\tbackground-color: rgb(var(--action-50));\r\n\t\t\tcolor: rgb(var(--action-contrast));\r\n\t\t\tborder-color: rgb(var(--action-50));\r\n\t\t}\r\n\t}\r\n}\r\n\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/feed/view.asset.php b/build/feed/view.asset.php
index 4e0bb07..7ea40c5 100644
--- a/build/feed/view.asset.php
+++ b/build/feed/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => '9d6597e998a64f7951ae');
+<?php return array('dependencies' => array(), 'version' => '66a07f12c0b535077080');
diff --git a/build/feed/view.js b/build/feed/view.js
index 7adb0dd..4cd0ac5 100644
--- a/build/feed/view.js
+++ b/build/feed/view.js
@@ -1 +1,689 @@
-(()=>{class e{constructor(){this.container=document.querySelector("section.feed-block"),this.container&&(this.a11y=window.jvbA11y,this.error=window.jvbError,this.cache=new window.jvbCache("feed"),this.templates=window.jvbTemplates,this.config={source:"",context:"",highlight:null,gallery:!1,view:this.cache.get("feedView")||"grid",...this.container.dataset},this.init())}init(){this.initElements(),this.defineTemplates(),this.initListeners(),this.initFilters(),"requestIdleCallback"in window?requestIdleCallback(()=>{this.initStore(),this.initTaxonomies(),this.processCachedFilters(),this.processURLFilters(),this.updateFilterUI(),this.initGallery()},{timeout:2e3}):setTimeout(()=>{this.initStore(),this.initTaxonomies(),this.processCachedFilters(),this.processURLFilters(),this.updateFilterUI(),this.initGallery()},100)}initElements(){this.selectors={filterTrigger:"[data-filter]",filters:{actions:".filter-actions .toggle-text",container:".all-filters",content:'[data-filter="content"]',orderby:'[data-filter="orderby"]',order:'[data-filter="order"]',match:'[data-filter="match"]',favourites:'[data-filter="favourites"]',taxonomy:'[data-filter^="taxonomy"]'},grid:".item-grid",selected:".selected-items",buttons:{loadMore:"button.load-more",remove:".remove-term",clearFilters:"button.clear-filters",refresh:'button[data-action="refresh"]'}},this.ui=window.uiFromSelectors(this.selectors,this.container),this.ui.buttons.refresh=document.querySelector(this.selectors.buttons.refresh),this.ui.content=this.ui.filters.container.querySelectorAll('[name="content"]'),0===this.ui.content.length&&(this.ui.content=!1),this.ui.taxonomies=this.ui.filters.container.querySelectorAll("[data-taxonomy]"),0===this.ui.taxonomies.length&&(this.ui.taxonomies=!1),this.ui.orderbyWrap=this.ui.filters.container.querySelector("[data-for-order]"),0===this.ui.orderbyWrap.length&&(this.ui.orderbyWrap=!1),this.ui.order=this.ui.filters.container.querySelectorAll('[data-filter="order"]'),0===this.ui.order.length&&(this.ui.order=!1),this.ui.orderby=this.ui.filters.container.querySelectorAll('[data-filter="orderby"]'),0===this.ui.orderby.length&&(this.ui.orderby=!1),this.orderbyFilters=this.ui.orderby?Array.from(this.ui.orderby).map(e=>e.value):[],this.contentTypes=this.ui.content?Array.from(this.ui.content).map(e=>e.value):[this.container.dataset.content],this.taxonomies=this.ui.taxonomies?.length>0?Array.from(this.ui.taxonomies).map(e=>e.dataset.taxonomy):[]}initListeners(){this.popStateHandler=this.handlePopState.bind(this),this.clickHandler=this.handleClick.bind(this),this.changeHandler=this.handleChange.bind(this),window.addEventListener("popstate",this.popStateHandler),document.addEventListener("click",this.clickHandler),document.addEventListener("change",this.changeHandler)}initFilters(){this.allowedFilters=["content","order","orderby","favourites","match"];let e={content:this.contentTypes[0],orderby:"date",order:"desc",page:1};this.config.context&&(e.context=this.config.context),this.config.source&&(e.source=this.config.source),this.filters=e,this.defaults={...e}}updateFilterUI(){if(this.ui.filters.container&&([this.ui.content,this.ui.orderby,this.ui.order].forEach(e=>{if(e)for(let t of e){let[e,i]=[t.dataset.filter,t.value];if(!Object.hasOwn(this.store.filters,e))break;let s=this.store.filters[e]===i;if(s){t.checked=s;break}}}),Object.hasOwn(this.store.filters,"taxonomy")))for(let[e,t]of Object.entries(this.store.filters.taxonomy))t.forEach(e=>{e=parseInt(e),this.selector.store.get(e)&&this.createTermElement(e)})}handlePopState(e){e.state?.filters&&this.processURLFilters()&&(this.store.setFilters(this.filters),this.a11y.announce("Feed filters updated from browser history"))}handleClick(e){window.targetCheck(e,this.selectors.buttons.loadMore)?this.nextPage():window.targetCheck(e,this.selectors.buttons.clearFilters)&&this.clearFilters();let t=window.targetCheck(e,this.selectors.buttons.remove);t&&this.removeSelectedTerm(t),window.targetCheck(e,this.selectors.buttons.refresh)&&(this.store.clearCache(),this.store.fetch());let i=window.targetCheck(e,'[data-filter="orderby"]');i&&"random"===i.value&&i.checked&&this.renderItems()}nextPage(){const e=(this.store.filters.page||1)+1,t=this.store.lastResponse?.pages||e;this.store.setFilters({page:Math.min(e,t)})}handleChange(e){const t=e.target;if(Object.hasOwn(t.dataset,"filter")){if(this.allowedFilters.includes(t.dataset.filter)){let e={};e[t.dataset.filter]=t.value,this.resetFilters(e)}switch(t.dataset.filter){case"content":this.updateContentFor(t.value);break;case"orderby":this.updateOrderOptions(t.value)}}}clearFilters(){this.taxFilters={},window.removeChildren(this.ui.selected),this.taxonomies.forEach(e=>{let t=this.getFieldId(e);this.selector.selectedTerms.get(t)?.clear()}),this.store.setFilters({...this.defaults,taxonomy:null}),this.updateURL(),this.saveToCacheFilters()}resetFilters(e){e={...this.store.filters,page:1,...e},this.store.setFilters(e),this.updateURL(),this.saveToCacheFilters()}getFieldId(e){return this.selector.getFieldId(Array.from(this.ui.taxonomies).filter(t=>t.dataset.taxonomy===e)[0]??null)}removeSelectedTerm(e){const t=parseInt(e.dataset.id),i=e.dataset.taxonomy;Object.hasOwn(this.taxFilters,i)&&(this.taxFilters[i]=this.taxFilters[i].filter(e=>e!==t),0===this.taxFilters[i].length&&delete this.taxFilters[i]),e.remove();const s=this.getFieldId(i);s&&(this.selector.activeField=s,this.selector.removeSelected(t,s)),this.resetFilters({taxonomy:Object.keys(this.taxFilters).length>0?this.taxFilters:null})}updateContentFor(e){[this.ui.taxonomies,this.ui.orderby].forEach(t=>{t&&t.forEach(t=>{const i=t.dataset.for?.split(",")??[];t.hidden=i.length>0&&!i.includes(e),t.hidden&&t.checked&&(t.checked=!1)})})}updateOrderOptions(e){if(this.ui.orderbyWrap){let t=this.ui.orderbyWrap.dataset.forOrder.split(",")??[];this.ui.orderbyWrap.hidden=!t.includes(e)}}updateFilterControls(){const e=Object.keys(this.taxFilters);this.ui.buttons.clearFilters&&(this.ui.buttons.clearFilters.hidden=0===e.length),this.ui.filters.actions&&(this.ui.filters.actions.hidden=e.length<=1)}async initTaxonomies(){this.taxFilters={},this.selector=window.jvbSelector,this.selector.subscribe((e,t)=>{"selected-terms"===e&&this.handleTaxonomyChange(t)})}handleTaxonomyChange(e){const{terms:t,taxonomy:i}=e;0!==t.size&&(this.taxFilters[i]=Array.from(t),this.resetFilters({taxonomy:this.taxFilters}),t.forEach(e=>{this.createTermElement(e)}),this.updateFilterControls())}getTaxonomyIcon(e){let t=Array.from(this.ui.taxonomies).find(t=>t.dataset.taxonomy===e);return t?.dataset.icon.trim()||"tag"}createTermElement(e){const t=this.selector.store.get(e);t&&(this.ui.selected.querySelector(`[data-id="${e}"]`)||(t.icon=this.getTaxonomyIcon(t.taxonomy),this.ui.selected.append(this.templates.create("feedTerm",t))))}processCachedFilters(){Object.keys(this.filters).forEach(e=>{let t=this.cache.get(`${this.config.source}_${this.config.context}_${e}`);t&&t!==this.filters[e]&&(this.filters[e]=t)})}processURLFilters(){if(!this.isFirstPage())return!1;const e=new URLSearchParams(window.location.search);if(!e.toString())return!1;let t=!1;this.allowedFilters.forEach(i=>{let s=e.get(`f_${i}`);s&&(t=!0,this.filters[i]=s)});let i=!1;return e.forEach((e,s)=>{if(s.startsWith("f_tax_")){i=!0,t=!0;const r=s.replace("f_tax_","");this.taxFilters[r]=e.split(",").map(Number)}}),t&&(i&&(this.filters.taxonomy=this.taxFilters),this.resetFilters(this.filters)),!0}updateURL(){const e=new URLSearchParams;this.allowedFilters.forEach(t=>{Object.hasOwn(this.store.filters,t)&&this.store.filters[t]!==this.defaults[t]&&e.set(`f_${t}`,this.store.filters[t])});for(let[t,i]of Object.entries(this.taxFilters))i.length>0&&e.set(`f_tax_${t}`,i.join(","));const t=`${window.location.pathname}${e.toString()?"?"+e.toString():""}`;t!==window.location.pathname+window.location.search&&window.history.pushState({filters:this.store.filters},"",t)}saveToCacheFilters(){Object.keys(this.store.filters).forEach(e=>{const t=`${this.config.source}_${this.config.context}_${e}`;this.store.filters[e]!==this.defaults[e]?this.cache.set(t,this.store.filters[e]):this.cache.remove(t)});const e=`${this.config.source}_${this.config.context}_taxonomy`;Object.keys(this.taxFilters).length>0?this.cache.set(e,this.taxFilters):this.cache.remove(e)}initGallery(){this.gallery=!!this.config.gallery&&window.jvbGallery,this.gallery&&this.gallery.subscribe((e,t)=>{"load-more"===e&&this.store.lastResponse?.has_more&&this.nextPage()})}initStore(){let e=this.orderbyFilters.filter(e=>!["date","modified","title","random"].includes(e)),t=[];e.forEach(e=>{t.push({name:e,keyPath:e})});const i=window.jvbStore.register("feed",{storeName:"feed",endpoint:"feed",keyPath:"id",indexes:[{name:"content",keyPath:"content"},{name:"taxonomy",keyPath:"taxonomy"},{name:"user",keyPath:"user"},{name:"date",keyPath:"date"},{name:"modified",keyPath:"modified"},{name:"title",keyPath:"title"},...t],filters:this.filters,TTL:216e5,showLoading:!0,required:"content"});this.store=i.feed,this.store.subscribe((e,t)=>{"data-loaded"===e&&(this.renderItems(t.items),this.ui.buttons.loadMore.hidden=!0,this.store.lastResponse&&this.store.lastResponse?.has_more&&(this.ui.buttons.loadMore.hidden=!this.store.lastResponse?.has_more??!0))})}isFirstPage(){return 1===this.store.filters.page}renderItems(e=null){e=e??this.store.getFiltered(),this.isFirstPage()&&window.removeChildren(this.ui.grid),0===e.length?(this.showEmptyState(),this.a11y.announceItems(0,this.isFirstPage())):window.chunkIt(e,e=>this.createItemElement(e),t=>{this.removePlaceholders(),this.ui.grid.append(t),this.config.gallery&&this.gallery.buildGalleryItems(".item img"),this.a11y.makeNavigable(this.ui.grid.querySelectorAll(".item:not([data-keyboard-nav])")),this.a11y.announceItems(e.length,!this.isFirstPage(),this.store.lastResponse?.has_more??!1)},5).then(()=>{}),this.updateFilterControls()}showEmptyState(){window.removeChildren(this.ui.grid),this.ui.grid.append(this.templates.create("emptyState"))}createItemElement(e){if("object"==typeof e||(e=this.store.get(e)))return this.templates.create(`feedItem${window.uppercaseFirst(e.content)}`,e)}splitIDs(e){return String(e).split(",").map(e=>parseInt(e.trim())).filter(e=>e)}isImageField(e,t){return!(!Object.hasOwn(e,"images")||0===Object.keys(e.images).length)&&this.splitIDs(t).some(t=>Object.keys(e.images).map(e=>parseInt(e)).includes(parseInt(t)))}formatImageFields(e,t,i){let s=this.splitIDs(t);if(0!==s.length)if(s.length>1){let t=e.querySelector("img");if(!t)return;s.forEach(s=>{let r=t.cloneNode(!0);this.formatImageField(r,s,i),e.append(r)}),t.remove()}else{if("IMG"!==e.tagName&&!(e=e.querySelector("img")))return;this.formatImageField(e,s[0],i)}}formatImageField(e,t,i){let s=i.images[t]??!1;s&&([e.src,e.srcset,e.alt]=[s.tiny,`${s.tiny} 50w, ${s.small} 300w, ${s.medium} 1024w`,s["image-alt-text"]])}isTaxonomyField(e,t){return!(!Object.hasOwn(e,"taxonomies")||0===Object.keys(e.taxonomies).length)&&Object.keys(e.taxonomies).includes(t)}formatTaxonomyField(e,t,i,s){if("UL"!==e.tagName||!e.querySelector("li"))return;let r=this.splitIDs(s);0===r.length&&e.remove();let o=e.querySelector("li");for(let s of r){let r=t.taxonomies[i][s]??!1;if(!r)continue;let a=o.cloneNode(!0),n=a.querySelector("a");if(!n)continue;let l=window.decodeHTMLEntities(r.title);[n.href,n.title,n.textContent]=[r.url,`See more ${l}`,l],e.append(a)}o.remove()}isTimeField(e){return"TIME"===e.tagName||null!==e.querySelector("time")}formatTimeField(e,t){("TIME"===e.tagName||(e=e.querySelector("time")))&&(e.setAttribute("datetime",t),e.textContent=window.formatTimeAgo(t,"F Y"))}formatField(e,t){e.textContent=window.decodeHTMLEntities(t)}addTimelineElements(e,t){let[i,s,r,o]=[t.querySelector("span.after-text"),t.querySelector('[data-field="number"] b'),t.querySelector('[data-field="started"] time'),t.querySelector('[data-field="updated"] time')];i&&(i.textContent=`After ${e.number-1} Tx`),s&&(s.textContent=e.number-1),r&&this.formatTimeField(r,e.fields.timeline[0].post_date),o&&this.formatTimeField(o,e.fields.timeline[e.fields.timeline.length-1].post_date)}removePlaceholders(){const e=this.ui.grid.querySelectorAll(".placeholder");e.length>0&&e.forEach(e=>e.remove())}defineTemplates(){const e=this.templates,t=this;e.define("feedTerm",{refs:{icon:".icon",span:"span"},setup({el:e,refs:t,manyRefs:i,data:s}){e.dataset.id=s.id,e.dataset.taxonomy=s.taxonomy,t.icon&&(t.icon.className=`icon icon-${s.icon}`),t.span&&(t.span.textContent=window.decodeHTMLEntities(s.name))}}),e.define("emptyState"),this.contentTypes.forEach(i=>{e.define(`feedItem${window.uppercaseFirst(i)}`,{refs:{link:"a"},manyRefs:{fields:"[data-field]"},setup({el:e,refs:i,manyRefs:s,data:r}){const o=Object.hasOwn(e.dataset,"timeline");if(s.fields){for(let e of s.fields){if(o&&["timeline","number"].includes(e.dataset.field))continue;const i=!!Object.hasOwn(r.fields,e.dataset.field)&&r.fields[e.dataset.field];i?t.isImageField(r,i)?t.formatImageField(e,i,r):t.isTaxonomyField(r,e.dataset.field)?t.formatTaxonomyField(e,r,e.dataset.field,i):t.isTimeField(e)?t.formatTimeField(e,i):t.formatField(e,i):e.remove()}i.link&&""!==r.url&&(i.link.href=r.url,i.link.title=`View ${r.fields.post_title??"Item"}`),o&&t.addTimelineElements(r,e)}}})})}}document.addEventListener("DOMContentLoaded",async function(){window.auth.subscribe(t=>{"auth-loaded"===t&&(window.feedBlock=new e)})})})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/*!**************************!*\
+  !*** ./src/feed/view.js ***!
+  \**************************/
+class FeedBlock {
+  constructor() {
+    this.container = document.querySelector('section.feed-block');
+    if (!this.container) return;
+    this.a11y = window.jvbA11y;
+    this.error = window.jvbError;
+    this.cache = new window.jvbCache('feed');
+    this.templates = window.jvbTemplates;
+    this.config = {
+      contextId: '',
+      context: '',
+      highlight: null,
+      gallery: false,
+      view: this.cache.get('feedView') || 'grid',
+      ...this.container.dataset
+    };
+    console.log(this.config);
+    this.init();
+  }
+  init() {
+    this.initElements();
+    this.defineTemplates();
+    this.initListeners();
+    this.initFilters();
+    if ('requestIdleCallback' in window) {
+      requestIdleCallback(() => {
+        this.initStore();
+        this.initTaxonomies();
+        this.processCachedFilters();
+        this.processURLFilters();
+        this.updateFilterUI();
+        this.initGallery();
+      }, {
+        timeout: 2000
+      });
+    } else {
+      setTimeout(() => {
+        this.initStore();
+        this.initTaxonomies();
+        this.processCachedFilters();
+        this.processURLFilters();
+        this.updateFilterUI();
+        this.initGallery();
+      }, 100);
+    }
+  }
+  initElements() {
+    this.selectors = {
+      filterTrigger: '[data-filter]',
+      filters: {
+        actions: '.filter-actions .toggle-text',
+        container: '.all-filters',
+        showing: '.all-filters summary .current',
+        content: '[data-filter="content"]',
+        ordering: '.ordering',
+        orderby: '[data-filter="orderby"]',
+        order: '[data-filter="order"]',
+        orderWrap: '.order-direction',
+        match: '[data-filter="match"]',
+        favourites: '[data-filter="favourites"]',
+        taxonomy: '[data-filter^="taxonomy"]'
+      },
+      grid: '.item-grid',
+      selected: '.selected-items',
+      buttons: {
+        loadMore: 'button.load-more',
+        remove: '.remove-term',
+        clearFilters: 'button.clear-filters',
+        refresh: 'button[data-action="refresh"]'
+      }
+    };
+    this.ui = window.uiFromSelectors(this.selectors, this.container);
+    this.ui.buttons.refresh = document.querySelector(this.selectors.buttons.refresh);
+
+    //Add content and taxonomies
+    let getAll = ['content', 'orderby', 'order', 'taxonomy'];
+    getAll.forEach(item => {
+      let items = this.ui.filters.container.querySelectorAll(this.selectors.filters[item]);
+      this.ui[item] = Array.from(items);
+    });
+    this.contentTypes = this.ui.content.length > 0 ? this.ui.content.map(c => c.value) : [this.container.dataset.content];
+    this.taxonomies = this.ui.taxonomies?.length > 0 ? Array.from(this.ui.taxonomies).map(t => t.dataset.taxonomy) : [];
+  }
+
+  /**
+   *
+   * @param {string} item
+   */
+  getChecked(item) {
+    if (!['content', 'orderby', 'order'].includes(item)) {
+      console.log('Invalid item to check: ', item);
+    }
+    let items = this.ui[item];
+    if (!items) {
+      return;
+    }
+    let checked = items.filter(i => i.checked);
+    if (item === 'content' && checked.length > 0) {
+      this.updateContentFor(checked[0].value);
+    }
+    return checked.length === 0 ? items[0].value : checked[0].value;
+  }
+  initListeners() {
+    this.popStateHandler = this.handlePopState.bind(this);
+    this.clickHandler = this.handleClick.bind(this);
+    this.changeHandler = this.handleChange.bind(this);
+    window.addEventListener('popstate', this.popStateHandler);
+    document.addEventListener('click', this.clickHandler);
+    document.addEventListener('change', this.changeHandler);
+  }
+  initFilters() {
+    this.allowedFilters = ['content', 'order', 'orderby', 'favourites', 'match'];
+    let defaults = {
+      content: this.getChecked('content'),
+      orderby: this.getChecked('orderby'),
+      order: this.getChecked('order'),
+      page: 1
+    };
+    if (this.config.context) defaults.context = this.config.context;
+    if (this.config.contextId) defaults.contextId = this.config.contextId;
+    this.filters = defaults;
+    console.log(this.filters);
+    this.defaults = {
+      ...defaults
+    };
+  }
+  updateFilterUI() {
+    if (this.ui.filters.container) {
+      //Get cached inputs
+      let groups = [this.ui.content, this.ui.orderby, this.ui.order];
+      groups.forEach(group => {
+        if (group) {
+          for (let input of group) {
+            let [filter, value] = [input.dataset.filter, input.value];
+            if (!Object.hasOwn(this.store.filters, filter)) break;
+            let doit = this.store.filters[filter] === value;
+            if (doit) {
+              input.checked = doit;
+              break;
+            }
+          }
+        }
+      });
+      if (Object.hasOwn(this.store.filters, 'taxonomy')) {
+        for (let [taxonomy, terms] of Object.entries(this.store.filters.taxonomy)) {
+          terms.forEach(termId => {
+            termId = parseInt(termId);
+            const term = this.selector.store.get(termId);
+            if (term) {
+              this.createTermElement(termId);
+            }
+          });
+        }
+      }
+    }
+  }
+  handlePopState(e) {
+    if (e.state?.filters) {
+      if (this.processURLFilters()) {
+        this.store.setFilters(this.filters);
+        this.a11y.announce('Feed filters updated from browser history');
+      }
+    }
+  }
+  handleClick(e) {
+    if (window.targetCheck(e, this.selectors.buttons.loadMore)) {
+      this.nextPage();
+    } else if (window.targetCheck(e, this.selectors.buttons.clearFilters)) {
+      this.clearFilters();
+    }
+    let remove = window.targetCheck(e, this.selectors.buttons.remove);
+    if (remove) {
+      this.removeSelectedTerm(remove);
+    }
+    let refresh = window.targetCheck(e, this.selectors.buttons.refresh);
+    if (refresh) {
+      this.store.clearCache();
+      this.store.fetch();
+    }
+    let orderbyButton = window.targetCheck(e, '[data-filter="orderby"]');
+    if (orderbyButton && orderbyButton.value === 'random' && orderbyButton.checked) {
+      // Already selected random, just re-render to trigger new shuffle
+      this.renderItems();
+    }
+  }
+  nextPage() {
+    const nextPage = (this.store.filters.page || 1) + 1;
+    const maxPage = this.store.lastResponse?.pages || nextPage;
+    this.store.setFilters({
+      page: Math.min(nextPage, maxPage)
+    });
+  }
+  handleChange(e) {
+    const target = e.target;
+    if (Object.hasOwn(target.dataset, 'filter')) {
+      if (this.allowedFilters.includes(target.dataset.filter)) {
+        let filters = {};
+        filters[target.dataset.filter] = target.value;
+        this.resetFilters(filters);
+      }
+      switch (target.dataset.filter) {
+        case 'content':
+          this.updateContentFor(target.value);
+          break;
+        case 'orderby':
+          this.updateOrderOptions(target.value);
+          break;
+      }
+    }
+  }
+  clearFilters() {
+    this.taxFilters = {};
+    window.removeChildren(this.ui.selected);
+    this.taxonomies.forEach(tax => {
+      let fieldId = this.getFieldId(tax);
+      this.selector.selectedTerms.get(fieldId)?.clear();
+    });
+    this.store.setFilters({
+      ...this.defaults,
+      taxonomy: null
+    });
+    this.updateURL();
+    this.saveToCacheFilters();
+  }
+  resetFilters(filters) {
+    filters = {
+      ...this.store.filters,
+      page: 1,
+      ...filters
+    };
+    this.store.setFilters(filters);
+    this.updateURL();
+    this.saveToCacheFilters();
+  }
+  getFieldId(taxonomy) {
+    return this.selector.getFieldId(this.ui.taxonomies.filter(tax => tax.dataset.taxonomy === taxonomy)[0] ?? null);
+  }
+  removeSelectedTerm(button) {
+    const termId = parseInt(button.dataset.id);
+    const taxonomy = button.dataset.taxonomy;
+    if (Object.hasOwn(this.taxFilters, taxonomy)) {
+      this.taxFilters[taxonomy] = this.taxFilters[taxonomy].filter(id => id !== termId);
+      if (this.taxFilters[taxonomy].length === 0) {
+        delete this.taxFilters[taxonomy];
+      }
+    }
+    button.remove();
+
+    // Find the fieldId for this taxonomy
+    const field = this.getFieldId(taxonomy);
+    if (field) {
+      this.selector.activeField = field;
+      // Notify selector to remove from its selectedTerms
+      this.selector.removeSelected(termId, field);
+    }
+    this.resetFilters({
+      taxonomy: Object.keys(this.taxFilters).length > 0 ? this.taxFilters : null
+    });
+  }
+  updateContentFor(content) {
+    let checkIt = [this.ui.taxonomies, this.ui.orderby];
+    this.ui.filters.showing.textContent = this.ui.content.filter(c => c.value === content)[0].dataset.label;
+    checkIt.forEach(check => {
+      if (!check) return;
+      check.forEach(button => {
+        const forTypes = button.dataset.for?.split(',') ?? [];
+        button.hidden = forTypes.length > 0 && !forTypes.includes(content);
+        if (button.hidden && button.checked) {
+          button.checked = false;
+        }
+      });
+    });
+  }
+  updateOrderOptions(order) {
+    if (this.ui.filters.orderWrap) {
+      let options = this.ui.filters.orderWrap.dataset.forOrder.split(',') ?? [];
+      this.ui.filters.orderWrap.hidden = !options.includes(order);
+    }
+  }
+  updateFilterControls() {
+    const keys = Object.keys(this.taxFilters);
+    if (this.ui.buttons.clearFilters) {
+      this.ui.buttons.clearFilters.hidden = keys.length === 0;
+    }
+    if (this.ui.filters.actions) {
+      this.ui.filters.actions.hidden = keys.length <= 1;
+    }
+  }
+  async initTaxonomies() {
+    this.taxFilters = {};
+    this.selector = window.jvbSelector;
+    // this.selector.scanExistingFields(this.ui.filters.container);
+    // this.taxonomies.map(tax => this.selector.batchFetch.add(tax));
+    // this.selector.batchFetchTaxonomies();
+    this.selector.subscribe((event, data) => {
+      switch (event) {
+        case 'selected-terms':
+          this.handleTaxonomyChange(data);
+          break;
+      }
+    });
+  }
+  handleTaxonomyChange(data) {
+    const {
+      terms,
+      taxonomy
+    } = data;
+    if (terms.size === 0) return;
+    this.taxFilters[taxonomy] = Array.from(terms);
+    this.resetFilters({
+      taxonomy: this.taxFilters
+    });
+    terms.forEach(t => {
+      this.createTermElement(t);
+    });
+    this.updateFilterControls();
+  }
+  getTaxonomyIcon(taxonomy) {
+    let iconButton = this.ui.taxonomies.find(t => t.dataset.taxonomy === taxonomy);
+    return iconButton?.dataset.icon.trim() || 'tag';
+  }
+  createTermElement(termId) {
+    const term = this.selector.store.get(termId);
+    if (!term) return;
+    if (this.ui.selected.querySelector(`[data-id="${termId}"]`)) return;
+    term.icon = this.getTaxonomyIcon(term.taxonomy);
+    this.ui.selected.append(this.templates.create('feedTerm', term));
+  }
+  processCachedFilters() {
+    Object.keys(this.filters).forEach(filter => {
+      let cached = this.cache.get(`${this.config.contextId}_${this.config.context}_${filter}`);
+      if (cached && cached !== this.filters[filter]) {
+        this.filters[filter] = cached;
+      }
+    });
+  }
+  processURLFilters() {
+    if (!this.isFirstPage()) return false;
+    const params = new URLSearchParams(window.location.search);
+    if (!params.toString()) return false;
+    let shouldUpdate = false;
+    this.allowedFilters.forEach(filter => {
+      let value = params.get(`f_${filter}`);
+      if (value) {
+        shouldUpdate = true;
+        this.filters[filter] = value;
+      }
+    });
+    let hasTax = false;
+    params.forEach((value, key) => {
+      if (key.startsWith('f_tax_')) {
+        hasTax = true;
+        shouldUpdate = true;
+        const taxonomy = key.replace('f_tax_', '');
+        this.taxFilters[taxonomy] = value.split(',').map(Number);
+      }
+    });
+    if (shouldUpdate) {
+      if (hasTax) {
+        this.filters.taxonomy = this.taxFilters;
+      }
+      this.resetFilters(this.filters);
+    }
+    return true;
+  }
+  updateURL() {
+    const params = new URLSearchParams();
+    this.allowedFilters.forEach(key => {
+      if (Object.hasOwn(this.store.filters, key) && this.store.filters[key] !== this.defaults[key]) {
+        params.set(`f_${key}`, this.store.filters[key]);
+      }
+    });
+    for (let [tax, terms] of Object.entries(this.taxFilters)) {
+      if (terms.length > 0) {
+        params.set(`f_tax_${tax}`, terms.join(','));
+      }
+    }
+    const newURL = `${window.location.pathname}${params.toString() ? '?' + params.toString() : ''}`;
+    const currentURL = window.location.pathname + window.location.search; // Change this line
+
+    if (newURL !== currentURL) {
+      window.history.pushState({
+        filters: this.store.filters
+      }, '', newURL);
+    }
+  }
+  saveToCacheFilters() {
+    Object.keys(this.store.filters).forEach(filter => {
+      const cacheKey = `${this.config.contextId}_${this.config.context}_${filter}`;
+      if (this.store.filters[filter] !== this.defaults[filter]) {
+        this.cache.set(cacheKey, this.store.filters[filter]);
+      } else {
+        this.cache.remove(cacheKey);
+      }
+    });
+    const taxCacheKey = `${this.config.contextId}_${this.config.context}_taxonomy`;
+    if (Object.keys(this.taxFilters).length > 0) {
+      this.cache.set(taxCacheKey, this.taxFilters);
+    } else {
+      this.cache.remove(taxCacheKey);
+    }
+  }
+  initGallery() {
+    this.gallery = this.config.gallery ? window.jvbGallery : false;
+    if (this.gallery) {
+      this.gallery.subscribe((event, data) => {
+        if (event === 'load-more' && this.store.lastResponse?.has_more) {
+          this.nextPage();
+        }
+      });
+    }
+  }
+  initStore() {
+    let extraOrderby = this.ui.orderby.filter(v => !['date', 'date_modified', 'title', 'random'].includes(v.value));
+    let extraIndexes = [];
+    extraOrderby.forEach(orderby => {
+      extraIndexes.push({
+        name: orderby.value,
+        keyPath: orderby.value
+      });
+    });
+    const store = window.jvbStore.register('feed', {
+      storeName: 'feed',
+      endpoint: 'feed',
+      keyPath: 'id',
+      indexes: [{
+        name: 'content',
+        keyPath: 'content'
+      }, {
+        name: 'taxonomy',
+        keyPath: 'taxonomy'
+      }, {
+        name: 'user',
+        keyPath: 'user'
+      }, {
+        name: 'date',
+        keyPath: 'date'
+      }, {
+        name: 'modified',
+        keyPath: 'modified'
+      }, {
+        name: 'title',
+        keyPath: 'title'
+      }, ...extraIndexes],
+      filters: this.filters,
+      TTL: 6 * 60 * 60 * 1000,
+      //6 hours
+      showLoading: true,
+      required: 'content'
+    });
+    this.store = store.feed;
+    this.store.subscribe((event, data) => {
+      switch (event) {
+        case 'data-loaded':
+          this.renderItems(data.items);
+          this.ui.buttons.loadMore.hidden = true;
+          if (this.store.lastResponse && this.store.lastResponse?.has_more) {
+            this.ui.buttons.loadMore.hidden = !this.store.lastResponse?.has_more ?? true;
+          }
+          break;
+      }
+    });
+  }
+  isFirstPage() {
+    return this.store.filters.page === 1;
+  }
+  renderItems(items = null) {
+    items = items ?? this.store.getFiltered();
+    if (this.isFirstPage()) {
+      window.removeChildren(this.ui.grid);
+    }
+    if (items.length === 0) {
+      this.showEmptyState();
+      this.a11y.announceItems(0, this.isFirstPage());
+    } else {
+      window.chunkIt(items, item => this.createItemElement(item), fragment => {
+        this.removePlaceholders();
+        this.ui.grid.append(fragment);
+        if (this.config.gallery) this.gallery.buildGalleryItems('.item img');
+        this.a11y.makeNavigable(this.ui.grid.querySelectorAll('.item:not([data-keyboard-nav])'));
+        this.a11y.announceItems(items.length, !this.isFirstPage(), this.store.lastResponse?.has_more ?? false);
+      }, 5).then(() => {});
+    }
+    this.updateFilterControls();
+  }
+  showEmptyState() {
+    window.removeChildren(this.ui.grid);
+    this.ui.grid.append(this.templates.create('emptyState'));
+  }
+  createItemElement(item) {
+    if (typeof item !== 'object') {
+      item = this.store.get(item);
+      if (!item) return;
+    }
+    return this.templates.create(`feedItem${window.uppercaseFirst(item.content)}`, item);
+  }
+  splitIDs(value) {
+    return String(value).split(',').map(value => parseInt(value.trim())).filter(value => value);
+  }
+  isImageField(item, value) {
+    if (!Object.hasOwn(item, 'images') || Object.keys(item.images).length === 0) {
+      return false;
+    }
+    let values = this.splitIDs(value);
+    return values.some(v => Object.keys(item.images).map(k => parseInt(k)).includes(parseInt(v)));
+  }
+  formatImageFields(element, value, item) {
+    let values = this.splitIDs(value); // Convert string to array first
+    if (values.length === 0) return;
+    if (values.length > 1) {
+      let image = element.querySelector('img');
+      if (!image) return;
+      values.forEach(imgID => {
+        let img = image.cloneNode(true);
+        this.formatImageField(img, imgID, item);
+        element.append(img);
+      });
+      image.remove();
+    } else {
+      if (element.tagName !== 'IMG') {
+        element = element.querySelector('img');
+        if (!element) return;
+      }
+      this.formatImageField(element, values[0], item);
+    }
+  }
+  formatImageField(element, value, item) {
+    let imgData = item.images[value] ?? false;
+    if (!imgData) return;
+    [element.src, element.srcset, element.alt] = [imgData.tiny, `${imgData.tiny} 50w, ${imgData.small} 300w, ${imgData.medium} 1024w`, imgData['image-alt-text']];
+  }
+  isTaxonomyField(item, field) {
+    if (!Object.hasOwn(item, 'taxonomies') || Object.keys(item.taxonomies).length === 0) {
+      return false;
+    }
+    return Object.keys(item.taxonomies).includes(field);
+  }
+  formatTaxonomyField(element, item, field, value) {
+    if (element.tagName !== 'UL' || !element.querySelector('li')) return;
+    let values = this.splitIDs(value);
+    if (values.length === 0) {
+      element.remove();
+    }
+    let listItem = element.querySelector('li');
+    for (let termID of values) {
+      let term = item.taxonomies[field][termID] ?? false;
+      if (!term) continue;
+      let termItem = listItem.cloneNode(true);
+      let link = termItem.querySelector('a');
+      if (!link) continue;
+      let title = window.decodeHTMLEntities(term.title);
+      [link.href, link.title, link.textContent] = [term.url, `See more ${title}`, title];
+      element.append(termItem);
+    }
+    listItem.remove();
+  }
+  isTimeField(el) {
+    return el.tagName === 'TIME' || el.querySelector('time') !== null;
+  }
+  formatTimeField(element, value) {
+    if (element.tagName !== 'TIME') {
+      element = element.querySelector('time');
+      if (!element) return;
+    }
+    element.setAttribute('datetime', value);
+    element.textContent = window.formatTimeAgo(value, 'F Y');
+  }
+  formatField(element, value) {
+    element.textContent = window.decodeHTMLEntities(value);
+  }
+  addTimelineElements(item, template) {
+    let [afterEl, number, started, last] = [template.querySelector('span.after-text'), template.querySelector('[data-field="number"] b'), template.querySelector('[data-field="started"] time'), template.querySelector('[data-field="updated"] time')];
+    if (afterEl) {
+      afterEl.textContent = `After ${item.number - 1} Tx`;
+    }
+    if (number) {
+      number.textContent = item.number - 1;
+    }
+    if (started) {
+      this.formatTimeField(started, item.fields.timeline[0]['post_date']);
+    }
+    if (last) {
+      this.formatTimeField(last, item.fields.timeline[item.fields.timeline.length - 1]['post_date']);
+    }
+  }
+  removePlaceholders() {
+    const placeholders = this.ui.grid.querySelectorAll('.placeholder');
+    if (placeholders.length > 0) {
+      placeholders.forEach(p => p.remove());
+    }
+  }
+  defineTemplates() {
+    const T = this.templates;
+    const f = this;
+    T.define('feedTerm', {
+      refs: {
+        icon: '.icon',
+        span: 'span'
+      },
+      setup({
+        el,
+        refs,
+        manyRefs,
+        data
+      }) {
+        el.dataset.id = data.id;
+        el.dataset.taxonomy = data.taxonomy;
+        if (refs.icon) refs.icon.className = `icon icon-${data.icon}`;
+        if (refs.span) refs.span.textContent = window.decodeHTMLEntities(data.name);
+      }
+    });
+    T.define('emptyState');
+    this.contentTypes.forEach(content => {
+      T.define(`feedItem${window.uppercaseFirst(content)}`, {
+        refs: {
+          link: 'a'
+        },
+        manyRefs: {
+          fields: '[data-field]'
+        },
+        setup({
+          el,
+          refs,
+          manyRefs,
+          data
+        }) {
+          const isTimeline = Object.hasOwn(el.dataset, 'timeline');
+          if (manyRefs.fields) {
+            for (let field of manyRefs.fields) {
+              if (isTimeline && ['timeline', 'number'].includes(field.dataset.field)) continue;
+              const value = Object.hasOwn(data.fields, field.dataset.field) ? data.fields[field.dataset.field] : false;
+              if (!value) {
+                field.remove();
+                continue;
+              }
+              if (f.isImageField(data, value)) {
+                f.formatImageField(field, value, data);
+              } else if (f.isTaxonomyField(data, field.dataset.field)) {
+                f.formatTaxonomyField(field, data, field.dataset.field, value);
+              } else if (f.isTimeField(field)) {
+                f.formatTimeField(field, value);
+              } else {
+                f.formatField(field, value);
+              }
+            }
+            if (refs.link && data.url !== '') {
+              refs.link.href = data.url;
+              refs.link.title = `View ${data.fields['post_title'] ?? 'Item'}`;
+            }
+            if (isTimeline) f.addTimelineElements(data, el);
+          }
+        }
+      });
+    });
+  }
+
+  // addPlaceholders() {
+  // 	let total = this.contentTypes.length;
+  // 	const fragment = document.createDocumentFragment();
+  // 	for (let i = 0; i < 12; i++) {
+  // 		let template = window.getTemplate('placeholderTemplate');
+  //
+  // 		let rand = Math.floor(Math.random() * total);
+  // 		let icon;
+  // 		if (this.ui.content && this.ui.content.length > 0) {
+  // 			icon = this.ui.content.filter((content) => { return content.value === this.contentTypes[rand]}).querySelector('.icon').cloneNode(true);
+  // 		} else {
+  // 			icon = window.getIcon(this.container.dataset.icon);
+  // 		}
+  // 		template.append(icon);
+  // 		fragment.append(template);
+  // 	}
+  // 	this.ui.grid.append(fragment);
+  // }
+}
+document.addEventListener('DOMContentLoaded', async function () {
+  window.auth.subscribe(event => {
+    if (event === 'auth-loaded') {
+      window.feedBlock = new FeedBlock();
+    }
+  });
+});
+/******/ })()
+;
+//# sourceMappingURL=view.js.map
\ No newline at end of file
diff --git a/build/feed/view.js.map b/build/feed/view.js.map
new file mode 100644
index 0000000..2b62a93
--- /dev/null
+++ b/build/feed/view.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"feed/view.js","mappings":"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","sources":["webpack://jvb/./src/feed/view.js"],"sourcesContent":["class FeedBlock {\r\n\tconstructor() {\r\n\t\tthis.container = document.querySelector('section.feed-block');\r\n\t\tif(!this.container) return;\r\n\r\n\t\tthis.a11y = window.jvbA11y;\r\n\t\tthis.error = window.jvbError;\r\n\t\tthis.cache = new window.jvbCache('feed');\r\n\t\tthis.templates = window.jvbTemplates;\r\n\r\n\t\tthis.config = {\r\n\t\t\tcontextId: '',\r\n\t\t\tcontext: '',\r\n\t\t\thighlight: null,\r\n\t\t\tgallery: false,\r\n\t\t\tview: this.cache.get('feedView') || 'grid',\r\n\t\t\t... this.container.dataset\r\n\t\t};\r\n\r\n\t\tconsole.log(this.config);\r\n\r\n\t\tthis.init();\r\n\t}\r\n\tinit() {\r\n\t\tthis.initElements();\r\n\t\tthis.defineTemplates();\r\n\t\tthis.initListeners();\r\n\t\tthis.initFilters();\r\n\r\n\t\tif ('requestIdleCallback' in window) {\r\n\t\t\trequestIdleCallback(() => {\r\n\t\t\t\tthis.initStore();\r\n\t\t\t\tthis.initTaxonomies();\r\n\r\n\t\t\t\tthis.processCachedFilters();\r\n\t\t\t\tthis.processURLFilters();\r\n\t\t\t\tthis.updateFilterUI();\r\n\t\t\t\tthis.initGallery();\r\n\t\t\t}, { timeout: 2000 });\r\n\t\t} else {\r\n\t\t\tsetTimeout(() => {\r\n\t\t\t\tthis.initStore();\r\n\t\t\t\tthis.initTaxonomies();\r\n\r\n\t\t\t\tthis.processCachedFilters();\r\n\t\t\t\tthis.processURLFilters();\r\n\t\t\t\tthis.updateFilterUI();\r\n\t\t\t\tthis.initGallery();\r\n\t\t\t}, 100);\r\n\t\t}\r\n\t}\r\n\r\n\tinitElements() {\r\n\t\tthis.selectors = {\r\n\t\t\tfilterTrigger: '[data-filter]',\r\n\t\t\tfilters: {\r\n\t\t\t\tactions: \t'.filter-actions .toggle-text',\r\n\t\t\t\tcontainer:\t'.all-filters',\r\n\t\t\t\tshowing:\t'.all-filters summary .current',\r\n\t\t\t\tcontent: \t'[data-filter=\"content\"]',\r\n\t\t\t\tordering:\t'.ordering',\r\n\t\t\t\torderby: \t'[data-filter=\"orderby\"]',\r\n\t\t\t\torder: \t\t'[data-filter=\"order\"]',\r\n\t\t\t\torderWrap:  '.order-direction',\r\n\t\t\t\tmatch: \t\t'[data-filter=\"match\"]',\r\n\t\t\t\tfavourites: '[data-filter=\"favourites\"]',\r\n\t\t\t\ttaxonomy: \t'[data-filter^=\"taxonomy\"]',\r\n\t\t\t},\r\n\t\t\tgrid: \t\t'.item-grid',\r\n\t\t\tselected: \t'.selected-items',\r\n\t\t\tbuttons: {\r\n\t\t\t\tloadMore: \t\t'button.load-more',\r\n\t\t\t\tremove:\t\t\t'.remove-term',\r\n\t\t\t\tclearFilters: \t'button.clear-filters',\r\n\t\t\t\trefresh:\t\t'button[data-action=\"refresh\"]'\r\n\t\t\t}\r\n\t\t};\r\n\t\tthis.ui = window.uiFromSelectors(this.selectors, this.container);\r\n\t\tthis.ui.buttons.refresh = document.querySelector(this.selectors.buttons.refresh);\r\n\r\n\t\t//Add content and taxonomies\r\n\t\tlet getAll = ['content','orderby','order','taxonomy'];\r\n\t\tgetAll.forEach(item => {\r\n\t\t\tlet items = this.ui.filters.container.querySelectorAll(this.selectors.filters[item]);\r\n\t\t\tthis.ui[item] = Array.from(items);\r\n\t\t});\r\n\r\n\t\tthis.contentTypes = (this.ui.content.length > 0)\r\n\t\t\t? this.ui.content.map(c => c.value)\r\n\t\t\t: [this.container.dataset.content];\r\n\t\tthis.taxonomies = (this.ui.taxonomies?.length > 0)\r\n\t\t\t? Array.from(this.ui.taxonomies).map(t => t.dataset.taxonomy)\r\n\t\t\t: [];\r\n\t}\r\n\r\n\t/**\r\n\t *\r\n\t * @param {string} item\r\n\t */\r\n\tgetChecked(item) {\r\n\t\tif (!['content', 'orderby','order'].includes(item)) {\r\n\t\t\tconsole.log('Invalid item to check: ', item);\r\n\t\t}\r\n\r\n\t\tlet items = this.ui[item];\r\n\t\tif (!items) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlet checked = items.filter(i => i.checked);\r\n\t\tif (item === 'content' && checked.length > 0) {\r\n\t\t\tthis.updateContentFor(checked[0].value);\r\n\t\t}\r\n\t\treturn checked.length === 0 ? items[0].value : checked[0].value;\r\n\t}\r\n\r\n\tinitListeners() {\r\n\t\tthis.popStateHandler\t= this.handlePopState.bind(this);\r\n\t\tthis.clickHandler\t\t= this.handleClick.bind(this);\r\n\t\tthis.changeHandler\t\t= this.handleChange.bind(this);\r\n\r\n\t\twindow.addEventListener('popstate', this.popStateHandler);\r\n\t\tdocument.addEventListener('click', this.clickHandler);\r\n\t\tdocument.addEventListener('change', this.changeHandler);\r\n\t}\r\n\r\n\tinitFilters() {\r\n\t\tthis.allowedFilters = ['content', 'order', 'orderby', 'favourites', 'match'];\r\n\t\tlet defaults = {\r\n\t\t\tcontent:\tthis.getChecked('content'),\r\n\t\t\torderby:\tthis.getChecked('orderby'),\r\n\t\t\torder:\t\tthis.getChecked('order'),\r\n\t\t\tpage:\t\t1,\r\n\t\t};\r\n\t\tif (this.config.context) defaults.context = this.config.context;\r\n\t\tif (this.config.contextId) defaults.contextId = this.config.contextId;\r\n\r\n\t\tthis.filters = defaults;\r\n\r\n\t\tconsole.log(this.filters);\r\n\t\tthis.defaults = {...defaults};\r\n\t}\r\n\tupdateFilterUI() {\r\n\t\tif (this.ui.filters.container) {\r\n\t\t\t//Get cached inputs\r\n\t\t\tlet groups = [\r\n\t\t\t\tthis.ui.content,\r\n\t\t\t\tthis.ui.orderby,\r\n\t\t\t\tthis.ui.order\r\n\t\t\t];\r\n\r\n\t\t\tgroups.forEach(group => {\r\n\t\t\t\tif(group) {\r\n\t\t\t\t\tfor (let input of group) {\r\n\t\t\t\t\t\tlet [filter, value] = [input.dataset.filter, input.value];\r\n\t\t\t\t\t\tif (!Object.hasOwn(this.store.filters, filter)) break;\r\n\t\t\t\t\t\tlet doit = this.store.filters[filter] === value;\r\n\t\t\t\t\t\tif (doit) {\r\n\t\t\t\t\t\t\tinput.checked = doit;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tif (Object.hasOwn(this.store.filters, 'taxonomy')) {\r\n\t\t\t\tfor (let [taxonomy, terms] of Object.entries(this.store.filters.taxonomy)) {\r\n\t\t\t\t\tterms.forEach(termId => {\r\n\t\t\t\t\t\ttermId = parseInt(termId);\r\n\t\t\t\t\t\tconst term = this.selector.store.get(termId);\r\n\t\t\t\t\t\tif (term) {\r\n\t\t\t\t\t\t\tthis.createTermElement(termId);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\thandlePopState(e) {\r\n\t\tif (e.state?.filters) {\r\n\t\t\tif (this.processURLFilters()) {\r\n\t\t\t\tthis.store.setFilters(this.filters);\r\n\t\t\t\tthis.a11y.announce('Feed filters updated from browser history');\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\thandleClick(e) {\r\n\t\tif (window.targetCheck(e, this.selectors.buttons.loadMore)) {\r\n\t\t\tthis.nextPage();\r\n\t\t} else if (window.targetCheck(e, this.selectors.buttons.clearFilters)) {\r\n\t\t\tthis.clearFilters();\r\n\t\t}\r\n\t\tlet remove = window.targetCheck(e, this.selectors.buttons.remove);\r\n\t\tif (remove) {\r\n\t\t\tthis.removeSelectedTerm(remove);\r\n\t\t}\r\n\r\n\t\tlet refresh = window.targetCheck(e, this.selectors.buttons.refresh);\r\n\t\tif (refresh) {\r\n\t\t\tthis.store.clearCache();\r\n\t\t\tthis.store.fetch();\r\n\t\t}\r\n\r\n\t\tlet orderbyButton = window.targetCheck(e, '[data-filter=\"orderby\"]');\r\n\t\tif (orderbyButton && orderbyButton.value === 'random' && orderbyButton.checked) {\r\n\t\t\t// Already selected random, just re-render to trigger new shuffle\r\n\t\t\tthis.renderItems();\r\n\t\t}\r\n\t}\r\n\r\n\tnextPage() {\r\n\t\tconst nextPage = (this.store.filters.page || 1) + 1;\r\n\t\tconst maxPage = this.store.lastResponse?.pages || nextPage;\r\n\t\tthis.store.setFilters({ page: Math.min(nextPage, maxPage) });\r\n\t}\r\n\r\n\thandleChange(e) {\r\n\t\tconst target = e.target;\r\n\t\tif (Object.hasOwn(target.dataset, 'filter')) {\r\n\t\t\tif (this.allowedFilters.includes(target.dataset.filter)) {\r\n\t\t\t\tlet filters = {};\r\n\t\t\t\tfilters[target.dataset.filter] = target.value;\r\n\t\t\t\tthis.resetFilters(filters);\r\n\t\t\t}\r\n\t\t\tswitch (target.dataset.filter) {\r\n\t\t\t\tcase 'content':\r\n\t\t\t\t\tthis.updateContentFor(target.value);\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tcase 'orderby':\r\n\t\t\t\t\tthis.updateOrderOptions(target.value);\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tclearFilters() {\r\n\t\tthis.taxFilters = {};\r\n\t\twindow.removeChildren(this.ui.selected);\r\n\r\n\t\tthis.taxonomies.forEach(tax => {\r\n\t\t\tlet fieldId = this.getFieldId(tax);\r\n\t\t\tthis.selector.selectedTerms.get(fieldId)?.clear();\r\n\t\t});\r\n\r\n\t\tthis.store.setFilters({\r\n\t\t\t...this.defaults,\r\n\t\t\ttaxonomy: null\r\n\t\t});\r\n\r\n\t\tthis.updateURL();\r\n\t\tthis.saveToCacheFilters();\r\n\t}\r\n\r\n\tresetFilters(filters) {\r\n\t\tfilters = {\r\n\t\t\t...this.store.filters,\r\n\t\t\tpage: 1,\r\n\t\t\t... filters\r\n\t\t}\r\n\t\tthis.store.setFilters(filters);\r\n\r\n\t\tthis.updateURL();\r\n\t\tthis.saveToCacheFilters();\r\n\t}\r\n\r\n\tgetFieldId(taxonomy) {\r\n\t\treturn this.selector.getFieldId(this.ui.taxonomies.filter(tax => tax.dataset.taxonomy === taxonomy)[0]??null);\r\n\t}\r\n\tremoveSelectedTerm(button) {\r\n\t\tconst termId = parseInt(button.dataset.id);\r\n\t\tconst taxonomy = button.dataset.taxonomy;\r\n\r\n\t\tif (Object.hasOwn(this.taxFilters, taxonomy)){\r\n\t\t\tthis.taxFilters[taxonomy] = this.taxFilters[taxonomy]\r\n\t\t\t\t.filter(id => id !== termId);\r\n\t\t\tif (this.taxFilters[taxonomy].length === 0) {\r\n\t\t\t\tdelete this.taxFilters[taxonomy];\r\n\t\t\t}\r\n\t\t}\r\n\t\tbutton.remove();\r\n\r\n\t\t// Find the fieldId for this taxonomy\r\n\t\tconst field = this.getFieldId(taxonomy);\r\n\t\tif (field) {\r\n\t\t\tthis.selector.activeField = field;\r\n\t\t\t// Notify selector to remove from its selectedTerms\r\n\t\t\tthis.selector.removeSelected(termId, field);\r\n\t\t}\r\n\r\n\t\tthis.resetFilters({\r\n\t\t\ttaxonomy: Object.keys(this.taxFilters).length > 0\r\n\t\t\t\t? this.taxFilters\r\n\t\t\t\t: null\r\n\t\t});\r\n\t}\r\n\r\n\tupdateContentFor(content) {\r\n\t\tlet checkIt = [\r\n\t\t\tthis.ui.taxonomies,\r\n\t\t\tthis.ui.orderby\r\n\t\t];\r\n\r\n\t\tthis.ui.filters.showing.textContent = this.ui.content.filter(c => c.value === content)[0].dataset.label;\r\n\t\tcheckIt.forEach(check => {\r\n\t\t\tif (!check) return;\r\n\t\t\tcheck.forEach(button => {\r\n\t\t\t\tconst forTypes = button.dataset.for?.split(',')??[];\r\n\t\t\t\tbutton.hidden = forTypes.length > 0 && !forTypes.includes(content);\r\n\t\t\t\tif (button.hidden && button.checked) {\r\n\t\t\t\t\tbutton.checked = false;\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t});\r\n\t}\r\n\tupdateOrderOptions(order) {\r\n\t\tif (this.ui.filters.orderWrap) {\r\n\t\t\tlet options = this.ui.filters.orderWrap.dataset.forOrder.split(',')??[];\r\n\t\t\tthis.ui.filters.orderWrap.hidden = !options.includes(order);\r\n\t\t}\r\n\t}\r\n\r\n\tupdateFilterControls() {\r\n\t\tconst keys = Object.keys(this.taxFilters);\r\n\t\tif (this.ui.buttons.clearFilters) {\r\n\t\t\tthis.ui.buttons.clearFilters.hidden = keys.length === 0;\r\n\t\t}\r\n\t\tif (this.ui.filters.actions) {\r\n\t\t\tthis.ui.filters.actions.hidden = keys.length <= 1;\r\n\t\t}\r\n\t}\r\n\r\n\tasync initTaxonomies() {\r\n\t\tthis.taxFilters = {};\r\n\t\tthis.selector = window.jvbSelector;\r\n\t\t// this.selector.scanExistingFields(this.ui.filters.container);\r\n\t\t// this.taxonomies.map(tax => this.selector.batchFetch.add(tax));\r\n\t\t// this.selector.batchFetchTaxonomies();\r\n\t\tthis.selector.subscribe((event, data) => {\r\n\t\t\tswitch (event) {\r\n\t\t\t\tcase 'selected-terms':\r\n\r\n\t\t\t\t\tthis.handleTaxonomyChange(data);\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\thandleTaxonomyChange(data) {\r\n\t\tconst {terms, taxonomy } = data;\r\n\t\tif (terms.size === 0) return;\r\n\t\tthis.taxFilters[taxonomy] = Array.from(terms);\r\n\t\tthis.resetFilters({ taxonomy: this.taxFilters });\r\n\r\n\t\tterms.forEach(t => {\r\n\t\t\tthis.createTermElement(t);\r\n\t\t});\r\n\t\tthis.updateFilterControls();\r\n\t}\r\n\tgetTaxonomyIcon(taxonomy) {\r\n\t\tlet iconButton = this.ui.taxonomies\r\n\t\t\t.find(t => t.dataset.taxonomy === taxonomy);\r\n\t\treturn iconButton?.dataset.icon.trim() || 'tag';\r\n\t}\r\n\tcreateTermElement(termId) {\r\n\t\tconst term = this.selector.store.get(termId);\r\n\t\tif (!term) return;\r\n\t\tif (this.ui.selected.querySelector(`[data-id=\"${termId}\"]`)) return;\r\n\r\n\t\tterm.icon = this.getTaxonomyIcon(term.taxonomy);\r\n\t\tthis.ui.selected.append(this.templates.create('feedTerm', term));\r\n\t}\r\n\r\n\tprocessCachedFilters() {\r\n\t\tObject.keys(this.filters).forEach(filter => {\r\n\t\t\tlet cached = this.cache.get(`${this.config.contextId}_${this.config.context}_${filter}`);\r\n\t\t\tif (cached && cached !== this.filters[filter]) {\r\n\t\t\t\tthis.filters[filter] = cached;\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tprocessURLFilters() {\r\n\t\tif (!this.isFirstPage()) return false;\r\n\t\tconst params = new URLSearchParams(window.location.search);\r\n\t\tif (!params.toString()) return false;\r\n\t\tlet shouldUpdate = false;\r\n\t\tthis.allowedFilters.forEach(filter => {\r\n\t\t\tlet value = params.get(`f_${filter}`);\r\n\t\t\tif (value) {\r\n\t\t\t\tshouldUpdate = true;\r\n\t\t\t\tthis.filters[filter] = value;\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tlet hasTax = false;\r\n\t\tparams.forEach((value, key) => {\r\n\t\t\tif (key.startsWith('f_tax_')) {\r\n\t\t\t\thasTax = true;\r\n\t\t\t\tshouldUpdate = true;\r\n\t\t\t\tconst taxonomy = key.replace('f_tax_','');\r\n\t\t\t\tthis.taxFilters[taxonomy] = value.split(',').map(Number);\r\n\t\t\t}\r\n\t\t});\r\n\t\tif (shouldUpdate) {\r\n\t\t\tif (hasTax) {\r\n\t\t\t\tthis.filters.taxonomy = this.taxFilters;\r\n\t\t\t}\r\n\t\t\tthis.resetFilters(this.filters);\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\tupdateURL() {\r\n\t\tconst params = new URLSearchParams();\r\n\t\tthis.allowedFilters.forEach(key => {\r\n\t\t\tif (Object.hasOwn(this.store.filters, key) && this.store.filters[key] !== this.defaults[key]) {\r\n\t\t\t\tparams.set(`f_${key}`, this.store.filters[key]);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tfor (let [tax, terms] of Object.entries(this.taxFilters)) {\r\n\t\t\tif (terms.length > 0) {\r\n\t\t\t\tparams.set(`f_tax_${tax}`, terms.join(','));\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst newURL = `${window.location.pathname}${params.toString() ? '?' + params.toString() : ''}`;\r\n\t\tconst currentURL = window.location.pathname + window.location.search;  // Change this line\r\n\r\n\t\tif (newURL !== currentURL) {\r\n\t\t\twindow.history.pushState({filters:this.store.filters}, '', newURL);\r\n\t\t}\r\n\t}\r\n\r\n\tsaveToCacheFilters() {\r\n\t\tObject.keys(this.store.filters).forEach(filter => {\r\n\t\t\tconst cacheKey = `${this.config.contextId}_${this.config.context}_${filter}`;\r\n\r\n\t\t\tif (this.store.filters[filter] !== this.defaults[filter]) {\r\n\t\t\t\tthis.cache.set(cacheKey, this.store.filters[filter]);\r\n\t\t\t} else {\r\n\t\t\t\tthis.cache.remove(cacheKey);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tconst taxCacheKey = `${this.config.contextId}_${this.config.context}_taxonomy`;\r\n\t\tif (Object.keys(this.taxFilters).length > 0) {\r\n\t\t\tthis.cache.set(taxCacheKey, this.taxFilters);\r\n\t\t} else {\r\n\t\t\tthis.cache.remove(taxCacheKey);\r\n\t\t}\r\n\t}\r\n\r\n\tinitGallery() {\r\n\t\tthis.gallery = (this.config.gallery) ? window.jvbGallery : false;\r\n\t\tif (this.gallery) {\r\n\t\t\tthis.gallery.subscribe((event, data) => {\r\n\t\t\t\tif (event === 'load-more' && this.store.lastResponse?.has_more) {\r\n\t\t\t\t\tthis.nextPage();\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tinitStore() {\r\n\t\tlet extraOrderby = this.ui.orderby.filter(v => !['date','date_modified','title','random'].includes(v.value));\r\n\r\n\t\tlet extraIndexes = [];\r\n\t\textraOrderby.forEach(orderby =>{\r\n\t\t\textraIndexes.push({name:orderby.value, keyPath: orderby.value});\r\n\t\t});\r\n\t\tconst store = window.jvbStore.register(\r\n\t\t\t'feed',\r\n\t\t\t{\r\n\t\t\t\tstoreName: 'feed',\r\n\t\t\t\tendpoint: 'feed',\r\n\t\t\t\tkeyPath: 'id',\r\n\t\t\t\tindexes: [\r\n\t\t\t\t\t{ name: 'content', keyPath: 'content'},\r\n\t\t\t\t\t{ name: 'taxonomy', keyPath: 'taxonomy'},\r\n\t\t\t\t\t{ name: 'user', keyPath: 'user'},\r\n\t\t\t\t\t{ name: 'date', keyPath: 'date'},\r\n\t\t\t\t\t{ name: 'modified', keyPath: 'modified'},\r\n\t\t\t\t\t{ name: 'title', keyPath: 'title'},\r\n\t\t\t\t\t... extraIndexes\r\n\t\t\t\t],\r\n\t\t\t\tfilters: this.filters,\r\n\t\t\t\tTTL: 6 * 60 * 60 * 1000, //6 hours\r\n\t\t\t\tshowLoading: true,\r\n\t\t\t\trequired: 'content',\r\n\t\t\t}\r\n\t\t);\r\n\r\n\t\tthis.store = store.feed;\r\n\r\n\t\tthis.store.subscribe((event, data) => {\r\n\t\t\tswitch (event) {\r\n\t\t\t\tcase 'data-loaded':\r\n\t\t\t\t\tthis.renderItems(data.items);\r\n\t\t\t\t\tthis.ui.buttons.loadMore.hidden = true;\r\n\t\t\t\t\tif (this.store.lastResponse && this.store.lastResponse?.has_more) {\r\n\t\t\t\t\t\tthis.ui.buttons.loadMore.hidden = !this.store.lastResponse?.has_more??true;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tisFirstPage() {\r\n\t\treturn this.store.filters.page === 1;\r\n\t}\r\n\r\n\trenderItems(items = null) {\r\n\t\titems = items??this.store.getFiltered();\r\n\t\tif (this.isFirstPage()) {\r\n\t\t\twindow.removeChildren(this.ui.grid);\r\n\t\t}\r\n\t\tif (items.length === 0) {\r\n\t\t\tthis.showEmptyState();\r\n\t\t\tthis.a11y.announceItems(0, this.isFirstPage());\r\n\t\t} else {\r\n\t\t\twindow.chunkIt(\r\n\t\t\t\titems,\r\n\t\t\t\t(item) => this.createItemElement(item),\r\n\t\t\t\t(fragment) => {\r\n\t\t\t\t\tthis.removePlaceholders();\r\n\t\t\t\t\tthis.ui.grid.append(fragment);\r\n\t\t\t\t\tif (this.config.gallery) this.gallery.buildGalleryItems('.item img');\r\n\t\t\t\t\tthis.a11y.makeNavigable(this.ui.grid.querySelectorAll('.item:not([data-keyboard-nav])'));\r\n\t\t\t\t\tthis.a11y.announceItems(items.length, !this.isFirstPage(), this.store.lastResponse?.has_more??false);\r\n\t\t\t\t},\r\n\t\t\t\t5\r\n\t\t\t).then(()=>{});\r\n\t\t}\r\n\r\n\t\tthis.updateFilterControls();\r\n\t}\r\n\r\n\tshowEmptyState() {\r\n\t\twindow.removeChildren(this.ui.grid);\r\n\t\tthis.ui.grid.append(this.templates.create('emptyState'));\r\n\t}\r\n\r\n\tcreateItemElement(item) {\r\n\t\tif (typeof item !== 'object') {\r\n\t\t\titem = this.store.get(item);\r\n\t\t\tif (!item) return;\r\n\t\t}\r\n\t\treturn this.templates.create(`feedItem${window.uppercaseFirst(item.content)}`, item);\r\n\t}\r\n\tsplitIDs(value) {\r\n\t\treturn String(value).split(',').map((value) => parseInt(value.trim())).filter(value=>value);\r\n\t}\r\n\r\n\tisImageField(item, value) {\r\n\t\tif (!Object.hasOwn(item, 'images') || Object.keys(item.images).length === 0) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tlet values = this.splitIDs(value);\r\n\r\n\t\treturn values.some(v =>\r\n\t\t\tObject.keys(item.images).map(k => parseInt(k)).includes(parseInt(v))\r\n\t\t);\r\n\t}\r\n\tformatImageFields(element, value, item) {\r\n\t\tlet values = this.splitIDs(value); // Convert string to array first\r\n\t\tif (values.length === 0) return;\r\n\r\n\t\tif (values.length > 1) {\r\n\t\t\tlet image = element.querySelector('img');\r\n\t\t\tif (!image) return;\r\n\t\t\tvalues.forEach(imgID => {\r\n\t\t\t\tlet img = image.cloneNode(true);\r\n\t\t\t\tthis.formatImageField(img, imgID, item);\r\n\t\t\t\telement.append(img);\r\n\t\t\t});\r\n\t\t\timage.remove();\r\n\t\t} else {\r\n\t\t\tif (element.tagName !== 'IMG') {\r\n\t\t\t\telement = element.querySelector('img');\r\n\t\t\t\tif (!element) return;\r\n\t\t\t}\r\n\t\t\tthis.formatImageField(element, values[0], item);\r\n\t\t}\r\n\t}\r\n\tformatImageField(element, value, item) {\r\n\t\tlet imgData = item.images[value]??false;\r\n\t\tif (!imgData) return;\r\n\t\t[\r\n\t\t\telement.src,\r\n\t\t\telement.srcset,\r\n\t\t\telement.alt\r\n\t\t] = [\r\n\t\t\timgData.tiny,\r\n\t\t\t`${imgData.tiny} 50w, ${imgData.small} 300w, ${imgData.medium} 1024w`,\r\n\t\t\timgData['image-alt-text']\r\n\t\t]\r\n\t}\r\n\tisTaxonomyField(item, field) {\r\n\t\tif (!Object.hasOwn(item, 'taxonomies') || Object.keys(item.taxonomies).length === 0) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\treturn Object.keys(item.taxonomies).includes(field);\r\n\t}\r\n\tformatTaxonomyField(element, item, field, value) {\r\n\t\tif (element.tagName !== 'UL' || !element.querySelector('li')) return;\r\n\t\tlet values = this.splitIDs(value);\r\n\t\tif (values.length === 0) {\r\n\t\t\telement.remove();\r\n\t\t}\r\n\t\tlet listItem = element.querySelector('li');\r\n\t\tfor (let termID of values) {\r\n\t\t\tlet term = item.taxonomies[field][termID]??false;\r\n\t\t\tif (!term) continue;\r\n\t\t\tlet termItem = listItem.cloneNode(true);\r\n\t\t\tlet link = termItem.querySelector('a');\r\n\t\t\tif (!link) continue;\r\n\r\n\t\t\tlet title = window.decodeHTMLEntities(term.title);\r\n\r\n\t\t\t[\r\n\t\t\t\tlink.href,\r\n\t\t\t\tlink.title,\r\n\t\t\t\tlink.textContent\r\n\t\t\t] = [\r\n\t\t\t\tterm.url,\r\n\t\t\t\t`See more ${title}`,\r\n\t\t\t\ttitle\r\n\t\t\t];\r\n\t\t\telement.append(termItem);\r\n\t\t}\r\n\t\tlistItem.remove();\r\n\t}\r\n\tisTimeField(el) {\r\n\t\treturn el.tagName === 'TIME' || el.querySelector('time') !== null;\r\n\t}\r\n\tformatTimeField(element, value) {\r\n\t\tif (element.tagName !== 'TIME') {\r\n\t\t\telement = element.querySelector('time');\r\n\t\t\tif (!element) return;\r\n\t\t}\r\n\t\telement.setAttribute('datetime', value);\r\n\t\telement.textContent = window.formatTimeAgo(value, 'F Y');\r\n\t}\r\n\tformatField(element, value) {\r\n\t\telement.textContent = window.decodeHTMLEntities(value);\r\n\t}\r\n\r\n\taddTimelineElements(item, template) {\r\n\t\tlet [\r\n\t\t\tafterEl,\r\n\t\t\tnumber,\r\n\t\t\tstarted,\r\n\t\t\tlast\r\n\t\t] = [\r\n\t\t\ttemplate.querySelector('span.after-text'),\r\n\t\t\ttemplate.querySelector('[data-field=\"number\"] b'),\r\n\t\t\ttemplate.querySelector('[data-field=\"started\"] time'),\r\n\t\t\ttemplate.querySelector('[data-field=\"updated\"] time')\r\n\t\t];\r\n\r\n\t\tif (afterEl) {\r\n\t\t\tafterEl.textContent = `After ${item.number - 1} Tx`;\r\n\t\t}\r\n\t\tif (number) {\r\n\t\t\tnumber.textContent = item.number - 1;\r\n\t\t}\r\n\t\tif (started) {\r\n\t\t\tthis.formatTimeField(started, item.fields.timeline[0]['post_date']);\r\n\t\t}\r\n\t\tif (last) {\r\n\t\t\tthis.formatTimeField(last, item.fields.timeline[item.fields.timeline.length - 1]['post_date']);\r\n\t\t}\r\n\t}\r\n\r\n\tremovePlaceholders() {\r\n\t\tconst placeholders = this.ui.grid.querySelectorAll('.placeholder');\r\n\t\tif (placeholders.length > 0) {\r\n\t\t\tplaceholders.forEach(p => p.remove());\r\n\t\t}\r\n\t}\r\n\r\n\tdefineTemplates() {\r\n\t\tconst T = this.templates;\r\n\t\tconst f = this;\r\n\r\n\t\tT.define('feedTerm', {\r\n\t\t\trefs: {\r\n\t\t\t\ticon: '.icon',\r\n\t\t\t\tspan: 'span'\r\n\t\t\t},\r\n\t\t\tsetup({el, refs, manyRefs, data}) {\r\n\t\t\t\tel.dataset.id = data.id;\r\n\t\t\t\tel.dataset.taxonomy = data.taxonomy;\r\n\t\t\t\tif (refs.icon) refs.icon.className = `icon icon-${data.icon}`;\r\n\t\t\t\tif (refs.span) refs.span.textContent = window.decodeHTMLEntities(data.name);\r\n\t\t\t}\r\n\t\t});\r\n\t\tT.define('emptyState');\r\n\r\n\t\tthis.contentTypes.forEach(content => {\r\n\t\t\tT.define(`feedItem${window.uppercaseFirst(content)}`, {\r\n\t\t\t\trefs: {\r\n\t\t\t\t\tlink: 'a',\r\n\t\t\t\t},\r\n\t\t\t\tmanyRefs: {\r\n\t\t\t\t\tfields: '[data-field]',\r\n\t\t\t\t},\r\n\t\t\t\tsetup({el, refs, manyRefs, data}) {\r\n\t\t\t\t\tconst isTimeline = Object.hasOwn(el.dataset, 'timeline');\r\n\t\t\t\t\tif (manyRefs.fields) {\r\n\t\t\t\t\t\tfor (let field of manyRefs.fields) {\r\n\t\t\t\t\t\t\tif (isTimeline && ['timeline','number'].includes(field.dataset.field)) continue;\r\n\r\n\t\t\t\t\t\t\tconst value = Object.hasOwn(data.fields, field.dataset.field)? data.fields[field.dataset.field] : false;\r\n\t\t\t\t\t\t\tif (!value) {\r\n\t\t\t\t\t\t\t\tfield.remove();\r\n\t\t\t\t\t\t\t\tcontinue;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tif (f.isImageField(data, value)) {\r\n\t\t\t\t\t\t\t\tf.formatImageField(field, value, data);\r\n\t\t\t\t\t\t\t} else if (f.isTaxonomyField(data, field.dataset.field)) {\r\n\t\t\t\t\t\t\t\tf.formatTaxonomyField(field, data, field.dataset.field, value);\r\n\t\t\t\t\t\t\t} else if (f.isTimeField(field)) {\r\n\t\t\t\t\t\t\t\tf.formatTimeField(field, value);\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tf.formatField(field, value);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (refs.link && data.url !== '') {\r\n\t\t\t\t\t\t\trefs.link.href = data.url;\r\n\t\t\t\t\t\t\trefs.link.title = `View ${data.fields['post_title']??'Item'}`;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif (isTimeline ) f.addTimelineElements(data, el);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t});\r\n\t}\r\n\r\n\t// addPlaceholders() {\r\n\t// \tlet total = this.contentTypes.length;\r\n\t// \tconst fragment = document.createDocumentFragment();\r\n\t// \tfor (let i = 0; i < 12; i++) {\r\n\t// \t\tlet template = window.getTemplate('placeholderTemplate');\r\n\t//\r\n\t// \t\tlet rand = Math.floor(Math.random() * total);\r\n\t// \t\tlet icon;\r\n\t// \t\tif (this.ui.content && this.ui.content.length > 0) {\r\n\t// \t\t\ticon = this.ui.content.filter((content) => { return content.value === this.contentTypes[rand]}).querySelector('.icon').cloneNode(true);\r\n\t// \t\t} else {\r\n\t// \t\t\ticon = window.getIcon(this.container.dataset.icon);\r\n\t// \t\t}\r\n\t// \t\ttemplate.append(icon);\r\n\t// \t\tfragment.append(template);\r\n\t// \t}\r\n\t// \tthis.ui.grid.append(fragment);\r\n\t// }\r\n}\r\n\r\ndocument.addEventListener('DOMContentLoaded', async function() {\r\n\twindow.auth.subscribe(event => {\r\n\t\tif (event === 'auth-loaded') {\r\n\t\t\twindow.feedBlock = new FeedBlock();\r\n\t\t}\r\n\t});\r\n});\r\n"],"names":["FeedBlock","constructor","container","document","querySelector","a11y","window","jvbA11y","error","jvbError","cache","jvbCache","templates","jvbTemplates","config","contextId","context","highlight","gallery","view","get","dataset","console","log","init","initElements","defineTemplates","initListeners","initFilters","requestIdleCallback","initStore","initTaxonomies","processCachedFilters","processURLFilters","updateFilterUI","initGallery","timeout","setTimeout","selectors","filterTrigger","filters","actions","showing","content","ordering","orderby","order","orderWrap","match","favourites","taxonomy","grid","selected","buttons","loadMore","remove","clearFilters","refresh","ui","uiFromSelectors","getAll","forEach","item","items","querySelectorAll","Array","from","contentTypes","length","map","c","value","taxonomies","t","getChecked","includes","checked","filter","i","updateContentFor","popStateHandler","handlePopState","bind","clickHandler","handleClick","changeHandler","handleChange","addEventListener","allowedFilters","defaults","page","groups","group","input","Object","hasOwn","store","doit","terms","entries","termId","parseInt","term","selector","createTermElement","e","state","setFilters","announce","targetCheck","nextPage","removeSelectedTerm","clearCache","fetch","orderbyButton","renderItems","maxPage","lastResponse","pages","Math","min","target","resetFilters","updateOrderOptions","taxFilters","removeChildren","tax","fieldId","getFieldId","selectedTerms","clear","updateURL","saveToCacheFilters","button","id","field","activeField","removeSelected","keys","checkIt","textContent","label","check","forTypes","for","split","hidden","options","forOrder","updateFilterControls","jvbSelector","subscribe","event","data","handleTaxonomyChange","size","getTaxonomyIcon","iconButton","find","icon","trim","append","create","cached","isFirstPage","params","URLSearchParams","location","search","toString","shouldUpdate","hasTax","key","startsWith","replace","Number","set","join","newURL","pathname","currentURL","history","pushState","cacheKey","taxCacheKey","jvbGallery","has_more","extraOrderby","v","extraIndexes","push","name","keyPath","jvbStore","register","storeName","endpoint","indexes","TTL","showLoading","required","feed","getFiltered","showEmptyState","announceItems","chunkIt","createItemElement","fragment","removePlaceholders","buildGalleryItems","makeNavigable","then","uppercaseFirst","splitIDs","String","isImageField","images","values","some","k","formatImageFields","element","image","imgID","img","cloneNode","formatImageField","tagName","imgData","src","srcset","alt","tiny","small","medium","isTaxonomyField","formatTaxonomyField","listItem","termID","termItem","link","title","decodeHTMLEntities","href","url","isTimeField","el","formatTimeField","setAttribute","formatTimeAgo","formatField","addTimelineElements","template","afterEl","number","started","last","fields","timeline","placeholders","p","T","f","define","refs","span","setup","manyRefs","className","isTimeline","auth","feedBlock"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/fields/block.json b/build/fields/block.json
deleted file mode 100644
index e6e281b..0000000
--- a/build/fields/block.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
-  "$schema": "https://schemas.wp.org/trunk/block.json",
-  "apiVersion": 3,
-  "name": "jvb/fields",
-  "title": "JakeVan Fields",
-  "category": "jvb",
-  "icon": "ellipses",
-  "description": "Access data from your custom fields",
-  "keywords": [
-    "field",
-    "custom",
-    "jake"
-  ],
-  "version": "0.9.0",
-  "textdomain": "jvb",
-  "supports": {
-    "html": false,
-    "align": [
-      "wide",
-      "full"
-    ]
-  },
-  "selectors": {
-    "root": ".jvb-f"
-  },
-  "styles": [],
-  "render": "file:./render.php",
-  "editorScript": "file:./index.js",
-  "editorStyle": "file:./index.css",
-  "style": "file:./style-index.css",
-  "viewScript": "file:./view.js"
-}
\ No newline at end of file
diff --git a/build/fields/index-rtl.css b/build/fields/index-rtl.css
deleted file mode 100644
index 6cfd5fd..0000000
--- a/build/fields/index-rtl.css
+++ /dev/null
@@ -1 +0,0 @@
-.jvb-summary-preview{background-color:#f8f9fa;border:1px solid #e2e4e7;border-radius:4px;padding:20px}.jvb-summary-preview h3{border-bottom:1px solid #ff0080;margin-top:0;padding-bottom:10px}.jvb-summary-preview-note{color:#555d66;font-style:italic;margin-bottom:0}
diff --git a/build/fields/index.asset.php b/build/fields/index.asset.php
deleted file mode 100644
index 55ce555..0000000
--- a/build/fields/index.asset.php
+++ /dev/null
@@ -1 +0,0 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '5b8000cf505c273c8c4b');
diff --git a/build/fields/index.css b/build/fields/index.css
deleted file mode 100644
index 6cfd5fd..0000000
--- a/build/fields/index.css
+++ /dev/null
@@ -1 +0,0 @@
-.jvb-summary-preview{background-color:#f8f9fa;border:1px solid #e2e4e7;border-radius:4px;padding:20px}.jvb-summary-preview h3{border-bottom:1px solid #ff0080;margin-top:0;padding-bottom:10px}.jvb-summary-preview-note{color:#555d66;font-style:italic;margin-bottom:0}
diff --git a/build/fields/index.js b/build/fields/index.js
deleted file mode 100644
index 0f940c9..0000000
--- a/build/fields/index.js
+++ /dev/null
@@ -1 +0,0 @@
-(()=>{"use strict";var r,e={158(){const r=window.wp.blocks,e=window.wp.i18n,t=window.wp.blockEditor,i=(window.wp.components,window.ReactJSXRuntime);(0,r.registerBlockType)("jvb/fields",{edit:function({attributes:r,setAttributes:n}){const o=(0,t.useBlockProps)();return(0,i.jsx)("div",{...o,children:(0,i.jsxs)("div",{className:"jvb-summary-preview",children:[(0,i.jsx)("h3",{children:(0,e.__)("Summary","jvb")}),(0,i.jsx)("p",{className:"jvb-list-preview-note",children:(0,e.__)("This will inherit the current query to build the information from our custom meta on the front end.","jvb")})]})})},save:function(){return null}})}},t={};function i(r){var n=t[r];if(void 0!==n)return n.exports;var o=t[r]={exports:{}};return e[r](o,o.exports,i),o.exports}i.m=e,r=[],i.O=(e,t,n,o)=>{if(!t){var s=1/0;for(u=0;u<r.length;u++){for(var[t,n,o]=r[u],l=!0,a=0;a<t.length;a++)(!1&o||s>=o)&&Object.keys(i.O).every(r=>i.O[r](t[a]))?t.splice(a--,1):(l=!1,o<s&&(s=o));if(l){r.splice(u--,1);var c=n();void 0!==c&&(e=c)}}return e}o=o||0;for(var u=r.length;u>0&&r[u-1][2]>o;u--)r[u]=r[u-1];r[u]=[t,n,o]},i.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={557:0,233:0};i.O.j=e=>0===r[e];var e=(e,t)=>{var n,o,[s,l,a]=t,c=0;if(s.some(e=>0!==r[e])){for(n in l)i.o(l,n)&&(i.m[n]=l[n]);if(a)var u=a(i)}for(e&&e(t);c<s.length;c++)o=s[c],i.o(r,o)&&r[o]&&r[o][0](),r[o]=0;return i.O(u)},t=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];t.forEach(e.bind(null,0)),t.push=e.bind(null,t.push.bind(t))})();var n=i.O(void 0,[233],()=>i(158));n=i.O(n)})();
\ No newline at end of file
diff --git a/build/fields/render.php b/build/fields/render.php
deleted file mode 100644
index b5645eb..0000000
--- a/build/fields/render.php
+++ /dev/null
@@ -1,320 +0,0 @@
-<?php
-
-use JVBase\managers\Cache;
-use JVBase\meta\Meta;
-use JVBase\meta\Render;
-use JVBase\registrar\Registrar;
-
-if (!defined('ABSPATH')) {
-    exit; // Exit if accessed directly
-}
-/**
- * Summary Block Render
- *
- * @package Edmonton_Ink
- */
-
-function jvbRenderSummaryBlock(array $attributes):string
-{
-
-    // Buffer output
-    if (is_tax()) {
-        switch (get_queried_object()->taxonomy) {
-            case BASE.'shop':
-                return jvbRenderShopSummary();
-            default:
-                return jvbRenderTermSummary();
-        }
-    } elseif (is_singular()) {
-        return jvbRenderArtistSummary();
-    }
-    return '';
-}
-
-function jvbRenderArtistSummary():string
-{
-    $current = get_queried_object();
-    $cache = Cache::for('artistSummary', WEEK_IN_SECONDS);
-    $key = $current->ID;
-    $cached = $cache->get($key);
-    if ($cached !== false) {
-        return $cached;
-    }
-
-    ob_start();
-    $meta = Meta::forPost($current->ID);
-    $artist = jvbContentFromUser((int)$current->post_author);
-
-	$registrar = Registrar::getInstance($current->post_type);
-	$sections = [];
-	if ($registrar) {
-		$sections = $registrar->getSections();
-	}
-
-
-
-
-//    $handler = JVB()->getContent(str_replace(BASE,'', $current->post_type));
-    ?>
-    <nav id="artist" class="on-this-page index">
-        <label>Jump to:
-            <button type="button" aria-label="Show Index" title="Show Index" class="toggle" aria-expanded="false">
-                <?= jvbIcon('plus-square')?>
-            </button>
-        </label>
-        <ul>
-            <li><a href="#top" title="Back to Top"><?=jvbIcon('caret-circle-up')?></a></li>
-            <li><a href="#about">About</a></li>
-            <li><a href="#styles">Styles</a></li>
-            <li><a href="#contact">Contact</a></li>
-            <li><a href="#work">Work</a></li>
-        </ul>
-    </nav>
-    <header id="top">
-        <h1><small><?=(!empty($artist['city'])) ? $artist['city']['name'] :'Edmonton'?>'s Best <?= (!empty($artist['type'])) ?
-                    $artist['type']['name']:'Tattoo Artists'?>:
-            </small><?=$artist['display_name']?></h1>
-        <div>
-			<?php if (!empty($artist['shop'])) : ?>
-            <ul class="term-list shop">
-                <li>
-                    <a href="<?=$artist['shop']['url']?>" title="Learn more about <?=$artist['shop']['name']?>">
-                        <?= strtolower($artist['shop']['name'])?>
-                    </a>
-                </li>
-            </ul>
-			<?php endif; ?>
-			<?php if (!empty($artist['city'])): ?>
-            <ul class="term-list city">
-                <li>
-                    <a href="<?=$artist['city']['url']?>" title="See who else is rocking out of <?=$artist['city']['name']?>">
-                        <?= strtolower($artist['city']['name'])?>
-                    </a>
-                </li>
-            </ul>
-			<?php endif; ?>
-            <?php $styles = $meta->get('top_styles');
-            if (!empty($styles)) {
-                ?>
-                <ul class="term-list style">
-                    <?php
-                    foreach ($styles as $style) {
-                        $term = get_term((int)$style, BASE.'style');
-                        if ($term && !is_wp_error($term)) {
-                            $link = get_term_link((int)$style, BASE.'style');
-                            ?>
-                            <li>
-                                <a href="<?=$link?>" title="Learn more about <?=html_entity_decode($term->name)?>">
-                                    <?=strtolower(html_entity_decode($term->name))?>
-                                </a>
-                            </li>
-                            <?php
-                        }
-                    }
-                    ?>
-                </ul>
-                <?php
-            }
-            ?>
-        </div>
-    </header>
-    <section>
-        <details class="bio-info">
-            <summary class="row x-btw">
-                <h2>About <?= ($artist['name'] !== '') ? $artist['name'] : strtok($artist['display_name'], ' ')?></h2>
-            </summary>
-            <div class="columns stack-small">
-                <div class="column">
-                    <?= Render::renderFrom($meta, 'image_portrait'); ?>
-                </div>
-                <div class="column">
-					<?= Render::renderFrom($meta, 'short_bio'); ?>
-                </div>
-            </div>
-            <div id="styles">
-                <h3>Works In</h3>
-                <?= jvbGetTheTerms('style', $current->ID) ?>
-            </div>
-            <div class="contact">
-                <h3>Contact:</h3>
-                <?php
-                echo jvbRenderContactInfo($current->ID, $meta);
-                echo jvbRenderLinks($current->ID, $meta);
-                ?>
-            </div>
-
-            <div id="about">
-				<?= Render::renderFrom($meta, 'bio')?>
-            </div>
-        </details>
-    </section>
-    <section id="contact" class="">
-        <h2>Contact <?=$artist['name']?></h2>
-        <?php
-        echo jvbRenderContactInfo($current->ID, 'post');
-        echo jvbRenderLinks($current->ID, 'post');
-        ?>
-    </section>
-    <?php
-    $finished = ob_get_clean();
-    $cache->set($key, $finished);
-    return $finished;
-}
-
-function jvbRenderShopSummary()
-{
-    $current = get_queried_object();
-
-    $cache = Cache::for('shop_bio', WEEK_IN_SECONDS)->connect('taxonomy');
-    $key = $current->term_id;
-    $cached = $cache->get($key);
-    if ($cached !== false) {
-        return $cached;
-    }
-
-    ob_start();
-
-    $meta = Meta::forTerm($current->term_id);
-	$fields = $meta->getAll(['average_rating', 'established', 'bio','location','hours','specialties','awards','reviews']);
-    ?>
-    <nav id="shop" class="on-this-page index">
-        <label>Jump to:
-            <button type="button" aria-label="Show Index" title="Show Index" class="toggle" aria-expanded="false">
-                <?= jvbIcon('plus-square')?>
-            </button>
-        </label>
-        <ul>
-            <li><a href="#top" title="Back to Top"><?=jvbIcon('caret-circle-up')?></a></li> <?php
-            if ($fields['rating'] !== 'none') {
-                ?>
-                <li><a href="#rating">Rating</a></li>
-                <?php
-            } elseif ($fields['opened'] !== '') {
-                ?>
-                <li><a href="#opened">Opened</a></li>
-                <?php
-            } elseif ($fields['location'] !== '') {
-                ?>
-                <li><a href="#location">Location</a></li>
-                <?php
-            } elseif ($fields['about'] !== '') {
-                ?>
-                <li><a href="#about">About</a></li>
-                <?php
-            } elseif ($fields['hours'] !== '') {
-                ?>
-                <li><a href="#hours">Hours</a></li>
-                <?php
-            } elseif ($fields['specialties'] !== '') {
-                ?>
-                <li><a href="#specialties">Specialties</a></li>
-                <?php
-            } elseif ($fields['awards'] !== '') {
-                ?>
-                <li><a href="#awards">Awards</a></li>
-                <?php
-            } elseif ($fields['reviews'] !== '') {
-                ?>
-                <li><a href="#reviews">Reviews</a></li>
-                <?php
-            }
-            ?>
-            <li><a href="#contact">Contact</a></li>
-            <li><a href="#artists">Artists</a></li>
-        </ul>
-    </nav>
-    <header id="top">
-        <div class="columns stack-small">
-            <div class="column">
-                <?=jvbFormatImage($meta->get('image'))?>
-            </div>
-            <div class="column">
-                <h1>
-                    <small><?= (get_term((int)$meta->get('city'), BASE.'city')) ?
-                            get_term((int)$meta->get('city'), BASE.'city')->name :
-                            'Edmonton'?>'s Best Tattoo Shops</small>
-                    <?=$current->name?>
-                </h1>
-                <?= jvbFormatRating($current->term_id, 'term') ?>
-				<?= Render::renderFrom($meta,   'slogan'); ?>
-            </div>
-        </div>
-    </header>
-    <section>
-        <details class="bio-info">
-            <summary class="row x-btw">
-                <h2>Learn More About <?=$current->name?></h2>
-            </summary>
-            <div class="map">
-				<?= Render::renderFrom($meta, 'location'); ?>
-            </div>
-            <div class="short-bio">
-				<?= Render::renderFrom($meta, 'short_bio'); ?>
-            </div>
-
-            <div class="contact">
-                <h3>Contact:</h3>
-                <?php
-                echo jvbRenderContactInfo($current->term_id, 'term');
-                echo jvbRenderLinks($current->term_id, 'term');
-                ?>
-            </div>
-
-            <div id="about">
-				<?= Render::renderFrom($meta, 'bio')?>
-            </div>
-        </details>
-    </section>
-    <section id="contact" class="">
-        <h2>Contact </h2>
-        <?php
-        echo jvbRenderContactInfo($current->term_id, 'term');
-        echo jvbRenderLinks($current->term_id, 'term');
-        ?>
-    </section>
-    <?= jvbRenderHours($current->term_id, 'term')?>
-
-
-    <?php
-    $finished = ob_get_clean();
-    $cache->set($key, $finished);
-    return $finished;
-}
-
-
-function jvbRenderTermSummary()
-{
-    $current = get_queried_object();
-    $cache = Cache::for('term_summary', WEEK_IN_SECONDS)->connect('taxonomy');
-    $key = $current->ID;
-    $cached = $cache->get($key);
-    if ($cached !== false) {
-        return $cached;
-    }
-
-    ob_start();
-	$tax = jvbNoBase($current->taxonomy);
-    switch ($tax) {
-        case 'style':
-            $title = 'Tattoo Artists';
-            break;
-        case 'theme':
-            $title = 'Tattoos';
-            break;
-        default:
-            $title = '';
-    }
-
-    $meta = Meta::forTerm($current->ID);
-    $fields = $meta->getAll();
-
-    ?>
-    <header id="top">
-        <h1><?= get_the_archive_title() ?></h1>
-    </header>
-
-    <?php
-    $finished = ob_get_clean();
-    $cache->set($key, $finished);
-    return $finished;
-}
diff --git a/build/fields/style-index-rtl.css b/build/fields/style-index-rtl.css
deleted file mode 100644
index ea88fca..0000000
--- a/build/fields/style-index-rtl.css
+++ /dev/null
@@ -1 +0,0 @@
-details>div{margin:1rem 0}main>header:not(:has(img)){margin-top:3rem!important}header a:before{display:none!important}header+details{margin:1.5rem auto 3rem!important;max-width:var(--wide)}main{padding-top:0!important}
diff --git a/build/fields/style-index.css b/build/fields/style-index.css
deleted file mode 100644
index ea88fca..0000000
--- a/build/fields/style-index.css
+++ /dev/null
@@ -1 +0,0 @@
-details>div{margin:1rem 0}main>header:not(:has(img)){margin-top:3rem!important}header a:before{display:none!important}header+details{margin:1.5rem auto 3rem!important;max-width:var(--wide)}main{padding-top:0!important}
diff --git a/build/fields/view.asset.php b/build/fields/view.asset.php
deleted file mode 100644
index f534533..0000000
--- a/build/fields/view.asset.php
+++ /dev/null
@@ -1 +0,0 @@
-<?php return array('dependencies' => array(), 'version' => '31d6cfe0d16ae931b73c');
diff --git a/build/fields/view.js b/build/fields/view.js
deleted file mode 100644
index e69de29..0000000
--- a/build/fields/view.js
+++ /dev/null
diff --git a/build/forms/block.json b/build/forms/block.json
index e443c56..5b8d875 100644
--- a/build/forms/block.json
+++ b/build/forms/block.json
@@ -52,7 +52,7 @@
   },
   "render": "file:./render.php",
   "editorScript": "file:./index.js",
-  "editorStyle": "file:./editor.scss",
+  "editorStyle": "file:./index.scss",
   "style": "file:./style-index.css",
   "viewScript": "file:./view.js"
 }
\ No newline at end of file
diff --git a/build/forms/index-rtl.css b/build/forms/index-rtl.css
index 8b13789..bce9332 100644
--- a/build/forms/index-rtl.css
+++ b/build/forms/index-rtl.css
@@ -1 +1,4 @@
+/*!**********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/forms/editor.scss ***!
+  \**********************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/forms/index.asset.php b/build/forms/index.asset.php
index 5981665..78b4680 100644
--- a/build/forms/index.asset.php
+++ b/build/forms/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '0627d4138bd3642db1b4');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => 'b663341232d8262dddc0');
diff --git a/build/forms/index.css b/build/forms/index.css
index 8b13789..bce9332 100644
--- a/build/forms/index.css
+++ b/build/forms/index.css
@@ -1 +1,4 @@
+/*!**********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/forms/editor.scss ***!
+  \**********************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/forms/index.js b/build/forms/index.js
index 3852071..2b2b406 100644
--- a/build/forms/index.js
+++ b/build/forms/index.js
@@ -1 +1,747 @@
-(()=>{"use strict";var e,l={677(){const e=window.wp.blocks,l=window.wp.i18n,a=window.wp.blockEditor,t=window.wp.components,i=window.wp.element,s=window.ReactJSXRuntime;(0,e.registerBlockType)("jvb/forms",{edit:function({attributes:e,setAttributes:r}){const{formType:o,showLabels:b,customEmailTo:n,turnstileEnabled:d}=e,[v,c]=(0,i.useState)(!0),j=(0,a.useBlockProps)({className:"jvb-form-block "+(o?`jvb-form-block-${o}`:"")}),p="undefined"!=typeof window&&window.jvbFormsData&&window.jvbFormsData.formTypes?window.jvbFormsData.formTypes:[{label:(0,l.__)("Select a form type","jvb"),value:""},{label:(0,l.__)("No forms available","jvb"),value:"",disabled:!0}],u=(console.log(window.jvbFormsData),"undefined"!=typeof window&&window.jvbFormsData&&window.jvbFormsData.availableForms?window.jvbFormsData.availableForms:{}),m=(()=>{const e=o&&u[o]?u[o]:null;return e?{title:e.title||(0,l.__)("Form","jvb"),description:Array.isArray(e.description)?e.description.join(" "):e.description||"",button:e.submit||(0,l.__)("Submit","jvb")}:{title:(0,l.__)("Form","jvb"),description:o?(0,l.__)("Loading form configuration...","jvb"):(0,l.__)("Please select a form type in the sidebar","jvb"),button:(0,l.__)("Submit","jvb")}})();return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(a.InspectorControls,{children:[(0,s.jsxs)(t.PanelBody,{title:(0,l.__)("Form Settings","jvb"),children:[(0,s.jsx)(t.SelectControl,{label:(0,l.__)("Form Type","jvb"),value:o,options:p,onChange:e=>r({formType:e})}),(0,s.jsx)(t.ToggleControl,{label:(0,l.__)("Show Field Labels","jvb"),checked:b,onChange:e=>r({showLabels:e}),help:(0,l.__)("Toggle to show or hide field labels.","jvb")}),(0,s.jsx)(t.TextControl,{label:(0,l.__)("Custom Recipient Email","jvb"),value:n||"",onChange:e=>r({customEmailTo:e}),help:(0,l.__)("Leave empty to use the default email.","jvb"),type:"email"})]}),(0,s.jsxs)(t.PanelBody,{title:(0,l.__)("Form Preview","jvb"),initialOpen:!1,children:[(0,s.jsx)(t.ToggleControl,{label:(0,l.__)("Show Preview","jvb"),checked:v,onChange:e=>c(e)}),(0,s.jsx)("p",{className:"components-base-control__help",children:(0,l.__)("This is just a preview. The actual form will be rendered on the frontend.","jvb")})]})]}),(0,s.jsx)("div",{...j,children:v?(()=>{if(!o)return(0,s.jsx)(t.Notice,{status:"warning",isDismissible:!1,children:(0,l.__)("Please select a form type in the block settings.","jvb")});let e=[];switch(o){case"contact":e=[{id:"name",label:(0,l.__)("Name","jvb"),type:"text",required:!0},{id:"email",label:(0,l.__)("Email","jvb"),type:"email",required:!0},{id:"phone",label:(0,l.__)("Phone","jvb"),type:"tel",required:!0},{id:"instagram",label:(0,l.__)("Instagram URL","jvb"),type:"url"},{id:"contact_methods",label:(0,l.__)("Preferred Contact","jvb"),type:"checkboxes",options:[{value:"text",label:(0,l.__)("Text","jvb")},{value:"call",label:(0,l.__)("Call","jvb")},{value:"email",label:(0,l.__)("Email","jvb")},{value:"instagram",label:(0,l.__)("Instagram","jvb")}]},{id:"message",label:(0,l.__)("Your Message","jvb"),type:"textarea",required:!0}];break;case"feature_request":e=[{id:"name",label:(0,l.__)("Name","jvb"),type:"text",help:(0,l.__)("Required if you want us to follow up.","jvb")},{id:"email",label:(0,l.__)("Email","jvb"),type:"email",help:(0,l.__)("Required if you want us to follow up.","jvb")},{id:"follow_up",label:(0,l.__)("Would you like me to follow up with you?","jvb"),type:"checkbox"},{id:"target_audience",label:(0,l.__)("This Feature is For","jvb"),type:"checkboxes",options:[{value:"artists",label:(0,l.__)("Artists","jvb")},{value:"visitors",label:(0,l.__)("Site Visitors","jvb")},{value:"partners",label:(0,l.__)("Partners","jvb")},{value:"other",label:(0,l.__)("Other","jvb")}]},{id:"feature_name",label:(0,l.__)("Name your Feature","jvb"),type:"text",required:!0},{id:"message",label:(0,l.__)("Describe Your Feature","jvb"),type:"textarea",required:!0}];break;case"technical_issue":e=[{id:"name",label:(0,l.__)("Name","jvb"),type:"text"},{id:"email",label:(0,l.__)("Email","jvb"),type:"email"},{id:"follow_up",label:(0,l.__)("Would you like me to follow up with you?","jvb"),type:"checkbox"},{id:"issue_type",label:(0,l.__)("Type of Issue","jvb"),type:"checkboxes",options:[{value:"visual",label:(0,l.__)("Visual","jvb")},{value:"error",label:(0,l.__)("Error Page","jvb")},{value:"other",label:(0,l.__)("Other","jvb")}]},{id:"message",label:(0,l.__)("Please describe the issue.","jvb"),type:"textarea",required:!0}]}return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("h3",{className:"jvb-form-title",children:m.title}),(0,s.jsx)("p",{className:"jvb-form-description",children:m.description}),(0,s.jsxs)("div",{className:"jvb-form-preview",children:[e.map(e=>(0,s.jsxs)("div",{className:"jvb-form-field",children:[b&&(0,s.jsx)("label",{htmlFor:`jvb-${e.id}`,className:e.required?"required":"",children:e.label}),"text"===e.type&&(0,s.jsx)("input",{type:"text",id:`jvb-${e.id}`,placeholder:b?"":e.label,disabled:!0}),"email"===e.type&&(0,s.jsx)("input",{type:"email",id:`jvb-${e.id}`,placeholder:b?"":e.label,disabled:!0}),"tel"===e.type&&(0,s.jsx)("input",{type:"tel",id:`jvb-${e.id}`,placeholder:b?"":e.label,disabled:!0}),"url"===e.type&&(0,s.jsx)("input",{type:"url",id:`jvb-${e.id}`,placeholder:b?"":e.label,disabled:!0}),"textarea"===e.type&&(0,s.jsx)("textarea",{id:`jvb-${e.id}`,placeholder:b?"":e.label,disabled:!0,rows:"4"}),"checkbox"===e.type&&(0,s.jsxs)("div",{className:"jvb-form-checkbox",children:[(0,s.jsx)("input",{type:"checkbox",id:`jvb-${e.id}`,disabled:!0}),(0,s.jsx)("label",{htmlFor:`jvb-${e.id}`,children:e.label})]}),"checkboxes"===e.type&&e.options&&(0,s.jsx)("div",{className:"jvb-form-checkboxes",children:e.options.map(l=>(0,s.jsxs)("div",{className:"jvb-form-checkbox",children:[(0,s.jsx)("input",{type:"checkbox",id:`jvb-${e.id}-${l.value}`,disabled:!0}),(0,s.jsx)("label",{htmlFor:`jvb-${e.id}-${l.value}`,children:l.label})]},l.value))}),e.help&&(0,s.jsx)("p",{className:"jvb-form-help",children:e.help})]},e.id)),d&&(0,s.jsx)("div",{className:"jvb-form-turnstile",children:(0,s.jsx)("div",{className:"jvb-turnstile-placeholder",children:(0,s.jsx)("span",{children:(0,l.__)("Cloudflare Turnstile will appear here","jvb")})})}),(0,s.jsx)("div",{className:"jvb-form-submit",children:(0,s.jsx)("button",{type:"button",className:"jvb-form-button",children:m.button})})]})]})})():(0,s.jsxs)("div",{className:"jvb-form-placeholder",children:[(0,s.jsx)("h3",{children:m.title}),(0,s.jsx)("p",{children:(0,l.__)("Form preview is hidden. Edit settings in the sidebar.","jvb")})]})})]})},save:function(){return null}})}},a={};function t(e){var i=a[e];if(void 0!==i)return i.exports;var s=a[e]={exports:{}};return l[e](s,s.exports,t),s.exports}t.m=l,e=[],t.O=(l,a,i,s)=>{if(!a){var r=1/0;for(d=0;d<e.length;d++){for(var[a,i,s]=e[d],o=!0,b=0;b<a.length;b++)(!1&s||r>=s)&&Object.keys(t.O).every(e=>t.O[e](a[b]))?a.splice(b--,1):(o=!1,s<r&&(r=s));if(o){e.splice(d--,1);var n=i();void 0!==n&&(l=n)}}return l}s=s||0;for(var d=e.length;d>0&&e[d-1][2]>s;d--)e[d]=e[d-1];e[d]=[a,i,s]},t.o=(e,l)=>Object.prototype.hasOwnProperty.call(e,l),(()=>{var e={637:0,705:0};t.O.j=l=>0===e[l];var l=(l,a)=>{var i,s,[r,o,b]=a,n=0;if(r.some(l=>0!==e[l])){for(i in o)t.o(o,i)&&(t.m[i]=o[i]);if(b)var d=b(t)}for(l&&l(a);n<r.length;n++)s=r[n],t.o(e,s)&&e[s]&&e[s][0](),e[s]=0;return t.O(d)},a=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];a.forEach(l.bind(null,0)),a.push=l.bind(null,a.push.bind(a))})();var i=t.O(void 0,[705],()=>t(677));i=t.O(i)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/forms/edit.js"
+/*!***************************!*\
+  !*** ./src/forms/edit.js ***!
+  \***************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__);
+/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/element */ "@wordpress/element");
+/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_3__);
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./editor.scss */ "./src/forms/editor.scss");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__);
+/**
+ * edit.js
+ * WordPress dependencies
+ */
+
+
+
+
+
+/**
+ * Styles
+ */
+
+
+/**
+ * Edit function for Form Block
+ */
+
+function Edit({
+  attributes,
+  setAttributes
+}) {
+  const {
+    formType,
+    showLabels,
+    customEmailTo,
+    turnstileEnabled
+  } = attributes;
+  const [isPreviewVisible, setIsPreviewVisible] = (0,_wordpress_element__WEBPACK_IMPORTED_MODULE_3__.useState)(true);
+  const blockProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.useBlockProps)({
+    className: `jvb-form-block ${formType ? `jvb-form-block-${formType}` : ''}`
+  });
+
+  // Get form types from localized data, with fallback
+  const getFormTypes = () => {
+    if (typeof window !== 'undefined' && window.jvbFormsData && window.jvbFormsData.formTypes) {
+      return window.jvbFormsData.formTypes;
+    }
+
+    // Fallback if data isn't available
+    return [{
+      label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Select a form type', 'jvb'),
+      value: ''
+    }, {
+      label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('No forms available', 'jvb'),
+      value: '',
+      disabled: true
+    }];
+  };
+
+  // Get available forms configuration
+  const getAvailableForms = () => {
+    console.log(window.jvbFormsData);
+    if (typeof window !== 'undefined' && window.jvbFormsData && window.jvbFormsData.availableForms) {
+      return window.jvbFormsData.availableForms;
+    }
+    return {};
+  };
+  const formTypes = getFormTypes();
+  const availableForms = getAvailableForms();
+
+  // Get form configuration based on selected type
+  const getCurrentFormConfig = () => {
+    if (!formType || !availableForms[formType]) {
+      return null;
+    }
+    return availableForms[formType];
+  };
+
+  // Form labels based on the selected form type
+  const getFormLabels = () => {
+    const formConfig = getCurrentFormConfig();
+    if (formConfig) {
+      return {
+        title: formConfig.title || (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Form', 'jvb'),
+        description: Array.isArray(formConfig.description) ? formConfig.description.join(' ') : formConfig.description || '',
+        button: formConfig.submit || (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Submit', 'jvb')
+      };
+    }
+    return {
+      title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Form', 'jvb'),
+      description: formType ? (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Loading form configuration...', 'jvb') : (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Please select a form type in the sidebar', 'jvb'),
+      button: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Submit', 'jvb')
+    };
+  };
+  const formLabels = getFormLabels();
+
+  // Render a preview of the form in the editor
+  const renderFormPreview = () => {
+    if (!formType) {
+      return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.Notice, {
+        status: "warning",
+        isDismissible: false,
+        children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Please select a form type in the block settings.', 'jvb')
+      });
+    }
+    let formFields = [];
+    switch (formType) {
+      case 'contact':
+        formFields = [{
+          id: 'name',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Name', 'jvb'),
+          type: 'text',
+          required: true
+        }, {
+          id: 'email',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Email', 'jvb'),
+          type: 'email',
+          required: true
+        }, {
+          id: 'phone',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Phone', 'jvb'),
+          type: 'tel',
+          required: true
+        }, {
+          id: 'instagram',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Instagram URL', 'jvb'),
+          type: 'url'
+        }, {
+          id: 'contact_methods',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Preferred Contact', 'jvb'),
+          type: 'checkboxes',
+          options: [{
+            value: 'text',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Text', 'jvb')
+          }, {
+            value: 'call',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Call', 'jvb')
+          }, {
+            value: 'email',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Email', 'jvb')
+          }, {
+            value: 'instagram',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Instagram', 'jvb')
+          }]
+        }, {
+          id: 'message',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Your Message', 'jvb'),
+          type: 'textarea',
+          required: true
+        }];
+        break;
+      case 'feature_request':
+        formFields = [{
+          id: 'name',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Name', 'jvb'),
+          type: 'text',
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Required if you want us to follow up.', 'jvb')
+        }, {
+          id: 'email',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Email', 'jvb'),
+          type: 'email',
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Required if you want us to follow up.', 'jvb')
+        }, {
+          id: 'follow_up',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Would you like me to follow up with you?', 'jvb'),
+          type: 'checkbox'
+        }, {
+          id: 'target_audience',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('This Feature is For', 'jvb'),
+          type: 'checkboxes',
+          options: [{
+            value: 'artists',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Artists', 'jvb')
+          }, {
+            value: 'visitors',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Site Visitors', 'jvb')
+          }, {
+            value: 'partners',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Partners', 'jvb')
+          }, {
+            value: 'other',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Other', 'jvb')
+          }]
+        }, {
+          id: 'feature_name',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Name your Feature', 'jvb'),
+          type: 'text',
+          required: true
+        }, {
+          id: 'message',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Describe Your Feature', 'jvb'),
+          type: 'textarea',
+          required: true
+        }];
+        break;
+      case 'technical_issue':
+        formFields = [{
+          id: 'name',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Name', 'jvb'),
+          type: 'text'
+        }, {
+          id: 'email',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Email', 'jvb'),
+          type: 'email'
+        }, {
+          id: 'follow_up',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Would you like me to follow up with you?', 'jvb'),
+          type: 'checkbox'
+        }, {
+          id: 'issue_type',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Type of Issue', 'jvb'),
+          type: 'checkboxes',
+          options: [{
+            value: 'visual',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Visual', 'jvb')
+          }, {
+            value: 'error',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Error Page', 'jvb')
+          }, {
+            value: 'other',
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Other', 'jvb')
+          }]
+        }, {
+          id: 'message',
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Please describe the issue.', 'jvb'),
+          type: 'textarea',
+          required: true
+        }];
+        break;
+    }
+    return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.Fragment, {
+      children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("h3", {
+        className: "jvb-form-title",
+        children: formLabels.title
+      }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+        className: "jvb-form-description",
+        children: formLabels.description
+      }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+        className: "jvb-form-preview",
+        children: [formFields.map(field => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+          className: "jvb-form-field",
+          children: [showLabels && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("label", {
+            htmlFor: `jvb-${field.id}`,
+            className: field.required ? 'required' : '',
+            children: field.label
+          }), field.type === 'text' && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("input", {
+            type: "text",
+            id: `jvb-${field.id}`,
+            placeholder: showLabels ? '' : field.label,
+            disabled: true
+          }), field.type === 'email' && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("input", {
+            type: "email",
+            id: `jvb-${field.id}`,
+            placeholder: showLabels ? '' : field.label,
+            disabled: true
+          }), field.type === 'tel' && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("input", {
+            type: "tel",
+            id: `jvb-${field.id}`,
+            placeholder: showLabels ? '' : field.label,
+            disabled: true
+          }), field.type === 'url' && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("input", {
+            type: "url",
+            id: `jvb-${field.id}`,
+            placeholder: showLabels ? '' : field.label,
+            disabled: true
+          }), field.type === 'textarea' && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("textarea", {
+            id: `jvb-${field.id}`,
+            placeholder: showLabels ? '' : field.label,
+            disabled: true,
+            rows: "4"
+          }), field.type === 'checkbox' && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+            className: "jvb-form-checkbox",
+            children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("input", {
+              type: "checkbox",
+              id: `jvb-${field.id}`,
+              disabled: true
+            }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("label", {
+              htmlFor: `jvb-${field.id}`,
+              children: field.label
+            })]
+          }), field.type === 'checkboxes' && field.options && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+            className: "jvb-form-checkboxes",
+            children: field.options.map(option => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+              className: "jvb-form-checkbox",
+              children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("input", {
+                type: "checkbox",
+                id: `jvb-${field.id}-${option.value}`,
+                disabled: true
+              }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("label", {
+                htmlFor: `jvb-${field.id}-${option.value}`,
+                children: option.label
+              })]
+            }, option.value))
+          }), field.help && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+            className: "jvb-form-help",
+            children: field.help
+          })]
+        }, field.id)), turnstileEnabled && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+          className: "jvb-form-turnstile",
+          children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+            className: "jvb-turnstile-placeholder",
+            children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("span", {
+              children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Cloudflare Turnstile will appear here', 'jvb')
+            })
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+          className: "jvb-form-submit",
+          children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("button", {
+            type: "button",
+            className: "jvb-form-button",
+            children: formLabels.button
+          })
+        })]
+      })]
+    });
+  };
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.Fragment, {
+    children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.InspectorControls, {
+      children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.PanelBody, {
+        title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Form Settings', 'jvb'),
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.SelectControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Form Type', 'jvb'),
+          value: formType,
+          options: formTypes,
+          onChange: value => setAttributes({
+            formType: value
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Show Field Labels', 'jvb'),
+          checked: showLabels,
+          onChange: value => setAttributes({
+            showLabels: value
+          }),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Toggle to show or hide field labels.', 'jvb')
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.TextControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Custom Recipient Email', 'jvb'),
+          value: customEmailTo || '',
+          onChange: value => setAttributes({
+            customEmailTo: value
+          }),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Leave empty to use the default email.', 'jvb'),
+          type: "email"
+        })]
+      }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.PanelBody, {
+        title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Form Preview', 'jvb'),
+        initialOpen: false,
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Show Preview', 'jvb'),
+          checked: isPreviewVisible,
+          onChange: value => setIsPreviewVisible(value)
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+          className: "components-base-control__help",
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('This is just a preview. The actual form will be rendered on the frontend.', 'jvb')
+        })]
+      })]
+    }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+      ...blockProps,
+      children: isPreviewVisible ? renderFormPreview() : /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsxs)("div", {
+        className: "jvb-form-placeholder",
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("h3", {
+          children: formLabels.title
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("p", {
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Form preview is hidden. Edit settings in the sidebar.', 'jvb')
+        })]
+      })
+    })]
+  });
+}
+
+/***/ },
+
+/***/ "./src/forms/index.js"
+/*!****************************!*\
+  !*** ./src/forms/index.js ***!
+  \****************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./style.scss */ "./src/forms/style.scss");
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./edit */ "./src/forms/edit.js");
+/* harmony import */ var _save__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./save */ "./src/forms/save.js");
+/* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./block.json */ "./src/forms/block.json");
+//index.js
+/**
+ * Registers a new block provided a unique name and an object defining its behavior.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+
+
+/**
+ * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
+ * All files containing `style` keyword are bundled together. The code used
+ * gets applied both to the front of your site and to the editor.
+ *
+ * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
+ */
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+/**
+ * Every block starts by registering a new block type definition.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)(_block_json__WEBPACK_IMPORTED_MODULE_4__.name, {
+  /**
+   * @see ./edit.js
+   */
+  edit: _edit__WEBPACK_IMPORTED_MODULE_2__["default"],
+  /**
+   * @see ./save.js
+   */
+  save: _save__WEBPACK_IMPORTED_MODULE_3__["default"]
+});
+
+/***/ },
+
+/***/ "./src/forms/save.js"
+/*!***************************!*\
+  !*** ./src/forms/save.js ***!
+  \***************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ save)
+/* harmony export */ });
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__);
+//save.js
+/**
+ * React hook that is used to mark the block wrapper element.
+ * It provides all the necessary props like the class name.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
+ */
+
+
+/**
+ * The save function defines the way in which the different attributes should
+ * be combined into the final markup, which is then serialized by the block
+ * editor into `post_content`.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#save
+ *
+ * @return {WPElement} Element to render.
+ */
+function save() {
+  // This is a dynamic block that is rendered on the server side
+  // Return null to let WordPress handle the saving and rendering
+  return null;
+}
+
+/***/ },
+
+/***/ "./src/forms/editor.scss"
+/*!*******************************!*\
+  !*** ./src/forms/editor.scss ***!
+  \*******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "./src/forms/style.scss"
+/*!******************************!*\
+  !*** ./src/forms/style.scss ***!
+  \******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/components"
+/*!************************************!*\
+  !*** external ["wp","components"] ***!
+  \************************************/
+(module) {
+
+module.exports = window["wp"]["components"];
+
+/***/ },
+
+/***/ "@wordpress/element"
+/*!*********************************!*\
+  !*** external ["wp","element"] ***!
+  \*********************************/
+(module) {
+
+module.exports = window["wp"]["element"];
+
+/***/ },
+
+/***/ "@wordpress/i18n"
+/*!******************************!*\
+  !*** external ["wp","i18n"] ***!
+  \******************************/
+(module) {
+
+module.exports = window["wp"]["i18n"];
+
+/***/ },
+
+/***/ "./src/forms/block.json"
+/*!******************************!*\
+  !*** ./src/forms/block.json ***!
+  \******************************/
+(module) {
+
+module.exports = /*#__PURE__*/JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/forms","title":"Contact Forms","category":"jvb","icon":"align-center","description":"Our custom contact forms","keywords":["form","forms","contact"],"version":"1.0.0","textdomain":"jvb","attributes":{"formType":{"type":"string","default":""},"showLabels":{"type":"boolean","default":true},"customEmailTo":{"type":"string","default":""}},"supports":{"html":false,"align":["wide","full"]},"selectors":{"root":".jvb-form-block"},"styles":[{"name":"default","label":"Default","isDefault":true}],"example":{"attributes":{"formType":"contact","showLabels":true}},"render":"file:./render.php","editorScript":"file:./index.js","editorStyle":"file:./index.scss","style":"file:./style-index.css","viewScript":"file:./view.js"}');
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"forms/index": 0,
+/******/ 			"forms/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["forms/style-index"], () => (__webpack_require__("./src/forms/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/forms/index.js.map b/build/forms/index.js.map
new file mode 100644
index 0000000..ad39766
--- /dev/null
+++ b/build/forms/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"forms/index.js","mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACqC;AACsC;AAO5C;AAC0B;;AAEzD;AACA;AACA;AACuB;;AAEvB;AACA;AACA;AAFA;AAGe,SAASgB,IAAIA,CAAC;EAAEC,UAAU;EAAEC;AAAc,CAAC,EAAE;EACxD,MAAM;IACFC,QAAQ;IACRC,UAAU;IACVC,aAAa;IACbC;EACJ,CAAC,GAAGL,UAAU;EAEd,MAAM,CAACM,gBAAgB,EAAEC,mBAAmB,CAAC,GAAGhB,4DAAQ,CAAC,IAAI,CAAC;EAE9D,MAAMiB,UAAU,GAAGxB,sEAAa,CAAC;IAC7ByB,SAAS,EAAE,kBAAkBP,QAAQ,GAAG,kBAAkBA,QAAQ,EAAE,GAAG,EAAE;EAC7E,CAAC,CAAC;;EAEL;EACA,MAAMQ,YAAY,GAAGA,CAAA,KAAM;IAC1B,IAAI,OAAOC,MAAM,KAAK,WAAW,IAAIA,MAAM,CAACC,YAAY,IAAID,MAAM,CAACC,YAAY,CAACC,SAAS,EAAE;MAC1F,OAAOF,MAAM,CAACC,YAAY,CAACC,SAAS;IACrC;;IAEA;IACA,OAAO,CACN;MAAEC,KAAK,EAAE/B,mDAAE,CAAC,oBAAoB,EAAE,KAAK,CAAC;MAAEgC,KAAK,EAAE;IAAG,CAAC,EACrD;MAAED,KAAK,EAAE/B,mDAAE,CAAC,oBAAoB,EAAE,KAAK,CAAC;MAAEgC,KAAK,EAAE,EAAE;MAAEC,QAAQ,EAAE;IAAK,CAAC,CACrE;EACF,CAAC;;EAED;EACA,MAAMC,iBAAiB,GAAGA,CAAA,KAAM;IAC/BC,OAAO,CAACC,GAAG,CAACR,MAAM,CAACC,YAAY,CAAC;IAChC,IAAI,OAAOD,MAAM,KAAK,WAAW,IAAIA,MAAM,CAACC,YAAY,IAAID,MAAM,CAACC,YAAY,CAACQ,cAAc,EAAE;MAC/F,OAAOT,MAAM,CAACC,YAAY,CAACQ,cAAc;IAC1C;IACA,OAAO,CAAC,CAAC;EACV,CAAC;EAED,MAAMP,SAAS,GAAGH,YAAY,CAAC,CAAC;EAChC,MAAMU,cAAc,GAAGH,iBAAiB,CAAC,CAAC;;EAE1C;EACA,MAAMI,oBAAoB,GAAGA,CAAA,KAAM;IAClC,IAAI,CAACnB,QAAQ,IAAI,CAACkB,cAAc,CAAClB,QAAQ,CAAC,EAAE;MAC3C,OAAO,IAAI;IACZ;IACA,OAAOkB,cAAc,CAAClB,QAAQ,CAAC;EAChC,CAAC;;EAED;EACA,MAAMoB,aAAa,GAAGA,CAAA,KAAM;IAC3B,MAAMC,UAAU,GAAGF,oBAAoB,CAAC,CAAC;IAEzC,IAAIE,UAAU,EAAE;MACf,OAAO;QACNC,KAAK,EAAED,UAAU,CAACC,KAAK,IAAIzC,mDAAE,CAAC,MAAM,EAAE,KAAK,CAAC;QAC5C0C,WAAW,EAAEC,KAAK,CAACC,OAAO,CAACJ,UAAU,CAACE,WAAW,CAAC,GAC/CF,UAAU,CAACE,WAAW,CAACG,IAAI,CAAC,GAAG,CAAC,GAC/BL,UAAU,CAACE,WAAW,IAAI,EAAG;QACjCI,MAAM,EAAEN,UAAU,CAACO,MAAM,IAAI/C,mDAAE,CAAC,QAAQ,EAAE,KAAK;MAChD,CAAC;IACF;IAEA,OAAO;MACNyC,KAAK,EAAEzC,mDAAE,CAAC,MAAM,EAAE,KAAK,CAAC;MACxB0C,WAAW,EAAEvB,QAAQ,GAAGnB,mDAAE,CAAC,+BAA+B,EAAE,KAAK,CAAC,GAAGA,mDAAE,CAAC,0CAA0C,EAAE,KAAK,CAAC;MAC1H8C,MAAM,EAAE9C,mDAAE,CAAC,QAAQ,EAAE,KAAK;IAC3B,CAAC;EACF,CAAC;EAED,MAAMgD,UAAU,GAAGT,aAAa,CAAC,CAAC;;EAE/B;EACA,MAAMU,iBAAiB,GAAGA,CAAA,KAAM;IAC5B,IAAI,CAAC9B,QAAQ,EAAE;MACX,oBACIR,sDAAA,CAACJ,yDAAM;QAAC2C,MAAM,EAAC,SAAS;QAACC,aAAa,EAAE,KAAM;QAAAC,QAAA,EACzCpD,mDAAE,CAAC,kDAAkD,EAAE,KAAK;MAAC,CAC1D,CAAC;IAEjB;IAEA,IAAIqD,UAAU,GAAG,EAAE;IAEnB,QAAQlC,QAAQ;MACZ,KAAK,SAAS;QACVkC,UAAU,GAAG,CACT;UAAEC,EAAE,EAAE,MAAM;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,MAAM,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,MAAM;UAAEC,QAAQ,EAAE;QAAK,CAAC,EACtE;UAAEF,EAAE,EAAE,OAAO;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,OAAO,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,OAAO;UAAEC,QAAQ,EAAE;QAAK,CAAC,EACzE;UAAEF,EAAE,EAAE,OAAO;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,OAAO,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,KAAK;UAAEC,QAAQ,EAAE;QAAK,CAAC,EACvE;UAAEF,EAAE,EAAE,WAAW;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,eAAe,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE;QAAM,CAAC,EACnE;UAAED,EAAE,EAAE,iBAAiB;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,mBAAmB,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,YAAY;UAC9EE,OAAO,EAAE,CACL;YAAEzB,KAAK,EAAE,MAAM;YAAED,KAAK,EAAE/B,mDAAE,CAAC,MAAM,EAAE,KAAK;UAAE,CAAC,EAC3C;YAAEgC,KAAK,EAAE,MAAM;YAAED,KAAK,EAAE/B,mDAAE,CAAC,MAAM,EAAE,KAAK;UAAE,CAAC,EAC3C;YAAEgC,KAAK,EAAE,OAAO;YAAED,KAAK,EAAE/B,mDAAE,CAAC,OAAO,EAAE,KAAK;UAAE,CAAC,EAC7C;YAAEgC,KAAK,EAAE,WAAW;YAAED,KAAK,EAAE/B,mDAAE,CAAC,WAAW,EAAE,KAAK;UAAE,CAAC;QAE7D,CAAC,EACD;UAAEsD,EAAE,EAAE,SAAS;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,cAAc,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,UAAU;UAAEC,QAAQ,EAAE;QAAK,CAAC,CACxF;QACD;MAEJ,KAAK,iBAAiB;QAClBH,UAAU,GAAG,CACT;UAAEC,EAAE,EAAE,MAAM;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,MAAM,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,MAAM;UAAEG,IAAI,EAAE1D,mDAAE,CAAC,uCAAuC,EAAE,KAAK;QAAE,CAAC,EAChH;UAAEsD,EAAE,EAAE,OAAO;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,OAAO,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,OAAO;UAAEG,IAAI,EAAE1D,mDAAE,CAAC,uCAAuC,EAAE,KAAK;QAAE,CAAC,EACnH;UAAEsD,EAAE,EAAE,WAAW;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,0CAA0C,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE;QAAW,CAAC,EACnG;UAAED,EAAE,EAAE,iBAAiB;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,qBAAqB,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,YAAY;UAChFE,OAAO,EAAE,CACL;YAAEzB,KAAK,EAAE,SAAS;YAAED,KAAK,EAAE/B,mDAAE,CAAC,SAAS,EAAE,KAAK;UAAE,CAAC,EACjD;YAAEgC,KAAK,EAAE,UAAU;YAAED,KAAK,EAAE/B,mDAAE,CAAC,eAAe,EAAE,KAAK;UAAE,CAAC,EACxD;YAAEgC,KAAK,EAAE,UAAU;YAAED,KAAK,EAAE/B,mDAAE,CAAC,UAAU,EAAE,KAAK;UAAE,CAAC,EACnD;YAAEgC,KAAK,EAAE,OAAO;YAAED,KAAK,EAAE/B,mDAAE,CAAC,OAAO,EAAE,KAAK;UAAE,CAAC;QAErD,CAAC,EACD;UAAEsD,EAAE,EAAE,cAAc;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,mBAAmB,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,MAAM;UAAEC,QAAQ,EAAE;QAAK,CAAC,EAC3F;UAAEF,EAAE,EAAE,SAAS;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,uBAAuB,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,UAAU;UAAEC,QAAQ,EAAE;QAAK,CAAC,CACjG;QACD;MAEJ,KAAK,iBAAiB;QAClBH,UAAU,GAAG,CACT;UAAEC,EAAE,EAAE,MAAM;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,MAAM,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE;QAAO,CAAC,EACtD;UAAED,EAAE,EAAE,OAAO;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,OAAO,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE;QAAQ,CAAC,EACzD;UAAED,EAAE,EAAE,WAAW;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,0CAA0C,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE;QAAW,CAAC,EACnG;UAAED,EAAE,EAAE,YAAY;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,eAAe,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,YAAY;UACrEE,OAAO,EAAE,CACL;YAAEzB,KAAK,EAAE,QAAQ;YAAED,KAAK,EAAE/B,mDAAE,CAAC,QAAQ,EAAE,KAAK;UAAE,CAAC,EAC/C;YAAEgC,KAAK,EAAE,OAAO;YAAED,KAAK,EAAE/B,mDAAE,CAAC,YAAY,EAAE,KAAK;UAAE,CAAC,EAClD;YAAEgC,KAAK,EAAE,OAAO;YAAED,KAAK,EAAE/B,mDAAE,CAAC,OAAO,EAAE,KAAK;UAAE,CAAC;QAErD,CAAC,EACD;UAAEsD,EAAE,EAAE,SAAS;UAAEvB,KAAK,EAAE/B,mDAAE,CAAC,4BAA4B,EAAE,KAAK,CAAC;UAAEuD,IAAI,EAAE,UAAU;UAAEC,QAAQ,EAAE;QAAK,CAAC,CACtG;QACD;IACR;IAEA,oBACI3C,uDAAA,CAAAE,uDAAA;MAAAqC,QAAA,gBACIzC,sDAAA;QAAIe,SAAS,EAAC,gBAAgB;QAAA0B,QAAA,EAAEJ,UAAU,CAACP;MAAK,CAAK,CAAC,eACtD9B,sDAAA;QAAGe,SAAS,EAAC,sBAAsB;QAAA0B,QAAA,EAAEJ,UAAU,CAACN;MAAW,CAAI,CAAC,eAEhE7B,uDAAA;QAAKa,SAAS,EAAC,kBAAkB;QAAA0B,QAAA,GAC5BC,UAAU,CAACM,GAAG,CAAEC,KAAK,iBAClB/C,uDAAA;UAAoBa,SAAS,EAAC,gBAAgB;UAAA0B,QAAA,GACzChC,UAAU,iBACPT,sDAAA;YAAOkD,OAAO,EAAE,OAAOD,KAAK,CAACN,EAAE,EAAG;YAAC5B,SAAS,EAAEkC,KAAK,CAACJ,QAAQ,GAAG,UAAU,GAAG,EAAG;YAAAJ,QAAA,EAC1EQ,KAAK,CAAC7B;UAAK,CACT,CACV,EAEA6B,KAAK,CAACL,IAAI,KAAK,MAAM,iBAClB5C,sDAAA;YACI4C,IAAI,EAAC,MAAM;YACXD,EAAE,EAAE,OAAOM,KAAK,CAACN,EAAE,EAAG;YACtBQ,WAAW,EAAE1C,UAAU,GAAG,EAAE,GAAGwC,KAAK,CAAC7B,KAAM;YAC3CE,QAAQ;UAAA,CACX,CACJ,EAEA2B,KAAK,CAACL,IAAI,KAAK,OAAO,iBACnB5C,sDAAA;YACI4C,IAAI,EAAC,OAAO;YACZD,EAAE,EAAE,OAAOM,KAAK,CAACN,EAAE,EAAG;YACtBQ,WAAW,EAAE1C,UAAU,GAAG,EAAE,GAAGwC,KAAK,CAAC7B,KAAM;YAC3CE,QAAQ;UAAA,CACX,CACJ,EAEA2B,KAAK,CAACL,IAAI,KAAK,KAAK,iBACjB5C,sDAAA;YACI4C,IAAI,EAAC,KAAK;YACVD,EAAE,EAAE,OAAOM,KAAK,CAACN,EAAE,EAAG;YACtBQ,WAAW,EAAE1C,UAAU,GAAG,EAAE,GAAGwC,KAAK,CAAC7B,KAAM;YAC3CE,QAAQ;UAAA,CACX,CACJ,EAEA2B,KAAK,CAACL,IAAI,KAAK,KAAK,iBACjB5C,sDAAA;YACI4C,IAAI,EAAC,KAAK;YACVD,EAAE,EAAE,OAAOM,KAAK,CAACN,EAAE,EAAG;YACtBQ,WAAW,EAAE1C,UAAU,GAAG,EAAE,GAAGwC,KAAK,CAAC7B,KAAM;YAC3CE,QAAQ;UAAA,CACX,CACJ,EAEA2B,KAAK,CAACL,IAAI,KAAK,UAAU,iBACtB5C,sDAAA;YACI2C,EAAE,EAAE,OAAOM,KAAK,CAACN,EAAE,EAAG;YACtBQ,WAAW,EAAE1C,UAAU,GAAG,EAAE,GAAGwC,KAAK,CAAC7B,KAAM;YAC3CE,QAAQ;YACR8B,IAAI,EAAC;UAAG,CACD,CACd,EAEAH,KAAK,CAACL,IAAI,KAAK,UAAU,iBACtB1C,uDAAA;YAAKa,SAAS,EAAC,mBAAmB;YAAA0B,QAAA,gBAC9BzC,sDAAA;cACI4C,IAAI,EAAC,UAAU;cACfD,EAAE,EAAE,OAAOM,KAAK,CAACN,EAAE,EAAG;cACtBrB,QAAQ;YAAA,CACX,CAAC,eACFtB,sDAAA;cAAOkD,OAAO,EAAE,OAAOD,KAAK,CAACN,EAAE,EAAG;cAAAF,QAAA,EAAEQ,KAAK,CAAC7B;YAAK,CAAQ,CAAC;UAAA,CACvD,CACR,EAEA6B,KAAK,CAACL,IAAI,KAAK,YAAY,IAAIK,KAAK,CAACH,OAAO,iBACzC9C,sDAAA;YAAKe,SAAS,EAAC,qBAAqB;YAAA0B,QAAA,EAC/BQ,KAAK,CAACH,OAAO,CAACE,GAAG,CAAEK,MAAM,iBACtBnD,uDAAA;cAAwBa,SAAS,EAAC,mBAAmB;cAAA0B,QAAA,gBACjDzC,sDAAA;gBACI4C,IAAI,EAAC,UAAU;gBACfD,EAAE,EAAE,OAAOM,KAAK,CAACN,EAAE,IAAIU,MAAM,CAAChC,KAAK,EAAG;gBACtCC,QAAQ;cAAA,CACX,CAAC,eACFtB,sDAAA;gBAAOkD,OAAO,EAAE,OAAOD,KAAK,CAACN,EAAE,IAAIU,MAAM,CAAChC,KAAK,EAAG;gBAAAoB,QAAA,EAAEY,MAAM,CAACjC;cAAK,CAAQ,CAAC;YAAA,GANnEiC,MAAM,CAAChC,KAOZ,CACR;UAAC,CACD,CACR,EAEA4B,KAAK,CAACF,IAAI,iBACP/C,sDAAA;YAAGe,SAAS,EAAC,eAAe;YAAA0B,QAAA,EAAEQ,KAAK,CAACF;UAAI,CAAI,CAC/C;QAAA,GAhFKE,KAAK,CAACN,EAiFX,CACR,CAAC,EAEDhC,gBAAgB,iBACbX,sDAAA;UAAKe,SAAS,EAAC,oBAAoB;UAAA0B,QAAA,eAC/BzC,sDAAA;YAAKe,SAAS,EAAC,2BAA2B;YAAA0B,QAAA,eACtCzC,sDAAA;cAAAyC,QAAA,EAAOpD,mDAAE,CAAC,uCAAuC,EAAE,KAAK;YAAC,CAAO;UAAC,CAChE;QAAC,CACL,CACR,eAEDW,sDAAA;UAAKe,SAAS,EAAC,iBAAiB;UAAA0B,QAAA,eAC5BzC,sDAAA;YAAQ4C,IAAI,EAAC,QAAQ;YAAC7B,SAAS,EAAC,iBAAiB;YAAA0B,QAAA,EAAEJ,UAAU,CAACF;UAAM,CAAS;QAAC,CAC7E,CAAC;MAAA,CACL,CAAC;IAAA,CACR,CAAC;EAEX,CAAC;EAED,oBACIjC,uDAAA,CAAAE,uDAAA;IAAAqC,QAAA,gBACIvC,uDAAA,CAACX,sEAAiB;MAAAkD,QAAA,gBACdvC,uDAAA,CAACV,4DAAS;QAACsC,KAAK,EAAEzC,mDAAE,CAAC,eAAe,EAAE,KAAK,CAAE;QAAAoD,QAAA,gBACzCzC,sDAAA,CAACP,gEAAa;UACV2B,KAAK,EAAE/B,mDAAE,CAAC,WAAW,EAAE,KAAK,CAAE;UAC9BgC,KAAK,EAAEb,QAAS;UAChBsC,OAAO,EAAE3B,SAAU;UACnBmC,QAAQ,EAAGjC,KAAK,IAAKd,aAAa,CAAC;YAAEC,QAAQ,EAAEa;UAAM,CAAC;QAAE,CAC3D,CAAC,eAEFrB,sDAAA,CAACN,gEAAa;UACV0B,KAAK,EAAE/B,mDAAE,CAAC,mBAAmB,EAAE,KAAK,CAAE;UACtCkE,OAAO,EAAE9C,UAAW;UACpB6C,QAAQ,EAAGjC,KAAK,IAAKd,aAAa,CAAC;YAAEE,UAAU,EAAEY;UAAM,CAAC,CAAE;UAC1D0B,IAAI,EAAE1D,mDAAE,CAAC,sCAAsC,EAAE,KAAK;QAAE,CAC3D,CAAC,eAEFW,sDAAA,CAACL,8DAAW;UACRyB,KAAK,EAAE/B,mDAAE,CAAC,wBAAwB,EAAE,KAAK,CAAE;UAC3CgC,KAAK,EAAEX,aAAa,IAAI,EAAG;UAC3B4C,QAAQ,EAAGjC,KAAK,IAAKd,aAAa,CAAC;YAAEG,aAAa,EAAEW;UAAM,CAAC,CAAE;UAC7D0B,IAAI,EAAE1D,mDAAE,CAAC,uCAAuC,EAAE,KAAK,CAAE;UACzDuD,IAAI,EAAC;QAAO,CACf,CAAC;MAAA,CACK,CAAC,eAEZ1C,uDAAA,CAACV,4DAAS;QAACsC,KAAK,EAAEzC,mDAAE,CAAC,cAAc,EAAE,KAAK,CAAE;QAACmE,WAAW,EAAE,KAAM;QAAAf,QAAA,gBAC5DzC,sDAAA,CAACN,gEAAa;UACV0B,KAAK,EAAE/B,mDAAE,CAAC,cAAc,EAAE,KAAK,CAAE;UACjCkE,OAAO,EAAE3C,gBAAiB;UAC1B0C,QAAQ,EAAGjC,KAAK,IAAKR,mBAAmB,CAACQ,KAAK;QAAE,CACnD,CAAC,eAEFrB,sDAAA;UAAGe,SAAS,EAAC,+BAA+B;UAAA0B,QAAA,EACvCpD,mDAAE,CAAC,2EAA2E,EAAE,KAAK;QAAC,CACxF,CAAC;MAAA,CACG,CAAC;IAAA,CACG,CAAC,eAEpBW,sDAAA;MAAA,GAASc,UAAU;MAAA2B,QAAA,EACd7B,gBAAgB,GACb0B,iBAAiB,CAAC,CAAC,gBAEnBpC,uDAAA;QAAKa,SAAS,EAAC,sBAAsB;QAAA0B,QAAA,gBACjCzC,sDAAA;UAAAyC,QAAA,EAAKJ,UAAU,CAACP;QAAK,CAAK,CAAC,eAC3B9B,sDAAA;UAAAyC,QAAA,EAAIpD,mDAAE,CAAC,uDAAuD,EAAE,KAAK;QAAC,CAAI,CAAC;MAAA,CAC1E;IACR,CACA,CAAC;EAAA,CACR,CAAC;AAEX,C;;;;;;;;;;;;;;;;;AC9TA;AACA;AACA;AACA;AACA;AACA;AACsD;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA;AACsB;;AAEtB;AACA;AACA;AAC0B;AACA;AACU;;AAEpC;AACA;AACA;AACA;AACA;AACAoE,oEAAiB,CAAEE,6CAAa,EAAE;EAC9B;AACJ;AACA;EACIE,IAAI,EAAExD,6CAAI;EAEV;AACJ;AACA;EACIqD,IAAIA,+CAAAA;AACR,CAAE,CAAC,C;;;;;;;;;;;;;;;;ACvCH;AACA;AACA;AACA;AACA;AACA;AACA;AACwD;;AAExD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACe,SAASA,IAAIA,CAAA,EAAG;EAC3B;EACA;EACA,OAAO,IAAI;AACf,C;;;;;;;;;;;ACtBA;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA,2C;;;;;;;;;;ACAA,6C;;;;;;;;;;ACAA,wC;;;;;;;;;;ACAA,4C;;;;;;;;;;ACAA,yC;;;;;;;;;;ACAA,sC;;;;;;;;;;;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WC/BA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G;;;;;UEjDA;UACA;UACA;UACA;UACA","sources":["webpack://jvb/./src/forms/edit.js","webpack://jvb/./src/forms/index.js","webpack://jvb/./src/forms/save.js","webpack://jvb/./src/forms/editor.scss","webpack://jvb/./src/forms/style.scss","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"components\"]","webpack://jvb/external window [\"wp\",\"element\"]","webpack://jvb/external window [\"wp\",\"i18n\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["/**\r\n * edit.js\r\n * WordPress dependencies\r\n */\r\nimport { __ } from '@wordpress/i18n';\r\nimport { useBlockProps, InspectorControls } from '@wordpress/block-editor';\r\nimport {\r\n    PanelBody,\r\n    SelectControl,\r\n    ToggleControl,\r\n    TextControl,\r\n    Notice\r\n} from '@wordpress/components';\r\nimport { useState, useEffect } from '@wordpress/element';\r\n\r\n/**\r\n * Styles\r\n */\r\nimport './editor.scss';\r\n\r\n/**\r\n * Edit function for Form Block\r\n */\r\nexport default function Edit({ attributes, setAttributes }) {\r\n    const {\r\n        formType,\r\n        showLabels,\r\n        customEmailTo,\r\n        turnstileEnabled\r\n    } = attributes;\r\n\r\n    const [isPreviewVisible, setIsPreviewVisible] = useState(true);\r\n\r\n    const blockProps = useBlockProps({\r\n        className: `jvb-form-block ${formType ? `jvb-form-block-${formType}` : ''}`\r\n    });\r\n\r\n\t// Get form types from localized data, with fallback\r\n\tconst getFormTypes = () => {\r\n\t\tif (typeof window !== 'undefined' && window.jvbFormsData && window.jvbFormsData.formTypes) {\r\n\t\t\treturn window.jvbFormsData.formTypes;\r\n\t\t}\r\n\r\n\t\t// Fallback if data isn't available\r\n\t\treturn [\r\n\t\t\t{ label: __('Select a form type', 'jvb'), value: '' },\r\n\t\t\t{ label: __('No forms available', 'jvb'), value: '', disabled: true }\r\n\t\t];\r\n\t};\r\n\r\n\t// Get available forms configuration\r\n\tconst getAvailableForms = () => {\r\n\t\tconsole.log(window.jvbFormsData);\r\n\t\tif (typeof window !== 'undefined' && window.jvbFormsData && window.jvbFormsData.availableForms) {\r\n\t\t\treturn window.jvbFormsData.availableForms;\r\n\t\t}\r\n\t\treturn {};\r\n\t};\r\n\r\n\tconst formTypes = getFormTypes();\r\n\tconst availableForms = getAvailableForms();\r\n\r\n\t// Get form configuration based on selected type\r\n\tconst getCurrentFormConfig = () => {\r\n\t\tif (!formType || !availableForms[formType]) {\r\n\t\t\treturn null;\r\n\t\t}\r\n\t\treturn availableForms[formType];\r\n\t};\r\n\r\n\t// Form labels based on the selected form type\r\n\tconst getFormLabels = () => {\r\n\t\tconst formConfig = getCurrentFormConfig();\r\n\r\n\t\tif (formConfig) {\r\n\t\t\treturn {\r\n\t\t\t\ttitle: formConfig.title || __('Form', 'jvb'),\r\n\t\t\t\tdescription: Array.isArray(formConfig.description)\r\n\t\t\t\t\t? formConfig.description.join(' ')\r\n\t\t\t\t\t: (formConfig.description || ''),\r\n\t\t\t\tbutton: formConfig.submit || __('Submit', 'jvb')\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\ttitle: __('Form', 'jvb'),\r\n\t\t\tdescription: formType ? __('Loading form configuration...', 'jvb') : __('Please select a form type in the sidebar', 'jvb'),\r\n\t\t\tbutton: __('Submit', 'jvb')\r\n\t\t};\r\n\t};\r\n\r\n\tconst formLabels = getFormLabels();\r\n\r\n    // Render a preview of the form in the editor\r\n    const renderFormPreview = () => {\r\n        if (!formType) {\r\n            return (\r\n                <Notice status=\"warning\" isDismissible={false}>\r\n                    {__('Please select a form type in the block settings.', 'jvb')}\r\n                </Notice>\r\n            );\r\n        }\r\n\r\n        let formFields = [];\r\n\r\n        switch (formType) {\r\n            case 'contact':\r\n                formFields = [\r\n                    { id: 'name', label: __('Name', 'jvb'), type: 'text', required: true },\r\n                    { id: 'email', label: __('Email', 'jvb'), type: 'email', required: true },\r\n                    { id: 'phone', label: __('Phone', 'jvb'), type: 'tel', required: true },\r\n                    { id: 'instagram', label: __('Instagram URL', 'jvb'), type: 'url' },\r\n                    { id: 'contact_methods', label: __('Preferred Contact', 'jvb'), type: 'checkboxes',\r\n                        options: [\r\n                            { value: 'text', label: __('Text', 'jvb') },\r\n                            { value: 'call', label: __('Call', 'jvb') },\r\n                            { value: 'email', label: __('Email', 'jvb') },\r\n                            { value: 'instagram', label: __('Instagram', 'jvb') }\r\n                        ]\r\n                    },\r\n                    { id: 'message', label: __('Your Message', 'jvb'), type: 'textarea', required: true }\r\n                ];\r\n                break;\r\n\r\n            case 'feature_request':\r\n                formFields = [\r\n                    { id: 'name', label: __('Name', 'jvb'), type: 'text', help: __('Required if you want us to follow up.', 'jvb') },\r\n                    { id: 'email', label: __('Email', 'jvb'), type: 'email', help: __('Required if you want us to follow up.', 'jvb') },\r\n                    { id: 'follow_up', label: __('Would you like me to follow up with you?', 'jvb'), type: 'checkbox' },\r\n                    { id: 'target_audience', label: __('This Feature is For', 'jvb'), type: 'checkboxes',\r\n                        options: [\r\n                            { value: 'artists', label: __('Artists', 'jvb') },\r\n                            { value: 'visitors', label: __('Site Visitors', 'jvb') },\r\n                            { value: 'partners', label: __('Partners', 'jvb') },\r\n                            { value: 'other', label: __('Other', 'jvb') }\r\n                        ]\r\n                    },\r\n                    { id: 'feature_name', label: __('Name your Feature', 'jvb'), type: 'text', required: true },\r\n                    { id: 'message', label: __('Describe Your Feature', 'jvb'), type: 'textarea', required: true }\r\n                ];\r\n                break;\r\n\r\n            case 'technical_issue':\r\n                formFields = [\r\n                    { id: 'name', label: __('Name', 'jvb'), type: 'text' },\r\n                    { id: 'email', label: __('Email', 'jvb'), type: 'email' },\r\n                    { id: 'follow_up', label: __('Would you like me to follow up with you?', 'jvb'), type: 'checkbox' },\r\n                    { id: 'issue_type', label: __('Type of Issue', 'jvb'), type: 'checkboxes',\r\n                        options: [\r\n                            { value: 'visual', label: __('Visual', 'jvb') },\r\n                            { value: 'error', label: __('Error Page', 'jvb') },\r\n                            { value: 'other', label: __('Other', 'jvb') }\r\n                        ]\r\n                    },\r\n                    { id: 'message', label: __('Please describe the issue.', 'jvb'), type: 'textarea', required: true }\r\n                ];\r\n                break;\r\n        }\r\n\r\n        return (\r\n            <>\r\n                <h3 className=\"jvb-form-title\">{formLabels.title}</h3>\r\n                <p className=\"jvb-form-description\">{formLabels.description}</p>\r\n\r\n                <div className=\"jvb-form-preview\">\r\n                    {formFields.map((field) => (\r\n                        <div key={field.id} className=\"jvb-form-field\">\r\n                            {showLabels && (\r\n                                <label htmlFor={`jvb-${field.id}`} className={field.required ? 'required' : ''}>\r\n                                    {field.label}\r\n                                </label>\r\n                            )}\r\n\r\n                            {field.type === 'text' && (\r\n                                <input\r\n                                    type=\"text\"\r\n                                    id={`jvb-${field.id}`}\r\n                                    placeholder={showLabels ? '' : field.label}\r\n                                    disabled\r\n                                />\r\n                            )}\r\n\r\n                            {field.type === 'email' && (\r\n                                <input\r\n                                    type=\"email\"\r\n                                    id={`jvb-${field.id}`}\r\n                                    placeholder={showLabels ? '' : field.label}\r\n                                    disabled\r\n                                />\r\n                            )}\r\n\r\n                            {field.type === 'tel' && (\r\n                                <input\r\n                                    type=\"tel\"\r\n                                    id={`jvb-${field.id}`}\r\n                                    placeholder={showLabels ? '' : field.label}\r\n                                    disabled\r\n                                />\r\n                            )}\r\n\r\n                            {field.type === 'url' && (\r\n                                <input\r\n                                    type=\"url\"\r\n                                    id={`jvb-${field.id}`}\r\n                                    placeholder={showLabels ? '' : field.label}\r\n                                    disabled\r\n                                />\r\n                            )}\r\n\r\n                            {field.type === 'textarea' && (\r\n                                <textarea\r\n                                    id={`jvb-${field.id}`}\r\n                                    placeholder={showLabels ? '' : field.label}\r\n                                    disabled\r\n                                    rows=\"4\"\r\n                                ></textarea>\r\n                            )}\r\n\r\n                            {field.type === 'checkbox' && (\r\n                                <div className=\"jvb-form-checkbox\">\r\n                                    <input\r\n                                        type=\"checkbox\"\r\n                                        id={`jvb-${field.id}`}\r\n                                        disabled\r\n                                    />\r\n                                    <label htmlFor={`jvb-${field.id}`}>{field.label}</label>\r\n                                </div>\r\n                            )}\r\n\r\n                            {field.type === 'checkboxes' && field.options && (\r\n                                <div className=\"jvb-form-checkboxes\">\r\n                                    {field.options.map((option) => (\r\n                                        <div key={option.value} className=\"jvb-form-checkbox\">\r\n                                            <input\r\n                                                type=\"checkbox\"\r\n                                                id={`jvb-${field.id}-${option.value}`}\r\n                                                disabled\r\n                                            />\r\n                                            <label htmlFor={`jvb-${field.id}-${option.value}`}>{option.label}</label>\r\n                                        </div>\r\n                                    ))}\r\n                                </div>\r\n                            )}\r\n\r\n                            {field.help && (\r\n                                <p className=\"jvb-form-help\">{field.help}</p>\r\n                            )}\r\n                        </div>\r\n                    ))}\r\n\r\n                    {turnstileEnabled && (\r\n                        <div className=\"jvb-form-turnstile\">\r\n                            <div className=\"jvb-turnstile-placeholder\">\r\n                                <span>{__('Cloudflare Turnstile will appear here', 'jvb')}</span>\r\n                            </div>\r\n                        </div>\r\n                    )}\r\n\r\n                    <div className=\"jvb-form-submit\">\r\n                        <button type=\"button\" className=\"jvb-form-button\">{formLabels.button}</button>\r\n                    </div>\r\n                </div>\r\n            </>\r\n        );\r\n    };\r\n\r\n    return (\r\n        <>\r\n            <InspectorControls>\r\n                <PanelBody title={__('Form Settings', 'jvb')}>\r\n                    <SelectControl\r\n                        label={__('Form Type', 'jvb')}\r\n                        value={formType}\r\n                        options={formTypes}\r\n                        onChange={(value) => setAttributes({ formType: value })}\r\n                    />\r\n\r\n                    <ToggleControl\r\n                        label={__('Show Field Labels', 'jvb')}\r\n                        checked={showLabels}\r\n                        onChange={(value) => setAttributes({ showLabels: value })}\r\n                        help={__('Toggle to show or hide field labels.', 'jvb')}\r\n                    />\r\n\r\n                    <TextControl\r\n                        label={__('Custom Recipient Email', 'jvb')}\r\n                        value={customEmailTo || ''}\r\n                        onChange={(value) => setAttributes({ customEmailTo: value })}\r\n                        help={__('Leave empty to use the default email.', 'jvb')}\r\n                        type=\"email\"\r\n                    />\r\n                </PanelBody>\r\n\r\n                <PanelBody title={__('Form Preview', 'jvb')} initialOpen={false}>\r\n                    <ToggleControl\r\n                        label={__('Show Preview', 'jvb')}\r\n                        checked={isPreviewVisible}\r\n                        onChange={(value) => setIsPreviewVisible(value)}\r\n                    />\r\n\r\n                    <p className=\"components-base-control__help\">\r\n                        {__('This is just a preview. The actual form will be rendered on the frontend.', 'jvb')}\r\n                    </p>\r\n                </PanelBody>\r\n            </InspectorControls>\r\n\r\n            <div {...blockProps}>\r\n                {isPreviewVisible ? (\r\n                    renderFormPreview()\r\n                ) : (\r\n                    <div className=\"jvb-form-placeholder\">\r\n                        <h3>{formLabels.title}</h3>\r\n                        <p>{__('Form preview is hidden. Edit settings in the sidebar.', 'jvb')}</p>\r\n                    </div>\r\n                )}\r\n            </div>\r\n        </>\r\n    );\r\n}\r\n","//index.js\r\n/**\r\n * Registers a new block provided a unique name and an object defining its behavior.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nimport { registerBlockType } from '@wordpress/blocks';\r\n\r\n/**\r\n * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.\r\n * All files containing `style` keyword are bundled together. The code used\r\n * gets applied both to the front of your site and to the editor.\r\n *\r\n * @see https://www.npmjs.com/package/@wordpress/scripts#using-css\r\n */\r\nimport './style.scss';\r\n\r\n/**\r\n * Internal dependencies\r\n */\r\nimport Edit from './edit';\r\nimport save from './save';\r\nimport metadata from './block.json';\r\n\r\n/**\r\n * Every block starts by registering a new block type definition.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nregisterBlockType( metadata.name, {\r\n    /**\r\n     * @see ./edit.js\r\n     */\r\n    edit: Edit,\r\n\r\n    /**\r\n     * @see ./save.js\r\n     */\r\n    save,\r\n} );\r\n","//save.js\r\n/**\r\n * React hook that is used to mark the block wrapper element.\r\n * It provides all the necessary props like the class name.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops\r\n */\r\nimport { useBlockProps } from '@wordpress/block-editor';\r\n\r\n/**\r\n * The save function defines the way in which the different attributes should\r\n * be combined into the final markup, which is then serialized by the block\r\n * editor into `post_content`.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#save\r\n *\r\n * @return {WPElement} Element to render.\r\n */\r\nexport default function save() {\r\n    // This is a dynamic block that is rendered on the server side\r\n    // Return null to let WordPress handle the saving and rendering\r\n    return null;\r\n}\r\n","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"components\"];","module.exports = window[\"wp\"][\"element\"];","module.exports = window[\"wp\"][\"i18n\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"forms/index\": 0,\n\t\"forms/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"forms/style-index\"], () => (__webpack_require__(\"./src/forms/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["__","useBlockProps","InspectorControls","PanelBody","SelectControl","ToggleControl","TextControl","Notice","useState","useEffect","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","Edit","attributes","setAttributes","formType","showLabels","customEmailTo","turnstileEnabled","isPreviewVisible","setIsPreviewVisible","blockProps","className","getFormTypes","window","jvbFormsData","formTypes","label","value","disabled","getAvailableForms","console","log","availableForms","getCurrentFormConfig","getFormLabels","formConfig","title","description","Array","isArray","join","button","submit","formLabels","renderFormPreview","status","isDismissible","children","formFields","id","type","required","options","help","map","field","htmlFor","placeholder","rows","option","onChange","checked","initialOpen","registerBlockType","save","metadata","name","edit"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/forms/style-index-rtl.css b/build/forms/style-index-rtl.css
index 8b13789..6137010 100644
--- a/build/forms/style-index-rtl.css
+++ b/build/forms/style-index-rtl.css
@@ -1 +1,4 @@
+/*!*********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/forms/style.scss ***!
+  \*********************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/forms/style-index.css b/build/forms/style-index.css
index 8b13789..6137010 100644
--- a/build/forms/style-index.css
+++ b/build/forms/style-index.css
@@ -1 +1,4 @@
+/*!*********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/forms/style.scss ***!
+  \*********************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/forms/view.asset.php b/build/forms/view.asset.php
index 9141c1e..37c3a7d 100644
--- a/build/forms/view.asset.php
+++ b/build/forms/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => 'bfff25a4ea4603e12189');
+<?php return array('dependencies' => array(), 'version' => '0d39a06fe13d4bdc84a0');
diff --git a/build/forms/view.js b/build/forms/view.js
index 9c3d446..f9dfe92 100644
--- a/build/forms/view.js
+++ b/build/forms/view.js
@@ -1 +1,116 @@
-(()=>{class o{constructor(){this.controller=window.jvbForm,document.querySelectorAll(".jvb-form-block form").forEach(o=>{this.controller.registerForm(o,{cache:!0,autoUpload:!1,imageMeta:!1})}),this.controller.subscribe((o,e)=>{"form-submit"===o&&this.handleFormSubmission(e).then(()=>{})})}async handleFormSubmission(o){const{config:e,data:r}=o,t=e.element,n=new FormData;for(const[o,e]of Object.entries(r))Array.isArray(e)?e.forEach(e=>n.append(`${o}[]`,e)):"object"==typeof e&&null!==e?n.append(o,JSON.stringify(e)):n.append(o,e);if(e.element.querySelectorAll('[name="form_id"],[name="form_type"],[name="timestamp"],[name="cf-turnstile-response"]').forEach(o=>{n.append(o.name,o.value)}),window.jvbUploads)try{(await window.jvbUploads.getFilesForForm(t)).forEach(({file:o,fieldName:e})=>{n.append(`${e}[]`,o)})}catch(o){console.error("Error getting files:",o)}this.controller.showFormStatus(e.id,"uploading");try{const o=await fetch(`${jvbSettings.api}forms`,{method:"POST",credentials:"same-origin",body:n}),a=await o.json();if(!o.ok)return this.controller.showFormStatus(e.id,"error"),void this.controller.handleFormError(t,a);if(this.controller.showFormStatus(e.id,"submitted"),this.controller.showSummary({changes:r,config:e}),window.jvbA11y.announce("Form successfully submitted!"),window.jvbUploads){const o=t.querySelectorAll("[data-upload-field]");for(const e of o){const o=window.jvbUploads.determineFieldId(e);await window.jvbUploads.clearFieldFromStores(o)}}}catch(o){console.error("Form submission error:",o),this.controller.showFormStatus(e.id,"error"),this.controller.handleFormError(t,{message:"Network error. Please check your connection and try again.",code:"network_error"})}finally{await this.controller.store.delete(e.id)}}}document.addEventListener("DOMContentLoaded",async function(){window.auth.subscribe(e=>{"auth-loaded"===e&&new o})})})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/*!***************************!*\
+  !*** ./src/forms/view.js ***!
+  \***************************/
+/**
+ * view.js
+ * Frontend JavaScript for the Form Block
+ * Handles form validation and submission
+ */
+/**
+ * view.js
+ * Frontend JavaScript for the Form Block
+ */
+class FormBlock {
+  constructor() {
+    this.controller = window.jvbForm;
+    document.querySelectorAll('.jvb-form-block form').forEach(form => {
+      this.controller.registerForm(form, {
+        cache: true,
+        autoUpload: false,
+        imageMeta: false
+      });
+    });
+    this.controller.subscribe((event, data) => {
+      if (event === 'form-submit') {
+        this.handleFormSubmission(data).then(() => {});
+      }
+    });
+  }
+  async handleFormSubmission(eventData) {
+    const {
+      config,
+      data
+    } = eventData;
+    const form = config.element;
+    const submitData = new FormData();
+
+    // Add regular form fields
+    for (const [key, value] of Object.entries(data)) {
+      if (Array.isArray(value)) {
+        value.forEach(v => submitData.append(`${key}[]`, v));
+      } else if (typeof value === 'object' && value !== null) {
+        submitData.append(key, JSON.stringify(value));
+      } else {
+        submitData.append(key, value);
+      }
+    }
+    config.element.querySelectorAll('[name="form_id"],[name="form_type"],[name="timestamp"],[name="cf-turnstile-response"]').forEach(input => {
+      submitData.append(input.name, input.value);
+    });
+
+    // Add uploaded files
+    if (window.jvbUploads) {
+      try {
+        const files = await window.jvbUploads.getFilesForForm(form);
+        files.forEach(({
+          file,
+          fieldName
+        }) => {
+          submitData.append(`${fieldName}[]`, file);
+        });
+      } catch (error) {
+        console.error('Error getting files:', error);
+      }
+    }
+    this.controller.showFormStatus(config.id, 'uploading');
+    try {
+      const response = await fetch(`${jvbSettings.api}forms`, {
+        method: 'POST',
+        credentials: 'same-origin',
+        body: submitData
+      });
+      const result = await response.json();
+      if (!response.ok) {
+        this.controller.showFormStatus(config.id, 'error');
+        this.controller.handleFormError(form, result);
+        return;
+      }
+      this.controller.showFormStatus(config.id, 'submitted');
+      // this.controller.handleFormSuccess(form, result);
+      this.controller.showSummary({
+        changes: data,
+        config: config
+      });
+      window.jvbA11y.announce('Form successfully submitted!');
+
+      // Clean up uploaded files
+      if (window.jvbUploads) {
+        const uploadFields = form.querySelectorAll('[data-upload-field]');
+        for (const field of uploadFields) {
+          const fieldId = window.jvbUploads.determineFieldId(field);
+          await window.jvbUploads.clearFieldFromStores(fieldId);
+        }
+      }
+    } catch (error) {
+      console.error('Form submission error:', error);
+      this.controller.showFormStatus(config.id, 'error');
+      this.controller.handleFormError(form, {
+        message: 'Network error. Please check your connection and try again.',
+        code: 'network_error'
+      });
+    } finally {
+      await this.controller.store.delete(config.id);
+    }
+  }
+}
+document.addEventListener('DOMContentLoaded', async function () {
+  window.auth.subscribe(event => {
+    if (event === 'auth-loaded') {
+      new FormBlock();
+    }
+  });
+});
+/******/ })()
+;
+//# sourceMappingURL=view.js.map
\ No newline at end of file
diff --git a/build/forms/view.js.map b/build/forms/view.js.map
new file mode 100644
index 0000000..d5899e2
--- /dev/null
+++ b/build/forms/view.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"forms/view.js","mappings":"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","sources":["webpack://jvb/./src/forms/view.js"],"sourcesContent":["/**\r\n * view.js\r\n * Frontend JavaScript for the Form Block\r\n * Handles form validation and submission\r\n */\r\n/**\r\n * view.js\r\n * Frontend JavaScript for the Form Block\r\n */\r\nclass FormBlock {\r\n\tconstructor() {\r\n\t\tthis.controller = window.jvbForm;\r\n\r\n\t\tdocument.querySelectorAll('.jvb-form-block form').forEach(form => {\r\n\t\t\tthis.controller.registerForm(form, {\r\n\t\t\t\tcache: true,\r\n\t\t\t\tautoUpload: false,\r\n\t\t\t\timageMeta: false,\r\n\t\t\t});\r\n\t\t});\r\n\r\n\t\tthis.controller.subscribe((event, data) => {\r\n\t\t\tif (event === 'form-submit') {\r\n\t\t\t\tthis.handleFormSubmission(data).then(()=>{});\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\tasync handleFormSubmission(eventData) {\r\n\t\tconst { config, data } = eventData;\r\n\t\tconst form = config.element;\r\n\r\n\t\tconst submitData = new FormData();\r\n\r\n\t\t// Add regular form fields\r\n\t\tfor (const [key, value] of Object.entries(data)) {\r\n\t\t\tif (Array.isArray(value)) {\r\n\t\t\t\tvalue.forEach(v => submitData.append(`${key}[]`, v));\r\n\t\t\t} else if (typeof value === 'object' && value !== null) {\r\n\t\t\t\tsubmitData.append(key, JSON.stringify(value));\r\n\t\t\t} else {\r\n\t\t\t\tsubmitData.append(key, value);\r\n\t\t\t}\r\n\t\t}\r\n\t\tconfig.element.querySelectorAll('[name=\"form_id\"],[name=\"form_type\"],[name=\"timestamp\"],[name=\"cf-turnstile-response\"]').forEach(input => {\r\n\t\t\tsubmitData.append(input.name, input.value);\r\n\t\t});\r\n\r\n\t\t// Add uploaded files\r\n\t\tif (window.jvbUploads) {\r\n\t\t\ttry {\r\n\t\t\t\tconst files = await window.jvbUploads.getFilesForForm(form);\r\n\r\n\t\t\t\tfiles.forEach(({ file, fieldName }) => {\r\n\t\t\t\t\tsubmitData.append(`${fieldName}[]`, file);\r\n\t\t\t\t});\r\n\t\t\t} catch (error) {\r\n\t\t\t\tconsole.error('Error getting files:', error);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.controller.showFormStatus(config.id, 'uploading');\r\n\r\n\t\ttry {\r\n\t\t\tconst response = await fetch(`${jvbSettings.api}forms`, {\r\n\t\t\t\tmethod: 'POST',\r\n\t\t\t\tcredentials: 'same-origin',\r\n\t\t\t\tbody: submitData\r\n\t\t\t});\r\n\r\n\t\t\tconst result = await response.json();\r\n\r\n\t\t\tif (!response.ok) {\r\n\t\t\t\tthis.controller.showFormStatus(config.id, 'error');\r\n\t\t\t\tthis.controller.handleFormError(form, result);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tthis.controller.showFormStatus(config.id, 'submitted');\r\n\t\t\t// this.controller.handleFormSuccess(form, result);\r\n\t\t\tthis.controller.showSummary({ changes: data, config: config });\r\n\t\t\twindow.jvbA11y.announce('Form successfully submitted!');\r\n\r\n\t\t\t// Clean up uploaded files\r\n\t\t\tif (window.jvbUploads) {\r\n\t\t\t\tconst uploadFields = form.querySelectorAll('[data-upload-field]');\r\n\t\t\t\tfor (const field of uploadFields) {\r\n\t\t\t\t\tconst fieldId = window.jvbUploads.determineFieldId(field);\r\n\t\t\t\t\tawait window.jvbUploads.clearFieldFromStores(fieldId);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t} catch (error) {\r\n\t\t\tconsole.error('Form submission error:', error);\r\n\t\t\tthis.controller.showFormStatus(config.id, 'error');\r\n\t\t\tthis.controller.handleFormError(form, {\r\n\t\t\t\tmessage: 'Network error. Please check your connection and try again.',\r\n\t\t\t\tcode: 'network_error'\r\n\t\t\t});\r\n\t\t} finally {\r\n\t\t\tawait this.controller.store.delete(config.id);\r\n\t\t}\r\n\t}\r\n}\r\n\r\ndocument.addEventListener('DOMContentLoaded', async function() {\r\n\twindow.auth.subscribe(event => {\r\n\t\tif (event === 'auth-loaded') {\r\n\t\t\tnew FormBlock();\r\n\t\t}\r\n\t});\r\n});\r\n"],"names":["FormBlock","constructor","controller","window","jvbForm","document","querySelectorAll","forEach","form","registerForm","cache","autoUpload","imageMeta","subscribe","event","data","handleFormSubmission","then","eventData","config","element","submitData","FormData","key","value","Object","entries","Array","isArray","v","append","JSON","stringify","input","name","jvbUploads","files","getFilesForForm","file","fieldName","error","console","showFormStatus","id","response","fetch","jvbSettings","api","method","credentials","body","result","json","ok","handleFormError","showSummary","changes","jvbA11y","announce","uploadFields","field","fieldId","determineFieldId","clearFieldFromStores","message","code","store","delete","addEventListener","auth"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/glossary/index-rtl.css b/build/glossary/index-rtl.css
index 8b13789..f6baea7 100644
--- a/build/glossary/index-rtl.css
+++ b/build/glossary/index-rtl.css
@@ -1 +1,4 @@
+/*!*************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/glossary/editor.scss ***!
+  \*************************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/glossary/index.asset.php b/build/glossary/index.asset.php
index c0f7d11..14c6351 100644
--- a/build/glossary/index.asset.php
+++ b/build/glossary/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => '809c5c76c0c41769d801');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => '79ce82491ba71adc10c3');
diff --git a/build/glossary/index.css b/build/glossary/index.css
index 8b13789..f6baea7 100644
--- a/build/glossary/index.css
+++ b/build/glossary/index.css
@@ -1 +1,4 @@
+/*!*************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/glossary/editor.scss ***!
+  \*************************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/glossary/index.js b/build/glossary/index.js
index ea2ddc8..ee7110a 100644
--- a/build/glossary/index.js
+++ b/build/glossary/index.js
@@ -1 +1,357 @@
-(()=>{"use strict";var r,o={359(){const r=window.wp.blocks,o=window.wp.i18n,e=window.wp.blockEditor,t=window.ReactJSXRuntime,i=JSON.parse('{"UU":"jvb/glossary"}');(0,r.registerBlockType)(i.UU,{edit:function(){return(0,t.jsx)("p",{...(0,e.useBlockProps)(),children:(0,o.__)("Will output the glossary","jvb")})}})}},e={};function t(r){var i=e[r];if(void 0!==i)return i.exports;var n=e[r]={exports:{}};return o[r](n,n.exports,t),n.exports}t.m=o,r=[],t.O=(o,e,i,n)=>{if(!e){var s=1/0;for(v=0;v<r.length;v++){for(var[e,i,n]=r[v],l=!0,a=0;a<e.length;a++)(!1&n||s>=n)&&Object.keys(t.O).every(r=>t.O[r](e[a]))?e.splice(a--,1):(l=!1,n<s&&(s=n));if(l){r.splice(v--,1);var p=i();void 0!==p&&(o=p)}}return o}n=n||0;for(var v=r.length;v>0&&r[v-1][2]>n;v--)r[v]=r[v-1];r[v]=[e,i,n]},t.o=(r,o)=>Object.prototype.hasOwnProperty.call(r,o),(()=>{var r={342:0,642:0};t.O.j=o=>0===r[o];var o=(o,e)=>{var i,n,[s,l,a]=e,p=0;if(s.some(o=>0!==r[o])){for(i in l)t.o(l,i)&&(t.m[i]=l[i]);if(a)var v=a(t)}for(o&&o(e);p<s.length;p++)n=s[p],t.o(r,n)&&r[n]&&r[n][0](),r[n]=0;return t.O(v)},e=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];e.forEach(o.bind(null,0)),e.push=o.bind(null,e.push.bind(e))})();var i=t.O(void 0,[642],()=>t(359));i=t.O(i)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/glossary/edit.js"
+/*!******************************!*\
+  !*** ./src/glossary/edit.js ***!
+  \******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./editor.scss */ "./src/glossary/editor.scss");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__);
+/**
+ * Retrieves the translation of text.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
+ */
+
+
+/**
+ * React hook that is used to mark the block wrapper element.
+ * It provides all the necessary props like the class name.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
+ */
+
+
+/**
+ * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
+ * Those files can contain any CSS code that gets applied to the editor.
+ *
+ * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
+ */
+
+
+/**
+ * The edit function describes the structure of your block in the context of the
+ * editor. This represents what the editor will render when the block is used.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
+ *
+ * @return {Element} Element to render.
+ */
+
+function Edit() {
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("p", {
+    ...(0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.useBlockProps)(),
+    children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Will output the glossary', 'jvb')
+  });
+}
+
+/***/ },
+
+/***/ "./src/glossary/index.js"
+/*!*******************************!*\
+  !*** ./src/glossary/index.js ***!
+  \*******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./style.scss */ "./src/glossary/style.scss");
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./edit */ "./src/glossary/edit.js");
+/* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./block.json */ "./src/glossary/block.json");
+/**
+ * Registers a new block provided a unique name and an object defining its behavior.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+
+
+/**
+ * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
+ * All files containing `style` keyword are bundled together. The code used
+ * gets applied both to the front of your site and to the editor.
+ *
+ * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
+ */
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+/**
+ * Every block starts by registering a new block type definition.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)(_block_json__WEBPACK_IMPORTED_MODULE_3__.name, {
+  /**
+   * @see ./edit.js
+   */
+  edit: _edit__WEBPACK_IMPORTED_MODULE_2__["default"]
+});
+
+/***/ },
+
+/***/ "./src/glossary/editor.scss"
+/*!**********************************!*\
+  !*** ./src/glossary/editor.scss ***!
+  \**********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "./src/glossary/style.scss"
+/*!*********************************!*\
+  !*** ./src/glossary/style.scss ***!
+  \*********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/i18n"
+/*!******************************!*\
+  !*** external ["wp","i18n"] ***!
+  \******************************/
+(module) {
+
+module.exports = window["wp"]["i18n"];
+
+/***/ },
+
+/***/ "./src/glossary/block.json"
+/*!*********************************!*\
+  !*** ./src/glossary/block.json ***!
+  \*********************************/
+(module) {
+
+module.exports = /*#__PURE__*/JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/glossary","version":"0.1.0","title":"Glossary of Terms","category":"jvb","icon":"excerpt-view","description":"Outputs the terms","example":{},"supports":{"html":false,"align":["wide","full"]},"textdomain":"jvb","selectors":{"root":".glossary"},"editorScript":"file:./index.js","editorStyle":"file:./index.css","style":"file:./style-index.css","render":"file:./render.php","viewScript":"file:./view.js"}');
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"glossary/index": 0,
+/******/ 			"glossary/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["glossary/style-index"], () => (__webpack_require__("./src/glossary/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/glossary/index.js.map b/build/glossary/index.js.map
new file mode 100644
index 0000000..9cf4356
--- /dev/null
+++ b/build/glossary/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"glossary/index.js","mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACqC;;AAErC;AACA;AACA;AACA;AACA;AACA;AACwD;;AAExD;AACA;AACA;AACA;AACA;AACA;AACuB;;AAEvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAQe,SAASI,IAAIA,CAAA,EAAG;EAC9B,oBACCD,sDAAA;IAAA,GAAQF,sEAAa,CAAC,CAAC;IAAAI,QAAA,EACpBL,mDAAE,CAAE,0BAA0B,EAAE,KAAM;EAAC,CACvC,CAAC;AAEN,C;;;;;;;;;;;;;;;;ACrCA;AACA;AACA;AACA;AACA;AACsD;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA;AACsB;;AAEtB;AACA;AACA;AAC0B;AACU;;AAEpC;AACA;AACA;AACA;AACA;AACAM,oEAAiB,CAAEC,6CAAa,EAAE;EACjC;AACD;AACA;EACCE,IAAI,EAAEL,6CAAIA;AACX,CAAE,CAAC,C;;;;;;;;;;;AChCH;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA,2C;;;;;;;;;;ACAA,6C;;;;;;;;;;ACAA,wC;;;;;;;;;;ACAA,sC;;;;;;;;;;;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WC/BA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G;;;;;UEjDA;UACA;UACA;UACA;UACA","sources":["webpack://jvb/./src/glossary/edit.js","webpack://jvb/./src/glossary/index.js","webpack://jvb/./src/glossary/editor.scss","webpack://jvb/./src/glossary/style.scss?adee","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"i18n\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["/**\r\n * Retrieves the translation of text.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/\r\n */\r\nimport { __ } from '@wordpress/i18n';\r\n\r\n/**\r\n * React hook that is used to mark the block wrapper element.\r\n * It provides all the necessary props like the class name.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops\r\n */\r\nimport { useBlockProps } from '@wordpress/block-editor';\r\n\r\n/**\r\n * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.\r\n * Those files can contain any CSS code that gets applied to the editor.\r\n *\r\n * @see https://www.npmjs.com/package/@wordpress/scripts#using-css\r\n */\r\nimport './editor.scss';\r\n\r\n/**\r\n * The edit function describes the structure of your block in the context of the\r\n * editor. This represents what the editor will render when the block is used.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit\r\n *\r\n * @return {Element} Element to render.\r\n */\r\nexport default function Edit() {\r\n\treturn (\r\n\t\t<p { ...useBlockProps() }>\r\n\t\t\t{ __( 'Will output the glossary', 'jvb' ) }\r\n\t\t</p>\r\n\t);\r\n}\r\n","/**\r\n * Registers a new block provided a unique name and an object defining its behavior.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nimport { registerBlockType } from '@wordpress/blocks';\r\n\r\n/**\r\n * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.\r\n * All files containing `style` keyword are bundled together. The code used\r\n * gets applied both to the front of your site and to the editor.\r\n *\r\n * @see https://www.npmjs.com/package/@wordpress/scripts#using-css\r\n */\r\nimport './style.scss';\r\n\r\n/**\r\n * Internal dependencies\r\n */\r\nimport Edit from './edit';\r\nimport metadata from './block.json';\r\n\r\n/**\r\n * Every block starts by registering a new block type definition.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nregisterBlockType( metadata.name, {\r\n\t/**\r\n\t * @see ./edit.js\r\n\t */\r\n\tedit: Edit,\r\n} );\r\n","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"i18n\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"glossary/index\": 0,\n\t\"glossary/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"glossary/style-index\"], () => (__webpack_require__(\"./src/glossary/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["__","useBlockProps","jsx","_jsx","Edit","children","registerBlockType","metadata","name","edit"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/glossary/style-index-rtl.css b/build/glossary/style-index-rtl.css
index f417e5a..9f57995 100644
--- a/build/glossary/style-index-rtl.css
+++ b/build/glossary/style-index-rtl.css
@@ -1 +1,109 @@
-:root{--navWidth:40vw}@media(min-width:768px){:root{--navWidth:22vw}}nav.glossary-index{height:60vh;position:fixed;left:-8px;top:50%;transform:translateY(-50%);width:var(--navWidth);z-index:var(--z-3)}nav.glossary-index>ul{--dir:column;--align:flex-start;--justify:flex-start;--gap:1px;height:100%;max-height:100%;overflow:hidden auto;scroll-behavior:smooth;touch-action:pan-y;width:100%}nav.glossary-index a,nav.glossary-index li{flex:1;height:-moz-max-content;height:max-content;min-height:max(var(--chipchip),-moz-max-content);min-height:max(var(--chipchip),max-content);width:100%}nav.glossary-index a{--justify:center;background-color:rgba(var(--base),var(--op-45));hyphens:auto;padding:.25rem .5rem;word-wrap:anywhere;white-space:wrap}nav.glossary-index a.active,nav.glossary-index a:focus,nav.glossary-index a:hover{background-color:rgba(var(--action-0),var(--op-6));color:var(--action-contrast)}.glossary dd{margin-right:.5rem;width:calc(100% + .75rem)}.glossary dd,.glossary dt{right:0;position:relative;transition:margin var(--trans-base),right var(--trans-base),width var(--trans-base)}.glossary dt.active,.glossary dt:target{color:rgb(var(--action-0));right:-1.5rem;outline:none;padding:0}.glossary dt.active+dd,.glossary dt:target+dd{right:-1.5rem}dl.glossary,main header{grid-column:full;padding:0 2rem 0 var(--navWidth)}@media(min-width:768px){dl.glossary,main header{margin-right:auto;margin-left:var(--navWidth);max-width:var(--content);padding-left:var(--btn)}}@media(max-width:768px){.glossary h2{font-size:var(--txt-medium)}.glossary p{font-size:var(--txt-x-small)}.glossary-index a,.glossary-index li{height:-moz-fit-content;height:fit-content}.glossary-index a{font-size:var(--txt-x-small);min-height:2em;padding:.25rem}body:has(.glossary) h1{font-size:var(--txt-xx-large)}}
+/*!************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/glossary/style.scss ***!
+  \************************************************************************************************************************************************************************************************************************************************/
+:root {
+  --navWidth: 40vw;
+}
+@media (min-width: 768px) {
+  :root {
+    --navWidth: 22vw;
+  }
+}
+nav.glossary-index {
+  position: fixed;
+  top: 50%;
+  transform: translateY(-50%);
+  width: var(--navWidth);
+  left: -8px;
+  height: 60vh;
+  z-index: var(--z-3);
+}
+nav.glossary-index > ul {
+  --dir: column;
+  --align: flex-start;
+  --justify: flex-start;
+  --gap: 1px;
+  touch-action: pan-y;
+  max-height: 100%;
+  height: 100%;
+  width: 100%;
+  overflow: hidden auto;
+  scroll-behavior: smooth;
+}
+nav.glossary-index li, nav.glossary-index a {
+  flex: 1;
+  width: 100%;
+  height: -moz-max-content;
+  height: max-content;
+  min-height: max(var(--chipchip), -moz-max-content);
+  min-height: max(var(--chipchip), max-content);
+}
+nav.glossary-index a {
+  --justify: center;
+  padding: 0.25rem 0.5rem;
+  hyphens: auto;
+  background-color: rgba(var(--base), var(--op-45));
+  word-wrap: anywhere;
+  white-space: wrap;
+}
+nav.glossary-index a:hover,
+nav.glossary-index a:focus,
+nav.glossary-index a.active {
+  background-color: rgba(var(--action-0), var(--op-6));
+  color: var(--action-contrast);
+}
+.glossary dd {
+  margin-right: 0.5rem;
+  width: calc(100% + 0.75rem);
+}
+.glossary dd,
+.glossary dt {
+  position: relative;
+  right: 0;
+  transition: margin var(--trans-base), right var(--trans-base), width var(--trans-base);
+}
+.glossary dt:target,
+.glossary dt.active {
+  outline: none;
+  right: -1.5rem;
+  padding: 0;
+  color: rgb(var(--action-0));
+}
+.glossary dt:target + dd,
+.glossary dt.active + dd {
+  right: -1.5rem;
+}
+main header,
+dl.glossary {
+  grid-column: full;
+  padding: 0 2rem 0 var(--navWidth);
+}
+@media (min-width: 768px) {
+  main header,
+  dl.glossary {
+    margin-right: auto;
+    max-width: var(--content);
+    margin-left: var(--navWidth);
+    padding-left: var(--btn);
+  }
+}
+@media (max-width: 768px) {
+  .glossary h2 {
+    font-size: var(--txt-medium);
+  }
+  .glossary p {
+    font-size: var(--txt-x-small);
+  }
+  .glossary-index li, .glossary-index a {
+    height: -moz-fit-content;
+    height: fit-content;
+  }
+  .glossary-index a {
+    font-size: var(--txt-x-small);
+    padding: 0.25rem;
+    min-height: 2em;
+  }
+  body:has(.glossary) h1 {
+    font-size: var(--txt-xx-large);
+  }
+}
diff --git a/build/glossary/style-index.css b/build/glossary/style-index.css
index eaaadb2..c750e73 100644
--- a/build/glossary/style-index.css
+++ b/build/glossary/style-index.css
@@ -1 +1,111 @@
-:root{--navWidth:40vw}@media(min-width:768px){:root{--navWidth:22vw}}nav.glossary-index{height:60vh;position:fixed;right:-8px;top:50%;transform:translateY(-50%);width:var(--navWidth);z-index:var(--z-3)}nav.glossary-index>ul{--dir:column;--align:flex-start;--justify:flex-start;--gap:1px;height:100%;max-height:100%;overflow:hidden auto;scroll-behavior:smooth;touch-action:pan-y;width:100%}nav.glossary-index a,nav.glossary-index li{flex:1;height:-moz-max-content;height:max-content;min-height:max(var(--chipchip),-moz-max-content);min-height:max(var(--chipchip),max-content);width:100%}nav.glossary-index a{--justify:center;background-color:rgba(var(--base),var(--op-45));hyphens:auto;padding:.25rem .5rem;word-wrap:anywhere;white-space:wrap}nav.glossary-index a.active,nav.glossary-index a:focus,nav.glossary-index a:hover{background-color:rgba(var(--action-0),var(--op-6));color:var(--action-contrast)}.glossary dd{margin-left:.5rem;width:calc(100% + .75rem)}.glossary dd,.glossary dt{left:0;position:relative;transition:margin var(--trans-base),left var(--trans-base),width var(--trans-base)}.glossary dt.active,.glossary dt:target{color:rgb(var(--action-0));left:-1.5rem;outline:none;padding:0}.glossary dt.active+dd,.glossary dt:target+dd{left:-1.5rem}dl.glossary,main header{grid-column:full;padding:0 var(--navWidth) 0 2rem}@media(min-width:768px){dl.glossary,main header{margin-left:auto;margin-right:var(--navWidth);max-width:var(--content);padding-right:var(--btn)}}@media(max-width:768px){.glossary h2{font-size:var(--txt-medium)}.glossary p{font-size:var(--txt-x-small)}.glossary-index a,.glossary-index li{height:-moz-fit-content;height:fit-content}.glossary-index a{font-size:var(--txt-x-small);min-height:2em;padding:.25rem}body:has(.glossary) h1{font-size:var(--txt-xx-large)}}
+/*!************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/glossary/style.scss ***!
+  \************************************************************************************************************************************************************************************************************************************************/
+:root {
+  --navWidth: 40vw;
+}
+@media (min-width: 768px) {
+  :root {
+    --navWidth: 22vw;
+  }
+}
+nav.glossary-index {
+  position: fixed;
+  top: 50%;
+  transform: translateY(-50%);
+  width: var(--navWidth);
+  right: -8px;
+  height: 60vh;
+  z-index: var(--z-3);
+}
+nav.glossary-index > ul {
+  --dir: column;
+  --align: flex-start;
+  --justify: flex-start;
+  --gap: 1px;
+  touch-action: pan-y;
+  max-height: 100%;
+  height: 100%;
+  width: 100%;
+  overflow: hidden auto;
+  scroll-behavior: smooth;
+}
+nav.glossary-index li, nav.glossary-index a {
+  flex: 1;
+  width: 100%;
+  height: -moz-max-content;
+  height: max-content;
+  min-height: max(var(--chipchip), -moz-max-content);
+  min-height: max(var(--chipchip), max-content);
+}
+nav.glossary-index a {
+  --justify: center;
+  padding: 0.25rem 0.5rem;
+  hyphens: auto;
+  background-color: rgba(var(--base), var(--op-45));
+  word-wrap: anywhere;
+  white-space: wrap;
+}
+nav.glossary-index a:hover,
+nav.glossary-index a:focus,
+nav.glossary-index a.active {
+  background-color: rgba(var(--action-0), var(--op-6));
+  color: var(--action-contrast);
+}
+.glossary dd {
+  margin-left: 0.5rem;
+  width: calc(100% + 0.75rem);
+}
+.glossary dd,
+.glossary dt {
+  position: relative;
+  left: 0;
+  transition: margin var(--trans-base), left var(--trans-base), width var(--trans-base);
+}
+.glossary dt:target,
+.glossary dt.active {
+  outline: none;
+  left: -1.5rem;
+  padding: 0;
+  color: rgb(var(--action-0));
+}
+.glossary dt:target + dd,
+.glossary dt.active + dd {
+  left: -1.5rem;
+}
+main header,
+dl.glossary {
+  grid-column: full;
+  padding: 0 var(--navWidth) 0 2rem;
+}
+@media (min-width: 768px) {
+  main header,
+  dl.glossary {
+    margin-left: auto;
+    max-width: var(--content);
+    margin-right: var(--navWidth);
+    padding-right: var(--btn);
+  }
+}
+@media (max-width: 768px) {
+  .glossary h2 {
+    font-size: var(--txt-medium);
+  }
+  .glossary p {
+    font-size: var(--txt-x-small);
+  }
+  .glossary-index li, .glossary-index a {
+    height: -moz-fit-content;
+    height: fit-content;
+  }
+  .glossary-index a {
+    font-size: var(--txt-x-small);
+    padding: 0.25rem;
+    min-height: 2em;
+  }
+  body:has(.glossary) h1 {
+    font-size: var(--txt-xx-large);
+  }
+}
+
+/*# sourceMappingURL=style-index.css.map*/
\ No newline at end of file
diff --git a/build/glossary/style-index.css.map b/build/glossary/style-index.css.map
new file mode 100644
index 0000000..620313f
--- /dev/null
+++ b/build/glossary/style-index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"glossary/style-index.css","mappings":";;;AAAA;EACC;AACD;AAAC;EAFD;IAGE;EAGA;AACF;AAAA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;AAGD;AADC;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AAGF;AADC;EACC;EACA;EACA;EAAA;EACA;EAAA;AAGF;AADC;EACC;EACA;EACA;EACA;EACA;EACA;AAGF;AADC;;;EAGC;EACA;AAGF;AAAA;EACC;EACA;AAGD;AADA;;EAEC;EACA;EACA;AAID;AAAA;;EAEC;EACA;EACA;EACA;AAGD;AADC;;EAEC;AAIF;AADA;;EAEC;EACA;AAID;AAHC;EAJD;;IAKE;IACA;IACA;IACA;EAOA;AACF;AAJA;EAEE;IACC;EAMD;EAJA;IACC;EAMD;EAFA;IACC;IAAA;EAID;EAFA;IACC;IACA;IACA;EAID;EAAD;IACC;EAEA;AACF,C","sources":["webpack://jvb/./src/glossary/style.scss"],"sourcesContent":[":root {\r\n\t--navWidth: 40vw;\r\n\t@media (min-width: 768px) {\r\n\t\t--navWidth: 22vw;\r\n\t}\r\n}\r\n\r\nnav.glossary-index {\r\n\tposition: fixed;\r\n\ttop: 50%;\r\n\ttransform: translateY(-50%);\r\n\twidth: var(--navWidth);\r\n\tright: -8px;\r\n\theight: 60vh;\r\n\tz-index: var(--z-3);\r\n\r\n\t> ul {\r\n\t\t--dir: column;\r\n\t\t--align: flex-start;\r\n\t\t--justify: flex-start;\r\n\t\t--gap: 1px;\r\n\t\ttouch-action: pan-y;\r\n\t\tmax-height: 100%;\r\n\t\theight: 100%;\r\n\t\twidth: 100%;\r\n\t\toverflow: hidden auto;\r\n\t\tscroll-behavior: smooth;\r\n\t}\r\n\tli, a {\r\n\t\tflex: 1;\r\n\t\twidth: 100%;\r\n\t\theight: max-content;\r\n\t\tmin-height: max(var(--chipchip), max-content);\r\n\t}\r\n\ta {\r\n\t\t--justify: center;\r\n\t\tpadding: .25rem .5rem;\r\n\t\thyphens: auto;\r\n\t\tbackground-color: rgba(var(--base),var(--op-45));\r\n\t\tword-wrap: anywhere;\r\n\t\twhite-space: wrap;\r\n\t}\r\n\ta:hover,\r\n\ta:focus,\r\n\ta.active {\r\n\t\tbackground-color: rgba(var(--action-0), var(--op-6));\r\n\t\tcolor: var(--action-contrast);\r\n\t}\r\n}\r\n.glossary dd {\r\n\tmargin-left: .5rem;\r\n\twidth: calc(100% + .75rem);\r\n}\r\n.glossary dd,\r\n.glossary dt {\r\n\tposition: relative;\r\n\tleft: 0;\r\n\ttransition: margin var(--trans-base),\r\n\tleft var(--trans-base),\r\n\twidth var(--trans-base);\r\n}\r\n.glossary dt:target,\r\n.glossary dt.active {\r\n\toutline: none;\r\n\tleft: -1.5rem;\r\n\tpadding: 0;\r\n\tcolor: rgb(var(--action-0));\r\n}\r\n\t.glossary dt:target + dd,\r\n\t.glossary dt.active + dd {\r\n\t\tleft: -1.5rem;\r\n\t}\r\n\r\nmain header,\r\ndl.glossary {\r\n\tgrid-column: full;\r\n\tpadding: 0 var(--navWidth) 0 2rem;\r\n\t@media (min-width:768px) {\r\n\t\tmargin-left: auto;\r\n\t\tmax-width: var(--content);\r\n\t\tmargin-right: var(--navWidth);\r\n\t\tpadding-right: var(--btn);\r\n\t}\r\n}\r\n\r\n@media (max-width: 768px) {\r\n\t.glossary {\r\n\t\th2 {\r\n\t\t\tfont-size: var(--txt-medium);\r\n\t\t}\r\n\t\tp {\r\n\t\t\tfont-size: var(--txt-x-small);\r\n\t\t}\r\n\t}\r\n\t.glossary-index {\r\n\t\tli,a {\r\n\t\t\theight: fit-content;\r\n\t\t}\r\n\t\ta {\r\n\t\t\tfont-size: var(--txt-x-small);\r\n\t\t\tpadding: .25rem;\r\n\t\t\tmin-height: 2em;\r\n\t\t}\r\n\t}\r\n\r\n\tbody:has(.glossary) h1 {\r\n\t\tfont-size: var(--txt-xx-large);\r\n\t}\r\n}\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/glossary/view.asset.php b/build/glossary/view.asset.php
index f23ba65..a696152 100644
--- a/build/glossary/view.asset.php
+++ b/build/glossary/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => '01134b86c4f4fc8a5f6e');
+<?php return array('dependencies' => array(), 'version' => 'e30b748c75ec41be86b1');
diff --git a/build/glossary/view.js b/build/glossary/view.js
index 1512f0c..36573e5 100644
--- a/build/glossary/view.js
+++ b/build/glossary/view.js
@@ -1 +1,165 @@
-(()=>{class t{constructor(t="dl.glossary",e="nav.glossary-index"){this.glossary=document.querySelector(t),this.nav=document.querySelector(e),this.glossary&&this.nav&&(this.terms=this.glossary.querySelectorAll("dt[id]"),this.navList=this.nav.querySelector("ul"),this.activeClass="active",this.currentActive=null,this.init(),this.setupResizeHandler())}init(){const t={root:null,rootMargin:this.getRootMargin(),threshold:0};this.observer=new IntersectionObserver(t=>this.handleIntersection(t),t),this.terms.forEach(t=>this.observer.observe(t)),this.handleScroll=this.debounce(()=>this.checkActiveTerm(),100),window.addEventListener("scroll",this.handleScroll,{passive:!0})}getRootMargin(){return"-50% 0px -50% 0px"}setupResizeHandler(){let t;window.addEventListener("resize",()=>{clearTimeout(t),t=setTimeout(()=>{this.reinitialize()},250)})}reinitialize(){this.observer&&this.observer.disconnect(),this.init()}handleIntersection(t){const e=t.find(t=>t.isIntersecting);e&&this.setActive(e.target)}checkActiveTerm(){parseFloat(getComputedStyle(document.documentElement).fontSize);let t=null,e=1/0;this.terms.forEach(i=>{const s=i.getBoundingClientRect();if(s.top+s.height/2>=0&&s.top+s.height/2<=window.innerHeight){const n=window.innerHeight/2,r=Math.abs(s.top-n);r<e&&(e=r,t=i)}}),t&&this.setActive(t)}setActive(t){this.currentActive!==t&&(this.currentActive&&this.currentActive.classList.remove(this.activeClass),t.classList.add(this.activeClass),this.currentActive=t,this.updateNavigation(t.id))}updateNavigation(t){this.nav.querySelectorAll("a").forEach(t=>t.classList.remove(this.activeClass));const e=this.nav.querySelector(`a[href="#${t}"]`);e&&(e.classList.add(this.activeClass),this.centerNavItem(e))}centerNavItem(t){const e=this.navList.getBoundingClientRect(),i=t.getBoundingClientRect(),s=this.navList.scrollTop,n=i.top-e.top,r=e.height/2-i.height/2;this.navList.scrollTo({top:s+n-r,behavior:"smooth"})}debounce(t,e){let i;return function(...s){clearTimeout(i),i=setTimeout(()=>{clearTimeout(i),t(...s)},e)}}destroy(){this.observer&&this.observer.disconnect(),window.removeEventListener("scroll",this.handleScroll)}}"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{new t}):new t})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/*!******************************!*\
+  !*** ./src/glossary/view.js ***!
+  \******************************/
+/**
+ * Glossary Navigation Active State Manager
+ * Handles highlighting active terms as they scroll into view
+ * and syncing navigation with scroll position
+ */
+class GlossaryNavigator {
+  constructor(glossarySelector = 'dl.glossary', navSelector = 'nav.glossary-index') {
+    this.glossary = document.querySelector(glossarySelector);
+    this.nav = document.querySelector(navSelector);
+    if (!this.glossary || !this.nav) return;
+    this.terms = this.glossary.querySelectorAll('dt[id]');
+    this.navList = this.nav.querySelector('ul');
+    this.activeClass = 'active';
+    this.currentActive = null;
+    this.init();
+    this.setupResizeHandler();
+  }
+  init() {
+    // Set up Intersection Observer with screen-size appropriate margins
+    const observerOptions = {
+      root: null,
+      // viewport
+      rootMargin: this.getRootMargin(),
+      threshold: 0
+    };
+    this.observer = new IntersectionObserver(entries => this.handleIntersection(entries), observerOptions);
+
+    // Observe all terms
+    this.terms.forEach(term => this.observer.observe(term));
+
+    // Also handle manual scroll for edge cases
+    this.handleScroll = this.debounce(() => this.checkActiveTerm(), 100);
+    window.addEventListener('scroll', this.handleScroll, {
+      passive: true
+    });
+  }
+  getRootMargin() {
+    // On larger screens: centered (50% from top and bottom)
+    return '-50% 0px -50% 0px';
+  }
+  setupResizeHandler() {
+    let resizeTimer;
+    window.addEventListener('resize', () => {
+      clearTimeout(resizeTimer);
+      resizeTimer = setTimeout(() => {
+        // Reinitialize observer with new margins on resize
+        this.reinitialize();
+      }, 250);
+    });
+  }
+  reinitialize() {
+    // Disconnect old observer
+    if (this.observer) {
+      this.observer.disconnect();
+    }
+
+    // Create new observer with updated margins
+    this.init();
+  }
+  handleIntersection(entries) {
+    // Find the entry that's intersecting
+    const intersecting = entries.find(entry => entry.isIntersecting);
+    if (intersecting) {
+      this.setActive(intersecting.target);
+    }
+  }
+  checkActiveTerm() {
+    // Fallback method to find which term is in the trigger zone
+    const remInPixels = parseFloat(getComputedStyle(document.documentElement).fontSize);
+    const margin = remInPixels * 4;
+    let closestTerm = null;
+    let closestDistance = Infinity;
+    this.terms.forEach(term => {
+      const rect = term.getBoundingClientRect();
+      const isInZone = rect.top + rect.height / 2 >= 0 && rect.top + rect.height / 2 <= window.innerHeight;
+      if (isInZone) {
+        // Find closest to the trigger point
+        const triggerPoint = window.innerHeight / 2;
+        const distance = Math.abs(rect.top - triggerPoint);
+        if (distance < closestDistance) {
+          closestDistance = distance;
+          closestTerm = term;
+        }
+      }
+    });
+    if (closestTerm) {
+      this.setActive(closestTerm);
+    }
+  }
+  setActive(term) {
+    if (this.currentActive === term) return;
+
+    // Remove active class from previous term
+    if (this.currentActive) {
+      this.currentActive.classList.remove(this.activeClass);
+    }
+
+    // Add active class to current term
+    term.classList.add(this.activeClass);
+    this.currentActive = term;
+
+    // Update navigation
+    this.updateNavigation(term.id);
+  }
+  updateNavigation(termId) {
+    // Remove active from all nav links
+    const navLinks = this.nav.querySelectorAll('a');
+    navLinks.forEach(link => link.classList.remove(this.activeClass));
+
+    // Find and activate corresponding nav link
+    const activeLink = this.nav.querySelector(`a[href="#${termId}"]`);
+    if (activeLink) {
+      activeLink.classList.add(this.activeClass);
+
+      // Scroll the nav list to center the active link
+      this.centerNavItem(activeLink);
+    }
+  }
+  centerNavItem(link) {
+    const listRect = this.navList.getBoundingClientRect();
+    const linkRect = link.getBoundingClientRect();
+
+    // Calculate position to center the link in the nav container
+    const scrollTop = this.navList.scrollTop;
+    const linkOffset = linkRect.top - listRect.top;
+    const centerOffset = listRect.height / 2 - linkRect.height / 2;
+    this.navList.scrollTo({
+      top: scrollTop + linkOffset - centerOffset,
+      behavior: 'smooth'
+    });
+  }
+  debounce(func, wait) {
+    let timeout;
+    return function executedFunction(...args) {
+      const later = () => {
+        clearTimeout(timeout);
+        func(...args);
+      };
+      clearTimeout(timeout);
+      timeout = setTimeout(later, wait);
+    };
+  }
+  destroy() {
+    if (this.observer) {
+      this.observer.disconnect();
+    }
+    window.removeEventListener('scroll', this.handleScroll);
+  }
+}
+
+// Initialize when DOM is ready
+if (document.readyState === 'loading') {
+  document.addEventListener('DOMContentLoaded', () => {
+    new GlossaryNavigator();
+  });
+} else {
+  new GlossaryNavigator();
+}
+/******/ })()
+;
+//# sourceMappingURL=view.js.map
\ No newline at end of file
diff --git a/build/glossary/view.js.map b/build/glossary/view.js.map
new file mode 100644
index 0000000..4e77f2c
--- /dev/null
+++ b/build/glossary/view.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"glossary/view.js","mappings":"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","sources":["webpack://jvb/./src/glossary/view.js"],"sourcesContent":["/**\r\n * Glossary Navigation Active State Manager\r\n * Handles highlighting active terms as they scroll into view\r\n * and syncing navigation with scroll position\r\n */\r\nclass GlossaryNavigator {\r\n\tconstructor(glossarySelector = 'dl.glossary', navSelector = 'nav.glossary-index') {\r\n\t\tthis.glossary = document.querySelector(glossarySelector);\r\n\t\tthis.nav = document.querySelector(navSelector);\r\n\r\n\t\tif (!this.glossary || !this.nav) return;\r\n\r\n\t\tthis.terms = this.glossary.querySelectorAll('dt[id]');\r\n\t\tthis.navList = this.nav.querySelector('ul');\r\n\t\tthis.activeClass = 'active';\r\n\t\tthis.currentActive = null;\r\n\r\n\t\tthis.init();\r\n\t\tthis.setupResizeHandler();\r\n\t}\r\n\r\n\tinit() {\r\n\t\t// Set up Intersection Observer with screen-size appropriate margins\r\n\t\tconst observerOptions = {\r\n\t\t\troot: null, // viewport\r\n\t\t\trootMargin: this.getRootMargin(),\r\n\t\t\tthreshold: 0\r\n\t\t};\r\n\r\n\t\tthis.observer = new IntersectionObserver(\r\n\t\t\t(entries) => this.handleIntersection(entries),\r\n\t\t\tobserverOptions\r\n\t\t);\r\n\r\n\t\t// Observe all terms\r\n\t\tthis.terms.forEach(term => this.observer.observe(term));\r\n\r\n\t\t// Also handle manual scroll for edge cases\r\n\t\tthis.handleScroll = this.debounce(() => this.checkActiveTerm(), 100);\r\n\t\twindow.addEventListener('scroll', this.handleScroll, { passive: true });\r\n\t}\r\n\r\n\tgetRootMargin() {\r\n\t\t// On larger screens: centered (50% from top and bottom)\r\n\t\treturn '-50% 0px -50% 0px';\r\n\t}\r\n\r\n\tsetupResizeHandler() {\r\n\t\tlet resizeTimer;\r\n\t\twindow.addEventListener('resize', () => {\r\n\t\t\tclearTimeout(resizeTimer);\r\n\t\t\tresizeTimer = setTimeout(() => {\r\n\t\t\t\t// Reinitialize observer with new margins on resize\r\n\t\t\t\tthis.reinitialize();\r\n\t\t\t}, 250);\r\n\t\t});\r\n\t}\r\n\r\n\treinitialize() {\r\n\t\t// Disconnect old observer\r\n\t\tif (this.observer) {\r\n\t\t\tthis.observer.disconnect();\r\n\t\t}\r\n\r\n\t\t// Create new observer with updated margins\r\n\t\tthis.init();\r\n\t}\r\n\r\n\thandleIntersection(entries) {\r\n\t\t// Find the entry that's intersecting\r\n\t\tconst intersecting = entries.find(entry => entry.isIntersecting);\r\n\r\n\t\tif (intersecting) {\r\n\t\t\tthis.setActive(intersecting.target);\r\n\t\t}\r\n\t}\r\n\r\n\tcheckActiveTerm() {\r\n\t\t// Fallback method to find which term is in the trigger zone\r\n\t\tconst remInPixels = parseFloat(getComputedStyle(document.documentElement).fontSize);\r\n\t\tconst margin = remInPixels * 4;\r\n\r\n\t\tlet closestTerm = null;\r\n\t\tlet closestDistance = Infinity;\r\n\r\n\t\tthis.terms.forEach(term => {\r\n\t\t\tconst rect = term.getBoundingClientRect();\r\n\r\n\t\t\tconst isInZone = rect.top + rect.height / 2 >= 0 && rect.top + rect.height / 2 <= window.innerHeight;\r\n\r\n\t\t\tif (isInZone) {\r\n\t\t\t\t// Find closest to the trigger point\r\n\t\t\t\tconst triggerPoint = window.innerHeight / 2;\r\n\r\n\t\t\t\tconst distance = Math.abs(rect.top - triggerPoint);\r\n\r\n\t\t\t\tif (distance < closestDistance) {\r\n\t\t\t\t\tclosestDistance = distance;\r\n\t\t\t\t\tclosestTerm = term;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tif (closestTerm) {\r\n\t\t\tthis.setActive(closestTerm);\r\n\t\t}\r\n\t}\r\n\r\n\tsetActive(term) {\r\n\t\tif (this.currentActive === term) return;\r\n\r\n\t\t// Remove active class from previous term\r\n\t\tif (this.currentActive) {\r\n\t\t\tthis.currentActive.classList.remove(this.activeClass);\r\n\t\t}\r\n\r\n\t\t// Add active class to current term\r\n\t\tterm.classList.add(this.activeClass);\r\n\t\tthis.currentActive = term;\r\n\r\n\t\t// Update navigation\r\n\t\tthis.updateNavigation(term.id);\r\n\t}\r\n\r\n\tupdateNavigation(termId) {\r\n\t\t// Remove active from all nav links\r\n\t\tconst navLinks = this.nav.querySelectorAll('a');\r\n\t\tnavLinks.forEach(link => link.classList.remove(this.activeClass));\r\n\r\n\t\t// Find and activate corresponding nav link\r\n\t\tconst activeLink = this.nav.querySelector(`a[href=\"#${termId}\"]`);\r\n\r\n\t\tif (activeLink) {\r\n\t\t\tactiveLink.classList.add(this.activeClass);\r\n\r\n\t\t\t// Scroll the nav list to center the active link\r\n\t\t\tthis.centerNavItem(activeLink);\r\n\t\t}\r\n\t}\r\n\r\n\tcenterNavItem(link) {\r\n\t\tconst listRect = this.navList.getBoundingClientRect();\r\n\t\tconst linkRect = link.getBoundingClientRect();\r\n\r\n\t\t// Calculate position to center the link in the nav container\r\n\t\tconst scrollTop = this.navList.scrollTop;\r\n\t\tconst linkOffset = linkRect.top - listRect.top;\r\n\t\tconst centerOffset = (listRect.height / 2) - (linkRect.height / 2);\r\n\r\n\t\tthis.navList.scrollTo({\r\n\t\t\ttop: scrollTop + linkOffset - centerOffset,\r\n\t\t\tbehavior: 'smooth'\r\n\t\t});\r\n\t}\r\n\r\n\tdebounce(func, wait) {\r\n\t\tlet timeout;\r\n\t\treturn function executedFunction(...args) {\r\n\t\t\tconst later = () => {\r\n\t\t\t\tclearTimeout(timeout);\r\n\t\t\t\tfunc(...args);\r\n\t\t\t};\r\n\t\t\tclearTimeout(timeout);\r\n\t\t\ttimeout = setTimeout(later, wait);\r\n\t\t};\r\n\t}\r\n\r\n\tdestroy() {\r\n\t\tif (this.observer) {\r\n\t\t\tthis.observer.disconnect();\r\n\t\t}\r\n\t\twindow.removeEventListener('scroll', this.handleScroll);\r\n\t}\r\n}\r\n\r\n\r\n// Initialize when DOM is ready\r\nif (document.readyState === 'loading') {\r\n\tdocument.addEventListener('DOMContentLoaded', () => {\r\n\t\tnew GlossaryNavigator();\r\n\t});\r\n} else {\r\n\tnew GlossaryNavigator();\r\n}\r\n"],"names":["GlossaryNavigator","constructor","glossarySelector","navSelector","glossary","document","querySelector","nav","terms","querySelectorAll","navList","activeClass","currentActive","init","setupResizeHandler","observerOptions","root","rootMargin","getRootMargin","threshold","observer","IntersectionObserver","entries","handleIntersection","forEach","term","observe","handleScroll","debounce","checkActiveTerm","window","addEventListener","passive","resizeTimer","clearTimeout","setTimeout","reinitialize","disconnect","intersecting","find","entry","isIntersecting","setActive","target","remInPixels","parseFloat","getComputedStyle","documentElement","fontSize","margin","closestTerm","closestDistance","Infinity","rect","getBoundingClientRect","isInZone","top","height","innerHeight","triggerPoint","distance","Math","abs","classList","remove","add","updateNavigation","id","termId","navLinks","link","activeLink","centerNavItem","listRect","linkRect","scrollTop","linkOffset","centerOffset","scrollTo","behavior","func","wait","timeout","executedFunction","args","later","destroy","removeEventListener","readyState"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/gmbreviews/index-rtl.css b/build/gmbreviews/index-rtl.css
index 8b13789..45fec35 100644
--- a/build/gmbreviews/index-rtl.css
+++ b/build/gmbreviews/index-rtl.css
@@ -1 +1,4 @@
+/*!***************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/gmbreviews/editor.scss ***!
+  \***************************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/gmbreviews/index.asset.php b/build/gmbreviews/index.asset.php
index 467523e..b18041a 100644
--- a/build/gmbreviews/index.asset.php
+++ b/build/gmbreviews/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n', 'wp-server-side-render'), 'version' => '9abfec4c1bba023a261c');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n', 'wp-server-side-render'), 'version' => 'dc847e00ceda934012c0');
diff --git a/build/gmbreviews/index.css b/build/gmbreviews/index.css
index 8b13789..45fec35 100644
--- a/build/gmbreviews/index.css
+++ b/build/gmbreviews/index.css
@@ -1 +1,4 @@
+/*!***************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/gmbreviews/editor.scss ***!
+  \***************************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/gmbreviews/index.js b/build/gmbreviews/index.js
index 4753593..05e614c 100644
--- a/build/gmbreviews/index.js
+++ b/build/gmbreviews/index.js
@@ -1 +1,408 @@
-(()=>{"use strict";var e,o={819(e,o,n){const r=window.wp.blocks,t=window.wp.blockEditor,i=window.wp.components,l=window.wp.i18n,s=window.wp.serverSideRender;var a=n.n(s);const h=window.ReactJSXRuntime,v=JSON.parse('{"UU":"jvb/gmbreviews"}');(0,r.registerBlockType)(v.UU,{edit:function({attributes:e,setAttributes:o}){const n=(0,t.useBlockProps)(),{count:r,inheritUser:s,showStats:v,minStars:w,showViewAllLink:b,showRating:c,showDate:g,showReviewLink:d}=e;return(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(t.InspectorControls,{children:(0,h.jsxs)(i.PanelBody,{title:(0,l.__)("Review Settings","jvb"),children:[(0,h.jsx)(i.ToggleControl,{label:(0,l.__)("Inherit User","jvb"),checked:s,onChange:e=>o({inheritUser:e})}),(0,h.jsx)(i.RangeControl,{label:(0,l.__)("Number of Reviews","jvb"),value:r,onChange:e=>o({count:e}),min:1,max:20}),(0,h.jsx)(i.ToggleControl,{label:(0,l.__)("Show Rating","jvb"),checked:c,onChange:e=>o({showRating:e})}),(0,h.jsx)(i.ToggleControl,{label:(0,l.__)("Show Date","jvb"),checked:g,onChange:e=>o({showDate:e})}),(0,h.jsx)(i.ToggleControl,{label:(0,l.__)("Show Review Link","jvb"),checked:d,onChange:e=>o({showReviewLink:e})}),(0,h.jsx)(i.ToggleControl,{label:(0,l.__)("Show Stats","jvb"),checked:v,onChange:e=>o({showStats:e})}),(0,h.jsx)(i.ToggleControl,{label:(0,l.__)("Show All Reviews Link","jvb"),checked:b,onChange:e=>o({showViewAllLink:e})}),(0,h.jsx)(i.RangeControl,{label:(0,l.__)("Minimum Rating","jvb"),value:w,onChange:e=>o({minStars:e}),min:1,max:5})]})}),(0,h.jsx)("div",{...n,children:(0,h.jsx)(a(),{block:"jvb/gmbreviews",attributes:e})})]})},save:()=>null})}},n={};function r(e){var t=n[e];if(void 0!==t)return t.exports;var i=n[e]={exports:{}};return o[e](i,i.exports,r),i.exports}r.m=o,e=[],r.O=(o,n,t,i)=>{if(!n){var l=1/0;for(v=0;v<e.length;v++){for(var[n,t,i]=e[v],s=!0,a=0;a<n.length;a++)(!1&i||l>=i)&&Object.keys(r.O).every(e=>r.O[e](n[a]))?n.splice(a--,1):(s=!1,i<l&&(l=i));if(s){e.splice(v--,1);var h=t();void 0!==h&&(o=h)}}return o}i=i||0;for(var v=e.length;v>0&&e[v-1][2]>i;v--)e[v]=e[v-1];e[v]=[n,t,i]},r.n=e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return r.d(o,{a:o}),o},r.d=(e,o)=>{for(var n in o)r.o(o,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:o[n]})},r.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),(()=>{var e={807:0,423:0};r.O.j=o=>0===e[o];var o=(o,n)=>{var t,i,[l,s,a]=n,h=0;if(l.some(o=>0!==e[o])){for(t in s)r.o(s,t)&&(r.m[t]=s[t]);if(a)var v=a(r)}for(o&&o(n);h<l.length;h++)i=l[h],r.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return r.O(v)},n=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];n.forEach(o.bind(null,0)),n.push=o.bind(null,n.push.bind(n))})();var t=r.O(void 0,[423],()=>r(819));t=r.O(t)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/gmbreviews/edit.js"
+/*!********************************!*\
+  !*** ./src/gmbreviews/edit.js ***!
+  \********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__);
+/* harmony import */ var _wordpress_server_side_render__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/server-side-render */ "@wordpress/server-side-render");
+/* harmony import */ var _wordpress_server_side_render__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_server_side_render__WEBPACK_IMPORTED_MODULE_3__);
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__);
+// src/gmbreviews/edit.js
+
+
+
+
+
+function Edit({
+  attributes,
+  setAttributes
+}) {
+  const blockProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__.useBlockProps)();
+  const {
+    count,
+    inheritUser,
+    showStats,
+    minStars,
+    showViewAllLink,
+    showRating,
+    showDate,
+    showReviewLink
+  } = attributes;
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.Fragment, {
+    children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_0__.InspectorControls, {
+      children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.PanelBody, {
+        title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Review Settings', 'jvb'),
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Inherit User', 'jvb'),
+          checked: inheritUser,
+          onChange: value => setAttributes({
+            inheritUser: value
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.RangeControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Number of Reviews', 'jvb'),
+          value: count,
+          onChange: value => setAttributes({
+            count: value
+          }),
+          min: 1,
+          max: 20
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Show Rating', 'jvb'),
+          checked: showRating,
+          onChange: value => setAttributes({
+            showRating: value
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Show Date', 'jvb'),
+          checked: showDate,
+          onChange: value => setAttributes({
+            showDate: value
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Show Review Link', 'jvb'),
+          checked: showReviewLink,
+          onChange: value => setAttributes({
+            showReviewLink: value
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Show Stats', 'jvb'),
+          checked: showStats,
+          onChange: value => setAttributes({
+            showStats: value
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Show All Reviews Link', 'jvb'),
+          checked: showViewAllLink,
+          onChange: value => setAttributes({
+            showViewAllLink: value
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_1__.RangeControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_2__.__)('Minimum Rating', 'jvb'),
+          value: minStars,
+          onChange: value => setAttributes({
+            minStars: value
+          }),
+          min: 1,
+          max: 5
+        })]
+      })
+    }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("div", {
+      ...blockProps,
+      children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)((_wordpress_server_side_render__WEBPACK_IMPORTED_MODULE_3___default()), {
+        block: "jvb/gmbreviews",
+        attributes: attributes
+      })
+    })]
+  });
+}
+
+/***/ },
+
+/***/ "./src/gmbreviews/index.js"
+/*!*********************************!*\
+  !*** ./src/gmbreviews/index.js ***!
+  \*********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./edit */ "./src/gmbreviews/edit.js");
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./style.scss */ "./src/gmbreviews/style.scss");
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./editor.scss */ "./src/gmbreviews/editor.scss");
+/* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./block.json */ "./src/gmbreviews/block.json");
+
+
+
+
+
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)(_block_json__WEBPACK_IMPORTED_MODULE_4__.name, {
+  edit: _edit__WEBPACK_IMPORTED_MODULE_1__["default"],
+  // No save function - dynamic block rendered on server
+  save: () => null
+});
+
+/***/ },
+
+/***/ "./src/gmbreviews/editor.scss"
+/*!************************************!*\
+  !*** ./src/gmbreviews/editor.scss ***!
+  \************************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "./src/gmbreviews/style.scss"
+/*!***********************************!*\
+  !*** ./src/gmbreviews/style.scss ***!
+  \***********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/components"
+/*!************************************!*\
+  !*** external ["wp","components"] ***!
+  \************************************/
+(module) {
+
+module.exports = window["wp"]["components"];
+
+/***/ },
+
+/***/ "@wordpress/i18n"
+/*!******************************!*\
+  !*** external ["wp","i18n"] ***!
+  \******************************/
+(module) {
+
+module.exports = window["wp"]["i18n"];
+
+/***/ },
+
+/***/ "@wordpress/server-side-render"
+/*!******************************************!*\
+  !*** external ["wp","serverSideRender"] ***!
+  \******************************************/
+(module) {
+
+module.exports = window["wp"]["serverSideRender"];
+
+/***/ },
+
+/***/ "./src/gmbreviews/block.json"
+/*!***********************************!*\
+  !*** ./src/gmbreviews/block.json ***!
+  \***********************************/
+(module) {
+
+module.exports = /*#__PURE__*/JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/gmbreviews","title":"GMB Reviews","category":"jvb","description":"Display top-rated Google My Business reviews with statistics and action buttons","keywords":["reviews","google","testimonials","gmb","ratings"],"textdomain":"jvb","attributes":{"inheritUser":{"type":"boolean","default":false},"count":{"type":"number","default":5},"showRating":{"type":"boolean","default":true},"showDate":{"type":"boolean","default":true},"showReviewLink":{"type":"boolean","default":true},"showViewAllLink":{"type":"boolean","default":true},"showStats":{"type":"boolean","default":true},"minStars":{"type":"number","default":4,"minimum":1,"maximum":5}},"supports":{"html":false,"align":true,"color":{"text":true,"background":true,"link":true},"spacing":{"margin":true,"padding":true},"typography":{"fontSize":true,"lineHeight":true}},"render":"file:./render.php","editorScript":"file:./index.js","editorStyle":"file:./index.css","style":"file:./style-index.css","viewScript":"file:./view.js"}');
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"gmbreviews/index": 0,
+/******/ 			"gmbreviews/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["gmbreviews/style-index"], () => (__webpack_require__("./src/gmbreviews/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/gmbreviews/index.js.map b/build/gmbreviews/index.js.map
new file mode 100644
index 0000000..a71db8b
--- /dev/null
+++ b/build/gmbreviews/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"gmbreviews/index.js","mappings":"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;;;;;;;;ACAA,4C;;;;;;;;;;ACAA,sC;;;;;;;;;;ACAA,kD;;;;;;;;;;;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WC/BA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G;;;;;UEjDA;UACA;UACA;UACA;UACA","sources":["webpack://jvb/./src/gmbreviews/edit.js","webpack://jvb/./src/gmbreviews/index.js","webpack://jvb/./src/gmbreviews/editor.scss","webpack://jvb/./src/gmbreviews/style.scss?439b","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"components\"]","webpack://jvb/external window [\"wp\",\"i18n\"]","webpack://jvb/external window [\"wp\",\"serverSideRender\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["// src/gmbreviews/edit.js\r\nimport { useBlockProps, InspectorControls } from '@wordpress/block-editor';\r\nimport { PanelBody, RangeControl, ToggleControl } from '@wordpress/components';\r\nimport { __ } from '@wordpress/i18n';\r\nimport ServerSideRender from '@wordpress/server-side-render';\r\n\r\nexport default function Edit({ attributes, setAttributes }) {\r\n\tconst blockProps = useBlockProps();\r\n\tconst { count, inheritUser, showStats, minStars, showViewAllLink, showRating, showDate, showReviewLink } = attributes;\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<InspectorControls>\r\n\t\t\t\t<PanelBody title={__('Review Settings', 'jvb')}>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Inherit User', 'jvb')}\r\n\t\t\t\t\t\tchecked={inheritUser}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ inheritUser: value })}\r\n\t\t\t\t\t/>\r\n\t\t\t\t\t<RangeControl\r\n\t\t\t\t\t\tlabel={__('Number of Reviews', 'jvb')}\r\n\t\t\t\t\t\tvalue={count}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ count: value })}\r\n\t\t\t\t\t\tmin={1}\r\n\t\t\t\t\t\tmax={20}\r\n\t\t\t\t\t/>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Show Rating', 'jvb')}\r\n\t\t\t\t\t\tchecked={showRating}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ showRating: value })}\r\n\t\t\t\t\t/>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Show Date', 'jvb')}\r\n\t\t\t\t\t\tchecked={showDate}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ showDate: value })}\r\n\t\t\t\t\t/>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Show Review Link', 'jvb')}\r\n\t\t\t\t\t\tchecked={showReviewLink}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ showReviewLink: value })}\r\n\t\t\t\t\t/>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Show Stats', 'jvb')}\r\n\t\t\t\t\t\tchecked={showStats}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ showStats: value })}\r\n\t\t\t\t\t/>\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Show All Reviews Link', 'jvb')}\r\n\t\t\t\t\t\tchecked={showViewAllLink}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ showViewAllLink: value })}\r\n\t\t\t\t\t/>\r\n\t\t\t\t\t<RangeControl\r\n\t\t\t\t\t\tlabel={__('Minimum Rating', 'jvb')}\r\n\t\t\t\t\t\tvalue={minStars}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ minStars: value })}\r\n\t\t\t\t\t\tmin={1}\r\n\t\t\t\t\t\tmax={5}\r\n\t\t\t\t\t/>\r\n\t\t\t\t</PanelBody>\r\n\t\t\t</InspectorControls>\r\n\t\t\t<div {...blockProps}>\r\n\t\t\t\t<ServerSideRender\r\n\t\t\t\t\tblock=\"jvb/gmbreviews\"\r\n\t\t\t\t\tattributes={attributes}\r\n\t\t\t\t/>\r\n\t\t\t</div>\r\n\t\t</>\r\n\t);\r\n}\r\n","import { registerBlockType } from '@wordpress/blocks';\r\nimport Edit from './edit';\r\nimport './style.scss';\r\nimport './editor.scss';\r\nimport metadata from './block.json';\r\n\r\nregisterBlockType(metadata.name, {\r\n\tedit: Edit,\r\n\t// No save function - dynamic block rendered on server\r\n\tsave: () => null,\r\n});\r\n","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"components\"];","module.exports = window[\"wp\"][\"i18n\"];","module.exports = window[\"wp\"][\"serverSideRender\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"gmbreviews/index\": 0,\n\t\"gmbreviews/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"gmbreviews/style-index\"], () => (__webpack_require__(\"./src/gmbreviews/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["useBlockProps","InspectorControls","PanelBody","RangeControl","ToggleControl","__","ServerSideRender","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","Edit","attributes","setAttributes","blockProps","count","inheritUser","showStats","minStars","showViewAllLink","showRating","showDate","showReviewLink","children","title","label","checked","onChange","value","min","max","block","registerBlockType","metadata","name","edit","save"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/gmbreviews/render.php b/build/gmbreviews/render.php
index 779c1c4..b3d9bbc 100644
--- a/build/gmbreviews/render.php
+++ b/build/gmbreviews/render.php
@@ -1,208 +1 @@
 <?php
-/**
- * GMB Reviews Block - Render Template
- *
- * Displays recent Google My Business reviews with a link to leave a review
- */
-function jvbRenderGMBReviewsBlock(array $attributes): string
-{
-	$count = $attributes['count'] ?? 5;
-	$showRating = $attributes['showRating'] ?? true;
-	$showDate = $attributes['showDate'] ?? true;
-	$showReviewLink = $attributes['showReviewLink'] ?? true;
-	$showViewAllLink = $attributes['showViewAllLink'] ?? true;
-	$showStats = $attributes['showStats'] ?? true;
-	$minStars = $attributes['minStars'] ?? 4; // Only show 4+ star reviews
-	$inheritUser = $attributes['inheritUser']??null;
-	if ($inheritUser) {
-		global $post;
-		$inheritUser = $post->post_author;
-	}else {
-		$inheritUser = null;
-	}
-	try {
-		$gmb = JVB()->connect('gmb', $inheritUser);
-		if (!$gmb->isSetUp()) {
-			error_log('GMB Not set up for: '.(int)$inheritUser);
-			return '';
-		}
-		$gotReviews = $gmb->getReviews();
-		// Get all data
-		$allReviews = $gotReviews['reviews']??[];
-		$reviewUrl = $gmb->getReviewUrl();
-		$viewAllUrl = $gmb->getReviewsViewUrl();
-
-		$average = $gotReviews['averageRating']??null;
-		$total = $gotReviews['totalReviewCount']??null;
-
-		// Filter reviews by minimum stars
-		$reviews = [];
-		if (!empty($allReviews)) {
-			foreach ($allReviews as $review) {
-				$rating = $review['starRating'] ?? 0;
-				if ($rating >= $minStars) {
-					$reviews[] = $review;
-					if (count($reviews) >= $count) {
-						break; // Got enough reviews
-					}
-				}
-			}
-		}
-
-		if (empty($reviews) && empty($reviewUrl) && empty($stats)) {
-			error_log('No reviews to display...');
-			return '';
-		}
-
-		ob_start();
-		?>
-		<div class="gmb-reviews">
-			<div class="row x-mid">
-			<?php
-			if ($showStats && !empty($average) && !empty($total)) {
-				?>
-				<p>
-					<span class="stars" title="<?= $average ?> out of 5 stars">
-						<?php
-						$fullStars = floor($average);
-						$hasHalfStar = ($average - $fullStars) >= 0.5;
-
-						for ($i = 1; $i <= 5; $i++) {
-							if ($i <= $fullStars) {
-								echo jvbIcon('star', ['style' => 'fill']);
-							} elseif ($i == $fullStars + 1 && $hasHalfStar) {
-								echo jvbIcon('star-half', ['style'=> 'fill']);
-							} else {
-								echo  jvbIcon('star', ['style' => 'light']);
-							}
-						}
-						?>
-					</span>
-					<i>Average</i>
-				</p>
-				<?php
-				if ($total > 0) {
-					?>
-					<p><i>{ <?= number_format($total ) . ' ' . _n('Review', 'Reviews', $total, 'jvb')?> Total }</i></p>
-					<?php
-				}
-			?>
-			<?php
-			}
-			?>
-
-
-		</div>
-			<?php
-			if ($showReviewLink && !empty($reviewUrl)) {
-				?>
-				<a href="<?=esc_url($reviewUrl)?>"
-				   class="btn"
-				   target="_blank"
-				   rel="noopener noreferrer">
-					<?= jvbIcon('star', ['style' => 'fill']) ?>
-					Leave Your Review
-				</a>
-				<?php
-			}
-			?>
-
-		<ul>
-			<?php
-			foreach ($reviews as $review) {
-				$reviewer = $review['reviewer']['displayName'] ?? 'Anonymous';
-				$reviewer = strtok($reviewer, ' ');
-				$profilePhoto = $review['reviewer']['profilePhotoUrl'] ?? '';
-				$rating = $review['starRating'] ?? 0;
-				$rating = match($rating) {
-					'FIVE'	=> 5,
-					'FOUR'	=> 4,
-					'THREE'	=> 3,
-					'TWO'	=> 2,
-					'ONE'	=> 1,
-					default =>  $rating
-				};
-				$comment = $review['comment'] ?? '';
-				$date = $review['updateTime'] ?? '';
-				?>
-				<li>
-					<blockquote class="review">
-						<?php
-						echo jvbIcon('quotes',['style' => 'fill']);
-						// Review text
-						if (!empty($comment)) { ?>
-							<div class="content review">
-								<?= apply_filters('wpautop', $comment) ?>
-							</div>
-						<?php } ?>
-						<cite class="row left nowrap">
-							<?php if (!empty($profilePhoto)) { ?>
-								<img src="<?=esc_url($profilePhoto)?>"
-									 alt="<?=esc_attr($reviewer)?>"
-								'loading="lazy">
-							<?php } else { ?>
-								<div class="avatar">
-									<?= jvbIcon('user-circle')?>
-								</div>
-							<?php } ?>
-
-							<div class="row left wrap">
-								<?php if ($showRating && $rating > 0) { ?>
-									<div class="stars" title="<?= $rating ?> out of 5 stars">
-										<?php
-										for ($i = 1; $i <= 5; $i++) {
-											echo ($i <= $rating) ? jvbIcon('star', ['style' => 'fill']) : jvbIcon('star', ['style' => 'light']);
-										} ?>
-									</div>
-								<?php } ?>
-								<p><?= esc_html($reviewer)?></p>
-								<?php
-								// Date
-								if ($showDate && !empty($date)) {
-									$formatted_date = human_time_diff(strtotime($date), current_time('timestamp')) . ' ago';
-									?>
-									<time datetime="<?=esc_attr($date)?>">
-										<?= esc_html($formatted_date) ?>
-									</time>
-								<?php } ?>
-
-							</div>
-						</cite>
-					</blockquote>
-				</li>
-			<?php
-			}
-			?>
-		</ul>
-		<?php
-		// Footer with "See All Reviews" button
-		if ($showViewAllLink && !empty($viewAllUrl)) {
-			?>
-			<div class="footer">
-				<a href=" <?= esc_url($viewAllUrl) ?>"
-					class="btn"
-					target="_blank"
-					rel="noopener noreferrer">
-
-					<?php
-					if ($showStats ) {
-						echo 'See All ' . number_format($total) . ' Reviews';
-					} else {
-						echo ' See All Reviews';
-					}
-					?>
-					<?= jvbIcon('arrow-square-out') ?>
-				</a>
-			</div>
-		<?php
-		}
-		?>
-		</div>
-		<?php
-		return ob_get_clean();
-
-	} catch (\Exception $e) {
-		error_log('[GMB Reviews Block] Error: ' . $e->getMessage());
-		return '';
-	}
-}
diff --git a/build/gmbreviews/style-index-rtl.css b/build/gmbreviews/style-index-rtl.css
index f4dca2a..a7f758b 100644
--- a/build/gmbreviews/style-index-rtl.css
+++ b/build/gmbreviews/style-index-rtl.css
@@ -1 +1,126 @@
-.gmb-reviews{max-width:none}.gmb-reviews>.row.x-mid{margin:0 auto;max-width:var(--content);--gap:.5rem 6rem}.gmb-reviews>.row.x-mid p{width:-moz-fit-content;width:fit-content}.gmb-reviews .button{display:flex;height:-moz-max-content;height:max-content;margin:0 auto 2rem;width:66.6%}.gmb-reviews .stars{align-items:center;display:inline-flex;flex-wrap:nowrap;justify-content:flex-start}.gmb-reviews ul{list-style:none;margin:0;max-width:var(--full);padding:0}.gmb-reviews ul li{max-width:none;padding:4rem 1rem;width:100%}.gmb-reviews ul li:nth-of-type(odd){background-color:rgb(var(--base-50))}.gmb-reviews ul li:nth-of-type(odd) blockquote{--background:rgb(var(--base-50))}.gmb-reviews ul li:nth-of-type(2n){background-color:rgb(var(--base-100))}.gmb-reviews ul li:nth-of-type(2n) blockquote{--background:rgb(var(--base-100))}.gmb-reviews blockquote{border-top:1px solid rgb(var(--base-200));margin:1rem auto;max-width:var(--content);padding:1rem 0 0}.gmb-reviews blockquote .icon-quotes-fi{right:calc(var(--btnbtn)*-1)}.gmb-reviews blockquote .content,.gmb-reviews blockquote .content:after{border-width:4px 1px}.gmb-reviews blockquote .content:before{border-width:8px;bottom:-4px}.gmb-reviews blockquote cite{margin-top:var(--btn);position:relative}.gmb-reviews blockquote cite img{right:-8rem;position:absolute;top:0;width:4.5rem}.gmb-reviews blockquote cite p{margin:0}.gmb-reviews blockquote cite .wrap{--wrap:wrap}.gmb-reviews blockquote cite .wrap p,.gmb-reviews blockquote cite .wrap time{max-width:49%}.gmb-reviews blockquote cite .wrap .stars{width:100%}.gmb-reviews blockquote time{white-space:nowrap}.gmb-reviews .stars .icon{background-color:rgb(var(--action-0))}.gmb-reviews article{background-color:rgb(var(--base));border-radius:var(--radius-outer);padding:1rem}.gmb-reviews article header{--align:center}.gmb-reviews article header>img{right:0;position:relative}.gmb-reviews article time{font-style:italic}.gmb-reviews article .review{padding:1.5rem}.gmb-reviews article h4{width:-moz-max-content;width:max-content}.gmb-reviews article .icon{color:rgb(var(--action-0))}.gmb-reviews .btn{width:100%}
+/*!**************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/gmbreviews/style.scss ***!
+  \**************************************************************************************************************************************************************************************************************************************************/
+.gmb-reviews {
+  max-width: none;
+}
+.gmb-reviews > .row.x-mid {
+  max-width: var(--content);
+  margin: 0 auto;
+  --gap: .5rem 6rem;
+}
+.gmb-reviews > .row.x-mid p {
+  width: -moz-fit-content;
+  width: fit-content;
+}
+.gmb-reviews .button {
+  width: 66.6%;
+  margin: 0 auto 2rem;
+  display: flex;
+  height: -moz-max-content;
+  height: max-content;
+}
+.gmb-reviews .stars {
+  display: inline-flex;
+  align-items: center;
+  justify-content: flex-start;
+  flex-wrap: nowrap;
+}
+.gmb-reviews ul {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  max-width: var(--full);
+}
+.gmb-reviews ul li {
+  width: 100%;
+  max-width: none;
+  padding: 4rem 1rem;
+}
+.gmb-reviews ul li:nth-of-type(odd) {
+  background-color: rgb(var(--base-50));
+}
+.gmb-reviews ul li:nth-of-type(odd) blockquote {
+  --background: rgb(var(--base-50));
+}
+.gmb-reviews ul li:nth-of-type(even) {
+  background-color: rgb(var(--base-100));
+}
+.gmb-reviews ul li:nth-of-type(even) blockquote {
+  --background: rgb(var(--base-100));
+}
+.gmb-reviews blockquote {
+  margin: 1rem auto;
+  padding: 1rem 0 0;
+  max-width: var(--content);
+  border-top: 1px solid rgb(var(--base-200));
+}
+.gmb-reviews blockquote .icon-quotes-fi {
+  right: calc(var(--btnbtn) * -1);
+}
+.gmb-reviews blockquote .content {
+  border-width: 4px 1px;
+}
+.gmb-reviews blockquote .content::after {
+  border-width: 4px 1px;
+}
+.gmb-reviews blockquote .content::before {
+  border-width: 8px;
+  bottom: -4px;
+}
+.gmb-reviews blockquote cite {
+  position: relative;
+  margin-top: var(--btn);
+}
+.gmb-reviews blockquote cite img {
+  width: 4.5rem;
+  position: absolute;
+  right: -8rem;
+  top: 0;
+}
+.gmb-reviews blockquote cite p {
+  margin: 0;
+}
+.gmb-reviews blockquote cite .wrap {
+  --wrap: wrap;
+}
+.gmb-reviews blockquote cite .wrap p, .gmb-reviews blockquote cite .wrap time {
+  max-width: 49%;
+}
+.gmb-reviews blockquote cite .wrap .stars {
+  width: 100%;
+}
+.gmb-reviews blockquote time {
+  white-space: nowrap;
+}
+.gmb-reviews .stars .icon {
+  background-color: rgb(var(--action-0));
+}
+.gmb-reviews article {
+  padding: 1rem;
+  border-radius: var(--radius-outer);
+  background-color: rgb(var(--base));
+}
+.gmb-reviews article header {
+  --align: center;
+}
+.gmb-reviews article header > img {
+  position: relative;
+  right: 0;
+}
+.gmb-reviews article time {
+  font-style: italic;
+}
+.gmb-reviews article .review {
+  padding: 1.5rem;
+}
+.gmb-reviews article h4 {
+  width: -moz-max-content;
+  width: max-content;
+}
+.gmb-reviews article .icon {
+  color: rgb(var(--action-0));
+}
+.gmb-reviews .btn {
+  width: 100%;
+}
diff --git a/build/gmbreviews/style-index.css b/build/gmbreviews/style-index.css
index 52b0a43..1c6c539 100644
--- a/build/gmbreviews/style-index.css
+++ b/build/gmbreviews/style-index.css
@@ -1 +1,128 @@
-.gmb-reviews{max-width:none}.gmb-reviews>.row.x-mid{margin:0 auto;max-width:var(--content);--gap:.5rem 6rem}.gmb-reviews>.row.x-mid p{width:-moz-fit-content;width:fit-content}.gmb-reviews .button{display:flex;height:-moz-max-content;height:max-content;margin:0 auto 2rem;width:66.6%}.gmb-reviews .stars{align-items:center;display:inline-flex;flex-wrap:nowrap;justify-content:flex-start}.gmb-reviews ul{list-style:none;margin:0;max-width:var(--full);padding:0}.gmb-reviews ul li{max-width:none;padding:4rem 1rem;width:100%}.gmb-reviews ul li:nth-of-type(odd){background-color:rgb(var(--base-50))}.gmb-reviews ul li:nth-of-type(odd) blockquote{--background:rgb(var(--base-50))}.gmb-reviews ul li:nth-of-type(2n){background-color:rgb(var(--base-100))}.gmb-reviews ul li:nth-of-type(2n) blockquote{--background:rgb(var(--base-100))}.gmb-reviews blockquote{border-top:1px solid rgb(var(--base-200));margin:1rem auto;max-width:var(--content);padding:1rem 0 0}.gmb-reviews blockquote .icon-quotes-fi{left:calc(var(--btnbtn)*-1)}.gmb-reviews blockquote .content,.gmb-reviews blockquote .content:after{border-width:4px 1px}.gmb-reviews blockquote .content:before{border-width:8px;bottom:-4px}.gmb-reviews blockquote cite{margin-top:var(--btn);position:relative}.gmb-reviews blockquote cite img{left:-8rem;position:absolute;top:0;width:4.5rem}.gmb-reviews blockquote cite p{margin:0}.gmb-reviews blockquote cite .wrap{--wrap:wrap}.gmb-reviews blockquote cite .wrap p,.gmb-reviews blockquote cite .wrap time{max-width:49%}.gmb-reviews blockquote cite .wrap .stars{width:100%}.gmb-reviews blockquote time{white-space:nowrap}.gmb-reviews .stars .icon{background-color:rgb(var(--action-0))}.gmb-reviews article{background-color:rgb(var(--base));border-radius:var(--radius-outer);padding:1rem}.gmb-reviews article header{--align:center}.gmb-reviews article header>img{left:0;position:relative}.gmb-reviews article time{font-style:italic}.gmb-reviews article .review{padding:1.5rem}.gmb-reviews article h4{width:-moz-max-content;width:max-content}.gmb-reviews article .icon{color:rgb(var(--action-0))}.gmb-reviews .btn{width:100%}
+/*!**************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/gmbreviews/style.scss ***!
+  \**************************************************************************************************************************************************************************************************************************************************/
+.gmb-reviews {
+  max-width: none;
+}
+.gmb-reviews > .row.x-mid {
+  max-width: var(--content);
+  margin: 0 auto;
+  --gap: .5rem 6rem;
+}
+.gmb-reviews > .row.x-mid p {
+  width: -moz-fit-content;
+  width: fit-content;
+}
+.gmb-reviews .button {
+  width: 66.6%;
+  margin: 0 auto 2rem;
+  display: flex;
+  height: -moz-max-content;
+  height: max-content;
+}
+.gmb-reviews .stars {
+  display: inline-flex;
+  align-items: center;
+  justify-content: flex-start;
+  flex-wrap: nowrap;
+}
+.gmb-reviews ul {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  max-width: var(--full);
+}
+.gmb-reviews ul li {
+  width: 100%;
+  max-width: none;
+  padding: 4rem 1rem;
+}
+.gmb-reviews ul li:nth-of-type(odd) {
+  background-color: rgb(var(--base-50));
+}
+.gmb-reviews ul li:nth-of-type(odd) blockquote {
+  --background: rgb(var(--base-50));
+}
+.gmb-reviews ul li:nth-of-type(even) {
+  background-color: rgb(var(--base-100));
+}
+.gmb-reviews ul li:nth-of-type(even) blockquote {
+  --background: rgb(var(--base-100));
+}
+.gmb-reviews blockquote {
+  margin: 1rem auto;
+  padding: 1rem 0 0;
+  max-width: var(--content);
+  border-top: 1px solid rgb(var(--base-200));
+}
+.gmb-reviews blockquote .icon-quotes-fi {
+  left: calc(var(--btnbtn) * -1);
+}
+.gmb-reviews blockquote .content {
+  border-width: 4px 1px;
+}
+.gmb-reviews blockquote .content::after {
+  border-width: 4px 1px;
+}
+.gmb-reviews blockquote .content::before {
+  border-width: 8px;
+  bottom: -4px;
+}
+.gmb-reviews blockquote cite {
+  position: relative;
+  margin-top: var(--btn);
+}
+.gmb-reviews blockquote cite img {
+  width: 4.5rem;
+  position: absolute;
+  left: -8rem;
+  top: 0;
+}
+.gmb-reviews blockquote cite p {
+  margin: 0;
+}
+.gmb-reviews blockquote cite .wrap {
+  --wrap: wrap;
+}
+.gmb-reviews blockquote cite .wrap p, .gmb-reviews blockquote cite .wrap time {
+  max-width: 49%;
+}
+.gmb-reviews blockquote cite .wrap .stars {
+  width: 100%;
+}
+.gmb-reviews blockquote time {
+  white-space: nowrap;
+}
+.gmb-reviews .stars .icon {
+  background-color: rgb(var(--action-0));
+}
+.gmb-reviews article {
+  padding: 1rem;
+  border-radius: var(--radius-outer);
+  background-color: rgb(var(--base));
+}
+.gmb-reviews article header {
+  --align: center;
+}
+.gmb-reviews article header > img {
+  position: relative;
+  left: 0;
+}
+.gmb-reviews article time {
+  font-style: italic;
+}
+.gmb-reviews article .review {
+  padding: 1.5rem;
+}
+.gmb-reviews article h4 {
+  width: -moz-max-content;
+  width: max-content;
+}
+.gmb-reviews article .icon {
+  color: rgb(var(--action-0));
+}
+.gmb-reviews .btn {
+  width: 100%;
+}
+
+/*# sourceMappingURL=style-index.css.map*/
\ No newline at end of file
diff --git a/build/gmbreviews/style-index.css.map b/build/gmbreviews/style-index.css.map
new file mode 100644
index 0000000..e7be42e
--- /dev/null
+++ b/build/gmbreviews/style-index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"gmbreviews/style-index.css","mappings":";;;AAAA;EACC;AACD;AAAC;EACC;EACA;EACA;AAEF;AAAE;EACC;EAAA;AAEH;AACC;EACC;EACA;EACA;EACA;EAAA;AACF;AACC;EACC;EACA;EACA;EACA;AACF;AACC;EACC;EACA;EACA;EACA;AACF;AAAE;EACC;EACA;EACA;AAEH;AADG;EACC;AAGJ;AAFI;EACC;AAIL;AADG;EACC;AAGJ;AAFI;EACC;AAIL;AACC;EACC;EACA;EACA;EACA;AACF;AACE;EACC;AACH;AACE;EACC;AACH;AAAG;EACC;AAEJ;AAAG;EACC;EACA;AAEJ;AACE;EACC;EACA;AACH;AACG;EACC;EACA;EACA;EACA;AACJ;AAEG;EACC;AAAJ;AAGG;EACC;AADJ;AAGI;EACC;AADL;AAII;EACC;AAFL;AAME;EACC;AAJH;AAOC;EACC;AALF;AAOC;EACC;EACA;EACA;AALF;AAME;EACC;AAJH;AAKG;EACC;EACA;AAHJ;AAME;EACC;AAJH;AAME;EACC;AAJH;AAOE;EACC;EAAA;AALH;AAOE;EACC;AALH;AAQC;EACC;AANF,C","sources":["webpack://jvb/./src/gmbreviews/style.scss"],"sourcesContent":[".gmb-reviews {\r\n\tmax-width: none;\r\n\t> .row.x-mid {\r\n\t\tmax-width:var(--content);\r\n\t\tmargin: 0 auto;\r\n\t\t--gap: .5rem 6rem;\r\n\r\n\t\tp {\r\n\t\t\twidth: fit-content;\r\n\t\t}\r\n\t}\r\n\t.button {\r\n\t\twidth: 66.6%;\r\n\t\tmargin: 0 auto 2rem;\r\n\t\tdisplay: flex;\r\n\t\theight: max-content;\r\n\t}\r\n\t.stars {\r\n\t\tdisplay: inline-flex;\r\n\t\talign-items: center;\r\n\t\tjustify-content: flex-start;\r\n\t\tflex-wrap: nowrap;\r\n\t}\r\n\tul {\r\n\t\tlist-style: none;\r\n\t\tmargin: 0;\r\n\t\tpadding: 0;\r\n\t\tmax-width: var(--full);\r\n\t\tli {\r\n\t\t\twidth: 100%;\r\n\t\t\tmax-width: none;\r\n\t\t\tpadding: 4rem 1rem;\r\n\t\t\t&:nth-of-type(odd) {\r\n\t\t\t\tbackground-color: rgb(var(--base-50));\r\n\t\t\t\tblockquote {\r\n\t\t\t\t\t--background: rgb(var(--base-50));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t&:nth-of-type(even) {\r\n\t\t\t\tbackground-color: rgb(var(--base-100));\r\n\t\t\t\tblockquote {\r\n\t\t\t\t\t--background: rgb(var(--base-100));\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tblockquote {\r\n\t\tmargin: 1rem auto;\r\n\t\tpadding: 1rem 0 0;\r\n\t\tmax-width: var(--content);\r\n\t\tborder-top: 1px solid rgb(var(--base-200));\r\n\r\n\t\t.icon-quotes-fi {\r\n\t\t\tleft: calc(var(--btnbtn) * -1);\r\n\t\t}\r\n\t\t.content {\r\n\t\t\tborder-width: 4px 1px;\r\n\t\t\t&::after {\r\n\t\t\t\tborder-width: 4px 1px;\r\n\t\t\t}\r\n\t\t\t&::before {\r\n\t\t\t\tborder-width: 8px;\r\n\t\t\t\tbottom: -4px;\r\n\t\t\t}\r\n\t\t}\r\n\t\tcite {\r\n\t\t\tposition: relative;\r\n\t\t\tmargin-top: var(--btn);\r\n\r\n\t\t\timg {\r\n\t\t\t\twidth: 4.5rem;\r\n\t\t\t\tposition: absolute;\r\n\t\t\t\tleft: -8rem;\r\n\t\t\t\ttop: 0;\r\n\t\t\t}\r\n\r\n\t\t\tp {\r\n\t\t\t\tmargin: 0;\r\n\t\t\t}\r\n\r\n\t\t\t.wrap {\r\n\t\t\t\t--wrap: wrap;\r\n\r\n\t\t\t\tp, time {\r\n\t\t\t\t\tmax-width: 49%;\r\n\t\t\t\t}\r\n\r\n\t\t\t\t.stars {\r\n\t\t\t\t\twidth: 100%;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\ttime {\r\n\t\t\twhite-space: nowrap;\r\n\t\t}\r\n\t}\r\n\t.stars .icon {\r\n\t\tbackground-color: rgb(var(--action-0));\r\n\t}\r\n\tarticle {\r\n\t\tpadding: 1rem;\r\n\t\tborder-radius: var(--radius-outer);\r\n\t\tbackground-color: rgb(var(--base));\r\n\t\theader {\r\n\t\t\t--align: center;\r\n\t\t\t>img {\r\n\t\t\t\tposition: relative;\r\n\t\t\t\tleft: 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\ttime {\r\n\t\t\tfont-style: italic;\r\n\t\t}\r\n\t\t.review {\r\n\t\t\tpadding: 1.5rem;\r\n\t\t}\r\n\r\n\t\th4 {\r\n\t\t\twidth: max-content;\r\n\t\t}\r\n\t\t.icon {\r\n\t\t\tcolor: rgb(var(--action-0));\r\n\t\t}\r\n\t}\r\n\t.btn {\r\n\t\twidth: 100%;\r\n\t}\r\n}\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/gmbreviews/view.asset.php b/build/gmbreviews/view.asset.php
index f534533..cc649c7 100644
--- a/build/gmbreviews/view.asset.php
+++ b/build/gmbreviews/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => '31d6cfe0d16ae931b73c');
+<?php return array('dependencies' => array(), 'version' => 'd580aba8c310115dcf70');
diff --git a/build/gmbreviews/view.js b/build/gmbreviews/view.js
index e69de29..15c807b 100644
--- a/build/gmbreviews/view.js
+++ b/build/gmbreviews/view.js
@@ -0,0 +1,7 @@
+/******/ (() => { // webpackBootstrap
+/*!********************************!*\
+  !*** ./src/gmbreviews/view.js ***!
+  \********************************/
+
+/******/ })()
+;
\ No newline at end of file
diff --git a/build/menu/index-rtl.css b/build/menu/index-rtl.css
index 8b13789..cb67611 100644
--- a/build/menu/index-rtl.css
+++ b/build/menu/index-rtl.css
@@ -1 +1,4 @@
+/*!*********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/menu/editor.scss ***!
+  \*********************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/menu/index.asset.php b/build/menu/index.asset.php
index 136decc..b708dfd 100644
--- a/build/menu/index.asset.php
+++ b/build/menu/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => '60dee3034fa9da82f1ec');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => 'e5ab84e1b3eacc46d4db');
diff --git a/build/menu/index.css b/build/menu/index.css
index 8b13789..cb67611 100644
--- a/build/menu/index.css
+++ b/build/menu/index.css
@@ -1 +1,4 @@
+/*!*********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/menu/editor.scss ***!
+  \*********************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/menu/index.js b/build/menu/index.js
index a03143b..83bc494 100644
--- a/build/menu/index.js
+++ b/build/menu/index.js
@@ -1 +1,357 @@
-(()=>{"use strict";var r,e={722(){const r=window.wp.blocks,e=window.wp.i18n,o=window.wp.blockEditor,n=window.ReactJSXRuntime;(0,r.registerBlockType)("jvb/menu",{edit:function(){return(0,n.jsx)("p",{...(0,o.useBlockProps)(),children:(0,e.__)("Will output the menu","jvb")})}})}},o={};function n(r){var t=o[r];if(void 0!==t)return t.exports;var i=o[r]={exports:{}};return e[r](i,i.exports,n),i.exports}n.m=e,r=[],n.O=(e,o,t,i)=>{if(!o){var l=1/0;for(u=0;u<r.length;u++){for(var[o,t,i]=r[u],s=!0,a=0;a<o.length;a++)(!1&i||l>=i)&&Object.keys(n.O).every(r=>n.O[r](o[a]))?o.splice(a--,1):(s=!1,i<l&&(l=i));if(s){r.splice(u--,1);var p=t();void 0!==p&&(e=p)}}return e}i=i||0;for(var u=r.length;u>0&&r[u-1][2]>i;u--)r[u]=r[u-1];r[u]=[o,t,i]},n.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={447:0,103:0};n.O.j=e=>0===r[e];var e=(e,o)=>{var t,i,[l,s,a]=o,p=0;if(l.some(e=>0!==r[e])){for(t in s)n.o(s,t)&&(n.m[t]=s[t]);if(a)var u=a(n)}for(e&&e(o);p<l.length;p++)i=l[p],n.o(r,i)&&r[i]&&r[i][0](),r[i]=0;return n.O(u)},o=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];o.forEach(e.bind(null,0)),o.push=e.bind(null,o.push.bind(o))})();var t=n.O(void 0,[103],()=>n(722));t=n.O(t)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/menu/edit.js"
+/*!**************************!*\
+  !*** ./src/menu/edit.js ***!
+  \**************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./editor.scss */ "./src/menu/editor.scss");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__);
+/**
+ * Retrieves the translation of text.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
+ */
+
+
+/**
+ * React hook that is used to mark the block wrapper element.
+ * It provides all the necessary props like the class name.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
+ */
+
+
+/**
+ * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
+ * Those files can contain any CSS code that gets applied to the editor.
+ *
+ * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
+ */
+
+
+/**
+ * The edit function describes the structure of your block in the context of the
+ * editor. This represents what the editor will render when the block is used.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
+ *
+ * @return {Element} Element to render.
+ */
+
+function Edit() {
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("p", {
+    ...(0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.useBlockProps)(),
+    children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Will output the menu', 'jvb')
+  });
+}
+
+/***/ },
+
+/***/ "./src/menu/index.js"
+/*!***************************!*\
+  !*** ./src/menu/index.js ***!
+  \***************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./style.scss */ "./src/menu/style.scss");
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./edit */ "./src/menu/edit.js");
+/* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./block.json */ "./src/menu/block.json");
+/**
+ * Registers a new block provided a unique name and an object defining its behavior.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+
+
+/**
+ * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
+ * All files containing `style` keyword are bundled together. The code used
+ * gets applied both to the front of your site and to the editor.
+ *
+ * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
+ */
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+/**
+ * Every block starts by registering a new block type definition.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)(_block_json__WEBPACK_IMPORTED_MODULE_3__.name, {
+  /**
+   * @see ./edit.js
+   */
+  edit: _edit__WEBPACK_IMPORTED_MODULE_2__["default"]
+});
+
+/***/ },
+
+/***/ "./src/menu/editor.scss"
+/*!******************************!*\
+  !*** ./src/menu/editor.scss ***!
+  \******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "./src/menu/style.scss"
+/*!*****************************!*\
+  !*** ./src/menu/style.scss ***!
+  \*****************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/i18n"
+/*!******************************!*\
+  !*** external ["wp","i18n"] ***!
+  \******************************/
+(module) {
+
+module.exports = window["wp"]["i18n"];
+
+/***/ },
+
+/***/ "./src/menu/block.json"
+/*!*****************************!*\
+  !*** ./src/menu/block.json ***!
+  \*****************************/
+(module) {
+
+module.exports = /*#__PURE__*/JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/menu","version":"0.1.0","title":"Our Menu","category":"jvb","icon":"food","description":"Outputs our menu, organized by categories","example":{},"supports":{"html":false,"align":["wide","full"]},"textdomain":"jvb","selectors":{"root":".menu-block"},"editorScript":"file:./index.js","editorStyle":"file:./index.css","style":"file:./style-index.css","render":"file:./render.php","viewScript":"file:./view.js"}');
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"menu/index": 0,
+/******/ 			"menu/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["menu/style-index"], () => (__webpack_require__("./src/menu/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/menu/index.js.map b/build/menu/index.js.map
new file mode 100644
index 0000000..351dc65
--- /dev/null
+++ b/build/menu/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"menu/index.js","mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACqC;;AAErC;AACA;AACA;AACA;AACA;AACA;AACwD;;AAExD;AACA;AACA;AACA;AACA;AACA;AACuB;;AAEvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAQe,SAASI,IAAIA,CAAA,EAAG;EAC9B,oBACCD,sDAAA;IAAA,GAAQF,sEAAa,CAAC,CAAC;IAAAI,QAAA,EACpBL,mDAAE,CAAE,sBAAsB,EAAE,KAAM;EAAC,CACnC,CAAC;AAEN,C;;;;;;;;;;;;;;;;ACrCA;AACA;AACA;AACA;AACA;AACsD;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA;AACsB;;AAEtB;AACA;AACA;AAC0B;AACU;;AAEpC;AACA;AACA;AACA;AACA;AACAM,oEAAiB,CAAEC,6CAAa,EAAE;EACjC;AACD;AACA;EACCE,IAAI,EAAEL,6CAAIA;AACX,CAAE,CAAC,C;;;;;;;;;;;AChCH;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA,2C;;;;;;;;;;ACAA,6C;;;;;;;;;;ACAA,wC;;;;;;;;;;ACAA,sC;;;;;;;;;;;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WC/BA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G;;;;;UEjDA;UACA;UACA;UACA;UACA","sources":["webpack://jvb/./src/menu/edit.js","webpack://jvb/./src/menu/index.js","webpack://jvb/./src/menu/editor.scss","webpack://jvb/./src/menu/style.scss","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"i18n\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["/**\r\n * Retrieves the translation of text.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/\r\n */\r\nimport { __ } from '@wordpress/i18n';\r\n\r\n/**\r\n * React hook that is used to mark the block wrapper element.\r\n * It provides all the necessary props like the class name.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops\r\n */\r\nimport { useBlockProps } from '@wordpress/block-editor';\r\n\r\n/**\r\n * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.\r\n * Those files can contain any CSS code that gets applied to the editor.\r\n *\r\n * @see https://www.npmjs.com/package/@wordpress/scripts#using-css\r\n */\r\nimport './editor.scss';\r\n\r\n/**\r\n * The edit function describes the structure of your block in the context of the\r\n * editor. This represents what the editor will render when the block is used.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit\r\n *\r\n * @return {Element} Element to render.\r\n */\r\nexport default function Edit() {\r\n\treturn (\r\n\t\t<p { ...useBlockProps() }>\r\n\t\t\t{ __( 'Will output the menu', 'jvb' ) }\r\n\t\t</p>\r\n\t);\r\n}\r\n","/**\r\n * Registers a new block provided a unique name and an object defining its behavior.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nimport { registerBlockType } from '@wordpress/blocks';\r\n\r\n/**\r\n * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.\r\n * All files containing `style` keyword are bundled together. The code used\r\n * gets applied both to the front of your site and to the editor.\r\n *\r\n * @see https://www.npmjs.com/package/@wordpress/scripts#using-css\r\n */\r\nimport './style.scss';\r\n\r\n/**\r\n * Internal dependencies\r\n */\r\nimport Edit from './edit';\r\nimport metadata from './block.json';\r\n\r\n/**\r\n * Every block starts by registering a new block type definition.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nregisterBlockType( metadata.name, {\r\n\t/**\r\n\t * @see ./edit.js\r\n\t */\r\n\tedit: Edit,\r\n} );\r\n","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"i18n\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"menu/index\": 0,\n\t\"menu/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"menu/style-index\"], () => (__webpack_require__(\"./src/menu/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["__","useBlockProps","jsx","_jsx","Edit","children","registerBlockType","metadata","name","edit"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/menu/style-index-rtl.css b/build/menu/style-index-rtl.css
index 8b13789..5475859 100644
--- a/build/menu/style-index-rtl.css
+++ b/build/menu/style-index-rtl.css
@@ -1 +1,4 @@
+/*!********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/menu/style.scss ***!
+  \********************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/menu/style-index.css b/build/menu/style-index.css
index 8b13789..5475859 100644
--- a/build/menu/style-index.css
+++ b/build/menu/style-index.css
@@ -1 +1,4 @@
+/*!********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/menu/style.scss ***!
+  \********************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/menu/view.asset.php b/build/menu/view.asset.php
index 8e32854..1019e35 100644
--- a/build/menu/view.asset.php
+++ b/build/menu/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => 'fa2ae0d9cf37735dbf5a');
+<?php return array('dependencies' => array(), 'version' => '6e7f34524894e70f78cb');
diff --git a/build/menu/view.js b/build/menu/view.js
index 59b25cd..16b618c 100644
--- a/build/menu/view.js
+++ b/build/menu/view.js
@@ -1 +1,45 @@
-window.details=document.querySelectorAll("details"),window.toggles=document.querySelectorAll(".toggle-details"),document.addEventListener("click",e=>{if(e.target.classList.contains("toggle-details")){e.target.classList.toggle("open");let t=e.target.classList.contains("open"),o=e.target.dataset.toggle;"all"===o&&function(e){window.toggles.forEach(t=>{"all"!==t.dataset.toggle&&(t.querySelector("span").textContent=e?"Close":"Open")})}(t),e.target.querySelector("span").textContent=t?"Close":"Open",function(e,t){if("all"===e)console.log("Toggling all!"),window.details.forEach(e=>{console.log(e),e.open=t});else for(let o of window.details)o.dataset.section===e&&(o.open=t)}(o,t)}}),console.log(window.details);
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/*!**************************!*\
+  !*** ./src/menu/view.js ***!
+  \**************************/
+window.details = document.querySelectorAll('details');
+window.toggles = document.querySelectorAll('.toggle-details');
+document.addEventListener('click', e => {
+  if (e.target.classList.contains('toggle-details')) {
+    e.target.classList.toggle('open');
+    let on = e.target.classList.contains('open');
+    let section = e.target.dataset.toggle;
+    if (section === 'all') {
+      toggleToggles(on);
+    }
+    let span = e.target.querySelector('span');
+    span.textContent = on ? 'Close' : 'Open';
+    toggleDetails(section, on);
+  }
+});
+console.log(window.details);
+function toggleDetails(name, toggle) {
+  if (name === 'all') {
+    console.log('Toggling all!');
+    window.details.forEach(detail => {
+      console.log(detail);
+      detail.open = toggle;
+    });
+  } else {
+    for (let detail of window.details) {
+      if (detail.dataset.section === name) {
+        detail.open = toggle;
+      }
+    }
+  }
+}
+function toggleToggles(on) {
+  window.toggles.forEach(toggle => {
+    if (toggle.dataset.toggle !== 'all') {
+      toggle.querySelector('span').textContent = on ? 'Close' : 'Open';
+    }
+  });
+}
+/******/ })()
+;
+//# sourceMappingURL=view.js.map
\ No newline at end of file
diff --git a/build/menu/view.js.map b/build/menu/view.js.map
new file mode 100644
index 0000000..b4a851c
--- /dev/null
+++ b/build/menu/view.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"menu/view.js","mappings":";;;;AAAAA,MAAM,CAACC,OAAO,GAAGC,QAAQ,CAACC,gBAAgB,CAAC,SAAS,CAAC;AACrDH,MAAM,CAACI,OAAO,GAAGF,QAAQ,CAACC,gBAAgB,CAAC,iBAAiB,CAAC;AAE7DD,QAAQ,CAACG,gBAAgB,CAAC,OAAO,EAAGC,CAAC,IAAK;EACzC,IAAIA,CAAC,CAACC,MAAM,CAACC,SAAS,CAACC,QAAQ,CAAC,gBAAgB,CAAC,EAAE;IAClDH,CAAC,CAACC,MAAM,CAACC,SAAS,CAACE,MAAM,CAAC,MAAM,CAAC;IACjC,IAAIC,EAAE,GAAGL,CAAC,CAACC,MAAM,CAACC,SAAS,CAACC,QAAQ,CAAC,MAAM,CAAC;IAC5C,IAAIG,OAAO,GAAGN,CAAC,CAACC,MAAM,CAACM,OAAO,CAACH,MAAM;IACrC,IAAIE,OAAO,KAAK,KAAK,EAAE;MACtBE,aAAa,CAACH,EAAE,CAAC;IAClB;IAEA,IAAII,IAAI,GAAGT,CAAC,CAACC,MAAM,CAACS,aAAa,CAAC,MAAM,CAAC;IACzCD,IAAI,CAACE,WAAW,GAAIN,EAAE,GAAI,OAAO,GAAE,MAAM;IACzCO,aAAa,CAACN,OAAO,EAAED,EAAE,CAAC;EAC3B;AACD,CAAC,CAAC;AAGFQ,OAAO,CAACC,GAAG,CAACpB,MAAM,CAACC,OAAO,CAAC;AAC3B,SAASiB,aAAaA,CAACG,IAAI,EAAEX,MAAM,EAAE;EACpC,IAAIW,IAAI,KAAK,KAAK,EAAE;IACnBF,OAAO,CAACC,GAAG,CAAC,eAAe,CAAC;IAC5BpB,MAAM,CAACC,OAAO,CAACqB,OAAO,CAACC,MAAM,IAAI;MAChCJ,OAAO,CAACC,GAAG,CAACG,MAAM,CAAC;MACnBA,MAAM,CAACC,IAAI,GAAGd,MAAM;IACrB,CAAC,CAAC;EACH,CAAC,MAAM;IACN,KAAK,IAAIa,MAAM,IAAIvB,MAAM,CAACC,OAAO,EAAE;MAClC,IAAIsB,MAAM,CAACV,OAAO,CAACD,OAAO,KAAKS,IAAI,EAAE;QACpCE,MAAM,CAACC,IAAI,GAAGd,MAAM;MACrB;IACD;EACD;AACD;AAEA,SAASI,aAAaA,CAACH,EAAE,EAAE;EAC1BX,MAAM,CAACI,OAAO,CAACkB,OAAO,CAACZ,MAAM,IAAI;IAChC,IAAIA,MAAM,CAACG,OAAO,CAACH,MAAM,KAAK,KAAK,EAAE;MACpCA,MAAM,CAACM,aAAa,CAAC,MAAM,CAAC,CAACC,WAAW,GAAIN,EAAE,GAAI,OAAO,GAAG,MAAM;IACnE;EACD,CAAC,CAAC;AACH,C","sources":["webpack://jvb/./src/menu/view.js"],"sourcesContent":["window.details = document.querySelectorAll('details');\r\nwindow.toggles = document.querySelectorAll('.toggle-details');\r\n\r\ndocument.addEventListener('click', (e) => {\r\n\tif (e.target.classList.contains('toggle-details')) {\r\n\t\te.target.classList.toggle('open');\r\n\t\tlet on = e.target.classList.contains('open');\r\n\t\tlet section = e.target.dataset.toggle;\r\n\t\tif (section === 'all') {\r\n\t\t\ttoggleToggles(on);\r\n\t\t}\r\n\r\n\t\tlet span = e.target.querySelector('span');\r\n\t\tspan.textContent = (on) ? 'Close': 'Open';\r\n\t\ttoggleDetails(section, on);\r\n\t}\r\n});\r\n\r\n\r\nconsole.log(window.details);\r\nfunction toggleDetails(name, toggle) {\r\n\tif (name === 'all') {\r\n\t\tconsole.log('Toggling all!');\r\n\t\twindow.details.forEach(detail => {\r\n\t\t\tconsole.log(detail);\r\n\t\t\tdetail.open = toggle;\r\n\t\t});\r\n\t} else {\r\n\t\tfor (let detail of window.details) {\r\n\t\t\tif (detail.dataset.section === name) {\r\n\t\t\t\tdetail.open = toggle;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunction toggleToggles(on) {\r\n\twindow.toggles.forEach(toggle => {\r\n\t\tif (toggle.dataset.toggle !== 'all') {\r\n\t\t\ttoggle.querySelector('span').textContent = (on) ? 'Close' : 'Open';\r\n\t\t}\r\n\t});\r\n}\r\n"],"names":["window","details","document","querySelectorAll","toggles","addEventListener","e","target","classList","contains","toggle","on","section","dataset","toggleToggles","span","querySelector","textContent","toggleDetails","console","log","name","forEach","detail","open"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/summary/index-rtl.css b/build/summary/index-rtl.css
index 6cfd5fd..3c6e8b0 100644
--- a/build/summary/index-rtl.css
+++ b/build/summary/index-rtl.css
@@ -1 +1,22 @@
-.jvb-summary-preview{background-color:#f8f9fa;border:1px solid #e2e4e7;border-radius:4px;padding:20px}.jvb-summary-preview h3{border-bottom:1px solid #ff0080;margin-top:0;padding-bottom:10px}.jvb-summary-preview-note{color:#555d66;font-style:italic;margin-bottom:0}
+/*!************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/summary/editor.scss ***!
+  \************************************************************************************************************************************************************************************************************************************************/
+/**
+ * Directory List Block Editor Styles
+ */
+.jvb-summary-preview {
+  padding: 20px;
+  background-color: #f8f9fa;
+  border: 1px solid #e2e4e7;
+  border-radius: 4px;
+}
+.jvb-summary-preview h3 {
+  margin-top: 0;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #ff0080;
+}
+.jvb-summary-preview-note {
+  font-style: italic;
+  color: #555d66;
+  margin-bottom: 0;
+}
diff --git a/build/summary/index.asset.php b/build/summary/index.asset.php
index c6ba96d..7e3745e 100644
--- a/build/summary/index.asset.php
+++ b/build/summary/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '7e1ea861fc0d23381c53');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '57ed577bade7a3bfaa6d');
diff --git a/build/summary/index.css b/build/summary/index.css
index 6cfd5fd..49288d3 100644
--- a/build/summary/index.css
+++ b/build/summary/index.css
@@ -1 +1,24 @@
-.jvb-summary-preview{background-color:#f8f9fa;border:1px solid #e2e4e7;border-radius:4px;padding:20px}.jvb-summary-preview h3{border-bottom:1px solid #ff0080;margin-top:0;padding-bottom:10px}.jvb-summary-preview-note{color:#555d66;font-style:italic;margin-bottom:0}
+/*!************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/summary/editor.scss ***!
+  \************************************************************************************************************************************************************************************************************************************************/
+/**
+ * Directory List Block Editor Styles
+ */
+.jvb-summary-preview {
+  padding: 20px;
+  background-color: #f8f9fa;
+  border: 1px solid #e2e4e7;
+  border-radius: 4px;
+}
+.jvb-summary-preview h3 {
+  margin-top: 0;
+  padding-bottom: 10px;
+  border-bottom: 1px solid #ff0080;
+}
+.jvb-summary-preview-note {
+  font-style: italic;
+  color: #555d66;
+  margin-bottom: 0;
+}
+
+/*# sourceMappingURL=index.css.map*/
\ No newline at end of file
diff --git a/build/summary/index.css.map b/build/summary/index.css.map
new file mode 100644
index 0000000..8fe0f32
--- /dev/null
+++ b/build/summary/index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"summary/index.css","mappings":";;;AAAA;;EAAA;AAGA;EACI;EACA;EACA;EACA;AACJ;AACI;EACI;EACA;EACA;AACR;AACI;EACI;EACA;EACA;AACR,C","sources":["webpack://jvb/./src/summary/editor.scss"],"sourcesContent":["/**\r\n * Directory List Block Editor Styles\r\n */\r\n.jvb-summary-preview {\r\n    padding: 20px;\r\n    background-color: #f8f9fa;\r\n    border: 1px solid #e2e4e7;\r\n    border-radius: 4px;\r\n\r\n    h3 {\r\n        margin-top: 0;\r\n        padding-bottom: 10px;\r\n        border-bottom: 1px solid #ff0080;\r\n    }\r\n    &-note {\r\n        font-style: italic;\r\n        color: #555d66;\r\n        margin-bottom: 0;\r\n    }\r\n}\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/summary/index.js b/build/summary/index.js
index 533f59c..6ebec2c 100644
--- a/build/summary/index.js
+++ b/build/summary/index.js
@@ -1 +1,387 @@
-(()=>{"use strict";var r,e={955(){const r=window.wp.blocks,e=window.wp.i18n,t=window.wp.blockEditor,n=(window.wp.components,window.ReactJSXRuntime);(0,r.registerBlockType)("jvb/summary",{edit:function({attributes:r,setAttributes:o}){const i=(0,t.useBlockProps)();return(0,n.jsx)("div",{...i,children:(0,n.jsxs)("div",{className:"jvb-summary-preview",children:[(0,n.jsx)("h3",{children:(0,e.__)("Summary","jvb")}),(0,n.jsx)("p",{className:"jvb-list-preview-note",children:(0,e.__)("This will inherit the current query to build the information from our custom meta on the front end.","jvb")})]})})},save:function(){return null}})}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,n),i.exports}n.m=e,r=[],n.O=(e,t,o,i)=>{if(!t){var s=1/0;for(c=0;c<r.length;c++){for(var[t,o,i]=r[c],l=!0,a=0;a<t.length;a++)(!1&i||s>=i)&&Object.keys(n.O).every(r=>n.O[r](t[a]))?t.splice(a--,1):(l=!1,i<s&&(s=i));if(l){r.splice(c--,1);var u=o();void 0!==u&&(e=u)}}return e}i=i||0;for(var c=r.length;c>0&&r[c-1][2]>i;c--)r[c]=r[c-1];r[c]=[t,o,i]},n.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={592:0,75:0};n.O.j=e=>0===r[e];var e=(e,t)=>{var o,i,[s,l,a]=t,u=0;if(s.some(e=>0!==r[e])){for(o in l)n.o(l,o)&&(n.m[o]=l[o]);if(a)var c=a(n)}for(e&&e(t);u<s.length;u++)i=s[u],n.o(r,i)&&r[i]&&r[i][0](),r[i]=0;return n.O(c)},t=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];t.forEach(e.bind(null,0)),t.push=e.bind(null,t.push.bind(t))})();var o=n.O(void 0,[75],()=>n(955));o=n.O(o)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/summary/edit.js"
+/*!*****************************!*\
+  !*** ./src/summary/edit.js ***!
+  \*****************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__);
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./editor.scss */ "./src/summary/editor.scss");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__);
+/**
+ * WordPress dependencies
+ */
+
+
+
+
+/**
+ * Styles
+ */
+
+
+/**
+ * Edit function for Summary Block
+ */
+
+function Edit({
+  attributes,
+  setAttributes
+}) {
+  const blockProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.useBlockProps)();
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("div", {
+    ...blockProps,
+    children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)("div", {
+      className: "jvb-summary-preview",
+      children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("h3", {
+        children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Summary', 'jvb')
+      }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("p", {
+        className: "jvb-list-preview-note",
+        children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('This will inherit the current query to build the information from our custom meta on the front end.', 'jvb')
+      })]
+    })
+  });
+}
+
+/***/ },
+
+/***/ "./src/summary/index.js"
+/*!******************************!*\
+  !*** ./src/summary/index.js ***!
+  \******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./style.scss */ "./src/summary/style.scss");
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./edit */ "./src/summary/edit.js");
+/* harmony import */ var _save__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./save */ "./src/summary/save.js");
+/* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./block.json */ "./src/summary/block.json");
+/**
+ * Registers a new block provided a unique name and an object defining its behavior.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+
+
+/**
+ * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
+ * All files containing `style` keyword are bundled together. The code used
+ * gets applied both to the front of your site and to the editor.
+ *
+ * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
+ */
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+
+/**
+ * Every block starts by registering a new block type definition.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)(_block_json__WEBPACK_IMPORTED_MODULE_4__.name, {
+  /**
+   * @see ./edit.js
+   */
+  edit: _edit__WEBPACK_IMPORTED_MODULE_2__["default"],
+  /**
+   * @see ./save.js
+   */
+  save: _save__WEBPACK_IMPORTED_MODULE_3__["default"]
+});
+
+/***/ },
+
+/***/ "./src/summary/save.js"
+/*!*****************************!*\
+  !*** ./src/summary/save.js ***!
+  \*****************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ save)
+/* harmony export */ });
+function save() {
+  return null; // Dynamic block rendered by PHP
+}
+
+/***/ },
+
+/***/ "./src/summary/editor.scss"
+/*!*********************************!*\
+  !*** ./src/summary/editor.scss ***!
+  \*********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "./src/summary/style.scss"
+/*!********************************!*\
+  !*** ./src/summary/style.scss ***!
+  \********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/components"
+/*!************************************!*\
+  !*** external ["wp","components"] ***!
+  \************************************/
+(module) {
+
+module.exports = window["wp"]["components"];
+
+/***/ },
+
+/***/ "@wordpress/i18n"
+/*!******************************!*\
+  !*** external ["wp","i18n"] ***!
+  \******************************/
+(module) {
+
+module.exports = window["wp"]["i18n"];
+
+/***/ },
+
+/***/ "./src/summary/block.json"
+/*!********************************!*\
+  !*** ./src/summary/block.json ***!
+  \********************************/
+(module) {
+
+module.exports = /*#__PURE__*/JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/summary","title":"Archive Summary","category":"jvb","icon":"align-center","description":"Outputs the information for the given archive page, or the bio for a profile. Pairs well with the feed block.","keywords":["summary","bio","style","term"],"version":"0.9.0","textdomain":"jvb","supports":{"html":false,"align":["wide","full"]},"selectors":{"root":".summary-block"},"styles":[{"name":"default","label":"Default","isDefault":true}],"example":{"attributes":{"listType":"tattoo"}},"render":"file:./render.php","editorScript":"file:./index.js","editorStyle":"file:./index.css","style":"file:./style-index.css","viewScript":"file:./view.js"}');
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"summary/index": 0,
+/******/ 			"summary/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["summary/style-index"], () => (__webpack_require__("./src/summary/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/summary/index.js.map b/build/summary/index.js.map
new file mode 100644
index 0000000..323f3e6
--- /dev/null
+++ b/build/summary/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"summary/index.js","mappings":";;;;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACqC;AACsC;AACK;;AAEhF;AACA;AACA;AACuB;;AAEvB;AACA;AACA;AAFA;AAGe,SAASU,IAAIA,CAAC;EAAEC,UAAU;EAAEC;AAAc,CAAC,EAAE;EACxD,MAAMC,UAAU,GAAGZ,sEAAa,CAAC,CAAC;EAElC,oBACIM,sDAAA;IAAA,GAASM,UAAU;IAAAC,QAAA,eACfL,uDAAA;MAAKM,SAAS,EAAC,qBAAqB;MAAAD,QAAA,gBAChCP,sDAAA;QAAAO,QAAA,EAAKd,mDAAE,CAAC,SAAS,EAAE,KAAK;MAAC,CAAK,CAAC,eAC/BO,sDAAA;QAAGQ,SAAS,EAAC,uBAAuB;QAAAD,QAAA,EAC/Bd,mDAAE,CAAC,qGAAqG,EAAE,KAAK;MAAC,CAClH,CAAC;IAAA,CACH;EAAC,CACL,CAAC;AAEd,C;;;;;;;;;;;;;;;;;AC5BA;AACA;AACA;AACA;AACA;AACsD;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA;AACsB;;AAEtB;AACA;AACA;AAC0B;AACA;AACU;;AAEpC;AACA;AACA;AACA;AACA;AACAgB,oEAAiB,CAAEE,6CAAa,EAAE;EAC9B;AACJ;AACA;EACIE,IAAI,EAAEV,6CAAI;EAEV;AACJ;AACA;EACIO,IAAIA,+CAAAA;AACR,CAAE,CAAC,C;;;;;;;;;;;;;;ACtCY,SAASA,IAAIA,CAAA,EAAG;EAC3B,OAAO,IAAI,CAAC,CAAC;AACjB,C;;;;;;;;;;;ACFA;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA,2C;;;;;;;;;;ACAA,6C;;;;;;;;;;ACAA,wC;;;;;;;;;;ACAA,4C;;;;;;;;;;ACAA,sC;;;;;;;;;;;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WC/BA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G;;;;;UEjDA;UACA;UACA;UACA;UACA","sources":["webpack://jvb/./src/summary/edit.js","webpack://jvb/./src/summary/index.js","webpack://jvb/./src/summary/save.js","webpack://jvb/./src/summary/editor.scss?264c","webpack://jvb/./src/summary/style.scss?10dd","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"components\"]","webpack://jvb/external window [\"wp\",\"i18n\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["/**\r\n * WordPress dependencies\r\n */\r\nimport { __ } from '@wordpress/i18n';\r\nimport { useBlockProps, InspectorControls } from '@wordpress/block-editor';\r\nimport { SelectControl, ToggleControl, PanelBody } from '@wordpress/components';\r\n\r\n/**\r\n * Styles\r\n */\r\nimport './editor.scss';\r\n\r\n/**\r\n * Edit function for Summary Block\r\n */\r\nexport default function Edit({ attributes, setAttributes }) {\r\n    const blockProps = useBlockProps();\r\n\r\n    return (\r\n        <div {...blockProps}>\r\n            <div className=\"jvb-summary-preview\">\r\n                <h3>{__('Summary', 'jvb')}</h3>\r\n                <p className=\"jvb-list-preview-note\">\r\n                    {__('This will inherit the current query to build the information from our custom meta on the front end.', 'jvb')}\r\n                </p>\r\n            </div>\r\n        </div>\r\n    );\r\n}\r\n","/**\r\n * Registers a new block provided a unique name and an object defining its behavior.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nimport { registerBlockType } from '@wordpress/blocks';\r\n\r\n/**\r\n * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.\r\n * All files containing `style` keyword are bundled together. The code used\r\n * gets applied both to the front of your site and to the editor.\r\n *\r\n * @see https://www.npmjs.com/package/@wordpress/scripts#using-css\r\n */\r\nimport './style.scss';\r\n\r\n/**\r\n * Internal dependencies\r\n */\r\nimport Edit from './edit';\r\nimport save from './save';\r\nimport metadata from './block.json';\r\n\r\n/**\r\n * Every block starts by registering a new block type definition.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nregisterBlockType( metadata.name, {\r\n    /**\r\n     * @see ./edit.js\r\n     */\r\n    edit: Edit,\r\n\r\n    /**\r\n     * @see ./save.js\r\n     */\r\n    save,\r\n} );\r\n","export default function save() {\r\n    return null; // Dynamic block rendered by PHP\r\n}\r\n","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"components\"];","module.exports = window[\"wp\"][\"i18n\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"summary/index\": 0,\n\t\"summary/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"summary/style-index\"], () => (__webpack_require__(\"./src/summary/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["__","useBlockProps","InspectorControls","SelectControl","ToggleControl","PanelBody","jsx","_jsx","jsxs","_jsxs","Edit","attributes","setAttributes","blockProps","children","className","registerBlockType","save","metadata","name","edit"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/summary/render.php b/build/summary/render.php
index c2c35fb..b5645eb 100644
--- a/build/summary/render.php
+++ b/build/summary/render.php
@@ -45,7 +45,7 @@
     $meta = Meta::forPost($current->ID);
     $artist = jvbContentFromUser((int)$current->post_author);
 
-	$registrar = Registrar::getInstance($current->post_type));
+	$registrar = Registrar::getInstance($current->post_type);
 	$sections = [];
 	if ($registrar) {
 		$sections = $registrar->getSections();
diff --git a/build/summary/style-index-rtl.css b/build/summary/style-index-rtl.css
index 2ef7961..df190d8 100644
--- a/build/summary/style-index-rtl.css
+++ b/build/summary/style-index-rtl.css
@@ -1 +1,29 @@
-details>div{margin:1rem 0}main>header:not(:has(img)){margin-top:3rem!important}header a:before{display:none!important}header+details{margin:1.5rem auto 3rem!important;max-width:var(--wide)}main{padding-top:0!important}ul.summary .term-list{display:flex;flex-wrap:nowrap;padding-right:0}
+/*!***********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/summary/style.scss ***!
+  \***********************************************************************************************************************************************************************************************************************************************/
+details > div {
+  margin: 1rem 0;
+}
+
+main > header:not(:has(img)) {
+  margin-top: 3rem !important;
+}
+
+header a::before {
+  display: none !important;
+}
+
+header + details {
+  margin: 1.5rem auto 3rem !important;
+  max-width: var(--wide);
+}
+
+main {
+  padding-top: 0 !important;
+}
+
+ul.summary .term-list {
+  padding-right: 0;
+  display: flex;
+  flex-wrap: nowrap;
+}
diff --git a/build/summary/style-index.css b/build/summary/style-index.css
index 7e6fb62..fa23812 100644
--- a/build/summary/style-index.css
+++ b/build/summary/style-index.css
@@ -1 +1,31 @@
-details>div{margin:1rem 0}main>header:not(:has(img)){margin-top:3rem!important}header a:before{display:none!important}header+details{margin:1.5rem auto 3rem!important;max-width:var(--wide)}main{padding-top:0!important}ul.summary .term-list{display:flex;flex-wrap:nowrap;padding-left:0}
+/*!***********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/summary/style.scss ***!
+  \***********************************************************************************************************************************************************************************************************************************************/
+details > div {
+  margin: 1rem 0;
+}
+
+main > header:not(:has(img)) {
+  margin-top: 3rem !important;
+}
+
+header a::before {
+  display: none !important;
+}
+
+header + details {
+  margin: 1.5rem auto 3rem !important;
+  max-width: var(--wide);
+}
+
+main {
+  padding-top: 0 !important;
+}
+
+ul.summary .term-list {
+  padding-left: 0;
+  display: flex;
+  flex-wrap: nowrap;
+}
+
+/*# sourceMappingURL=style-index.css.map*/
\ No newline at end of file
diff --git a/build/summary/style-index.css.map b/build/summary/style-index.css.map
new file mode 100644
index 0000000..b02a698
--- /dev/null
+++ b/build/summary/style-index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"summary/style-index.css","mappings":";;;AAAA;EACC;AACD;;AAEA;EACC;AACD;;AAEA;EACC;AACD;;AAEA;EACC;EACA;AACD;;AAEA;EACC;AACD;;AAEA;EACC;EACA;EACA;AACD,C","sources":["webpack://jvb/./src/summary/style.scss"],"sourcesContent":["details > div {\r\n\tmargin: 1rem 0;\r\n}\r\n\r\nmain > header:not(:has(img)) {\r\n\tmargin-top: 3rem!important;\r\n}\r\n\r\nheader a::before {\r\n\tdisplay: none!important;\r\n}\r\n\r\nheader + details {\r\n\tmargin: 1.5rem auto 3rem!important;\r\n\tmax-width: var(--wide);\r\n}\r\n\r\nmain {\r\n\tpadding-top: 0!important;\r\n}\r\n\r\nul.summary .term-list {\r\n\tpadding-left: 0;\r\n\tdisplay: flex;\r\n\tflex-wrap: nowrap;\r\n}\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/summary/view.asset.php b/build/summary/view.asset.php
index f534533..f041d0c 100644
--- a/build/summary/view.asset.php
+++ b/build/summary/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => '31d6cfe0d16ae931b73c');
+<?php return array('dependencies' => array(), 'version' => '36101a3ecdf0d3b75d47');
diff --git a/build/summary/view.js b/build/summary/view.js
index e69de29..10c9910 100644
--- a/build/summary/view.js
+++ b/build/summary/view.js
@@ -0,0 +1,7 @@
+/******/ (() => { // webpackBootstrap
+/*!*****************************!*\
+  !*** ./src/summary/view.js ***!
+  \*****************************/
+
+/******/ })()
+;
\ No newline at end of file
diff --git a/build/timeline/index-rtl.css b/build/timeline/index-rtl.css
index 8b13789..757ff1c 100644
--- a/build/timeline/index-rtl.css
+++ b/build/timeline/index-rtl.css
@@ -1 +1,4 @@
+/*!*************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/timeline/editor.scss ***!
+  \*************************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/timeline/index.asset.php b/build/timeline/index.asset.php
index c075e0d..e136f4a 100644
--- a/build/timeline/index.asset.php
+++ b/build/timeline/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => '52e1cf3b8eb73003e597');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => '1af5090201888138cb2b');
diff --git a/build/timeline/index.css b/build/timeline/index.css
index 8b13789..757ff1c 100644
--- a/build/timeline/index.css
+++ b/build/timeline/index.css
@@ -1 +1,4 @@
+/*!*************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/timeline/editor.scss ***!
+  \*************************************************************************************************************************************************************************************************************************************************/
 
diff --git a/build/timeline/index.js b/build/timeline/index.js
index 6c1e194..72d7403 100644
--- a/build/timeline/index.js
+++ b/build/timeline/index.js
@@ -1 +1,357 @@
-(()=>{"use strict";var r,e={798(){const r=window.wp.blocks,e=window.wp.i18n,o=window.wp.blockEditor,i=window.ReactJSXRuntime,t=JSON.parse('{"UU":"jvb/timeline"}');(0,r.registerBlockType)(t.UU,{edit:function(){return(0,i.jsx)("p",{...(0,o.useBlockProps)(),children:(0,e.__)("Will output the timeline","jvb")})}})}},o={};function i(r){var t=o[r];if(void 0!==t)return t.exports;var n=o[r]={exports:{}};return e[r](n,n.exports,i),n.exports}i.m=e,r=[],i.O=(e,o,t,n)=>{if(!o){var l=1/0;for(v=0;v<r.length;v++){for(var[o,t,n]=r[v],s=!0,a=0;a<o.length;a++)(!1&n||l>=n)&&Object.keys(i.O).every(r=>i.O[r](o[a]))?o.splice(a--,1):(s=!1,n<l&&(l=n));if(s){r.splice(v--,1);var p=t();void 0!==p&&(e=p)}}return e}n=n||0;for(var v=r.length;v>0&&r[v-1][2]>n;v--)r[v]=r[v-1];r[v]=[o,t,n]},i.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={643:0,627:0};i.O.j=e=>0===r[e];var e=(e,o)=>{var t,n,[l,s,a]=o,p=0;if(l.some(e=>0!==r[e])){for(t in s)i.o(s,t)&&(i.m[t]=s[t]);if(a)var v=a(i)}for(e&&e(o);p<l.length;p++)n=l[p],i.o(r,n)&&r[n]&&r[n][0](),r[n]=0;return i.O(v)},o=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];o.forEach(e.bind(null,0)),o.push=e.bind(null,o.push.bind(o))})();var t=i.O(void 0,[627],()=>i(798));t=i.O(t)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/timeline/edit.js"
+/*!******************************!*\
+  !*** ./src/timeline/edit.js ***!
+  \******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./editor.scss */ "./src/timeline/editor.scss");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__);
+/**
+ * Retrieves the translation of text.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
+ */
+
+
+/**
+ * React hook that is used to mark the block wrapper element.
+ * It provides all the necessary props like the class name.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
+ */
+
+
+/**
+ * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
+ * Those files can contain any CSS code that gets applied to the editor.
+ *
+ * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
+ */
+
+
+/**
+ * The edit function describes the structure of your block in the context of the
+ * editor. This represents what the editor will render when the block is used.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
+ *
+ * @return {Element} Element to render.
+ */
+
+function Edit() {
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_3__.jsx)("p", {
+    ...(0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.useBlockProps)(),
+    children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Will output the timeline', 'jvb')
+  });
+}
+
+/***/ },
+
+/***/ "./src/timeline/index.js"
+/*!*******************************!*\
+  !*** ./src/timeline/index.js ***!
+  \*******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./style.scss */ "./src/timeline/style.scss");
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./edit */ "./src/timeline/edit.js");
+/* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./block.json */ "./src/timeline/block.json");
+/**
+ * Registers a new block provided a unique name and an object defining its behavior.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+
+
+/**
+ * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
+ * All files containing `style` keyword are bundled together. The code used
+ * gets applied both to the front of your site and to the editor.
+ *
+ * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
+ */
+
+
+/**
+ * Internal dependencies
+ */
+
+
+
+/**
+ * Every block starts by registering a new block type definition.
+ *
+ * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
+ */
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)(_block_json__WEBPACK_IMPORTED_MODULE_3__.name, {
+  /**
+   * @see ./edit.js
+   */
+  edit: _edit__WEBPACK_IMPORTED_MODULE_2__["default"]
+});
+
+/***/ },
+
+/***/ "./src/timeline/editor.scss"
+/*!**********************************!*\
+  !*** ./src/timeline/editor.scss ***!
+  \**********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "./src/timeline/style.scss"
+/*!*********************************!*\
+  !*** ./src/timeline/style.scss ***!
+  \*********************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/i18n"
+/*!******************************!*\
+  !*** external ["wp","i18n"] ***!
+  \******************************/
+(module) {
+
+module.exports = window["wp"]["i18n"];
+
+/***/ },
+
+/***/ "./src/timeline/block.json"
+/*!*********************************!*\
+  !*** ./src/timeline/block.json ***!
+  \*********************************/
+(module) {
+
+module.exports = /*#__PURE__*/JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/timeline","version":"0.1.0","title":"Timeline","category":"jvb","icon":"shortcode","description":"Outputs a single timeline post in a cool way","example":{},"supports":{"html":false,"align":["wide","full"]},"textdomain":"jvb","selectors":{"root":".timeline"},"editorScript":"file:./index.js","editorStyle":"file:./index.css","style":"file:./style-index.css","viewScript":"file:./view.js"}');
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"timeline/index": 0,
+/******/ 			"timeline/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["timeline/style-index"], () => (__webpack_require__("./src/timeline/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/timeline/index.js.map b/build/timeline/index.js.map
new file mode 100644
index 0000000..81c59b4
--- /dev/null
+++ b/build/timeline/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"timeline/index.js","mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACqC;;AAErC;AACA;AACA;AACA;AACA;AACA;AACwD;;AAExD;AACA;AACA;AACA;AACA;AACA;AACuB;;AAEvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA;AAQe,SAASI,IAAIA,CAAA,EAAG;EAC9B,oBACCD,sDAAA;IAAA,GAAQF,sEAAa,CAAC,CAAC;IAAAI,QAAA,EACpBL,mDAAE,CAAE,0BAA0B,EAAE,KAAM;EAAC,CACvC,CAAC;AAEN,C;;;;;;;;;;;;;;;;ACrCA;AACA;AACA;AACA;AACA;AACsD;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA;AACsB;;AAEtB;AACA;AACA;AAC0B;AACU;;AAEpC;AACA;AACA;AACA;AACA;AACAM,oEAAiB,CAAEC,6CAAa,EAAE;EACjC;AACD;AACA;EACCE,IAAI,EAAEL,6CAAIA;AACX,CAAE,CAAC,C;;;;;;;;;;;AChCH;;;;;;;;;;;;ACAA;;;;;;;;;;;ACAA,2C;;;;;;;;;;ACAA,6C;;;;;;;;;;ACAA,wC;;;;;;;;;;ACAA,sC;;;;;;;;;;;;;;;;UCAA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;UACA;;UAEA;UACA;;;;;WC/BA;WACA;WACA;WACA;WACA,+BAA+B,wCAAwC;WACvE;WACA;WACA;WACA;WACA,iBAAiB,qBAAqB;WACtC;WACA;WACA,kBAAkB,qBAAqB;WACvC;WACA;WACA,KAAK;WACL;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,E;;;;;WC3BA;WACA;WACA;WACA;WACA;WACA,iCAAiC,WAAW;WAC5C;WACA,E;;;;;WCPA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA,E;;;;;WCPA,wF;;;;;WCAA;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D,E;;;;;WCNA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA,MAAM,qBAAqB;WAC3B;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;WAEA;WACA;WACA,4G;;;;;UEjDA;UACA;UACA;UACA;UACA","sources":["webpack://jvb/./src/timeline/edit.js","webpack://jvb/./src/timeline/index.js","webpack://jvb/./src/timeline/editor.scss","webpack://jvb/./src/timeline/style.scss?2389","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"i18n\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["/**\r\n * Retrieves the translation of text.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/\r\n */\r\nimport { __ } from '@wordpress/i18n';\r\n\r\n/**\r\n * React hook that is used to mark the block wrapper element.\r\n * It provides all the necessary props like the class name.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops\r\n */\r\nimport { useBlockProps } from '@wordpress/block-editor';\r\n\r\n/**\r\n * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.\r\n * Those files can contain any CSS code that gets applied to the editor.\r\n *\r\n * @see https://www.npmjs.com/package/@wordpress/scripts#using-css\r\n */\r\nimport './editor.scss';\r\n\r\n/**\r\n * The edit function describes the structure of your block in the context of the\r\n * editor. This represents what the editor will render when the block is used.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit\r\n *\r\n * @return {Element} Element to render.\r\n */\r\nexport default function Edit() {\r\n\treturn (\r\n\t\t<p { ...useBlockProps() }>\r\n\t\t\t{ __( 'Will output the timeline', 'jvb' ) }\r\n\t\t</p>\r\n\t);\r\n}\r\n","/**\r\n * Registers a new block provided a unique name and an object defining its behavior.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nimport { registerBlockType } from '@wordpress/blocks';\r\n\r\n/**\r\n * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.\r\n * All files containing `style` keyword are bundled together. The code used\r\n * gets applied both to the front of your site and to the editor.\r\n *\r\n * @see https://www.npmjs.com/package/@wordpress/scripts#using-css\r\n */\r\nimport './style.scss';\r\n\r\n/**\r\n * Internal dependencies\r\n */\r\nimport Edit from './edit';\r\nimport metadata from './block.json';\r\n\r\n/**\r\n * Every block starts by registering a new block type definition.\r\n *\r\n * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/\r\n */\r\nregisterBlockType( metadata.name, {\r\n\t/**\r\n\t * @see ./edit.js\r\n\t */\r\n\tedit: Edit,\r\n} );\r\n","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"i18n\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"timeline/index\": 0,\n\t\"timeline/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"timeline/style-index\"], () => (__webpack_require__(\"./src/timeline/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["__","useBlockProps","jsx","_jsx","Edit","children","registerBlockType","metadata","name","edit"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/timeline/style-index-rtl.css b/build/timeline/style-index-rtl.css
index 49d43a6..8262603 100644
--- a/build/timeline/style-index-rtl.css
+++ b/build/timeline/style-index-rtl.css
@@ -1 +1,121 @@
-main{--gap:0}main section:last-of-type{margin-bottom:0}#at-a-glance{padding:0 10vw;--gap:0}#at-a-glance img{border:2px solid rgb(var(--action-0));height:auto;width:100%}#at-a-glance h3{font-size:var(--txt-x-small)}#at-a-glance .before img{border-right:0;border-left-width:1px;border-top:0}#at-a-glance .after img{border-bottom:0;border-right-width:1px;border-left:0}.timeline-point.timeline-point{--lineWidth:1px;--gap:2rem;background-color:rgb(var(--base));margin:0;max-width:100vw;overflow:hidden;padding:0;position:relative}.timeline-point.timeline-point img{border-radius:4px;padding:.5rem;position:sticky;width:40%}.timeline-point.timeline-point .info{padding:1rem .5rem .5rem;position:relative;width:60%}.timeline-point.timeline-point .info h2{font-size:var(--txt-medium);margin:0 0 .5rem;position:relative}.timeline-point.timeline-point .info h2 .icon{--w:2.5rem;background-color:rgb(var(--action-100));right:-2.5rem;position:absolute;top:.25rem;transform:rotate(90deg)}.timeline-point.timeline-point:after,.timeline-point.timeline-point:before{background-color:rgb(var(--action-0));content:"";display:block;height:100%;right:45%;position:absolute;width:var(--lineWidth)}.timeline-point.timeline-point:before{height:1rem}.timeline-point.timeline-point:after{top:4rem}.timeline-point.timeline-point#before-treatment:before,.timeline-point.timeline-point:last-of-type:after{display:none}@media(min-width:768px){#at-a-glance h3{font-size:var(--txt-x-large)}.timeline-point.timeline-point{--gap:4rem}.timeline-point.timeline-point img{width:50%}.timeline-point.timeline-point .info{padding:25vh 1rem 1rem;width:50%}.timeline-point.timeline-point .info h2 .icon{--w:4rem;right:-6.15rem;top:0}.timeline-point.timeline-point .info a{align-items:center;display:flex;flex-wrap:wrap}.timeline-point.timeline-point .info time{font-size:var(--txt-x-small);text-transform:uppercase}.timeline-point.timeline-point:after,.timeline-point.timeline-point:before{right:calc(50% + 2rem)}.timeline-point.timeline-point:before{height:calc(25vh - 2rem)}.timeline-point.timeline-point:after{top:calc(25vh + 6rem)}}
+/*!************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/timeline/style.scss ***!
+  \************************************************************************************************************************************************************************************************************************************************/
+main {
+  --gap: 0;
+}
+main section:last-of-type {
+  margin-bottom: 0;
+}
+#at-a-glance {
+  padding: 0 10vw;
+  --gap: 0;
+}
+#at-a-glance img {
+  width: 100%;
+  height: auto;
+  border: 2px solid rgb(var(--action-0));
+}
+#at-a-glance h3 {
+  font-size: var(--txt-x-small);
+}
+#at-a-glance .before img {
+  border-left-width: 1px;
+  border-right: 0;
+  border-top: 0;
+}
+#at-a-glance .after img {
+  border-right-width: 1px;
+  border-left: 0;
+  border-bottom: 0;
+}
+.timeline-point.timeline-point {
+  --lineWidth: 1px;
+  --gap: 2rem;
+  padding: 0;
+  margin: 0;
+  background-color: rgb(var(--base));
+  max-width: 100vw;
+  position: relative;
+  overflow: hidden;
+}
+.timeline-point.timeline-point img {
+  width: 40%;
+  border-radius: 4px;
+  position: sticky;
+  padding: 0.5rem;
+}
+.timeline-point.timeline-point .info {
+  padding: 1rem 0.5rem 0.5rem;
+  width: 60%;
+  position: relative;
+}
+.timeline-point.timeline-point .info h2 {
+  margin: 0 0 0.5rem;
+  font-size: var(--txt-medium);
+  position: relative;
+}
+.timeline-point.timeline-point .info h2 .icon {
+  --w: 2.5rem;
+  transform: rotate(90deg);
+  position: absolute;
+  right: -2.5rem;
+  top: 0.25rem;
+  background-color: rgb(var(--action-100));
+}
+.timeline-point.timeline-point::before, .timeline-point.timeline-point::after {
+  content: "";
+  display: block;
+  position: absolute;
+  right: 45%;
+  height: 100%;
+  width: var(--lineWidth);
+  background-color: rgb(var(--action-0));
+}
+.timeline-point.timeline-point::before {
+  height: 1rem;
+}
+.timeline-point.timeline-point::after {
+  top: 4rem;
+}
+.timeline-point.timeline-point#before-treatment::before, .timeline-point.timeline-point:last-of-type::after {
+  display: none;
+}
+@media (min-width: 768px) {
+  #at-a-glance h3 {
+    font-size: var(--txt-x-large);
+  }
+  .timeline-point.timeline-point {
+    --gap: 4rem;
+  }
+  .timeline-point.timeline-point img {
+    width: 50%;
+  }
+  .timeline-point.timeline-point .info {
+    width: 50%;
+    padding: 25vh 1rem 1rem;
+  }
+  .timeline-point.timeline-point .info h2 .icon {
+    --w: 4rem;
+    right: -6.15rem;
+    top: 0;
+  }
+  .timeline-point.timeline-point .info a {
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+  }
+  .timeline-point.timeline-point .info time {
+    text-transform: uppercase;
+    font-size: var(--txt-x-small);
+  }
+  .timeline-point.timeline-point::before, .timeline-point.timeline-point::after {
+    right: calc(50% + 2rem);
+  }
+  .timeline-point.timeline-point::before {
+    height: calc(25vh - 2rem);
+  }
+  .timeline-point.timeline-point::after {
+    top: calc(25vh + 6rem);
+  }
+}
diff --git a/build/timeline/style-index.css b/build/timeline/style-index.css
index 0d9dbbc..cae0546 100644
--- a/build/timeline/style-index.css
+++ b/build/timeline/style-index.css
@@ -1 +1,123 @@
-main{--gap:0}main section:last-of-type{margin-bottom:0}#at-a-glance{padding:0 10vw;--gap:0}#at-a-glance img{border:2px solid rgb(var(--action-0));height:auto;width:100%}#at-a-glance h3{font-size:var(--txt-x-small)}#at-a-glance .before img{border-left:0;border-right-width:1px;border-top:0}#at-a-glance .after img{border-bottom:0;border-left-width:1px;border-right:0}.timeline-point.timeline-point{--lineWidth:1px;--gap:2rem;background-color:rgb(var(--base));margin:0;max-width:100vw;overflow:hidden;padding:0;position:relative}.timeline-point.timeline-point img{border-radius:4px;padding:.5rem;position:sticky;width:40%}.timeline-point.timeline-point .info{padding:1rem .5rem .5rem;position:relative;width:60%}.timeline-point.timeline-point .info h2{font-size:var(--txt-medium);margin:0 0 .5rem;position:relative}.timeline-point.timeline-point .info h2 .icon{--w:2.5rem;background-color:rgb(var(--action-100));left:-2.5rem;position:absolute;top:.25rem;transform:rotate(-90deg)}.timeline-point.timeline-point:after,.timeline-point.timeline-point:before{background-color:rgb(var(--action-0));content:"";display:block;height:100%;left:45%;position:absolute;width:var(--lineWidth)}.timeline-point.timeline-point:before{height:1rem}.timeline-point.timeline-point:after{top:4rem}.timeline-point.timeline-point#before-treatment:before,.timeline-point.timeline-point:last-of-type:after{display:none}@media(min-width:768px){#at-a-glance h3{font-size:var(--txt-x-large)}.timeline-point.timeline-point{--gap:4rem}.timeline-point.timeline-point img{width:50%}.timeline-point.timeline-point .info{padding:25vh 1rem 1rem;width:50%}.timeline-point.timeline-point .info h2 .icon{--w:4rem;left:-6.15rem;top:0}.timeline-point.timeline-point .info a{align-items:center;display:flex;flex-wrap:wrap}.timeline-point.timeline-point .info time{font-size:var(--txt-x-small);text-transform:uppercase}.timeline-point.timeline-point:after,.timeline-point.timeline-point:before{left:calc(50% + 2rem)}.timeline-point.timeline-point:before{height:calc(25vh - 2rem)}.timeline-point.timeline-point:after{top:calc(25vh + 6rem)}}
+/*!************************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/timeline/style.scss ***!
+  \************************************************************************************************************************************************************************************************************************************************/
+main {
+  --gap: 0;
+}
+main section:last-of-type {
+  margin-bottom: 0;
+}
+#at-a-glance {
+  padding: 0 10vw;
+  --gap: 0;
+}
+#at-a-glance img {
+  width: 100%;
+  height: auto;
+  border: 2px solid rgb(var(--action-0));
+}
+#at-a-glance h3 {
+  font-size: var(--txt-x-small);
+}
+#at-a-glance .before img {
+  border-right-width: 1px;
+  border-left: 0;
+  border-top: 0;
+}
+#at-a-glance .after img {
+  border-left-width: 1px;
+  border-right: 0;
+  border-bottom: 0;
+}
+.timeline-point.timeline-point {
+  --lineWidth: 1px;
+  --gap: 2rem;
+  padding: 0;
+  margin: 0;
+  background-color: rgb(var(--base));
+  max-width: 100vw;
+  position: relative;
+  overflow: hidden;
+}
+.timeline-point.timeline-point img {
+  width: 40%;
+  border-radius: 4px;
+  position: sticky;
+  padding: 0.5rem;
+}
+.timeline-point.timeline-point .info {
+  padding: 1rem 0.5rem 0.5rem;
+  width: 60%;
+  position: relative;
+}
+.timeline-point.timeline-point .info h2 {
+  margin: 0 0 0.5rem;
+  font-size: var(--txt-medium);
+  position: relative;
+}
+.timeline-point.timeline-point .info h2 .icon {
+  --w: 2.5rem;
+  transform: rotate(-90deg);
+  position: absolute;
+  left: -2.5rem;
+  top: 0.25rem;
+  background-color: rgb(var(--action-100));
+}
+.timeline-point.timeline-point::before, .timeline-point.timeline-point::after {
+  content: "";
+  display: block;
+  position: absolute;
+  left: 45%;
+  height: 100%;
+  width: var(--lineWidth);
+  background-color: rgb(var(--action-0));
+}
+.timeline-point.timeline-point::before {
+  height: 1rem;
+}
+.timeline-point.timeline-point::after {
+  top: 4rem;
+}
+.timeline-point.timeline-point#before-treatment::before, .timeline-point.timeline-point:last-of-type::after {
+  display: none;
+}
+@media (min-width: 768px) {
+  #at-a-glance h3 {
+    font-size: var(--txt-x-large);
+  }
+  .timeline-point.timeline-point {
+    --gap: 4rem;
+  }
+  .timeline-point.timeline-point img {
+    width: 50%;
+  }
+  .timeline-point.timeline-point .info {
+    width: 50%;
+    padding: 25vh 1rem 1rem;
+  }
+  .timeline-point.timeline-point .info h2 .icon {
+    --w: 4rem;
+    left: -6.15rem;
+    top: 0;
+  }
+  .timeline-point.timeline-point .info a {
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+  }
+  .timeline-point.timeline-point .info time {
+    text-transform: uppercase;
+    font-size: var(--txt-x-small);
+  }
+  .timeline-point.timeline-point::before, .timeline-point.timeline-point::after {
+    left: calc(50% + 2rem);
+  }
+  .timeline-point.timeline-point::before {
+    height: calc(25vh - 2rem);
+  }
+  .timeline-point.timeline-point::after {
+    top: calc(25vh + 6rem);
+  }
+}
+
+/*# sourceMappingURL=style-index.css.map*/
\ No newline at end of file
diff --git a/build/timeline/style-index.css.map b/build/timeline/style-index.css.map
new file mode 100644
index 0000000..f366ec5
--- /dev/null
+++ b/build/timeline/style-index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"timeline/style-index.css","mappings":";;;AAAA;EACC;AACD;AAAC;EACC;AAEF;AAEA;EACC;EACA;AACD;AAAC;EACC;EACA;EACA;AAEF;AAAC;EACC;AAEF;AACE;EACC;EACA;EACA;AACH;AAGE;EACC;EACA;EACA;AADH;AAMA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AAHD;AAIC;EACC;EACA;EACA;EACA;AAFF;AAIC;EACC;EACA;EACA;AAFF;AAGE;EACC;EACA;EACA;AADH;AAEG;EACC;EACA;EACA;EACA;EACA;EACA;AAAJ;AAKC;EAEC;EACA;EACA;EACA;EACA;EACA;EACA;AAJF;AAOC;EACC;AALF;AAOC;EACC;AALF;AAOC;EAEC;AANF;AASA;EAEE;IACC;EAPD;EAUD;IACC;EARA;EASA;IACC;EAPD;EASA;IACC;IACA;EAPD;EASE;IACC;IACA;IACA;EAPH;EAUC;IACC;IACA;IACA;EARF;EAWC;IACC;IACA;EATF;EAYA;IAEC;EAXD;EAcA;IACC;EAZD;EAcA;IACC;EAZD;AACF,C","sources":["webpack://jvb/./src/timeline/style.scss"],"sourcesContent":["main {\r\n\t--gap: 0;\r\n\tsection:last-of-type {\r\n\t\tmargin-bottom: 0;\r\n\t}\r\n}\r\n\r\n#at-a-glance {\r\n\tpadding: 0 10vw;\r\n\t--gap: 0;\r\n\timg {\r\n\t\twidth: 100%;\r\n\t\theight: auto;\r\n\t\tborder: 2px solid rgb(var(--action-0));\r\n\t}\r\n\th3 {\r\n\t\tfont-size: var(--txt-x-small);\r\n\t}\r\n\t.before {\r\n\t\timg {\r\n\t\t\tborder-right-width: 1px;\r\n\t\t\tborder-left: 0;\r\n\t\t\tborder-top: 0;\r\n\t\t}\r\n\t}\r\n\t.after {\r\n\t\timg {\r\n\t\t\tborder-left-width: 1px;\r\n\t\t\tborder-right: 0;\r\n\t\t\tborder-bottom: 0;\r\n\t\t}\r\n\t}\r\n}\r\n\r\n.timeline-point.timeline-point {\r\n\t--lineWidth: 1px;\r\n\t--gap: 2rem;\r\n\tpadding: 0;\r\n\tmargin:0;\r\n\tbackground-color: rgb(var(--base));\r\n\tmax-width: 100vw;\r\n\tposition: relative;\r\n\toverflow: hidden;\r\n\timg {\r\n\t\twidth: 40%;\r\n\t\tborder-radius: 4px;\r\n\t\tposition: sticky;\r\n\t\tpadding: .5rem;\r\n\t}\r\n\t.info {\r\n\t\tpadding: 1rem .5rem .5rem;\r\n\t\twidth: 60%;\r\n\t\tposition: relative;\r\n\t\th2 {\r\n\t\t\tmargin: 0 0 .5rem;\r\n\t\t\tfont-size: var(--txt-medium);\r\n\t\t\tposition: relative;\r\n\t\t\t.icon {\r\n\t\t\t\t--w: 2.5rem;\r\n\t\t\t\ttransform: rotate(-90deg);\r\n\t\t\t\tposition: absolute;\r\n\t\t\t\tleft: -2.5rem;\r\n\t\t\t\ttop: .25rem;\r\n\t\t\t\tbackground-color: rgb(var(--action-100));\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t}\r\n\t&::before,\r\n\t&::after {\r\n\t\tcontent: '';\r\n\t\tdisplay: block;\r\n\t\tposition: absolute;\r\n\t\tleft: 45%;\r\n\t\theight: 100%;\r\n\t\twidth: var(--lineWidth);\r\n\t\tbackground-color: rgb(var(--action-0));\r\n\t\t//box-shadow: var(--action-shadow);\r\n\t}\r\n\t&::before {\r\n\t\theight: 1rem;\r\n\t}\r\n\t&::after {\r\n\t\ttop: 4rem;\r\n\t}\r\n\t&#before-treatment::before,\r\n\t&:last-of-type::after {\r\n\t\tdisplay: none;\r\n\t}\r\n}\r\n@media (min-width:768px) {\r\n\t#at-a-glance {\r\n\t\th3  {\r\n\t\t\tfont-size: var(--txt-x-large);\r\n\t\t}\r\n\t}\r\n\t.timeline-point.timeline-point {\r\n\t\t--gap: 4rem;\r\n\t\timg {\r\n\t\t\twidth: 50%;\r\n\t\t}\r\n\t\t.info {\r\n\t\t\twidth: 50%;\r\n\t\t\tpadding: 25vh 1rem 1rem;\r\n\t\t\th2 {\r\n\t\t\t\t.icon {\r\n\t\t\t\t\t--w: 4rem;\r\n\t\t\t\t\tleft: -6.15rem;\r\n\t\t\t\t\ttop: 0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\ta {\r\n\t\t\t\tdisplay: flex;\r\n\t\t\t\tflex-wrap: wrap;\r\n\t\t\t\talign-items: center;\r\n\t\t\t}\r\n\r\n\t\t\ttime {\r\n\t\t\t\ttext-transform: uppercase;\r\n\t\t\t\tfont-size: var(--txt-x-small);\r\n\t\t\t}\r\n\t\t}\r\n\t\t&::before,\r\n\t\t&::after {\r\n\t\t\tleft: calc(50% + 2rem);\r\n\t\t}\r\n\r\n\t\t&::before {\r\n\t\t\theight: calc(25vh - 2rem);\r\n\t\t}\r\n\t\t&::after {\r\n\t\t\ttop: calc(25vh + 6rem);\r\n\t\t}\r\n\t}\r\n}\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/timeline/view.asset.php b/build/timeline/view.asset.php
index f534533..3bef9ef 100644
--- a/build/timeline/view.asset.php
+++ b/build/timeline/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => '31d6cfe0d16ae931b73c');
+<?php return array('dependencies' => array(), 'version' => '15793ef55a73b3a89877');
diff --git a/build/timeline/view.js b/build/timeline/view.js
index e69de29..cabec61 100644
--- a/build/timeline/view.js
+++ b/build/timeline/view.js
@@ -0,0 +1,7 @@
+/******/ (() => { // webpackBootstrap
+/*!******************************!*\
+  !*** ./src/timeline/view.js ***!
+  \******************************/
+
+/******/ })()
+;
\ No newline at end of file
diff --git a/build/video/block.json b/build/video/block.json
index da6ef1d..a30b033 100644
--- a/build/video/block.json
+++ b/build/video/block.json
@@ -28,7 +28,7 @@
       "default": ""
     },
     "description": {
-      "type": "rich-text",
+      "type": "string",
       "default": ""
     },
     "posterId": {
diff --git a/build/video/index-rtl.css b/build/video/index-rtl.css
index a6ed157..ea4d099 100644
--- a/build/video/index-rtl.css
+++ b/build/video/index-rtl.css
@@ -1 +1,128 @@
-.video-cover-editor{background:#f0f0f0;border:2px dashed #ccc;border-radius:4px;min-height:200px;position:relative}.video-cover-editor .video-cover-preview{min-height:300px;position:relative;width:100%}.video-cover-editor .video-cover-preview img{display:block;height:auto;width:100%}.video-cover-editor .video-cover-preview .video-overlay-preview{background:#000;bottom:0;right:0;pointer-events:none;position:absolute;left:0;top:0}.video-cover-editor .video-cover-preview .video-cover-content-preview{bottom:0;display:flex;right:0;padding:2rem;position:absolute;left:0;top:0;z-index:2}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-left{align-items:flex-start;justify-content:flex-start}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-center{align-items:flex-start;justify-content:center}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-right{align-items:flex-start;justify-content:flex-end}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center-left{align-items:center;justify-content:flex-start}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center{align-items:center;justify-content:center}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center-right{align-items:center;justify-content:flex-end}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-left{align-items:flex-end;justify-content:flex-start}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-center{align-items:flex-end;justify-content:center}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-right{align-items:flex-end;justify-content:flex-end}.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content{color:#fff;max-width:1200px;text-shadow:0 2px 4px rgba(0,0,0,.5);width:100%}.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h1,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h2,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h3,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h4,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h5,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h6,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content p{color:#fff}.video-cover-editor .video-cover-preview .video-info{background:rgba(0,0,0,.7);bottom:0;color:#fff;font-size:14px;right:0;padding:10px;position:absolute;left:0;z-index:3}.video-cover-editor .video-cover-preview .video-info p{margin:0}.video-cover-editor .video-cover-placeholder{align-items:center;color:#666;display:flex;font-size:16px;justify-content:center;min-height:200px}.video-source-list{list-style:none;margin:10px 0;padding:0}.video-source-list .video-source-item{align-items:center;background:#f5f5f5;border-radius:4px;display:flex;justify-content:space-between;margin-bottom:5px;padding:8px 12px}.video-source-list .video-source-item .video-source-mime{font-family:monospace;font-size:13px}
+/*!**********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/video/editor.scss ***!
+  \**********************************************************************************************************************************************************************************************************************************************/
+/* editor.scss */
+.video-cover-editor {
+  position: relative;
+  min-height: 200px;
+  background: #f0f0f0;
+  border: 2px dashed #ccc;
+  border-radius: 4px;
+}
+.video-cover-editor .video-cover-preview {
+  position: relative;
+  width: 100%;
+  min-height: 300px;
+}
+.video-cover-editor .video-cover-preview img {
+  width: 100%;
+  height: auto;
+  display: block;
+}
+.video-cover-editor .video-cover-preview .video-overlay-preview {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  background: rgb(0, 0, 0);
+  pointer-events: none;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  bottom: 0;
+  display: flex;
+  z-index: 2;
+  padding: 2rem;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-left {
+  align-items: flex-start;
+  justify-content: flex-start;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-center {
+  align-items: flex-start;
+  justify-content: center;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-right {
+  align-items: flex-start;
+  justify-content: flex-end;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center-left {
+  align-items: center;
+  justify-content: flex-start;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center {
+  align-items: center;
+  justify-content: center;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center-right {
+  align-items: center;
+  justify-content: flex-end;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-left {
+  align-items: flex-end;
+  justify-content: flex-start;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-center {
+  align-items: flex-end;
+  justify-content: center;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-right {
+  align-items: flex-end;
+  justify-content: flex-end;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content {
+  width: 100%;
+  max-width: 1200px;
+  color: white;
+  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h1, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h2, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h3, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h4, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h5, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h6 {
+  color: white;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content p {
+  color: white;
+}
+.video-cover-editor .video-cover-preview .video-info {
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  left: 0;
+  background: rgba(0, 0, 0, 0.7);
+  color: white;
+  padding: 10px;
+  font-size: 14px;
+  z-index: 3;
+}
+.video-cover-editor .video-cover-preview .video-info p {
+  margin: 0;
+}
+.video-cover-editor .video-cover-placeholder {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 200px;
+  color: #666;
+  font-size: 16px;
+}
+.video-source-list {
+  list-style: none;
+  margin: 10px 0;
+  padding: 0;
+}
+.video-source-list .video-source-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 8px 12px;
+  background: #f5f5f5;
+  border-radius: 4px;
+  margin-bottom: 5px;
+}
+.video-source-list .video-source-item .video-source-mime {
+  font-family: monospace;
+  font-size: 13px;
+}
diff --git a/build/video/index.asset.php b/build/video/index.asset.php
index 24a0e78..cfcffb9 100644
--- a/build/video/index.asset.php
+++ b/build/video/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => 'c48f86c4435d0e281940');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-i18n'), 'version' => '96181be3142bbc60239d');
diff --git a/build/video/index.css b/build/video/index.css
index 5616a94..f4807fa 100644
--- a/build/video/index.css
+++ b/build/video/index.css
@@ -1 +1,130 @@
-.video-cover-editor{background:#f0f0f0;border:2px dashed #ccc;border-radius:4px;min-height:200px;position:relative}.video-cover-editor .video-cover-preview{min-height:300px;position:relative;width:100%}.video-cover-editor .video-cover-preview img{display:block;height:auto;width:100%}.video-cover-editor .video-cover-preview .video-overlay-preview{background:#000;bottom:0;left:0;pointer-events:none;position:absolute;right:0;top:0}.video-cover-editor .video-cover-preview .video-cover-content-preview{bottom:0;display:flex;left:0;padding:2rem;position:absolute;right:0;top:0;z-index:2}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-left{align-items:flex-start;justify-content:flex-start}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-center{align-items:flex-start;justify-content:center}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-right{align-items:flex-start;justify-content:flex-end}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center-left{align-items:center;justify-content:flex-start}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center{align-items:center;justify-content:center}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center-right{align-items:center;justify-content:flex-end}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-left{align-items:flex-end;justify-content:flex-start}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-center{align-items:flex-end;justify-content:center}.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-right{align-items:flex-end;justify-content:flex-end}.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content{color:#fff;max-width:1200px;text-shadow:0 2px 4px rgba(0,0,0,.5);width:100%}.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h1,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h2,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h3,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h4,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h5,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h6,.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content p{color:#fff}.video-cover-editor .video-cover-preview .video-info{background:rgba(0,0,0,.7);bottom:0;color:#fff;font-size:14px;left:0;padding:10px;position:absolute;right:0;z-index:3}.video-cover-editor .video-cover-preview .video-info p{margin:0}.video-cover-editor .video-cover-placeholder{align-items:center;color:#666;display:flex;font-size:16px;justify-content:center;min-height:200px}.video-source-list{list-style:none;margin:10px 0;padding:0}.video-source-list .video-source-item{align-items:center;background:#f5f5f5;border-radius:4px;display:flex;justify-content:space-between;margin-bottom:5px;padding:8px 12px}.video-source-list .video-source-item .video-source-mime{font-family:monospace;font-size:13px}
+/*!**********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/video/editor.scss ***!
+  \**********************************************************************************************************************************************************************************************************************************************/
+/* editor.scss */
+.video-cover-editor {
+  position: relative;
+  min-height: 200px;
+  background: #f0f0f0;
+  border: 2px dashed #ccc;
+  border-radius: 4px;
+}
+.video-cover-editor .video-cover-preview {
+  position: relative;
+  width: 100%;
+  min-height: 300px;
+}
+.video-cover-editor .video-cover-preview img {
+  width: 100%;
+  height: auto;
+  display: block;
+}
+.video-cover-editor .video-cover-preview .video-overlay-preview {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background: rgb(0, 0, 0);
+  pointer-events: none;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  display: flex;
+  z-index: 2;
+  padding: 2rem;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-left {
+  align-items: flex-start;
+  justify-content: flex-start;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-center {
+  align-items: flex-start;
+  justify-content: center;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-top-right {
+  align-items: flex-start;
+  justify-content: flex-end;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center-left {
+  align-items: center;
+  justify-content: flex-start;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center {
+  align-items: center;
+  justify-content: center;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-center-right {
+  align-items: center;
+  justify-content: flex-end;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-left {
+  align-items: flex-end;
+  justify-content: flex-start;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-center {
+  align-items: flex-end;
+  justify-content: center;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview.align-bottom-right {
+  align-items: flex-end;
+  justify-content: flex-end;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content {
+  width: 100%;
+  max-width: 1200px;
+  color: white;
+  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h1, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h2, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h3, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h4, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h5, .video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content h6 {
+  color: white;
+}
+.video-cover-editor .video-cover-preview .video-cover-content-preview .video-cover-content p {
+  color: white;
+}
+.video-cover-editor .video-cover-preview .video-info {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  background: rgba(0, 0, 0, 0.7);
+  color: white;
+  padding: 10px;
+  font-size: 14px;
+  z-index: 3;
+}
+.video-cover-editor .video-cover-preview .video-info p {
+  margin: 0;
+}
+.video-cover-editor .video-cover-placeholder {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  min-height: 200px;
+  color: #666;
+  font-size: 16px;
+}
+.video-source-list {
+  list-style: none;
+  margin: 10px 0;
+  padding: 0;
+}
+.video-source-list .video-source-item {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 8px 12px;
+  background: #f5f5f5;
+  border-radius: 4px;
+  margin-bottom: 5px;
+}
+.video-source-list .video-source-item .video-source-mime {
+  font-family: monospace;
+  font-size: 13px;
+}
+
+/*# sourceMappingURL=index.css.map*/
\ No newline at end of file
diff --git a/build/video/index.css.map b/build/video/index.css.map
new file mode 100644
index 0000000..31ea0d9
--- /dev/null
+++ b/build/video/index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"video/index.css","mappings":";;;AAAA;AACA;EACC;EACA;EACA;EACA;EACA;AACD;AACC;EACC;EACA;EACA;AACF;AACE;EACC;EACA;EACA;AACH;AAEE;EACC;EACA;EACA;EACA;EACA;EACA;EACA;AAAH;AAGE;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AADH;AAIG;EACC;EACA;AAFJ;AAIG;EACC;EACA;AAFJ;AAIG;EACC;EACA;AAFJ;AAIG;EACC;EACA;AAFJ;AAIG;EACC;EACA;AAFJ;AAIG;EACC;EACA;AAFJ;AAIG;EACC;EACA;AAFJ;AAIG;EACC;EACA;AAFJ;AAIG;EACC;EACA;AAFJ;AAKG;EACC;EACA;EACA;EACA;AAHJ;AAMI;EACC;AAJL;AAOI;EACC;AALL;AAUE;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AARH;AAUG;EACC;AARJ;AAaC;EACC;EACA;EACA;EACA;EACA;EACA;AAXF;AAeA;EACC;EACA;EACA;AAZD;AAcC;EACC;EACA;EACA;EACA;EACA;EACA;EACA;AAZF;AAcE;EACC;EACA;AAZH,C","sources":["webpack://jvb/./src/video/editor.scss"],"sourcesContent":["/* editor.scss */\r\n.video-cover-editor {\r\n\tposition: relative;\r\n\tmin-height: 200px;\r\n\tbackground: #f0f0f0;\r\n\tborder: 2px dashed #ccc;\r\n\tborder-radius: 4px;\r\n\r\n\t.video-cover-preview {\r\n\t\tposition: relative;\r\n\t\twidth: 100%;\r\n\t\tmin-height: 300px;\r\n\r\n\t\timg {\r\n\t\t\twidth: 100%;\r\n\t\t\theight: auto;\r\n\t\t\tdisplay: block;\r\n\t\t}\r\n\r\n\t\t.video-overlay-preview {\r\n\t\t\tposition: absolute;\r\n\t\t\ttop: 0;\r\n\t\t\tleft: 0;\r\n\t\t\tright: 0;\r\n\t\t\tbottom: 0;\r\n\t\t\tbackground: rgba(0, 0, 0, 1);\r\n\t\t\tpointer-events: none;\r\n\t\t}\r\n\r\n\t\t.video-cover-content-preview {\r\n\t\t\tposition: absolute;\r\n\t\t\ttop: 0;\r\n\t\t\tleft: 0;\r\n\t\t\tright: 0;\r\n\t\t\tbottom: 0;\r\n\t\t\tdisplay: flex;\r\n\t\t\tz-index: 2;\r\n\t\t\tpadding: 2rem;\r\n\r\n\t\t\t// Content alignment classes\r\n\t\t\t&.align-top-left {\r\n\t\t\t\talign-items: flex-start;\r\n\t\t\t\tjustify-content: flex-start;\r\n\t\t\t}\r\n\t\t\t&.align-top-center {\r\n\t\t\t\talign-items: flex-start;\r\n\t\t\t\tjustify-content: center;\r\n\t\t\t}\r\n\t\t\t&.align-top-right {\r\n\t\t\t\talign-items: flex-start;\r\n\t\t\t\tjustify-content: flex-end;\r\n\t\t\t}\r\n\t\t\t&.align-center-left {\r\n\t\t\t\talign-items: center;\r\n\t\t\t\tjustify-content: flex-start;\r\n\t\t\t}\r\n\t\t\t&.align-center {\r\n\t\t\t\talign-items: center;\r\n\t\t\t\tjustify-content: center;\r\n\t\t\t}\r\n\t\t\t&.align-center-right {\r\n\t\t\t\talign-items: center;\r\n\t\t\t\tjustify-content: flex-end;\r\n\t\t\t}\r\n\t\t\t&.align-bottom-left {\r\n\t\t\t\talign-items: flex-end;\r\n\t\t\t\tjustify-content: flex-start;\r\n\t\t\t}\r\n\t\t\t&.align-bottom-center {\r\n\t\t\t\talign-items: flex-end;\r\n\t\t\t\tjustify-content: center;\r\n\t\t\t}\r\n\t\t\t&.align-bottom-right {\r\n\t\t\t\talign-items: flex-end;\r\n\t\t\t\tjustify-content: flex-end;\r\n\t\t\t}\r\n\r\n\t\t\t.video-cover-content {\r\n\t\t\t\twidth: 100%;\r\n\t\t\t\tmax-width: 1200px;\r\n\t\t\t\tcolor: white;\r\n\t\t\t\ttext-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);\r\n\r\n\t\t\t\t// Style inner blocks for better visibility in editor\r\n\t\t\t\th1, h2, h3, h4, h5, h6 {\r\n\t\t\t\t\tcolor: white;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tp {\r\n\t\t\t\t\tcolor: white;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t.video-info {\r\n\t\t\tposition: absolute;\r\n\t\t\tbottom: 0;\r\n\t\t\tleft: 0;\r\n\t\t\tright: 0;\r\n\t\t\tbackground: rgba(0, 0, 0, 0.7);\r\n\t\t\tcolor: white;\r\n\t\t\tpadding: 10px;\r\n\t\t\tfont-size: 14px;\r\n\t\t\tz-index: 3;\r\n\r\n\t\t\tp {\r\n\t\t\t\tmargin: 0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t.video-cover-placeholder {\r\n\t\tdisplay: flex;\r\n\t\talign-items: center;\r\n\t\tjustify-content: center;\r\n\t\tmin-height: 200px;\r\n\t\tcolor: #666;\r\n\t\tfont-size: 16px;\r\n\t}\r\n}\r\n\r\n.video-source-list {\r\n\tlist-style: none;\r\n\tmargin: 10px 0;\r\n\tpadding: 0;\r\n\r\n\t.video-source-item {\r\n\t\tdisplay: flex;\r\n\t\tjustify-content: space-between;\r\n\t\talign-items: center;\r\n\t\tpadding: 8px 12px;\r\n\t\tbackground: #f5f5f5;\r\n\t\tborder-radius: 4px;\r\n\t\tmargin-bottom: 5px;\r\n\r\n\t\t.video-source-mime {\r\n\t\t\tfont-family: monospace;\r\n\t\t\tfont-size: 13px;\r\n\t\t}\r\n\t}\r\n}\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/video/index.js b/build/video/index.js
index acb5065..414c944 100644
--- a/build/video/index.js
+++ b/build/video/index.js
@@ -1 +1,586 @@
-(()=>{"use strict";var e,t={747(){const e=window.wp.blocks,t=window.wp.blockEditor,o=window.wp.i18n,l=window.wp.components,r=window.ReactJSXRuntime,i=["video"],n=[["core/heading",{level:1,placeholder:"Add heading...",textAlign:"center"}],["core/paragraph",{placeholder:"Add description...",align:"center"}],["core/buttons",{layout:{type:"flex",justifyContent:"center"}}]];(0,e.registerBlockType)("jvb/video",{edit:function({attributes:e,setAttributes:s}){const{posterId:a,posterUrl:c,videoSources:d,fadeEffect:v,overlayOpacity:p,contentAlignment:h,minHeight:j}=e,b=(0,t.useBlockProps)({className:"video-cover-editor",style:{minHeight:j?`${j}px`:void 0}}),m=(0,t.useInnerBlocksProps)({className:"video-cover-content"},{template:n,templateLock:!1});return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)(t.InspectorControls,{children:[(0,r.jsxs)(l.PanelBody,{title:(0,o.__)("Video Settings","jvb"),initialOpen:!0,children:[(0,r.jsx)(l.BaseControl,{label:(0,o.__)("Poster Image","jvb"),help:(0,o.__)("Image shown while video loads","jvb"),children:(0,r.jsx)(t.MediaUploadCheck,{children:(0,r.jsx)(t.MediaUpload,{onSelect:e=>{s({posterId:e.id,posterUrl:e.url})},allowedTypes:["image"],value:a,render:({open:e})=>(0,r.jsxs)(r.Fragment,{children:[c&&(0,r.jsx)("img",{src:c,alt:(0,o.__)("Poster preview","jvb"),style:{maxWidth:"100%",marginBottom:"10px"}}),(0,r.jsx)(l.Button,{onClick:e,variant:c?"secondary":"primary",children:c?(0,o.__)("Change Poster","jvb"):(0,o.__)("Select Poster","jvb")}),c&&(0,r.jsx)(l.Button,{isDestructive:!0,onClick:()=>s({posterId:0,posterUrl:""}),style:{marginLeft:"10px"},children:(0,o.__)("Remove","jvb")})]})})})}),(0,r.jsxs)(l.BaseControl,{label:(0,o.__)("Video Sources","jvb"),help:(0,o.__)("Add multiple formats for better browser support (mp4, webm, etc.)","jvb"),children:[d.length>0&&(0,r.jsx)("ul",{className:"video-source-list",children:d.map((e,t)=>(0,r.jsxs)("li",{className:"video-source-item",children:[(0,r.jsx)("span",{className:"video-source-mime",children:e.mime}),(0,r.jsx)(l.Button,{isDestructive:!0,isSmall:!0,onClick:()=>(e=>{const t=[...d];t.splice(e,1),s({videoSources:t})})(t),children:(0,o.__)("Remove","jvb")})]},t))}),(0,r.jsx)(t.MediaUploadCheck,{children:(0,r.jsx)(t.MediaUpload,{multiple:!0,onSelect:e=>{const t=(Array.isArray(e)?e:[e]).filter(e=>!d.some(t=>t.id===e.id)).map(e=>({id:e.id,url:e.url,mime:e.mime}));t.length&&s({videoSources:[...d,...t]})},allowedTypes:i,render:({open:e})=>(0,r.jsx)(l.Button,{onClick:e,variant:"secondary",children:(0,o.__)("Add Video","jvb")})})})]}),(0,r.jsx)(l.ToggleControl,{label:(0,o.__)("Fade Effect","jvb"),help:(0,o.__)("Add fade class to video element","jvb"),checked:v,onChange:e=>s({fadeEffect:e})})]}),(0,r.jsxs)(l.PanelBody,{title:(0,o.__)("Overlay Settings","jvb"),initialOpen:!0,children:[(0,r.jsx)(l.RangeControl,{label:(0,o.__)("Overlay Opacity","jvb"),help:(0,o.__)("Darken video for better text readability","jvb"),value:p,onChange:e=>s({overlayOpacity:e}),min:0,max:100,step:5}),(0,r.jsx)(l.SelectControl,{label:(0,o.__)("Content Alignment","jvb"),value:h,options:[{label:(0,o.__)("Top Left","jvb"),value:"top-left"},{label:(0,o.__)("Top Center","jvb"),value:"top-center"},{label:(0,o.__)("Top Right","jvb"),value:"top-right"},{label:(0,o.__)("Center Left","jvb"),value:"center-left"},{label:(0,o.__)("Center","jvb"),value:"center"},{label:(0,o.__)("Center Right","jvb"),value:"center-right"},{label:(0,o.__)("Bottom Left","jvb"),value:"bottom-left"},{label:(0,o.__)("Bottom Center","jvb"),value:"bottom-center"},{label:(0,o.__)("Bottom Right","jvb"),value:"bottom-right"}],onChange:e=>s({contentAlignment:e})}),(0,r.jsx)(l.RangeControl,{label:(0,o.__)("Minimum Height","jvb"),help:(0,o.__)("Minimum height in pixels (leave 0 for auto)","jvb"),value:j,onChange:e=>s({minHeight:e}),min:0,max:1e3,step:50})]})]}),(0,r.jsx)("div",{...b,children:c||d.length>0?(0,r.jsxs)("div",{className:"video-cover-preview",children:[c&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("img",{src:c,alt:(0,o.__)("Video poster","jvb")}),p>0&&(0,r.jsx)("div",{className:"video-overlay-preview",style:{opacity:p/100}})]}),(0,r.jsx)("div",{className:`video-cover-content-preview align-${h}`,children:(0,r.jsx)("div",{...m})}),(0,r.jsx)("div",{className:"video-info",children:(0,r.jsxs)("p",{children:[d.length," ",(0,o.__)("desktop source(s)","jvb")]})})]}):(0,r.jsx)("div",{className:"video-cover-placeholder",children:(0,r.jsx)("p",{children:(0,o.__)("Configure video sources in the sidebar →","jvb")})})})]})},save:({attributes:e})=>{const o=t.useBlockProps.save({className:"video-cover-wrapper-placeholder"});return(0,r.jsx)("div",{...o,children:(0,r.jsx)(t.InnerBlocks.Content,{})})}})}},o={};function l(e){var r=o[e];if(void 0!==r)return r.exports;var i=o[e]={exports:{}};return t[e](i,i.exports,l),i.exports}l.m=t,e=[],l.O=(t,o,r,i)=>{if(!o){var n=1/0;for(d=0;d<e.length;d++){for(var[o,r,i]=e[d],s=!0,a=0;a<o.length;a++)(!1&i||n>=i)&&Object.keys(l.O).every(e=>l.O[e](o[a]))?o.splice(a--,1):(s=!1,i<n&&(n=i));if(s){e.splice(d--,1);var c=r();void 0!==c&&(t=c)}}return t}i=i||0;for(var d=e.length;d>0&&e[d-1][2]>i;d--)e[d]=e[d-1];e[d]=[o,r,i]},l.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={205:0,601:0};l.O.j=t=>0===e[t];var t=(t,o)=>{var r,i,[n,s,a]=o,c=0;if(n.some(t=>0!==e[t])){for(r in s)l.o(s,r)&&(l.m[r]=s[r]);if(a)var d=a(l)}for(t&&t(o);c<n.length;c++)i=n[c],l.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return l.O(d)},o=globalThis.webpackChunkjvb=globalThis.webpackChunkjvb||[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})();var r=l.O(void 0,[601],()=>l(747));r=l.O(r)})();
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/******/ 	"use strict";
+/******/ 	var __webpack_modules__ = ({
+
+/***/ "./src/video/edit.js"
+/*!***************************!*\
+  !*** ./src/video/edit.js ***!
+  \***************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
+/* harmony export */   "default": () => (/* binding */ Edit)
+/* harmony export */ });
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/i18n */ "@wordpress/i18n");
+/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @wordpress/components */ "@wordpress/components");
+/* harmony import */ var _wordpress_components__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__);
+/* harmony import */ var _editor_scss__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./editor.scss */ "./src/video/editor.scss");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__);
+//edit.js
+
+
+
+
+
+const ALLOWED_VIDEO_TYPES = ['video'];
+const INNER_BLOCKS_TEMPLATE = [['core/heading', {
+  level: 1,
+  placeholder: 'Add heading...',
+  textAlign: 'center'
+}], ['core/paragraph', {
+  placeholder: 'Add description...',
+  align: 'center'
+}], ['core/buttons', {
+  layout: {
+    type: 'flex',
+    justifyContent: 'center'
+  }
+}]];
+function Edit({
+  attributes,
+  setAttributes
+}) {
+  const {
+    posterId,
+    posterUrl,
+    videoSources,
+    fadeEffect,
+    overlayOpacity,
+    contentAlignment,
+    minHeight
+  } = attributes;
+  const blockProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.useBlockProps)({
+    className: 'video-cover-editor',
+    style: {
+      minHeight: minHeight ? `${minHeight}px` : undefined
+    }
+  });
+  const innerBlocksProps = (0,_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.useInnerBlocksProps)({
+    className: 'video-cover-content'
+  }, {
+    template: INNER_BLOCKS_TEMPLATE,
+    templateLock: false
+  });
+  const onSelectPoster = media => {
+    setAttributes({
+      posterId: media.id,
+      posterUrl: media.url
+    });
+  };
+  const onSelectVideos = mediaItems => {
+    // multiple=true returns an array
+    const items = Array.isArray(mediaItems) ? mediaItems : [mediaItems];
+    const newSources = items.filter(media => !videoSources.some(s => s.id === media.id)).map(media => ({
+      id: media.id,
+      url: media.url,
+      mime: media.mime
+    }));
+    if (newSources.length) {
+      setAttributes({
+        videoSources: [...videoSources, ...newSources]
+      });
+    }
+  };
+  const removeVideoSource = index => {
+    const updated = [...videoSources];
+    updated.splice(index, 1);
+    setAttributes({
+      videoSources: updated
+    });
+  };
+  const renderVideoSourceList = (sources, isMobile = false) => {
+    if (sources.length === 0) return null;
+    return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("ul", {
+      className: "video-source-list",
+      children: sources.map((source, index) => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)("li", {
+        className: "video-source-item",
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("span", {
+          className: "video-source-mime",
+          children: source.mime
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.Button, {
+          isDestructive: true,
+          isSmall: true,
+          onClick: () => removeVideoSource(index, isMobile),
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Remove', 'jvb')
+        })]
+      }, index))
+    });
+  };
+  return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.Fragment, {
+    children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.InspectorControls, {
+      children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.PanelBody, {
+        title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Video Settings', 'jvb'),
+        initialOpen: true,
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.BaseControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Poster Image', 'jvb'),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Image shown while video loads', 'jvb'),
+          children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.MediaUploadCheck, {
+            children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.MediaUpload, {
+              onSelect: onSelectPoster,
+              allowedTypes: ['image'],
+              value: posterId,
+              render: ({
+                open
+              }) => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.Fragment, {
+                children: [posterUrl && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("img", {
+                  src: posterUrl,
+                  alt: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Poster preview', 'jvb'),
+                  style: {
+                    maxWidth: '100%',
+                    marginBottom: '10px'
+                  }
+                }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.Button, {
+                  onClick: open,
+                  variant: posterUrl ? 'secondary' : 'primary',
+                  children: posterUrl ? (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Change Poster', 'jvb') : (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Select Poster', 'jvb')
+                }), posterUrl && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.Button, {
+                  isDestructive: true,
+                  onClick: () => setAttributes({
+                    posterId: 0,
+                    posterUrl: ''
+                  }),
+                  style: {
+                    marginLeft: '10px'
+                  },
+                  children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Remove', 'jvb')
+                })]
+              })
+            })
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.BaseControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Video Sources', 'jvb'),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Add multiple formats for better browser support (mp4, webm, etc.)', 'jvb'),
+          children: [videoSources.length > 0 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("ul", {
+            className: "video-source-list",
+            children: videoSources.map((source, index) => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)("li", {
+              className: "video-source-item",
+              children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("span", {
+                className: "video-source-mime",
+                children: source.mime
+              }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.Button, {
+                isDestructive: true,
+                isSmall: true,
+                onClick: () => removeVideoSource(index),
+                children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Remove', 'jvb')
+              })]
+            }, index))
+          }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.MediaUploadCheck, {
+            children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.MediaUpload, {
+              multiple: true,
+              onSelect: onSelectVideos,
+              allowedTypes: ALLOWED_VIDEO_TYPES,
+              render: ({
+                open
+              }) => /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.Button, {
+                onClick: open,
+                variant: "secondary",
+                children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Add Video', 'jvb')
+              })
+            })
+          })]
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.ToggleControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Fade Effect', 'jvb'),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Add fade class to video element', 'jvb'),
+          checked: fadeEffect,
+          onChange: value => setAttributes({
+            fadeEffect: value
+          })
+        })]
+      }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.PanelBody, {
+        title: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Overlay Settings', 'jvb'),
+        initialOpen: true,
+        children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.RangeControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Overlay Opacity', 'jvb'),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Darken video for better text readability', 'jvb'),
+          value: overlayOpacity,
+          onChange: value => setAttributes({
+            overlayOpacity: value
+          }),
+          min: 0,
+          max: 100,
+          step: 5
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.SelectControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Content Alignment', 'jvb'),
+          value: contentAlignment,
+          options: [{
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Top Left', 'jvb'),
+            value: 'top-left'
+          }, {
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Top Center', 'jvb'),
+            value: 'top-center'
+          }, {
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Top Right', 'jvb'),
+            value: 'top-right'
+          }, {
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Center Left', 'jvb'),
+            value: 'center-left'
+          }, {
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Center', 'jvb'),
+            value: 'center'
+          }, {
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Center Right', 'jvb'),
+            value: 'center-right'
+          }, {
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Bottom Left', 'jvb'),
+            value: 'bottom-left'
+          }, {
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Bottom Center', 'jvb'),
+            value: 'bottom-center'
+          }, {
+            label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Bottom Right', 'jvb'),
+            value: 'bottom-right'
+          }],
+          onChange: value => setAttributes({
+            contentAlignment: value
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)(_wordpress_components__WEBPACK_IMPORTED_MODULE_2__.RangeControl, {
+          label: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Minimum Height', 'jvb'),
+          help: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Minimum height in pixels (leave 0 for auto)', 'jvb'),
+          value: minHeight,
+          onChange: value => setAttributes({
+            minHeight: value
+          }),
+          min: 0,
+          max: 1000,
+          step: 50
+        })]
+      })]
+    }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("div", {
+      ...blockProps,
+      children: posterUrl || videoSources.length > 0 ? /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)("div", {
+        className: "video-cover-preview",
+        children: [posterUrl && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.Fragment, {
+          children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("img", {
+            src: posterUrl,
+            alt: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Video poster', 'jvb')
+          }), overlayOpacity > 0 && /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("div", {
+            className: "video-overlay-preview",
+            style: {
+              opacity: overlayOpacity / 100
+            }
+          })]
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("div", {
+          className: `video-cover-content-preview align-${contentAlignment}`,
+          children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("div", {
+            ...innerBlocksProps
+          })
+        }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("div", {
+          className: "video-info",
+          children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsxs)("p", {
+            children: [videoSources.length, " ", (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('desktop source(s)', 'jvb')]
+          })
+        })]
+      }) : /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("div", {
+        className: "video-cover-placeholder",
+        children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_4__.jsx)("p", {
+          children: (0,_wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__.__)('Configure video sources in the sidebar →', 'jvb')
+        })
+      })
+    })]
+  });
+}
+
+/***/ },
+
+/***/ "./src/video/index.js"
+/*!****************************!*\
+  !*** ./src/video/index.js ***!
+  \****************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/blocks */ "@wordpress/blocks");
+/* harmony import */ var _wordpress_blocks__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__);
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @wordpress/block-editor */ "@wordpress/block-editor");
+/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__);
+/* harmony import */ var _style_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./style.scss */ "./src/video/style.scss");
+/* harmony import */ var _edit__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./edit */ "./src/video/edit.js");
+/* harmony import */ var _block_json__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./block.json */ "./src/video/block.json");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! react/jsx-runtime */ "react/jsx-runtime");
+/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__);
+/* index.js */
+
+
+
+
+
+
+(0,_wordpress_blocks__WEBPACK_IMPORTED_MODULE_0__.registerBlockType)(_block_json__WEBPACK_IMPORTED_MODULE_4__.name, {
+  edit: _edit__WEBPACK_IMPORTED_MODULE_3__["default"],
+  save: ({
+    attributes
+  }) => {
+    const blockProps = _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.useBlockProps.save({
+      className: 'video-cover-wrapper-placeholder'
+    });
+    return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)("div", {
+      ...blockProps,
+      children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_5__.jsx)(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_1__.InnerBlocks.Content, {})
+    });
+  }
+});
+
+/***/ },
+
+/***/ "./src/video/editor.scss"
+/*!*******************************!*\
+  !*** ./src/video/editor.scss ***!
+  \*******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "./src/video/style.scss"
+/*!******************************!*\
+  !*** ./src/video/style.scss ***!
+  \******************************/
+(__unused_webpack_module, __webpack_exports__, __webpack_require__) {
+
+__webpack_require__.r(__webpack_exports__);
+// extracted by mini-css-extract-plugin
+
+
+/***/ },
+
+/***/ "react/jsx-runtime"
+/*!**********************************!*\
+  !*** external "ReactJSXRuntime" ***!
+  \**********************************/
+(module) {
+
+module.exports = window["ReactJSXRuntime"];
+
+/***/ },
+
+/***/ "@wordpress/block-editor"
+/*!*************************************!*\
+  !*** external ["wp","blockEditor"] ***!
+  \*************************************/
+(module) {
+
+module.exports = window["wp"]["blockEditor"];
+
+/***/ },
+
+/***/ "@wordpress/blocks"
+/*!********************************!*\
+  !*** external ["wp","blocks"] ***!
+  \********************************/
+(module) {
+
+module.exports = window["wp"]["blocks"];
+
+/***/ },
+
+/***/ "@wordpress/components"
+/*!************************************!*\
+  !*** external ["wp","components"] ***!
+  \************************************/
+(module) {
+
+module.exports = window["wp"]["components"];
+
+/***/ },
+
+/***/ "@wordpress/i18n"
+/*!******************************!*\
+  !*** external ["wp","i18n"] ***!
+  \******************************/
+(module) {
+
+module.exports = window["wp"]["i18n"];
+
+/***/ },
+
+/***/ "./src/video/block.json"
+/*!******************************!*\
+  !*** ./src/video/block.json ***!
+  \******************************/
+(module) {
+
+module.exports = /*#__PURE__*/JSON.parse('{"$schema":"https://schemas.wp.org/trunk/block.json","apiVersion":3,"name":"jvb/video","version":"1.0.0","title":"Video Cover","category":"jvb","icon":"video-alt3","description":"Self-hosted video cover with poster and multiple format support","supports":{"html":false,"align":["wide","full"],"spacing":{"margin":true,"padding":true},"color":{"background":true,"text":true}},"attributes":{"title":{"type":"string","default":""},"description":{"type":"string","default":""},"posterId":{"type":"number","default":0},"posterUrl":{"type":"string","default":""},"videoSources":{"type":"array","default":[],"items":{"type":"object","properties":{"id":{"type":"number"},"url":{"type":"string"},"mime":{"type":"string"}}}},"fadeEffect":{"type":"boolean","default":false},"overlayOpacity":{"type":"number","default":0},"contentAlignment":{"type":"string","default":"center"},"minHeight":{"type":"number","default":0}},"textdomain":"jvb","editorScript":"file:./index.js","viewScript":"file:./view.js","editorStyle":"file:./index.css","style":"file:./style-index.css"}');
+
+/***/ }
+
+/******/ 	});
+/************************************************************************/
+/******/ 	// The module cache
+/******/ 	var __webpack_module_cache__ = {};
+/******/ 	
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+/******/ 		// Check if module is in cache
+/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
+/******/ 		if (cachedModule !== undefined) {
+/******/ 			return cachedModule.exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = __webpack_module_cache__[moduleId] = {
+/******/ 			// no module.id needed
+/******/ 			// no module.loaded needed
+/******/ 			exports: {}
+/******/ 		};
+/******/ 	
+/******/ 		// Execute the module function
+/******/ 		if (!(moduleId in __webpack_modules__)) {
+/******/ 			delete __webpack_module_cache__[moduleId];
+/******/ 			var e = new Error("Cannot find module '" + moduleId + "'");
+/******/ 			e.code = 'MODULE_NOT_FOUND';
+/******/ 			throw e;
+/******/ 		}
+/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
+/******/ 	
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/ 	
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = __webpack_modules__;
+/******/ 	
+/************************************************************************/
+/******/ 	/* webpack/runtime/chunk loaded */
+/******/ 	(() => {
+/******/ 		var deferred = [];
+/******/ 		__webpack_require__.O = (result, chunkIds, fn, priority) => {
+/******/ 			if(chunkIds) {
+/******/ 				priority = priority || 0;
+/******/ 				for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];
+/******/ 				deferred[i] = [chunkIds, fn, priority];
+/******/ 				return;
+/******/ 			}
+/******/ 			var notFulfilled = Infinity;
+/******/ 			for (var i = 0; i < deferred.length; i++) {
+/******/ 				var [chunkIds, fn, priority] = deferred[i];
+/******/ 				var fulfilled = true;
+/******/ 				for (var j = 0; j < chunkIds.length; j++) {
+/******/ 					if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {
+/******/ 						chunkIds.splice(j--, 1);
+/******/ 					} else {
+/******/ 						fulfilled = false;
+/******/ 						if(priority < notFulfilled) notFulfilled = priority;
+/******/ 					}
+/******/ 				}
+/******/ 				if(fulfilled) {
+/******/ 					deferred.splice(i--, 1)
+/******/ 					var r = fn();
+/******/ 					if (r !== undefined) result = r;
+/******/ 				}
+/******/ 			}
+/******/ 			return result;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/compat get default export */
+/******/ 	(() => {
+/******/ 		// getDefaultExport function for compatibility with non-harmony modules
+/******/ 		__webpack_require__.n = (module) => {
+/******/ 			var getter = module && module.__esModule ?
+/******/ 				() => (module['default']) :
+/******/ 				() => (module);
+/******/ 			__webpack_require__.d(getter, { a: getter });
+/******/ 			return getter;
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/define property getters */
+/******/ 	(() => {
+/******/ 		// define getter functions for harmony exports
+/******/ 		__webpack_require__.d = (exports, definition) => {
+/******/ 			for(var key in definition) {
+/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
+/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
+/******/ 				}
+/******/ 			}
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
+/******/ 	(() => {
+/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/make namespace object */
+/******/ 	(() => {
+/******/ 		// define __esModule on exports
+/******/ 		__webpack_require__.r = (exports) => {
+/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 			}
+/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 		};
+/******/ 	})();
+/******/ 	
+/******/ 	/* webpack/runtime/jsonp chunk loading */
+/******/ 	(() => {
+/******/ 		// no baseURI
+/******/ 		
+/******/ 		// object to store loaded and loading chunks
+/******/ 		// undefined = chunk not loaded, null = chunk preloaded/prefetched
+/******/ 		// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
+/******/ 		var installedChunks = {
+/******/ 			"video/index": 0,
+/******/ 			"video/style-index": 0
+/******/ 		};
+/******/ 		
+/******/ 		// no chunk on demand loading
+/******/ 		
+/******/ 		// no prefetching
+/******/ 		
+/******/ 		// no preloaded
+/******/ 		
+/******/ 		// no HMR
+/******/ 		
+/******/ 		// no HMR manifest
+/******/ 		
+/******/ 		__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);
+/******/ 		
+/******/ 		// install a JSONP callback for chunk loading
+/******/ 		var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
+/******/ 			var [chunkIds, moreModules, runtime] = data;
+/******/ 			// add "moreModules" to the modules object,
+/******/ 			// then flag all "chunkIds" as loaded and fire callback
+/******/ 			var moduleId, chunkId, i = 0;
+/******/ 			if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
+/******/ 				for(moduleId in moreModules) {
+/******/ 					if(__webpack_require__.o(moreModules, moduleId)) {
+/******/ 						__webpack_require__.m[moduleId] = moreModules[moduleId];
+/******/ 					}
+/******/ 				}
+/******/ 				if(runtime) var result = runtime(__webpack_require__);
+/******/ 			}
+/******/ 			if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
+/******/ 			for(;i < chunkIds.length; i++) {
+/******/ 				chunkId = chunkIds[i];
+/******/ 				if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
+/******/ 					installedChunks[chunkId][0]();
+/******/ 				}
+/******/ 				installedChunks[chunkId] = 0;
+/******/ 			}
+/******/ 			return __webpack_require__.O(result);
+/******/ 		}
+/******/ 		
+/******/ 		var chunkLoadingGlobal = globalThis["webpackChunkjvb"] = globalThis["webpackChunkjvb"] || [];
+/******/ 		chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
+/******/ 		chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
+/******/ 	})();
+/******/ 	
+/************************************************************************/
+/******/ 	
+/******/ 	// startup
+/******/ 	// Load entry module and return exports
+/******/ 	// This entry module depends on other loaded chunks and execution need to be delayed
+/******/ 	var __webpack_exports__ = __webpack_require__.O(undefined, ["video/style-index"], () => (__webpack_require__("./src/video/index.js")))
+/******/ 	__webpack_exports__ = __webpack_require__.O(__webpack_exports__);
+/******/ 	
+/******/ })()
+;
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/build/video/index.js.map b/build/video/index.js.map
new file mode 100644
index 0000000..14022b5
--- /dev/null
+++ b/build/video/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"video/index.js","mappings":"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","sources":["webpack://jvb/./src/video/edit.js","webpack://jvb/./src/video/index.js","webpack://jvb/./src/video/editor.scss?94da","webpack://jvb/./src/video/style.scss?c91d","webpack://jvb/external window \"ReactJSXRuntime\"","webpack://jvb/external window [\"wp\",\"blockEditor\"]","webpack://jvb/external window [\"wp\",\"blocks\"]","webpack://jvb/external window [\"wp\",\"components\"]","webpack://jvb/external window [\"wp\",\"i18n\"]","webpack://jvb/webpack/bootstrap","webpack://jvb/webpack/runtime/chunk loaded","webpack://jvb/webpack/runtime/compat get default export","webpack://jvb/webpack/runtime/define property getters","webpack://jvb/webpack/runtime/hasOwnProperty shorthand","webpack://jvb/webpack/runtime/make namespace object","webpack://jvb/webpack/runtime/jsonp chunk loading","webpack://jvb/webpack/before-startup","webpack://jvb/webpack/startup","webpack://jvb/webpack/after-startup"],"sourcesContent":["//edit.js\r\nimport { __ } from '@wordpress/i18n';\r\nimport {\r\n\tuseBlockProps,\r\n\tInspectorControls,\r\n\tMediaUpload,\r\n\tMediaUploadCheck,\r\n\tInnerBlocks,\r\n\tuseInnerBlocksProps\r\n} from '@wordpress/block-editor';\r\nimport {\r\n\tPanelBody,\r\n\tButton,\r\n\tToggleControl,\r\n\tBaseControl,\r\n\tRangeControl,\r\n\tSelectControl\r\n} from '@wordpress/components';\r\nimport './editor.scss';\r\n\r\nconst ALLOWED_VIDEO_TYPES = ['video'];\r\n\r\nconst INNER_BLOCKS_TEMPLATE = [\r\n\t['core/heading', {\r\n\t\tlevel: 1,\r\n\t\tplaceholder: 'Add heading...',\r\n\t\ttextAlign: 'center'\r\n\t}],\r\n\t['core/paragraph', {\r\n\t\tplaceholder: 'Add description...',\r\n\t\talign: 'center'\r\n\t}],\r\n\t['core/buttons', {\r\n\t\tlayout: { type: 'flex', justifyContent: 'center' }\r\n\t}]\r\n];\r\n\r\n\r\n\r\nexport default function Edit({ attributes, setAttributes }) {\r\n\tconst {\r\n\t\tposterId,\r\n\t\tposterUrl,\r\n\t\tvideoSources,\r\n\t\tfadeEffect,\r\n\t\toverlayOpacity,\r\n\t\tcontentAlignment,\r\n\t\tminHeight\r\n\t} = attributes;\r\n\r\n\tconst blockProps = useBlockProps({\r\n\t\tclassName: 'video-cover-editor',\r\n\t\tstyle: {\r\n\t\t\tminHeight: minHeight ? `${minHeight}px` : undefined\r\n\t\t}\r\n\t});\r\n\r\n\tconst innerBlocksProps = useInnerBlocksProps(\r\n\t\t{ className: 'video-cover-content' },\r\n\t\t{\r\n\t\t\ttemplate: INNER_BLOCKS_TEMPLATE,\r\n\t\t\ttemplateLock: false\r\n\t\t}\r\n\t);\r\n\r\n\tconst onSelectPoster = (media) => {\r\n\t\tsetAttributes({\r\n\t\t\tposterId: media.id,\r\n\t\t\tposterUrl: media.url\r\n\t\t});\r\n\t};\r\n\r\n\tconst onSelectVideos = (mediaItems) => {\r\n\t\t// multiple=true returns an array\r\n\t\tconst items = Array.isArray(mediaItems) ? mediaItems : [mediaItems];\r\n\t\tconst newSources = items\r\n\t\t\t.filter(media => !videoSources.some(s => s.id === media.id))\r\n\t\t\t.map(media => ({\r\n\t\t\t\tid: media.id,\r\n\t\t\t\turl: media.url,\r\n\t\t\t\tmime: media.mime\r\n\t\t\t}));\r\n\r\n\t\tif (newSources.length) {\r\n\t\t\tsetAttributes({\r\n\t\t\t\tvideoSources: [...videoSources, ...newSources]\r\n\t\t\t});\r\n\t\t}\r\n\t};\r\n\r\n\tconst removeVideoSource = (index) => {\r\n\t\tconst updated = [...videoSources];\r\n\t\tupdated.splice(index, 1);\r\n\t\tsetAttributes({ videoSources: updated });\r\n\t};\r\n\r\n\tconst renderVideoSourceList = (sources, isMobile = false) => {\r\n\t\tif (sources.length === 0) return null;\r\n\r\n\t\treturn (\r\n\t\t\t<ul className=\"video-source-list\">\r\n\t\t\t\t{sources.map((source, index) => (\r\n\t\t\t\t\t<li key={index} className=\"video-source-item\">\r\n\t\t\t\t\t\t<span className=\"video-source-mime\">{source.mime}</span>\r\n\t\t\t\t\t\t<Button\r\n\t\t\t\t\t\t\tisDestructive\r\n\t\t\t\t\t\t\tisSmall\r\n\t\t\t\t\t\t\tonClick={() => removeVideoSource(index, isMobile)}\r\n\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t{__('Remove', 'jvb')}\r\n\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t</li>\r\n\t\t\t\t))}\r\n\t\t\t</ul>\r\n\t\t);\r\n\t};\r\n\r\n\treturn (\r\n\t\t<>\r\n\t\t\t<InspectorControls>\r\n\t\t\t\t<PanelBody title={__('Video Settings', 'jvb')} initialOpen={true}>\r\n\t\t\t\t\t<BaseControl\r\n\t\t\t\t\t\tlabel={__('Poster Image', 'jvb')}\r\n\t\t\t\t\t\thelp={__('Image shown while video loads', 'jvb')}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t<MediaUploadCheck>\r\n\t\t\t\t\t\t\t<MediaUpload\r\n\t\t\t\t\t\t\t\tonSelect={onSelectPoster}\r\n\t\t\t\t\t\t\t\tallowedTypes={['image']}\r\n\t\t\t\t\t\t\t\tvalue={posterId}\r\n\t\t\t\t\t\t\t\trender={({ open }) => (\r\n\t\t\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t\t\t{posterUrl && (\r\n\t\t\t\t\t\t\t\t\t\t\t<img\r\n\t\t\t\t\t\t\t\t\t\t\t\tsrc={posterUrl}\r\n\t\t\t\t\t\t\t\t\t\t\t\talt={__('Poster preview', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{ maxWidth: '100%', marginBottom: '10px' }}\r\n\t\t\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t\t\t<Button\r\n\t\t\t\t\t\t\t\t\t\t\tonClick={open}\r\n\t\t\t\t\t\t\t\t\t\t\tvariant={posterUrl ? 'secondary' : 'primary'}\r\n\t\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t\t{posterUrl\r\n\t\t\t\t\t\t\t\t\t\t\t\t? __('Change Poster', 'jvb')\r\n\t\t\t\t\t\t\t\t\t\t\t\t: __('Select Poster', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t\t\t\t\t{posterUrl && (\r\n\t\t\t\t\t\t\t\t\t\t\t<Button\r\n\t\t\t\t\t\t\t\t\t\t\t\tisDestructive\r\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => setAttributes({ posterId: 0, posterUrl: '' })}\r\n\t\t\t\t\t\t\t\t\t\t\t\tstyle={{ marginLeft: '10px' }}\r\n\t\t\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t\t\t{__('Remove', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t</MediaUploadCheck>\r\n\t\t\t\t\t</BaseControl>\r\n\r\n\t\t\t\t\t<BaseControl\r\n\t\t\t\t\t\tlabel={__('Video Sources', 'jvb')}\r\n\t\t\t\t\t\thelp={__('Add multiple formats for better browser support (mp4, webm, etc.)', 'jvb')}\r\n\t\t\t\t\t>\r\n\t\t\t\t\t\t{videoSources.length > 0 && (\r\n\t\t\t\t\t\t\t<ul className=\"video-source-list\">\r\n\t\t\t\t\t\t\t\t{videoSources.map((source, index) => (\r\n\t\t\t\t\t\t\t\t\t<li key={index} className=\"video-source-item\">\r\n\t\t\t\t\t\t\t\t\t\t<span className=\"video-source-mime\">{source.mime}</span>\r\n\t\t\t\t\t\t\t\t\t\t<Button\r\n\t\t\t\t\t\t\t\t\t\t\tisDestructive\r\n\t\t\t\t\t\t\t\t\t\t\tisSmall\r\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => removeVideoSource(index)}\r\n\t\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t\t{__('Remove', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t\t\t\t</li>\r\n\t\t\t\t\t\t\t\t))}\r\n\t\t\t\t\t\t\t</ul>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t<MediaUploadCheck>\r\n\t\t\t\t\t\t\t<MediaUpload\r\n\t\t\t\t\t\t\t\tmultiple={true}\r\n\t\t\t\t\t\t\t\tonSelect={onSelectVideos}\r\n\t\t\t\t\t\t\t\tallowedTypes={ALLOWED_VIDEO_TYPES}\r\n\t\t\t\t\t\t\t\trender={({ open }) => (\r\n\t\t\t\t\t\t\t\t\t<Button onClick={open} variant=\"secondary\">\r\n\t\t\t\t\t\t\t\t\t\t{__('Add Video', 'jvb')}\r\n\t\t\t\t\t\t\t\t\t</Button>\r\n\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t</MediaUploadCheck>\r\n\t\t\t\t\t</BaseControl>\r\n\r\n\t\t\t\t\t<ToggleControl\r\n\t\t\t\t\t\tlabel={__('Fade Effect', 'jvb')}\r\n\t\t\t\t\t\thelp={__('Add fade class to video element', 'jvb')}\r\n\t\t\t\t\t\tchecked={fadeEffect}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ fadeEffect: value })}\r\n\t\t\t\t\t/>\r\n\t\t\t\t</PanelBody>\r\n\r\n\t\t\t\t<PanelBody title={__('Overlay Settings', 'jvb')} initialOpen={true}>\r\n\t\t\t\t\t<RangeControl\r\n\t\t\t\t\t\tlabel={__('Overlay Opacity', 'jvb')}\r\n\t\t\t\t\t\thelp={__('Darken video for better text readability', 'jvb')}\r\n\t\t\t\t\t\tvalue={overlayOpacity}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ overlayOpacity: value })}\r\n\t\t\t\t\t\tmin={0}\r\n\t\t\t\t\t\tmax={100}\r\n\t\t\t\t\t\tstep={5}\r\n\t\t\t\t\t/>\r\n\r\n\t\t\t\t\t<SelectControl\r\n\t\t\t\t\t\tlabel={__('Content Alignment', 'jvb')}\r\n\t\t\t\t\t\tvalue={contentAlignment}\r\n\t\t\t\t\t\toptions={[\r\n\t\t\t\t\t\t\t{ label: __('Top Left', 'jvb'), value: 'top-left' },\r\n\t\t\t\t\t\t\t{ label: __('Top Center', 'jvb'), value: 'top-center' },\r\n\t\t\t\t\t\t\t{ label: __('Top Right', 'jvb'), value: 'top-right' },\r\n\t\t\t\t\t\t\t{ label: __('Center Left', 'jvb'), value: 'center-left' },\r\n\t\t\t\t\t\t\t{ label: __('Center', 'jvb'), value: 'center' },\r\n\t\t\t\t\t\t\t{ label: __('Center Right', 'jvb'), value: 'center-right' },\r\n\t\t\t\t\t\t\t{ label: __('Bottom Left', 'jvb'), value: 'bottom-left' },\r\n\t\t\t\t\t\t\t{ label: __('Bottom Center', 'jvb'), value: 'bottom-center' },\r\n\t\t\t\t\t\t\t{ label: __('Bottom Right', 'jvb'), value: 'bottom-right' }\r\n\t\t\t\t\t\t]}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ contentAlignment: value })}\r\n\t\t\t\t\t/>\r\n\r\n\t\t\t\t\t<RangeControl\r\n\t\t\t\t\t\tlabel={__('Minimum Height', 'jvb')}\r\n\t\t\t\t\t\thelp={__('Minimum height in pixels (leave 0 for auto)', 'jvb')}\r\n\t\t\t\t\t\tvalue={minHeight}\r\n\t\t\t\t\t\tonChange={(value) => setAttributes({ minHeight: value })}\r\n\t\t\t\t\t\tmin={0}\r\n\t\t\t\t\t\tmax={1000}\r\n\t\t\t\t\t\tstep={50}\r\n\t\t\t\t\t/>\r\n\t\t\t\t</PanelBody>\r\n\t\t\t</InspectorControls>\r\n\r\n\t\t\t<div {...blockProps}>\r\n\t\t\t\t{posterUrl || videoSources.length > 0 ? (\r\n\t\t\t\t\t<div className=\"video-cover-preview\">\r\n\t\t\t\t\t\t{posterUrl && (\r\n\t\t\t\t\t\t\t<>\r\n\t\t\t\t\t\t\t\t<img src={posterUrl} alt={__('Video poster', 'jvb')} />\r\n\t\t\t\t\t\t\t\t{overlayOpacity > 0 && (\r\n\t\t\t\t\t\t\t\t\t<div\r\n\t\t\t\t\t\t\t\t\t\tclassName=\"video-overlay-preview\"\r\n\t\t\t\t\t\t\t\t\t\tstyle={{ opacity: overlayOpacity / 100 }}\r\n\t\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t\t</>\r\n\t\t\t\t\t\t)}\r\n\t\t\t\t\t\t<div className={`video-cover-content-preview align-${contentAlignment}`}>\r\n\t\t\t\t\t\t\t<div {...innerBlocksProps} />\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t\t<div className=\"video-info\">\r\n\t\t\t\t\t\t\t<p>\r\n\t\t\t\t\t\t\t\t{videoSources.length} {__('desktop source(s)', 'jvb')}\r\n\t\t\t\t\t\t\t</p>\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t) : (\r\n\t\t\t\t\t<div className=\"video-cover-placeholder\">\r\n\t\t\t\t\t\t<p>{__('Configure video sources in the sidebar →', 'jvb')}</p>\r\n\t\t\t\t\t</div>\r\n\t\t\t\t)}\r\n\t\t\t</div>\r\n\t\t</>\r\n\t);\r\n}\r\n","/* index.js */\r\nimport { registerBlockType } from '@wordpress/blocks';\r\nimport { useBlockProps, InnerBlocks } from '@wordpress/block-editor';\r\nimport './style.scss';\r\nimport Edit from './edit';\r\nimport metadata from './block.json';\r\n\r\nregisterBlockType(metadata.name, {\r\n\tedit: Edit,\r\n\tsave: ({ attributes }) => {\r\n\t\tconst blockProps = useBlockProps.save({\r\n\t\t\tclassName: 'video-cover-wrapper-placeholder'\r\n\t\t});\r\n\r\n\t\treturn (\r\n\t\t\t<div {...blockProps}>\r\n\t\t\t\t<InnerBlocks.Content />\r\n\t\t\t</div>\r\n\t\t);\r\n\t}\r\n});\r\n","// extracted by mini-css-extract-plugin\nexport {};","// extracted by mini-css-extract-plugin\nexport {};","module.exports = window[\"ReactJSXRuntime\"];","module.exports = window[\"wp\"][\"blockEditor\"];","module.exports = window[\"wp\"][\"blocks\"];","module.exports = window[\"wp\"][\"components\"];","module.exports = window[\"wp\"][\"i18n\"];","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tif (!(moduleId in __webpack_modules__)) {\n\t\tdelete __webpack_module_cache__[moduleId];\n\t\tvar e = new Error(\"Cannot find module '\" + moduleId + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar [chunkIds, fn, priority] = deferred[i];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t\"video/index\": 0,\n\t\"video/style-index\": 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar [chunkIds, moreModules, runtime] = data;\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = globalThis[\"webpackChunkjvb\"] = globalThis[\"webpackChunkjvb\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [\"video/style-index\"], () => (__webpack_require__(\"./src/video/index.js\")))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n",""],"names":["__","useBlockProps","InspectorControls","MediaUpload","MediaUploadCheck","InnerBlocks","useInnerBlocksProps","PanelBody","Button","ToggleControl","BaseControl","RangeControl","SelectControl","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","ALLOWED_VIDEO_TYPES","INNER_BLOCKS_TEMPLATE","level","placeholder","textAlign","align","layout","type","justifyContent","Edit","attributes","setAttributes","posterId","posterUrl","videoSources","fadeEffect","overlayOpacity","contentAlignment","minHeight","blockProps","className","style","undefined","innerBlocksProps","template","templateLock","onSelectPoster","media","id","url","onSelectVideos","mediaItems","items","Array","isArray","newSources","filter","some","s","map","mime","length","removeVideoSource","index","updated","splice","renderVideoSourceList","sources","isMobile","children","source","isDestructive","isSmall","onClick","title","initialOpen","label","help","onSelect","allowedTypes","value","render","open","src","alt","maxWidth","marginBottom","variant","marginLeft","multiple","checked","onChange","min","max","step","options","opacity","registerBlockType","metadata","name","edit","save","Content"],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/video/style-index-rtl.css b/build/video/style-index-rtl.css
index 7c14dd7..2d0ec34 100644
--- a/build/video/style-index-rtl.css
+++ b/build/video/style-index-rtl.css
@@ -1 +1,168 @@
-.video-cover{display:flex;min-height:75vh;overflow:hidden;position:relative;width:100%}.video-cover .wrap{background-color:rgb(var(--contrast-200))}.video-cover .video-container{background-color:rgb(var(--action-50));bottom:0;display:flex;right:0;min-height:100%;min-width:100%;position:absolute;left:0;top:0;z-index:0}.video-cover .video-container.fade{animation:fadeIn 1s ease-in}.video-cover .video-container video{filter:grayscale(100%) contrast(1);flex:1 0 100%;mix-blend-mode:multiply;-o-object-fit:cover;object-fit:cover;opacity:.85;pointer-events:none}.video-cover .inner-wrap{color:var(--action-contrast);padding:2rem;position:relative;width:100%;z-index:2}.video-cover .inner-wrap h1,.video-cover .inner-wrap h2,.video-cover .inner-wrap h3,.video-cover .inner-wrap h4,.video-cover .inner-wrap h5,.video-cover .inner-wrap h6{color:var(--action-contrast);margin:2rem 0 0;text-shadow:0 2px 4px rgba(0,0,0,.5);word-spacing:100vw}.video-cover .inner-wrap p{color:var(--action-contrast);letter-spacing:2px;margin:0;text-shadow:0 1px 2px rgba(0,0,0,.5);text-transform:uppercase}.video-cover .inner-wrap .media-text figure{max-width:50%}@media(min-width:768px){.video-cover .inner-wrap .media-text{--align:flex-start;gap:3rem;max-width:var(--content)}}.video-cover .inner-wrap .media-text>div{width:-moz-fit-content;width:fit-content}.video-cover .inner-wrap .buttons a{border-color:var(--action-contrast);color:var(--action-contrast);font-weight:var(--fw-h-bold)}.video-cover .inner-wrap .buttons a:visited,.video-cover .inner-wrap .buttons a:visited:hover{color:var(--action-contrast)}.video-cover .inner-wrap .buttons a:hover{background-color:rgb(var(--action-0));color:var(--action-contrast)}.video-cover .inner-wrap .outline a{background-color:rgba(var(--base),rgba(var(--base),var(--op-3)))}.video-cover .inner-wrap .buttons{margin:3rem 0}.video-cover .inner-wrap .buttons li{background-color:rgba(var(--action-0),var(--op-4))}.video-cover .inner-wrap .wp-block-button__link{text-shadow:none}.video-cover.align-top-left{align-items:flex-start;justify-content:flex-start}.video-cover.align-top-center{align-items:flex-start;justify-content:center}.video-cover.align-top-right{align-items:flex-start;justify-content:flex-end}.video-cover.align-center-left{align-items:center;justify-content:flex-start}.video-cover.align-center{align-items:center;justify-content:center}.video-cover.align-center-right{align-items:center;justify-content:flex-end}.video-cover.align-bottom-left{align-items:flex-end;justify-content:flex-start}.video-cover.align-bottom-center{align-items:flex-end;justify-content:center}.video-cover.align-bottom-right{align-items:flex-end;justify-content:flex-end}.video-cover.alignfull{margin-right:calc(50% - 50vw);margin-left:calc(50% - 50vw);max-width:none;width:100vw}.video-cover.alignwide{max-width:1200px}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}
+/*!*********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/video/style.scss ***!
+  \*********************************************************************************************************************************************************************************************************************************************/
+/** style.scss **/
+.video-cover {
+  position: relative;
+  width: 100%;
+  min-height: 75vh;
+  overflow: hidden;
+  display: flex;
+}
+.video-cover .wrap {
+  background-color: rgb(var(--contrast-200));
+}
+.video-cover {
+  /* Video background */
+}
+.video-cover .video-container {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  right: 0;
+  left: 0;
+  min-width: 100%;
+  min-height: 100%;
+  z-index: 0;
+  display: flex;
+  background-color: rgb(var(--action-50));
+}
+.video-cover .video-container.fade {
+  animation: fadeIn 1s ease-in;
+}
+.video-cover .video-container video {
+  pointer-events: none;
+  opacity: 0.85;
+  mix-blend-mode: multiply;
+  filter: grayscale(100%) contrast(1);
+  flex: 1 0 100%;
+  -o-object-fit: cover;
+     object-fit: cover;
+}
+.video-cover .inner-wrap {
+  position: relative;
+  z-index: 2;
+  width: 100%;
+  padding: 2rem;
+  color: var(--action-contrast);
+  /* Better text readability */
+}
+.video-cover .inner-wrap h1, .video-cover .inner-wrap h2, .video-cover .inner-wrap h3, .video-cover .inner-wrap h4, .video-cover .inner-wrap h5, .video-cover .inner-wrap h6 {
+  word-spacing: 100vw;
+  color: var(--action-contrast);
+  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
+  margin: 2rem 0 0;
+}
+.video-cover .inner-wrap p {
+  text-transform: uppercase;
+  letter-spacing: 2px;
+  margin: 0;
+  color: var(--action-contrast);
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
+}
+.video-cover .inner-wrap .media-text figure {
+  max-width: 50%;
+}
+@media (min-width: 768px) {
+  .video-cover .inner-wrap .media-text {
+    --align: flex-start;
+    gap: 3rem;
+    max-width: var(--content);
+  }
+}
+.video-cover .inner-wrap .media-text > div {
+  width: -moz-fit-content;
+  width: fit-content;
+}
+.video-cover .inner-wrap .buttons a {
+  font-weight: var(--fw-h-bold);
+  color: var(--action-contrast);
+  border-color: var(--action-contrast);
+}
+.video-cover .inner-wrap .buttons a:visited {
+  color: var(--action-contrast);
+}
+.video-cover .inner-wrap .buttons a:visited:hover {
+  color: var(--action-contrast);
+}
+.video-cover .inner-wrap .buttons a:hover {
+  background-color: rgb(var(--action-0));
+  color: var(--action-contrast);
+}
+.video-cover .inner-wrap .outline a {
+  background-color: rgba(var(--base), rgba(var(--base), var(--op-3)));
+}
+.video-cover .inner-wrap .buttons {
+  margin: 3rem 0;
+}
+.video-cover .inner-wrap .buttons li {
+  background-color: rgba(var(--action-0), var(--op-4));
+}
+.video-cover .inner-wrap {
+  /* Button styles */
+}
+.video-cover .inner-wrap .wp-block-button__link {
+  text-shadow: none;
+}
+.video-cover {
+  /* Alignment classes */
+}
+.video-cover.align-top-left {
+  align-items: flex-start;
+  justify-content: flex-start;
+}
+.video-cover.align-top-center {
+  align-items: flex-start;
+  justify-content: center;
+}
+.video-cover.align-top-right {
+  align-items: flex-start;
+  justify-content: flex-end;
+}
+.video-cover.align-center-left {
+  align-items: center;
+  justify-content: flex-start;
+}
+.video-cover.align-center {
+  align-items: center;
+  justify-content: center;
+}
+.video-cover.align-center-right {
+  align-items: center;
+  justify-content: flex-end;
+}
+.video-cover.align-bottom-left {
+  align-items: flex-end;
+  justify-content: flex-start;
+}
+.video-cover.align-bottom-center {
+  align-items: flex-end;
+  justify-content: center;
+}
+.video-cover.align-bottom-right {
+  align-items: flex-end;
+  justify-content: flex-end;
+}
+.video-cover {
+  /* Full-width alignment  */
+}
+.video-cover.alignfull {
+  width: 100vw;
+  max-width: none;
+  margin-right: calc(50% - 50vw);
+  margin-left: calc(50% - 50vw);
+}
+.video-cover {
+  /* Wide alignment */
+}
+.video-cover.alignwide {
+  max-width: 1200px;
+}
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
diff --git a/build/video/style-index.css b/build/video/style-index.css
index 78851c5..69173b8 100644
--- a/build/video/style-index.css
+++ b/build/video/style-index.css
@@ -1 +1,170 @@
-.video-cover{display:flex;min-height:75vh;overflow:hidden;position:relative;width:100%}.video-cover .wrap{background-color:rgb(var(--contrast-200))}.video-cover .video-container{background-color:rgb(var(--action-50));bottom:0;display:flex;left:0;min-height:100%;min-width:100%;position:absolute;right:0;top:0;z-index:0}.video-cover .video-container.fade{animation:fadeIn 1s ease-in}.video-cover .video-container video{filter:grayscale(100%) contrast(1);flex:1 0 100%;mix-blend-mode:multiply;-o-object-fit:cover;object-fit:cover;opacity:.85;pointer-events:none}.video-cover .inner-wrap{color:var(--action-contrast);padding:2rem;position:relative;width:100%;z-index:2}.video-cover .inner-wrap h1,.video-cover .inner-wrap h2,.video-cover .inner-wrap h3,.video-cover .inner-wrap h4,.video-cover .inner-wrap h5,.video-cover .inner-wrap h6{color:var(--action-contrast);margin:2rem 0 0;text-shadow:0 2px 4px rgba(0,0,0,.5);word-spacing:100vw}.video-cover .inner-wrap p{color:var(--action-contrast);letter-spacing:2px;margin:0;text-shadow:0 1px 2px rgba(0,0,0,.5);text-transform:uppercase}.video-cover .inner-wrap .media-text figure{max-width:50%}@media(min-width:768px){.video-cover .inner-wrap .media-text{--align:flex-start;gap:3rem;max-width:var(--content)}}.video-cover .inner-wrap .media-text>div{width:-moz-fit-content;width:fit-content}.video-cover .inner-wrap .buttons a{border-color:var(--action-contrast);color:var(--action-contrast);font-weight:var(--fw-h-bold)}.video-cover .inner-wrap .buttons a:visited,.video-cover .inner-wrap .buttons a:visited:hover{color:var(--action-contrast)}.video-cover .inner-wrap .buttons a:hover{background-color:rgb(var(--action-0));color:var(--action-contrast)}.video-cover .inner-wrap .outline a{background-color:rgba(var(--base),rgba(var(--base),var(--op-3)))}.video-cover .inner-wrap .buttons{margin:3rem 0}.video-cover .inner-wrap .buttons li{background-color:rgba(var(--action-0),var(--op-4))}.video-cover .inner-wrap .wp-block-button__link{text-shadow:none}.video-cover.align-top-left{align-items:flex-start;justify-content:flex-start}.video-cover.align-top-center{align-items:flex-start;justify-content:center}.video-cover.align-top-right{align-items:flex-start;justify-content:flex-end}.video-cover.align-center-left{align-items:center;justify-content:flex-start}.video-cover.align-center{align-items:center;justify-content:center}.video-cover.align-center-right{align-items:center;justify-content:flex-end}.video-cover.align-bottom-left{align-items:flex-end;justify-content:flex-start}.video-cover.align-bottom-center{align-items:flex-end;justify-content:center}.video-cover.align-bottom-right{align-items:flex-end;justify-content:flex-end}.video-cover.alignfull{margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);max-width:none;width:100vw}.video-cover.alignwide{max-width:1200px}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}
+/*!*********************************************************************************************************************************************************************************************************************************************!*\
+  !*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[4].use[1]!./node_modules/postcss-loader/dist/cjs.js??ruleSet[1].rules[4].use[2]!./node_modules/sass-loader/dist/cjs.js??ruleSet[1].rules[4].use[3]!./src/video/style.scss ***!
+  \*********************************************************************************************************************************************************************************************************************************************/
+/** style.scss **/
+.video-cover {
+  position: relative;
+  width: 100%;
+  min-height: 75vh;
+  overflow: hidden;
+  display: flex;
+}
+.video-cover .wrap {
+  background-color: rgb(var(--contrast-200));
+}
+.video-cover {
+  /* Video background */
+}
+.video-cover .video-container {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  min-width: 100%;
+  min-height: 100%;
+  z-index: 0;
+  display: flex;
+  background-color: rgb(var(--action-50));
+}
+.video-cover .video-container.fade {
+  animation: fadeIn 1s ease-in;
+}
+.video-cover .video-container video {
+  pointer-events: none;
+  opacity: 0.85;
+  mix-blend-mode: multiply;
+  filter: grayscale(100%) contrast(1);
+  flex: 1 0 100%;
+  -o-object-fit: cover;
+     object-fit: cover;
+}
+.video-cover .inner-wrap {
+  position: relative;
+  z-index: 2;
+  width: 100%;
+  padding: 2rem;
+  color: var(--action-contrast);
+  /* Better text readability */
+}
+.video-cover .inner-wrap h1, .video-cover .inner-wrap h2, .video-cover .inner-wrap h3, .video-cover .inner-wrap h4, .video-cover .inner-wrap h5, .video-cover .inner-wrap h6 {
+  word-spacing: 100vw;
+  color: var(--action-contrast);
+  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
+  margin: 2rem 0 0;
+}
+.video-cover .inner-wrap p {
+  text-transform: uppercase;
+  letter-spacing: 2px;
+  margin: 0;
+  color: var(--action-contrast);
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
+}
+.video-cover .inner-wrap .media-text figure {
+  max-width: 50%;
+}
+@media (min-width: 768px) {
+  .video-cover .inner-wrap .media-text {
+    --align: flex-start;
+    gap: 3rem;
+    max-width: var(--content);
+  }
+}
+.video-cover .inner-wrap .media-text > div {
+  width: -moz-fit-content;
+  width: fit-content;
+}
+.video-cover .inner-wrap .buttons a {
+  font-weight: var(--fw-h-bold);
+  color: var(--action-contrast);
+  border-color: var(--action-contrast);
+}
+.video-cover .inner-wrap .buttons a:visited {
+  color: var(--action-contrast);
+}
+.video-cover .inner-wrap .buttons a:visited:hover {
+  color: var(--action-contrast);
+}
+.video-cover .inner-wrap .buttons a:hover {
+  background-color: rgb(var(--action-0));
+  color: var(--action-contrast);
+}
+.video-cover .inner-wrap .outline a {
+  background-color: rgba(var(--base), rgba(var(--base), var(--op-3)));
+}
+.video-cover .inner-wrap .buttons {
+  margin: 3rem 0;
+}
+.video-cover .inner-wrap .buttons li {
+  background-color: rgba(var(--action-0), var(--op-4));
+}
+.video-cover .inner-wrap {
+  /* Button styles */
+}
+.video-cover .inner-wrap .wp-block-button__link {
+  text-shadow: none;
+}
+.video-cover {
+  /* Alignment classes */
+}
+.video-cover.align-top-left {
+  align-items: flex-start;
+  justify-content: flex-start;
+}
+.video-cover.align-top-center {
+  align-items: flex-start;
+  justify-content: center;
+}
+.video-cover.align-top-right {
+  align-items: flex-start;
+  justify-content: flex-end;
+}
+.video-cover.align-center-left {
+  align-items: center;
+  justify-content: flex-start;
+}
+.video-cover.align-center {
+  align-items: center;
+  justify-content: center;
+}
+.video-cover.align-center-right {
+  align-items: center;
+  justify-content: flex-end;
+}
+.video-cover.align-bottom-left {
+  align-items: flex-end;
+  justify-content: flex-start;
+}
+.video-cover.align-bottom-center {
+  align-items: flex-end;
+  justify-content: center;
+}
+.video-cover.align-bottom-right {
+  align-items: flex-end;
+  justify-content: flex-end;
+}
+.video-cover {
+  /* Full-width alignment  */
+}
+.video-cover.alignfull {
+  width: 100vw;
+  max-width: none;
+  margin-left: calc(50% - 50vw);
+  margin-right: calc(50% - 50vw);
+}
+.video-cover {
+  /* Wide alignment */
+}
+.video-cover.alignwide {
+  max-width: 1200px;
+}
+@keyframes fadeIn {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+
+/*# sourceMappingURL=style-index.css.map*/
\ No newline at end of file
diff --git a/build/video/style-index.css.map b/build/video/style-index.css.map
new file mode 100644
index 0000000..2d6a4f2
--- /dev/null
+++ b/build/video/style-index.css.map
@@ -0,0 +1 @@
+{"version":3,"file":"video/style-index.css","mappings":";;;AAAA;AACA;EACC;EACA;EACA;EACA;EACA;AACD;AAAC;EACC;AAEF;AATA;EAoBC;AARD;AASC;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;AAPF;AASE;EACC;AAPH;AAUE;EACC;EACA;EACA;EACA;EACA;EACA;KAAA;AARH;AAYC;EACC;EACA;EACA;EACA;EACA;EAEA;AAXF;AAYE;EACC;EACA;EACA;EACA;AAVH;AAaE;EACC;EACA;EACA;EACA;EACA;AAXH;AAgBG;EACC;AAdJ;AAgBG;EACC;IACC;IACA;IACA;EAdH;AACF;AAgBG;EACC;EAAA;AAdJ;AAgBE;EACC;EACA;EACA;AAdH;AAeG;EACC;AAbJ;AAcI;EACC;AAZL;AAeG;EACC;EACA;AAbJ;AAiBE;EACC;AAfH;AAiBE;EACC;AAfH;AAgBG;EACC;AAdJ;AA9CC;EA+DC;AAdF;AAeE;EACC;AAbH;AAnGA;EAoHC;AAdD;AAeC;EACC;EACA;AAbF;AAeC;EACC;EACA;AAbF;AAeC;EACC;EACA;AAbF;AAeC;EACC;EACA;AAbF;AAeC;EACC;EACA;AAbF;AAeC;EACC;EACA;AAbF;AAeC;EACC;EACA;AAbF;AAeC;EACC;EACA;AAbF;AAeC;EACC;EACA;AAbF;AA1IA;EA0JC;AAbD;AAcC;EACC;EACA;EACA;EACA;AAZF;AAnJA;EAkKC;AAZD;AAaC;EACC;AAXF;AAeA;EACC;IACC;EAZA;EAcD;IACC;EAZA;AACF,C","sources":["webpack://jvb/./src/video/style.scss"],"sourcesContent":["/** style.scss **/\r\n.video-cover {\r\n\tposition: relative;\r\n\twidth: 100%;\r\n\tmin-height: 75vh;\r\n\toverflow: hidden;\r\n\tdisplay: flex;\r\n\t.wrap {\r\n\t\tbackground-color: rgb(var(--contrast-200));\r\n\t\t//&::before {\r\n\t\t//\tposition: absolute;\r\n\t\t//\ttop: 0;\r\n\t\t//\tbottom: 0;\r\n\t\t//\tleft: 0;\r\n\t\t//\tright: 0;\r\n\t\t//\tbackground-color: rgb(var(--base));\r\n\t\t//\tmix-blend-mode: lighten;\r\n\t\t//\tcontent: '';\r\n\t\t//\tz-index: 1;\r\n\t\t//}\r\n\t}\r\n\t/* Video background */\r\n\t.video-container {\r\n\t\tposition: absolute;\r\n\t\ttop: 0;\r\n\t\tbottom: 0;\r\n\t\tleft: 0;\r\n\t\tright: 0;\r\n\t\tmin-width: 100%;\r\n\t\tmin-height: 100%;\r\n\t\tz-index: 0;\r\n\t\tdisplay: flex;\r\n\t\tbackground-color: rgb(var(--action-50));\r\n\r\n\t\t&.fade {\r\n\t\t\tanimation: fadeIn 1s ease-in;\r\n\t\t}\r\n\r\n\t\tvideo {\r\n\t\t\tpointer-events: none;\r\n\t\t\topacity: .85;\r\n\t\t\tmix-blend-mode: multiply;\r\n\t\t\tfilter: grayscale(100%) contrast(1);\r\n\t\t\tflex: 1 0 100%;\r\n\t\t\tobject-fit: cover;\r\n\t\t}\r\n\t}\r\n\r\n\t.inner-wrap {\r\n\t\tposition: relative;\r\n\t\tz-index: 2;\r\n\t\twidth: 100%;\r\n\t\tpadding: 2rem;\r\n\t\tcolor: var(--action-contrast);\r\n\r\n\t\t/* Better text readability */\r\n\t\th1, h2, h3, h4, h5, h6 {\r\n\t\t\tword-spacing: 100vw;\r\n\t\t\tcolor: var(--action-contrast);\r\n\t\t\ttext-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);\r\n\t\t\tmargin: 2rem 0 0;\r\n\t\t}\r\n\r\n\t\tp {\r\n\t\t\ttext-transform: uppercase;\r\n\t\t\tletter-spacing: 2px;\r\n\t\t\tmargin: 0;\r\n\t\t\tcolor: var(--action-contrast);\r\n\t\t\ttext-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);\r\n\t\t}\r\n\r\n\t\t.media-text {\r\n\t\t}\r\n\t\t\t.media-text figure {\r\n\t\t\t\tmax-width: 50%;\r\n\t\t\t}\r\n\t\t\t@media (min-width: 768px) {\r\n\t\t\t\t.media-text {\r\n\t\t\t\t\t--align: flex-start;\r\n\t\t\t\t\tgap: 3rem;\r\n\t\t\t\t\tmax-width: var(--content);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t.media-text > div {\r\n\t\t\t\twidth: fit-content;\r\n\t\t\t}\r\n\t\t.buttons a {\r\n\t\t\tfont-weight: var(--fw-h-bold);\r\n\t\t\tcolor: var(--action-contrast);\r\n\t\t\tborder-color: var(--action-contrast);\r\n\t\t\t&:visited {\r\n\t\t\t\tcolor: var(--action-contrast);\r\n\t\t\t\t&:hover {\r\n\t\t\t\t\tcolor: var(--action-contrast);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t&:hover {\r\n\t\t\t\tbackground-color: rgb(var(--action-0));\r\n\t\t\t\tcolor: var(--action-contrast);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t.outline a {\r\n\t\t\tbackground-color: rgba(var(--base), rgba(var(--base),var(--op-3)));\r\n\t\t}\r\n\t\t.buttons {\r\n\t\t\tmargin: 3rem 0;\r\n\t\t\tli {\r\n\t\t\t\tbackground-color: rgba(var(--action-0), var(--op-4));\r\n\t\t\t}\r\n\t\t}\r\n\t\t/* Button styles */\r\n\t\t.wp-block-button__link {\r\n\t\t\ttext-shadow: none;\r\n\t\t}\r\n\t}\r\n\r\n\t/* Alignment classes */\r\n\t&.align-top-left {\r\n\t\talign-items: flex-start;\r\n\t\tjustify-content: flex-start;\r\n\t}\r\n\t&.align-top-center {\r\n\t\talign-items: flex-start;\r\n\t\tjustify-content: center;\r\n\t}\r\n\t&.align-top-right {\r\n\t\talign-items: flex-start;\r\n\t\tjustify-content: flex-end;\r\n\t}\r\n\t&.align-center-left {\r\n\t\talign-items: center;\r\n\t\tjustify-content: flex-start;\r\n\t}\r\n\t&.align-center {\r\n\t\talign-items: center;\r\n\t\tjustify-content: center;\r\n\t}\r\n\t&.align-center-right {\r\n\t\talign-items: center;\r\n\t\tjustify-content: flex-end;\r\n\t}\r\n\t&.align-bottom-left {\r\n\t\talign-items: flex-end;\r\n\t\tjustify-content: flex-start;\r\n\t}\r\n\t&.align-bottom-center {\r\n\t\talign-items: flex-end;\r\n\t\tjustify-content: center;\r\n\t}\r\n\t&.align-bottom-right {\r\n\t\talign-items: flex-end;\r\n\t\tjustify-content: flex-end;\r\n\t}\r\n\r\n\t/* Full-width alignment  */\r\n\t&.alignfull {\r\n\t\twidth: 100vw;\r\n\t\tmax-width: none;\r\n\t\tmargin-left: calc(50% - 50vw);\r\n\t\tmargin-right: calc(50% - 50vw);\r\n\t}\r\n\r\n\t/* Wide alignment */\r\n\t&.alignwide {\r\n\t\tmax-width: 1200px;\r\n\t}\r\n}\r\n\r\n@keyframes fadeIn {\r\n\tfrom {\r\n\t\topacity: 0;\r\n\t}\r\n\tto {\r\n\t\topacity: 1;\r\n\t}\r\n}\r\n\r\n"],"names":[],"sourceRoot":""}
\ No newline at end of file
diff --git a/build/video/view.asset.php b/build/video/view.asset.php
index 5be2bc5..5050427 100644
--- a/build/video/view.asset.php
+++ b/build/video/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => 'e7b9a67683fd33c56748');
+<?php return array('dependencies' => array(), 'version' => 'ef402281b8b0f16a5412');
diff --git a/build/video/view.js b/build/video/view.js
index e72c7ef..76c32ab 100644
--- a/build/video/view.js
+++ b/build/video/view.js
@@ -1 +1,48 @@
-document.addEventListener("DOMContentLoaded",function(){const e=[].slice.call(document.querySelectorAll(".video-container video"));function r(e){e.querySelectorAll("source[data-src]").forEach(e=>{e.src=e.dataset.src}),e.load()}if("IntersectionObserver"in window){const t=new IntersectionObserver(function(e,t){e.forEach(e=>{e.isIntersecting&&(r(e.target),t.unobserve(e.target))})},{rootMargin:"200px 0px",threshold:.1});return void e.forEach(e=>t.observe(e))}"requestIdleCallback"in window?requestIdleCallback(()=>{e.forEach(e=>r(e))}):e.forEach(e=>r(e))});
\ No newline at end of file
+/******/ (() => { // webpackBootstrap
+/*!***************************!*\
+  !*** ./src/video/view.js ***!
+  \***************************/
+/** view.js **/
+document.addEventListener("DOMContentLoaded", function () {
+  const lazyVideos = [].slice.call(document.querySelectorAll(".video-container video"));
+
+  // Build a helper to actually set sources + load
+  function loadVideo(video) {
+    const sources = video.querySelectorAll("source[data-src]");
+    sources.forEach(source => {
+      source.src = source.dataset.src;
+    });
+    video.load();
+  }
+
+  // --- 1. IntersectionObserver (best case) ---
+  if ("IntersectionObserver" in window) {
+    const lazyVideoObserver = new IntersectionObserver(function (entries, observer) {
+      entries.forEach(entry => {
+        if (entry.isIntersecting) {
+          loadVideo(entry.target);
+          observer.unobserve(entry.target);
+        }
+      });
+    }, {
+      rootMargin: "200px 0px",
+      threshold: 0.1
+    });
+    lazyVideos.forEach(video => lazyVideoObserver.observe(video));
+    return;
+  }
+
+  // --- 2. Fallback: requestIdleCallback ---
+  if ("requestIdleCallback" in window) {
+    requestIdleCallback(() => {
+      lazyVideos.forEach(video => loadVideo(video));
+    });
+    return;
+  }
+
+  // --- 3. Final fallback: load immediately ---
+  lazyVideos.forEach(video => loadVideo(video));
+});
+/******/ })()
+;
+//# sourceMappingURL=view.js.map
\ No newline at end of file
diff --git a/build/video/view.js.map b/build/video/view.js.map
new file mode 100644
index 0000000..e4ef9c2
--- /dev/null
+++ b/build/video/view.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"video/view.js","mappings":";;;;AAAA;AACAA,QAAQ,CAACC,gBAAgB,CAAC,kBAAkB,EAAE,YAAY;EACzD,MAAMC,UAAU,GAAG,EAAE,CAACC,KAAK,CAACC,IAAI,CAC/BJ,QAAQ,CAACK,gBAAgB,CAAC,wBAAwB,CACnD,CAAC;;EAED;EACA,SAASC,SAASA,CAACC,KAAK,EAAE;IACzB,MAAMC,OAAO,GAAGD,KAAK,CAACF,gBAAgB,CAAC,kBAAkB,CAAC;IAC1DG,OAAO,CAACC,OAAO,CAACC,MAAM,IAAI;MACzBA,MAAM,CAACC,GAAG,GAAGD,MAAM,CAACE,OAAO,CAACD,GAAG;IAChC,CAAC,CAAC;IACFJ,KAAK,CAACM,IAAI,CAAC,CAAC;EACb;;EAEA;EACA,IAAI,sBAAsB,IAAIC,MAAM,EAAE;IACrC,MAAMC,iBAAiB,GAAG,IAAIC,oBAAoB,CACjD,UAAUC,OAAO,EAAEC,QAAQ,EAAE;MAC5BD,OAAO,CAACR,OAAO,CAACU,KAAK,IAAI;QACxB,IAAIA,KAAK,CAACC,cAAc,EAAE;UACzBd,SAAS,CAACa,KAAK,CAACE,MAAM,CAAC;UACvBH,QAAQ,CAACI,SAAS,CAACH,KAAK,CAACE,MAAM,CAAC;QACjC;MACD,CAAC,CAAC;IACH,CAAC,EACD;MACCE,UAAU,EAAE,WAAW;MACvBC,SAAS,EAAE;IACZ,CACD,CAAC;IAEDtB,UAAU,CAACO,OAAO,CAACF,KAAK,IAAIQ,iBAAiB,CAACU,OAAO,CAAClB,KAAK,CAAC,CAAC;IAC7D;EACD;;EAEA;EACA,IAAI,qBAAqB,IAAIO,MAAM,EAAE;IACpCY,mBAAmB,CAAC,MAAM;MACzBxB,UAAU,CAACO,OAAO,CAACF,KAAK,IAAID,SAAS,CAACC,KAAK,CAAC,CAAC;IAC9C,CAAC,CAAC;IACF;EACD;;EAEA;EACAL,UAAU,CAACO,OAAO,CAACF,KAAK,IAAID,SAAS,CAACC,KAAK,CAAC,CAAC;AAC9C,CAAC,CAAC,C","sources":["webpack://jvb/./src/video/view.js"],"sourcesContent":["/** view.js **/\r\ndocument.addEventListener(\"DOMContentLoaded\", function () {\r\n\tconst lazyVideos = [].slice.call(\r\n\t\tdocument.querySelectorAll(\".video-container video\")\r\n\t);\r\n\r\n\t// Build a helper to actually set sources + load\r\n\tfunction loadVideo(video) {\r\n\t\tconst sources = video.querySelectorAll(\"source[data-src]\");\r\n\t\tsources.forEach(source => {\r\n\t\t\tsource.src = source.dataset.src;\r\n\t\t});\r\n\t\tvideo.load();\r\n\t}\r\n\r\n\t// --- 1. IntersectionObserver (best case) ---\r\n\tif (\"IntersectionObserver\" in window) {\r\n\t\tconst lazyVideoObserver = new IntersectionObserver(\r\n\t\t\tfunction (entries, observer) {\r\n\t\t\t\tentries.forEach(entry => {\r\n\t\t\t\t\tif (entry.isIntersecting) {\r\n\t\t\t\t\t\tloadVideo(entry.target);\r\n\t\t\t\t\t\tobserver.unobserve(entry.target);\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\trootMargin: \"200px 0px\",\r\n\t\t\t\tthreshold: 0.1,\r\n\t\t\t}\r\n\t\t);\r\n\r\n\t\tlazyVideos.forEach(video => lazyVideoObserver.observe(video));\r\n\t\treturn;\r\n\t}\r\n\r\n\t// --- 2. Fallback: requestIdleCallback ---\r\n\tif (\"requestIdleCallback\" in window) {\r\n\t\trequestIdleCallback(() => {\r\n\t\t\tlazyVideos.forEach(video => loadVideo(video));\r\n\t\t});\r\n\t\treturn;\r\n\t}\r\n\r\n\t// --- 3. Final fallback: load immediately ---\r\n\tlazyVideos.forEach(video => loadVideo(video));\r\n});\r\n"],"names":["document","addEventListener","lazyVideos","slice","call","querySelectorAll","loadVideo","video","sources","forEach","source","src","dataset","load","window","lazyVideoObserver","IntersectionObserver","entries","observer","entry","isIntersecting","target","unobserve","rootMargin","threshold","observe","requestIdleCallback"],"sourceRoot":""}
\ No newline at end of file
diff --git a/inc/blocks/DrawerMenuBlock.php b/inc/blocks/DrawerMenuBlock.php
new file mode 100644
index 0000000..386c123
--- /dev/null
+++ b/inc/blocks/DrawerMenuBlock.php
@@ -0,0 +1,76 @@
+<?php
+namespace JVBase\blocks;
+
+use JVBase\managers\Cache;
+use JVBase\ui\Navigation;
+use WP_Block;
+
+class DrawerMenuBlock {
+	protected Cache $cache;
+	public function __construct()
+	{
+		add_action('init', [ $this, 'registerBlock' ]);
+	}
+
+	/**
+	 * Register the FAQ block
+	 */
+	public function registerBlock():void {
+		// Register the block
+		register_block_type(
+			JVB_DIR . '/build/drawer-menu',
+			[
+				'render_callback' => [$this, 'render'],
+			]
+		);
+	}
+
+	/**
+	 * Render callback
+	 *
+	 * @param array $attributes Block attributes
+	 * @param string $content Block content
+	 * @param WP_Block $block Block instance
+	 * @return string Rendered block HTML
+	 */
+	public function render(array $attributes, string $content, WP_Block $block):string
+	{
+
+		$menu_id = $attributes['menuId'] ?? '';
+		$collapsed = $attributes['collapsed'] ?? true;
+
+// You'd populate this from options, a filter, or however you store menu data
+		$menu_items = apply_filters('jvbDrawerItems', [], $menu_id);
+
+		if (empty($menu_items) || empty($menu_id)) {
+			return '<p>Please configure the drawer menu in block settings.</p>';
+		}
+
+		$cache = Cache::for('drawer');
+		if (JVB_TESTING) {
+			$cache->flush();
+		}
+
+		if (!is_front_page()) {
+			$menu_items[] = [
+				'text'	=> 'Home',
+				'url'	=> home_url(),
+				'icon'	=> 'house-simple',
+			];
+		}
+		$items = array_map(function($item) { return $item['text'];}, $menu_items);
+
+		$key = $cache->generateKey($items);
+		$menu =  $cache->remember($key,
+			function () use ($menu_items, $menu_id, $collapsed) {
+				$menu = new Navigation($menu_id);
+				$menu->asDrawer($collapsed)->populateFromArray($menu_items);
+				return $menu->render();
+			});
+
+		global $wp;
+
+		$current = home_url($wp->request.'/');
+		return str_replace($current.'"', $current.'" class="current" aria-current="page"', $menu);
+	}
+}
diff --git a/inc/blocks/FAQBlock.php b/inc/blocks/FAQBlock.php
index 00f9c1d..90443e6 100644
--- a/inc/blocks/FAQBlock.php
+++ b/inc/blocks/FAQBlock.php
@@ -25,12 +25,6 @@
 				'render_callback' => [$this, 'render'],
 			]
 		);
-//
-//		// Localize script data for the editor
-//		add_action('enqueue_block_editor_assets', [$this, 'enqueue_editor_assets']);
-//
-//		// Enqueue frontend scripts
-//		add_action('wp_enqueue_scripts', [$this, 'enqueue_frontend_assets']);
 	}
 
 	/**
diff --git a/inc/blocks/FeedBlock.php b/inc/blocks/FeedBlock.php
index 3ed2f38..8a8f835 100644
--- a/inc/blocks/FeedBlock.php
+++ b/inc/blocks/FeedBlock.php
@@ -7,6 +7,7 @@
 use JVBase\forms\TaxonomySelector;
 use JVBase\ui\CRUDSkeleton;
 use WP_Block;
+use WP_Query;
 
 if (!defined('ABSPATH')) {
 	exit;
@@ -20,6 +21,9 @@
 
 	protected array $content = [];
 	protected array $taxonomies = [];
+	protected ?string $context = null;
+	protected ?int $contextID = null;
+
 	protected bool $isGallery = false;
 
 	public function __construct()
@@ -53,13 +57,15 @@
 		$classes = '';
 
 		return sprintf(
-			'<section class="feed-block%s" data-content="%s"%s>
+			'<section class="feed-block%s" data-content="%s"%s%s%s>
 			%s%s%s%s%s
 			<footer>%s</footer>
 			</section>',
 			$classes,
 			$this->getContent(),
 			$this->isGallery ? ' data-gallery' : '',
+			is_null($this->context) ? '' : ' data-context="'.$this->context.'"',
+			is_null($this->contextID) ? '' : ' data-context-id="'.$this->contextID.'"',
 			$this->renderFiltersAndControls(),
 			$this->renderGrid(),
 			$this->renderTemplates(),
@@ -80,6 +86,9 @@
 				global $post;
 				$author = $post->post_author;
 				$role = jvbUserRole($author);
+
+				$this->context = jvbNoBase($role);
+				$this->contextID = $author;
 				$registrar = Registrar::getInstance($role);
 				if (!$registrar) {
 					return;
@@ -88,6 +97,8 @@
 				return;
 			} elseif (is_tax()) {
 				$obj = get_queried_object();
+				$this->context = jvbNoBase($obj->taxonomy);
+				$this->contextID = $obj->term_id;
 				$registrar = Registrar::getInstance($obj->taxonomy);
 				if (!$registrar) {
 					return;
@@ -133,7 +144,7 @@
 	protected function renderFiltersAndControls():string
 	{
 		return sprintf(
-			'<details class="all-filters col top left" data-ignore open>
+			'<details class="all-filters col top left" data-ignore>
 			<summary>Filters %s</summary>
 			%s%s%s%s%s
 			</details>
@@ -159,23 +170,11 @@
 		}
 		protected function renderContentLabels():string
 		{
-			$inside = '';
-			if (count($this->content) === 1) {
-				return '';
-			}
-			foreach ($this->content as $i => $type) {
-				$active = $i === 0 ? ' class="active"' : '';
-				$inside .= sprintf(
-					'<li id="filter-%s"%s>%s</li>',
-					$type,
-					$active,
-					Registrar::getInstance($type)->getPlural()??''
-				);
-			}
 			return sprintf(
-				'<ul class="filter-label">%s</ul>',
-				$inside
+				'<span class="label">Showing: <span class="current">%s</span></span>',
+				$this->content[0]??''
 			);
+
 		}
 		protected function renderContent():string
 		{
@@ -191,7 +190,7 @@
 			if (count($this->content) === 1) {
 				return empty($favourites)
 					? sprintf(
-						'<input type="hidden" name="content" value="%s">',
+						'<input type="hidden" data-filter="content" name="content" value="%s">',
 						implode(',', $this->content)
 					)
 					: sprintf(
@@ -205,23 +204,55 @@
 			}
 			$i = 0;
 			$content = implode('', array_map(function($type) use (&$i) {
-				$i++;
 				$registrar = Registrar::getInstance($type);
+
+				$args = [
+					'post_type'	=> $registrar->getBased(),
+					'posts_per_page'	=> 1,
+					'fields'	=> 'ids',
+				];
+				if (!is_null($this->context)) {
+
+					$context = Registrar::getInstance($this->context);
+					switch ($context->getType()) {
+						case 'term':
+							$args['tax_query'] = [];
+							$args['tax_query'][] = [
+								'taxonomy'	=> $context->getBased(),
+								'terms'		=> $this->contextID
+							];
+							break;
+						case 'user':
+							$args['author'] = $this->contextID;
+							break;
+					}
+				}
+				$check = new WP_Query($args);
+				$hasPosts = !empty($check->posts);
+
+				$disabled = !$hasPosts;
+				$checked = $i === 0 && $hasPosts;
+				if ($hasPosts) {
+					$i++;
+				}
 				return sprintf(
 					'<input type="radio"
 					id="filter-%s"
 					class="btn"
 					name="content"
 					data-filter="content"
-					value="%s"%s>
-					<label for="filter-%s" title="Show %s">%s<span class="screen-reader-text">%s</span></label>',
+					data-label="%s"
+					value="%s"%s%s>
+					<label for="filter-%s" title="Show %s">%s<span class="label">%s</span></label>',
 					$type,
+					$registrar->getSingular(),
 					$type,
-					$i === 0 ? ' checked' : '',
+					$checked ? ' checked' : '',
+					$disabled ? ' disabled' : '',
 					$type,
-					$registrar->getPlural(),
+					$registrar->getSingular(),
 					jvbIcon($registrar->getIcon()),
-					$registrar->getPlural()
+					$registrar->getSingular()
 				);
 			}, $this->content));
 
@@ -267,9 +298,9 @@
 			}, $this->taxonomies)));
 			return sprintf(
 				'<div class="taxonomies row left">
-				<div class="row top nowrap">
-				<span class="label">Filter By:</span>
-				<div class="row left">%s</div>
+				<div class="row top wrap">
+					<span class="label">Filter By:</span>
+					%s
 				</div>
 				<div class="selected-items-section">
 					<div class="selected-items row left"></div>
@@ -382,7 +413,7 @@
 			);
 
 			return sprintf(
-				'<div class="ordering row left nowrap">%s%s</div>',
+				'<div class="ordering row top left nowrap">%s%s</div>',
 				$orderby,
 				$order
 			);
diff --git a/inc/blocks/GMBReviewBlock.php b/inc/blocks/GMBReviewBlock.php
new file mode 100644
index 0000000..7225625
--- /dev/null
+++ b/inc/blocks/GMBReviewBlock.php
@@ -0,0 +1,237 @@
+<?php
+namespace JVBase\blocks;
+
+use JVBase\managers\Cache;
+use WP_Block;
+
+class GMBReviewBlock {
+	protected Cache $cache;
+	public function __construct()
+	{
+		add_action('init', [ $this, 'registerBlock' ]);
+	}
+
+	/**
+	 * Register the FAQ block
+	 */
+	public function registerBlock():void {
+		// Register the block
+		register_block_type(
+			JVB_DIR . '/build/gmbreviews',
+			[
+				'render_callback' => [$this, 'render'],
+			]
+		);
+	}
+
+	/**
+	 * Render callback
+	 *
+	 * @param array $attributes Block attributes
+	 * @param string $content Block content
+	 * @param WP_Block $block Block instance
+	 * @return string Rendered block HTML
+	 */
+	public function render(array $attributes, string $content, WP_Block $block):string
+	{
+		$count = $attributes['count'] ?? 5;
+		$showRating = $attributes['showRating'] ?? true;
+		$showDate = $attributes['showDate'] ?? true;
+		$showReviewLink = $attributes['showReviewLink'] ?? true;
+		$showViewAllLink = $attributes['showViewAllLink'] ?? true;
+		$showStats = $attributes['showStats'] ?? true;
+		$minStars = $attributes['minStars'] ?? 4; // Only show 4+ star reviews
+		$inheritUser = $attributes['inheritUser']??null;
+		if ($inheritUser) {
+			global $post;
+			$inheritUser = $post->post_author;
+		}else {
+			$inheritUser = null;
+		}
+		try {
+			$gmb = JVB()->connect('gmb', $inheritUser);
+			if (!$gmb->isSetUp()) {
+				error_log('GMB Not set up for: '.(int)$inheritUser);
+				return '';
+			}
+			$gotReviews = $gmb->getReviews();
+			// Get all data
+			$allReviews = $gotReviews['reviews']??[];
+			$reviewUrl = $gmb->getReviewUrl();
+			$viewAllUrl = $gmb->getReviewsViewUrl();
+
+			$average = $gotReviews['averageRating']??null;
+			$total = $gotReviews['totalReviewCount']??null;
+
+			// Filter reviews by minimum stars
+			$reviews = [];
+			if (!empty($allReviews)) {
+				foreach ($allReviews as $review) {
+					$rating = $review['starRating'] ?? 0;
+					if ($rating >= $minStars) {
+						$reviews[] = $review;
+						if (count($reviews) >= $count) {
+							break; // Got enough reviews
+						}
+					}
+				}
+			}
+
+			if (empty($reviews) && empty($reviewUrl) && empty($stats)) {
+				error_log('No reviews to display...');
+				return '';
+			}
+
+			ob_start();
+			?>
+			<div class="gmb-reviews">
+				<div class="row x-mid">
+					<?php
+					if ($showStats && !empty($average) && !empty($total)) {
+						?>
+						<p>
+					<span class="stars" title="<?= $average ?> out of 5 stars">
+						<?php
+						$fullStars = floor($average);
+						$hasHalfStar = ($average - $fullStars) >= 0.5;
+
+						for ($i = 1; $i <= 5; $i++) {
+							if ($i <= $fullStars) {
+								echo jvbIcon('star', ['style' => 'fill']);
+							} elseif ($i == $fullStars + 1 && $hasHalfStar) {
+								echo jvbIcon('star-half', ['style'=> 'fill']);
+							} else {
+								echo  jvbIcon('star', ['style' => 'light']);
+							}
+						}
+						?>
+					</span>
+							<i>Average</i>
+						</p>
+						<?php
+						if ($total > 0) {
+							?>
+							<p><i>{ <?= number_format($total ) . ' ' . _n('Review', 'Reviews', $total, 'jvb')?> Total }</i></p>
+							<?php
+						}
+						?>
+						<?php
+					}
+					?>
+
+
+				</div>
+				<?php
+				if ($showReviewLink && !empty($reviewUrl)) {
+					?>
+					<a href="<?=esc_url($reviewUrl)?>"
+					   class="btn"
+					   target="_blank"
+					   rel="noopener noreferrer">
+						<?= jvbIcon('star', ['style' => 'fill']) ?>
+						Leave Your Review
+					</a>
+					<?php
+				}
+				?>
+
+				<ul>
+					<?php
+					foreach ($reviews as $review) {
+						$reviewer = $review['reviewer']['displayName'] ?? 'Anonymous';
+						$reviewer = strtok($reviewer, ' ');
+						$profilePhoto = $review['reviewer']['profilePhotoUrl'] ?? '';
+						$rating = $review['starRating'] ?? 0;
+						$rating = match($rating) {
+							'FIVE'	=> 5,
+							'FOUR'	=> 4,
+							'THREE'	=> 3,
+							'TWO'	=> 2,
+							'ONE'	=> 1,
+							default =>  $rating
+						};
+						$comment = $review['comment'] ?? '';
+						$date = $review['updateTime'] ?? '';
+						?>
+						<li>
+							<blockquote class="review">
+								<?php
+								echo jvbIcon('quotes',['style' => 'fill']);
+								// Review text
+								if (!empty($comment)) { ?>
+									<div class="content review">
+										<?= apply_filters('wpautop', $comment) ?>
+									</div>
+								<?php } ?>
+								<cite class="row left nowrap">
+									<?php if (!empty($profilePhoto)) { ?>
+										<img src="<?=esc_url($profilePhoto)?>"
+											 alt="<?=esc_attr($reviewer)?>"
+										'loading="lazy">
+									<?php } else { ?>
+										<div class="avatar">
+											<?= jvbIcon('user-circle')?>
+										</div>
+									<?php } ?>
+
+									<div class="row left wrap">
+										<?php if ($showRating && $rating > 0) { ?>
+											<div class="stars" title="<?= $rating ?> out of 5 stars">
+												<?php
+												for ($i = 1; $i <= 5; $i++) {
+													echo ($i <= $rating) ? jvbIcon('star', ['style' => 'fill']) : jvbIcon('star', ['style' => 'light']);
+												} ?>
+											</div>
+										<?php } ?>
+										<p><?= esc_html($reviewer)?></p>
+										<?php
+										// Date
+										if ($showDate && !empty($date)) {
+											$formatted_date = human_time_diff(strtotime($date), current_time('timestamp')) . ' ago';
+											?>
+											<time datetime="<?=esc_attr($date)?>">
+												<?= esc_html($formatted_date) ?>
+											</time>
+										<?php } ?>
+
+									</div>
+								</cite>
+							</blockquote>
+						</li>
+						<?php
+					}
+					?>
+				</ul>
+				<?php
+				// Footer with "See All Reviews" button
+				if ($showViewAllLink && !empty($viewAllUrl)) {
+					?>
+					<div class="footer">
+						<a href=" <?= esc_url($viewAllUrl) ?>"
+						   class="btn"
+						   target="_blank"
+						   rel="noopener noreferrer">
+
+							<?php
+							if ($showStats ) {
+								echo 'See All ' . number_format($total) . ' Reviews';
+							} else {
+								echo ' See All Reviews';
+							}
+							?>
+							<?= jvbIcon('arrow-square-out') ?>
+						</a>
+					</div>
+					<?php
+				}
+				?>
+			</div>
+			<?php
+			return ob_get_clean();
+
+		} catch (\Exception $e) {
+			error_log('[GMB Reviews Block] Error: ' . $e->getMessage());
+			return '';
+		}
+	}
+}
diff --git a/inc/blocks/_setup.php b/inc/blocks/_setup.php
index 889320e..cdae9f1 100644
--- a/inc/blocks/_setup.php
+++ b/inc/blocks/_setup.php
@@ -11,37 +11,33 @@
 function jvb_conditionally_load_blocks(): void
 {
 	if (Site::has('feed_block')) {
-		require(JVB_DIR . '/inc/blocks/FeedBlock.php');
+		require('FeedBlock.php');
 		new JVBase\blocks\FeedBlock();
 	}
 
 	if (Site::has('is_restaurant')) {
-		require(JVB_DIR . '/inc/blocks/MenuBlock.php');
+		require('MenuBlock.php');
 		new JVBase\blocks\MenuBlock();
 	}
 
 	if (!empty(Registrar::getFeatured('is_faq'))) {
-		require(JVB_DIR . '/inc/blocks/FAQBlock.php');
+		require('FAQBlock.php');
 		new JVBase\blocks\FAQBlock();
 	}
 
 	if (!empty(Registrar::getFeatured('is_glossary'))) {
-		require(JVB_DIR . '/inc/blocks/GlossaryBlock.php');
+		require('GlossaryBlock.php');
 		new JVBase\blocks\GlossaryBlock();
 	}
 
 	if (!empty(Registrar::getFeatured('is_timeline'))) {
-		require(JVB_DIR . '/inc/blocks/TimelineBlock.php');
+		require('TimelineBlock.php');
 		new JVBase\blocks\TimelineBlock();
 	}
 
 	if (Site::hasIntegration('gmb')) {
-		require(JVB_DIR . '/build/gmbreviews/render.php');
-		register_block_type(
-			JVB_DIR . '/build/gmbreviews',
-			[
-				'render_callback'	=> 'jvbRenderGMBReviewsBlock'
-			]);
+		require('GMBReviewBlock.php');
+		new JVBase\blocks\GMBReviewBlock();
 	}
 //    if (jvbSiteUsesFeedBlock()) {
 //        register_block_type(
@@ -60,21 +56,22 @@
 //			]
 //		);
 //	}
-	register_block_type(
-		JVB_DIR . '/build/drawer-menu',
-	);
+
 }
 
 
-require(JVB_DIR . '/inc/blocks/SummaryBlock.php');
+require('SummaryBlock.php');
 new JVBase\blocks\SummaryBlock();
 
-require(JVB_DIR . '/inc/blocks/VideoCoverBlock.php');
+require('VideoCoverBlock.php');
 new JVBase\blocks\VideoCoverBlock();
 
-require(JVB_DIR . '/inc/blocks/FormBlock.php');
+require('FormBlock.php');
 new JVBase\blocks\FormBlock();
 
+require ('DrawerMenuBlock.php');
+new JVBase\blocks\DrawerMenuBlock();
+
 
 function jvbRegisterBlockCategory(array $categories):array
 {
diff --git a/inc/managers/DashboardManager.php b/inc/managers/DashboardManager.php
index 28aa956..26b724f 100644
--- a/inc/managers/DashboardManager.php
+++ b/inc/managers/DashboardManager.php
@@ -29,6 +29,7 @@
 		if (JVB_TESTING) {
 			$this->cache->flush();
 		}
+		$this->cache->flush();
         add_action('init', [$this, 'registerDashboard']);
 
         $this->user = wp_get_current_user();
diff --git a/inc/managers/ErrorHandler.php b/inc/managers/ErrorHandler.php
index 9aefef1..a3b1f33 100644
--- a/inc/managers/ErrorHandler.php
+++ b/inc/managers/ErrorHandler.php
@@ -138,10 +138,10 @@
 
             if (!$result) {
                 // If insert fails, log to PHP error log as fallback
-                error_log("[ErrorHandler] Database insert failed: " . $$this->table->getLastError());
+                error_log("[ErrorHandler] Database insert failed: " . $this->table->getLastError());
                 return [
 					'success'	=> false,
-					'message'	=> "[ErrorHandler] Database insert failed: " . $$this->table->getLastError()
+					'message'	=> "[ErrorHandler] Database insert failed: " . $this->table->getLastError()
 				];
             }
 
diff --git a/inc/managers/SEO/BreadcrumbManager.php b/inc/managers/SEO/BreadcrumbManager.php
index 225e615..633ade4 100644
--- a/inc/managers/SEO/BreadcrumbManager.php
+++ b/inc/managers/SEO/BreadcrumbManager.php
@@ -28,6 +28,7 @@
 		if (JVB_TESTING) {
 			$this->cache->flush();
 		}
+		$this->cache->flush();
 	}
 
 	public static function getInstance(): self
diff --git a/inc/managers/SEO/render/Traits/_Properties/sourceOrganizationTrait.php b/inc/managers/SEO/render/Traits/_Properties/sourceOrganizationTrait.php
index 4cb72f9..0f25b6d 100644
--- a/inc/managers/SEO/render/Traits/_Properties/sourceOrganizationTrait.php
+++ b/inc/managers/SEO/render/Traits/_Properties/sourceOrganizationTrait.php
@@ -2,21 +2,23 @@
 namespace JVBase\managers\SEO\render\Traits\_Properties;
 
 use JVBase\managers\SEO\render\Thing\Organization\Organization;
+use JVBase\managers\SEO\render\Traits\_Helpers\arrayHelper;
 
 if (!defined('ABSPATH')) {
 	exit;
 }
 trait sourceOrganizationTrait {
+	use arrayHelper;
 	/**
-	 * @var Organization The Organization on whose behalf the creator was working.
+	 * @var Organization|array The Organization on whose behalf the creator was working.
 	 */
-	protected Organization $sourceOrganization;
+	protected Organization|array $sourceOrganization;
 
 	public function getSourceOrganization():?Organization
 	{
 		return $this->sourceOrganization??null;
 	}
-	public function setSourceOrganization(string|Organization $sourceOrganization):void
+	public function setSourceOrganization(string|array|Organization $sourceOrganization):void
 	{
 		if (is_string($sourceOrganization)) {
 			if (empty($sourceOrganization)) {
@@ -24,6 +26,12 @@
 			}
 			//TODO: create organization from string
 			return;
+		} elseif (is_array($sourceOrganization)) {
+			$sourceOrganization = $this->mixedArray('sourceOrganization', $sourceOrganization, [
+				'JVBase\managers\SEO\render\Thing\Person',
+				'JVBase\managers\SEO\render\Thing\Organization\LocalBusiness\LocalBusiness',
+            	'JVBase\managers\SEO\render\Thing\Organization\Organization',
+			]);
 		}
 		$this->sourceOrganization = $sourceOrganization;
 	}
diff --git a/inc/meta/Meta.php b/inc/meta/Meta.php
index 744fae5..35a8c3d 100644
--- a/inc/meta/Meta.php
+++ b/inc/meta/Meta.php
@@ -197,6 +197,11 @@
 		}
 		if (!array_key_exists($name, $this->fields)) {
 			error_log('[Meta]::get Attempted to get unregistered field: '.$name);
+			return '';
+		}
+		if (is_null($this->fields[$name])) {
+			error_log('[Meta]::get Field does not seem to be setup yet: '.$name);
+			return '';
 		}
 		return $this->fields[$name]->get()??'';
 	}
diff --git a/inc/registrar/Registrar.php b/inc/registrar/Registrar.php
index 38233f9..a133ab1 100644
--- a/inc/registrar/Registrar.php
+++ b/inc/registrar/Registrar.php
@@ -888,17 +888,25 @@
             'offset'    => ($page - 1) * $per_page,
             'meta_key'  => BASE.'date_modified',
             'meta_type' => 'DATETIME',
-            'orderby'   => 'meta_value'
+            'orderby'   => 'meta_value',
+			'order'		=> 'desc',
         ]);
-        $cache = Cache::for($this->slug);
 
-        $max = get_terms([
-            'taxonomy'  => $this->based,
-            'fields'    => 'ids',
-            'number'     => 0,
-            'hide_empty'    => true
-        ]);
-        $max = count($max??[]);
+        $cache = Cache::for($this->slug)->connect('taxonomy');
+		$max = $cache->remember(
+			'max',
+			function () {
+				$max = get_terms([
+					'taxonomy'  => $this->based,
+					'fields'    => 'ids',
+					'number'     => 0,
+					'hide_empty'    => true
+				]);
+				return  count($max??[]);
+			}
+		);
+
+
         $totalPages = floor($max/$per_page);
 
         global $wp;
@@ -924,6 +932,7 @@
             $page < $totalPages ? '<a href="'.add_query_arg('tp', $page+1, $current).'" title="Next Page" class="btn">'.jvbIcon('arrow-circle-right').'<span class="screen-reader-text">Next Page</span></a>' : '',
         );
 
+
 		$out = $nav. Cache::for($this->slug)->remember(
 			$cache->generateKey(['type' =>'contentArchive', ... $args]),
 			function() use ($args) {
@@ -936,6 +945,7 @@
                 $method = BASE.'render_'.$this->slug.'_content';
 				if ($items && !is_wp_error($items)) {
 					foreach ($items as $termID) {
+						$meta = Meta::forTerm($termID);
                         if (function_exists($method)) {
                             $out[] = $method($termID);
                             continue;
diff --git a/inc/registrar/config/seo/Resolver.php b/inc/registrar/config/seo/Resolver.php
index db40ea7..99b4586 100644
--- a/inc/registrar/config/seo/Resolver.php
+++ b/inc/registrar/config/seo/Resolver.php
@@ -15,7 +15,7 @@
 class Resolver {
 	protected static ?Meta $meta;
 
-	public static function resolve(string $template, ?Meta $meta): string
+	public static function resolve(string $template, ?Meta $meta): string|array|\JVBase\managers\SEO\render\Thing\Thing
 	{
 		if (!$meta) {
 			if (is_singular()){
@@ -25,6 +25,11 @@
 			}
 		}
 		self::$meta = $meta;
+
+		if (preg_match('/^\{\{([^}]+)}}$/', trim($template), $matches)) {
+			return self::resolveVariable($matches[1], $meta);
+		}
+
 		return preg_replace_callback(
 			'/\{\{([^}]+)}}/',
 			fn($matches) => self::resolveVariable($matches[1], $meta),
@@ -34,6 +39,7 @@
 	protected static function resolveVariable(string $variable, ?Meta $meta = null): mixed
 	{
 		$variable = trim($variable);
+
 		switch ($variable) {
 			case 'CREATOR':
 				return JVB()->seo()->getCreator();
@@ -50,6 +56,10 @@
 		if (str_contains($variable, '.') && $meta) {
 			return self::resolveRelation($variable, $meta);
 		}
+		$function = BASE.'resolve_'.$variable;
+		if (function_exists($function)) {
+			return $function($variable, $meta);
+		}
 		if ($meta && $variable === 'post_permalink') {
 			return get_the_permalink($meta->id());
 		}
@@ -78,7 +88,6 @@
 		$relation = array_shift($parts);
 		$field = implode('.', $parts);
 
-
 		//We need to:
 			// 1) Get the id of the item we're fetching (meta value of the $relation)
 		if ($relation === 'registrar') {
@@ -94,6 +103,7 @@
 		if (!$meta) {
 			return'';
 		}
+
 		$ID = $meta->get($relation);
 		if (empty($ID)) {
 			return '';
diff --git a/inc/registrar/config/seo/Schema.php b/inc/registrar/config/seo/Schema.php
index 6e67534..9fc1394 100644
--- a/inc/registrar/config/seo/Schema.php
+++ b/inc/registrar/config/seo/Schema.php
@@ -333,7 +333,10 @@
 				}
 				$config = $this->getConfig();
 				$class = JVB()->schemaHelper()::classFromConfig($config, $meta);
-				$class->delete('about');
+				if ($class) {
+					$class->delete('about');
+				}
+
 
 				switch ($type) {
 					case 'post':
diff --git a/inc/rest/routes/FeedRoutes.php b/inc/rest/routes/FeedRoutes.php
index ec2d4cc..76f6b61 100644
--- a/inc/rest/routes/FeedRoutes.php
+++ b/inc/rest/routes/FeedRoutes.php
@@ -68,7 +68,7 @@
 				'dateFrom' => 'string',
 				'dateTo' => 'string',
 				'context' => 'string',
-				'source' => 'string',
+				'contextId' => 'string',
 				'favourites' => 'boolean',
 				'user' => 'integer',
 				'highlight' => 'string',
@@ -87,7 +87,7 @@
 				'dateFrom' => 'string',
 				'dateTo' => 'string',
 				'context' => 'string',
-				'source' => 'string',
+				'contextId' => 'string',
 				'favourites' => 'boolean',
 				'user' => 'integer',
 				'highlight' => 'string',
@@ -213,7 +213,7 @@
 						break;
 					case 'post':
 						$out['date'] = $post->post_date;
-						$out['modified'] = $post->post_modified;
+						$out['date_modified'] = $post->post_modified;
 						$out['user_id'] = (int)$post->post_author;
 						$out['url'] = get_the_permalink($postID);
 						$out['title']= get_the_title($postID);
@@ -410,7 +410,7 @@
 			$args = $this->applyContextFilters(
 				$args,
 				[
-					'id' => $data['source']??'0',
+					'id' => $data['contextId']??'0',
 					'type' => $data['context']
 				]
 			);
@@ -537,8 +537,16 @@
 
 				// Add term to tax query
 				$args['tax_query'][] = [
-					'taxonomy' => jvbCheckBase($context['type']),
-					'field' => 'term_id',
+					'taxonomy' => $registrar->getBased(),
+//					'field' => 'term_id',
+					'terms' => [(int)$context['id']],
+				];
+				break;
+			case $registrar->getType() === 'term':
+				// Add term to tax query
+				$args['tax_query'][] = [
+					'taxonomy' => $registrar->getBased(),
+//					'field' => 'term_id',
 					'terms' => [(int)$context['id']],
 				];
 				break;
diff --git a/jvb.php b/jvb.php
index af29dad..0fcddcc 100644
--- a/jvb.php
+++ b/jvb.php
@@ -20,6 +20,17 @@
     exit;
 }
 
+//add_action('admin_enqueue_scripts', function() {
+//	global $wp_scripts;
+//	add_action('admin_print_scripts', function() use ($wp_scripts) {
+//		$queue = $wp_scripts->queue ?? [];
+//		foreach ($queue as $handle) {
+//			$src = $wp_scripts->registered[$handle]->src ?? 'unknown';
+//			error_log("Enqueued: $handle => $src");
+//		}
+//	}, 999);
+//}, 999);
+
 
 /**
  * Track REST API errors by wrapping request execution
diff --git a/package.json b/package.json
index 0b4942f..ac5d729 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
     "name": "jvb",
-    "version": "0.1.0",
-    "description": "Example block scaffolded with Create Block tool.",
+    "version": "0.2.0",
+    "description": "JVB Blocks",
     "author": "The WordPress Contributors",
     "license": "GPL-2.0-or-later",
     "main": "build/index.js",
diff --git a/src/drawer-menu/render.php b/src/drawer-menu/render.php
index d2fe96c..b3d9bbc 100644
--- a/src/drawer-menu/render.php
+++ b/src/drawer-menu/render.php
@@ -1,41 +1 @@
 <?php
-
-use JVBase\managers\Cache;
-use JVBase\ui\Navigation;
-
-$menu_id = $attributes['menuId'] ?? '';
-$collapsed = $attributes['collapsed'] ?? true;
-
-// You'd populate this from options, a filter, or however you store menu data
-$menu_items = apply_filters('jvbDrawerItems', [], $menu_id);
-
-if (empty($menu_items) || empty($menu_id)) {
-	return '<p>Please configure the drawer menu in block settings.</p>';
-}
-
-$cache = Cache::for('drawer');
-if (JVB_TESTING) {
-	$cache->flush();
-}
-
-if (!is_front_page()) {
-	$menu_items[] = [
-		'text'	=> 'Home',
-		'url'	=> home_url(),
-		'icon'	=> 'house-simple',
-	];
-}
-$items = array_map(function($item) { return $item['text'];}, $menu_items);
-
-$key = $cache->generateKey($items);
-$menu =  $cache->remember($key,
-function () use ($menu_items, $menu_id, $collapsed) {
-	$menu = new Navigation($menu_id);
-	$menu->asDrawer($collapsed)->populateFromArray($menu_items);
-	return $menu->render();
-});
-
-global $wp;
-
-$current = home_url($wp->request.'/');
-echo str_replace($current.'"', $current.'" class="current" aria-current="page"', $menu);
diff --git a/src/drawer-menu/style.scss b/src/drawer-menu/style.scss
index 5731e6e..1016989 100644
--- a/src/drawer-menu/style.scss
+++ b/src/drawer-menu/style.scss
@@ -94,5 +94,5 @@
 }
 
 nav.on-this-page.on-this-page.on-this-page {
-	max-width: calc(100vw - var(--btn_))!important;
+	width: calc(100vw - var(--btn))!important;
 }
diff --git a/src/feed/style.scss b/src/feed/style.scss
index 263a663..5bf4033 100644
--- a/src/feed/style.scss
+++ b/src/feed/style.scss
@@ -1141,6 +1141,10 @@
 			--w: 1.5em;
 		}
 	}
+	.all-filters summary {
+		display: flex;
+		justify-content: space-between;
+	}
 }
 .all-filters {
 	font-size: var(--txt-x-small);
@@ -1215,6 +1219,25 @@
 	.view.row {
 		display: none;
 	}
+	.ordering {
+		padding: 2rem 0 .75rem 0;
+	}
+	.ordering > .row label {
+		position: unset;
+	}
+	.ordering .row {
+
+		.label {
+			top: -1rem;
+			color: rgb(var(--contrast));
+		}
+		&.orderby .label {
+			left: 0;
+		}
+		&.order-direction .label {
+			right: 0;
+		}
+	}
 }
 
 
diff --git a/src/feed/view.js b/src/feed/view.js
index 894f85c..308865e 100644
--- a/src/feed/view.js
+++ b/src/feed/view.js
@@ -9,7 +9,7 @@
 		this.templates = window.jvbTemplates;
 
 		this.config = {
-			source: '',
+			contextId: '',
 			context: '',
 			highlight: null,
 			gallery: false,
@@ -17,6 +17,8 @@
 			... this.container.dataset
 		};
 
+		console.log(this.config);
+
 		this.init();
 	}
 	init() {
@@ -54,9 +56,12 @@
 			filters: {
 				actions: 	'.filter-actions .toggle-text',
 				container:	'.all-filters',
+				showing:	'.all-filters summary .current',
 				content: 	'[data-filter="content"]',
+				ordering:	'.ordering',
 				orderby: 	'[data-filter="orderby"]',
 				order: 		'[data-filter="order"]',
+				orderWrap:  '.order-direction',
 				match: 		'[data-filter="match"]',
 				favourites: '[data-filter="favourites"]',
 				taxonomy: 	'[data-filter^="taxonomy"]',
@@ -74,29 +79,41 @@
 		this.ui.buttons.refresh = document.querySelector(this.selectors.buttons.refresh);
 
 		//Add content and taxonomies
-		this.ui.content = this.ui.filters.container.querySelectorAll('[name="content"]');
-		if (this.ui.content.length === 0) this.ui.content = false;
-		this.ui.taxonomies = this.ui.filters.container.querySelectorAll('[data-taxonomy]');
-		if (this.ui.taxonomies.length === 0) this.ui.taxonomies = false;
-		this.ui.orderbyWrap = this.ui.filters.container.querySelector('[data-for-order]');
-		if (this.ui.orderbyWrap.length === 0) this.ui.orderbyWrap = false;
-		this.ui.order = this.ui.filters.container.querySelectorAll('[data-filter="order"]');
-		if (this.ui.order.length === 0) this.ui.order = false;
-		this.ui.orderby = this.ui.filters.container.querySelectorAll('[data-filter="orderby"]');
-		if (this.ui.orderby.length === 0) this.ui.orderby = false;
+		let getAll = ['content','orderby','order','taxonomy'];
+		getAll.forEach(item => {
+			let items = this.ui.filters.container.querySelectorAll(this.selectors.filters[item]);
+			this.ui[item] = Array.from(items);
+		});
 
-		this.orderbyFilters = (this.ui.orderby)
-			? Array.from(this.ui.orderby).map(o => o.value)
-			: [];
-
-		this.contentTypes = (this.ui.content)
-			? Array.from(this.ui.content).map(c => c.value)
+		this.contentTypes = (this.ui.content.length > 0)
+			? this.ui.content.map(c => c.value)
 			: [this.container.dataset.content];
 		this.taxonomies = (this.ui.taxonomies?.length > 0)
 			? Array.from(this.ui.taxonomies).map(t => t.dataset.taxonomy)
 			: [];
 	}
 
+	/**
+	 *
+	 * @param {string} item
+	 */
+	getChecked(item) {
+		if (!['content', 'orderby','order'].includes(item)) {
+			console.log('Invalid item to check: ', item);
+		}
+
+		let items = this.ui[item];
+		if (!items) {
+			return;
+		}
+
+		let checked = items.filter(i => i.checked);
+		if (item === 'content' && checked.length > 0) {
+			this.updateContentFor(checked[0].value);
+		}
+		return checked.length === 0 ? items[0].value : checked[0].value;
+	}
+
 	initListeners() {
 		this.popStateHandler	= this.handlePopState.bind(this);
 		this.clickHandler		= this.handleClick.bind(this);
@@ -110,15 +127,17 @@
 	initFilters() {
 		this.allowedFilters = ['content', 'order', 'orderby', 'favourites', 'match'];
 		let defaults = {
-			content:	this.contentTypes[0],
-			orderby:	'date',
-			order:		'desc',
+			content:	this.getChecked('content'),
+			orderby:	this.getChecked('orderby'),
+			order:		this.getChecked('order'),
 			page:		1,
 		};
 		if (this.config.context) defaults.context = this.config.context;
-		if (this.config.source) defaults.source = this.config.source;
+		if (this.config.contextId) defaults.contextId = this.config.contextId;
 
 		this.filters = defaults;
+
+		console.log(this.filters);
 		this.defaults = {...defaults};
 	}
 	updateFilterUI() {
@@ -247,7 +266,7 @@
 	}
 
 	getFieldId(taxonomy) {
-		return this.selector.getFieldId(Array.from(this.ui.taxonomies).filter(tax => tax.dataset.taxonomy === taxonomy)[0]??null);
+		return this.selector.getFieldId(this.ui.taxonomies.filter(tax => tax.dataset.taxonomy === taxonomy)[0]??null);
 	}
 	removeSelectedTerm(button) {
 		const termId = parseInt(button.dataset.id);
@@ -282,6 +301,8 @@
 			this.ui.taxonomies,
 			this.ui.orderby
 		];
+
+		this.ui.filters.showing.textContent = this.ui.content.filter(c => c.value === content)[0].dataset.label;
 		checkIt.forEach(check => {
 			if (!check) return;
 			check.forEach(button => {
@@ -294,9 +315,9 @@
 		});
 	}
 	updateOrderOptions(order) {
-		if (this.ui.orderbyWrap) {
-			let options = this.ui.orderbyWrap.dataset.forOrder.split(',')??[];
-			this.ui.orderbyWrap.hidden = !options.includes(order);
+		if (this.ui.filters.orderWrap) {
+			let options = this.ui.filters.orderWrap.dataset.forOrder.split(',')??[];
+			this.ui.filters.orderWrap.hidden = !options.includes(order);
 		}
 	}
 
@@ -338,7 +359,7 @@
 		this.updateFilterControls();
 	}
 	getTaxonomyIcon(taxonomy) {
-		let iconButton = Array.from(this.ui.taxonomies)
+		let iconButton = this.ui.taxonomies
 			.find(t => t.dataset.taxonomy === taxonomy);
 		return iconButton?.dataset.icon.trim() || 'tag';
 	}
@@ -353,7 +374,7 @@
 
 	processCachedFilters() {
 		Object.keys(this.filters).forEach(filter => {
-			let cached = this.cache.get(`${this.config.source}_${this.config.context}_${filter}`);
+			let cached = this.cache.get(`${this.config.contextId}_${this.config.context}_${filter}`);
 			if (cached && cached !== this.filters[filter]) {
 				this.filters[filter] = cached;
 			}
@@ -415,7 +436,7 @@
 
 	saveToCacheFilters() {
 		Object.keys(this.store.filters).forEach(filter => {
-			const cacheKey = `${this.config.source}_${this.config.context}_${filter}`;
+			const cacheKey = `${this.config.contextId}_${this.config.context}_${filter}`;
 
 			if (this.store.filters[filter] !== this.defaults[filter]) {
 				this.cache.set(cacheKey, this.store.filters[filter]);
@@ -424,7 +445,7 @@
 			}
 		});
 
-		const taxCacheKey = `${this.config.source}_${this.config.context}_taxonomy`;
+		const taxCacheKey = `${this.config.contextId}_${this.config.context}_taxonomy`;
 		if (Object.keys(this.taxFilters).length > 0) {
 			this.cache.set(taxCacheKey, this.taxFilters);
 		} else {
@@ -443,10 +464,11 @@
 		}
 	}
 	initStore() {
-		let extraOrderby = this.orderbyFilters.filter(v => !['date','modified','title','random'].includes(v));
+		let extraOrderby = this.ui.orderby.filter(v => !['date','date_modified','title','random'].includes(v.value));
+
 		let extraIndexes = [];
 		extraOrderby.forEach(orderby =>{
-			extraIndexes.push({name:orderby, keyPath: orderby});
+			extraIndexes.push({name:orderby.value, keyPath: orderby.value});
 		});
 		const store = window.jvbStore.register(
 			'feed',
diff --git a/src/fields/block.json b/src/fields/block.json
deleted file mode 100644
index 085ccdf..0000000
--- a/src/fields/block.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    "$schema": "https://schemas.wp.org/trunk/block.json",
-    "apiVersion": 3,
-    "name": "jvb/fields",
-    "title": "JakeVan Fields",
-    "category": "jvb",
-    "icon": "ellipses",
-    "description": "Access data from your custom fields",
-    "keywords": [ "field", "custom", "jake" ],
-    "version": "0.9.0",
-    "textdomain": "jvb",
-    "supports": {
-        "html": false,
-        "align": ["wide", "full"]
-    },
-    "selectors": {
-        "root": ".jvb-f"
-    },
-    "styles": [],
-    "render": "file:./render.php",
-    "editorScript": "file:./index.js",
-    "editorStyle": "file:./index.css",
-    "style": "file:./style-index.css",
-    "viewScript": "file:./view.js"
-}
diff --git a/src/fields/edit.js b/src/fields/edit.js
deleted file mode 100644
index 6741773..0000000
--- a/src/fields/edit.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
-import { SelectControl, ToggleControl, PanelBody } from '@wordpress/components';
-
-/**
- * Styles
- */
-import './editor.scss';
-
-/**
- * Edit function for Summary Block
- */
-export default function Edit({ attributes, setAttributes }) {
-    const blockProps = useBlockProps();
-
-    return (
-        <div {...blockProps}>
-            <div className="jvb-summary-preview">
-                <h3>{__('Summary', 'jvb')}</h3>
-                <p className="jvb-list-preview-note">
-                    {__('This will inherit the current query to build the information from our custom meta on the front end.', 'jvb')}
-                </p>
-            </div>
-        </div>
-    );
-}
diff --git a/src/fields/editor.scss b/src/fields/editor.scss
deleted file mode 100644
index bdf5776..0000000
--- a/src/fields/editor.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- * Directory List Block Editor Styles
- */
-.jvb-summary-preview {
-    padding: 20px;
-    background-color: #f8f9fa;
-    border: 1px solid #e2e4e7;
-    border-radius: 4px;
-
-    h3 {
-        margin-top: 0;
-        padding-bottom: 10px;
-        border-bottom: 1px solid #ff0080;
-    }
-    &-note {
-        font-style: italic;
-        color: #555d66;
-        margin-bottom: 0;
-    }
-}
diff --git a/src/fields/index.js b/src/fields/index.js
deleted file mode 100644
index c477d23..0000000
--- a/src/fields/index.js
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Registers a new block provided a unique name and an object defining its behavior.
- *
- * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
- */
-import { registerBlockType } from '@wordpress/blocks';
-
-/**
- * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
- * All files containing `style` keyword are bundled together. The code used
- * gets applied both to the front of your site and to the editor.
- *
- * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
- */
-import './style.scss';
-
-/**
- * Internal dependencies
- */
-import Edit from './edit';
-import save from './save';
-import metadata from './block.json';
-
-/**
- * Every block starts by registering a new block type definition.
- *
- * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
- */
-registerBlockType( metadata.name, {
-    /**
-     * @see ./edit.js
-     */
-    edit: Edit,
-
-    /**
-     * @see ./save.js
-     */
-    save,
-} );
diff --git a/src/fields/index.php b/src/fields/index.php
deleted file mode 100644
index e69de29..0000000
--- a/src/fields/index.php
+++ /dev/null
diff --git a/src/fields/render.php b/src/fields/render.php
deleted file mode 100644
index b5645eb..0000000
--- a/src/fields/render.php
+++ /dev/null
@@ -1,320 +0,0 @@
-<?php
-
-use JVBase\managers\Cache;
-use JVBase\meta\Meta;
-use JVBase\meta\Render;
-use JVBase\registrar\Registrar;
-
-if (!defined('ABSPATH')) {
-    exit; // Exit if accessed directly
-}
-/**
- * Summary Block Render
- *
- * @package Edmonton_Ink
- */
-
-function jvbRenderSummaryBlock(array $attributes):string
-{
-
-    // Buffer output
-    if (is_tax()) {
-        switch (get_queried_object()->taxonomy) {
-            case BASE.'shop':
-                return jvbRenderShopSummary();
-            default:
-                return jvbRenderTermSummary();
-        }
-    } elseif (is_singular()) {
-        return jvbRenderArtistSummary();
-    }
-    return '';
-}
-
-function jvbRenderArtistSummary():string
-{
-    $current = get_queried_object();
-    $cache = Cache::for('artistSummary', WEEK_IN_SECONDS);
-    $key = $current->ID;
-    $cached = $cache->get($key);
-    if ($cached !== false) {
-        return $cached;
-    }
-
-    ob_start();
-    $meta = Meta::forPost($current->ID);
-    $artist = jvbContentFromUser((int)$current->post_author);
-
-	$registrar = Registrar::getInstance($current->post_type);
-	$sections = [];
-	if ($registrar) {
-		$sections = $registrar->getSections();
-	}
-
-
-
-
-//    $handler = JVB()->getContent(str_replace(BASE,'', $current->post_type));
-    ?>
-    <nav id="artist" class="on-this-page index">
-        <label>Jump to:
-            <button type="button" aria-label="Show Index" title="Show Index" class="toggle" aria-expanded="false">
-                <?= jvbIcon('plus-square')?>
-            </button>
-        </label>
-        <ul>
-            <li><a href="#top" title="Back to Top"><?=jvbIcon('caret-circle-up')?></a></li>
-            <li><a href="#about">About</a></li>
-            <li><a href="#styles">Styles</a></li>
-            <li><a href="#contact">Contact</a></li>
-            <li><a href="#work">Work</a></li>
-        </ul>
-    </nav>
-    <header id="top">
-        <h1><small><?=(!empty($artist['city'])) ? $artist['city']['name'] :'Edmonton'?>'s Best <?= (!empty($artist['type'])) ?
-                    $artist['type']['name']:'Tattoo Artists'?>:
-            </small><?=$artist['display_name']?></h1>
-        <div>
-			<?php if (!empty($artist['shop'])) : ?>
-            <ul class="term-list shop">
-                <li>
-                    <a href="<?=$artist['shop']['url']?>" title="Learn more about <?=$artist['shop']['name']?>">
-                        <?= strtolower($artist['shop']['name'])?>
-                    </a>
-                </li>
-            </ul>
-			<?php endif; ?>
-			<?php if (!empty($artist['city'])): ?>
-            <ul class="term-list city">
-                <li>
-                    <a href="<?=$artist['city']['url']?>" title="See who else is rocking out of <?=$artist['city']['name']?>">
-                        <?= strtolower($artist['city']['name'])?>
-                    </a>
-                </li>
-            </ul>
-			<?php endif; ?>
-            <?php $styles = $meta->get('top_styles');
-            if (!empty($styles)) {
-                ?>
-                <ul class="term-list style">
-                    <?php
-                    foreach ($styles as $style) {
-                        $term = get_term((int)$style, BASE.'style');
-                        if ($term && !is_wp_error($term)) {
-                            $link = get_term_link((int)$style, BASE.'style');
-                            ?>
-                            <li>
-                                <a href="<?=$link?>" title="Learn more about <?=html_entity_decode($term->name)?>">
-                                    <?=strtolower(html_entity_decode($term->name))?>
-                                </a>
-                            </li>
-                            <?php
-                        }
-                    }
-                    ?>
-                </ul>
-                <?php
-            }
-            ?>
-        </div>
-    </header>
-    <section>
-        <details class="bio-info">
-            <summary class="row x-btw">
-                <h2>About <?= ($artist['name'] !== '') ? $artist['name'] : strtok($artist['display_name'], ' ')?></h2>
-            </summary>
-            <div class="columns stack-small">
-                <div class="column">
-                    <?= Render::renderFrom($meta, 'image_portrait'); ?>
-                </div>
-                <div class="column">
-					<?= Render::renderFrom($meta, 'short_bio'); ?>
-                </div>
-            </div>
-            <div id="styles">
-                <h3>Works In</h3>
-                <?= jvbGetTheTerms('style', $current->ID) ?>
-            </div>
-            <div class="contact">
-                <h3>Contact:</h3>
-                <?php
-                echo jvbRenderContactInfo($current->ID, $meta);
-                echo jvbRenderLinks($current->ID, $meta);
-                ?>
-            </div>
-
-            <div id="about">
-				<?= Render::renderFrom($meta, 'bio')?>
-            </div>
-        </details>
-    </section>
-    <section id="contact" class="">
-        <h2>Contact <?=$artist['name']?></h2>
-        <?php
-        echo jvbRenderContactInfo($current->ID, 'post');
-        echo jvbRenderLinks($current->ID, 'post');
-        ?>
-    </section>
-    <?php
-    $finished = ob_get_clean();
-    $cache->set($key, $finished);
-    return $finished;
-}
-
-function jvbRenderShopSummary()
-{
-    $current = get_queried_object();
-
-    $cache = Cache::for('shop_bio', WEEK_IN_SECONDS)->connect('taxonomy');
-    $key = $current->term_id;
-    $cached = $cache->get($key);
-    if ($cached !== false) {
-        return $cached;
-    }
-
-    ob_start();
-
-    $meta = Meta::forTerm($current->term_id);
-	$fields = $meta->getAll(['average_rating', 'established', 'bio','location','hours','specialties','awards','reviews']);
-    ?>
-    <nav id="shop" class="on-this-page index">
-        <label>Jump to:
-            <button type="button" aria-label="Show Index" title="Show Index" class="toggle" aria-expanded="false">
-                <?= jvbIcon('plus-square')?>
-            </button>
-        </label>
-        <ul>
-            <li><a href="#top" title="Back to Top"><?=jvbIcon('caret-circle-up')?></a></li> <?php
-            if ($fields['rating'] !== 'none') {
-                ?>
-                <li><a href="#rating">Rating</a></li>
-                <?php
-            } elseif ($fields['opened'] !== '') {
-                ?>
-                <li><a href="#opened">Opened</a></li>
-                <?php
-            } elseif ($fields['location'] !== '') {
-                ?>
-                <li><a href="#location">Location</a></li>
-                <?php
-            } elseif ($fields['about'] !== '') {
-                ?>
-                <li><a href="#about">About</a></li>
-                <?php
-            } elseif ($fields['hours'] !== '') {
-                ?>
-                <li><a href="#hours">Hours</a></li>
-                <?php
-            } elseif ($fields['specialties'] !== '') {
-                ?>
-                <li><a href="#specialties">Specialties</a></li>
-                <?php
-            } elseif ($fields['awards'] !== '') {
-                ?>
-                <li><a href="#awards">Awards</a></li>
-                <?php
-            } elseif ($fields['reviews'] !== '') {
-                ?>
-                <li><a href="#reviews">Reviews</a></li>
-                <?php
-            }
-            ?>
-            <li><a href="#contact">Contact</a></li>
-            <li><a href="#artists">Artists</a></li>
-        </ul>
-    </nav>
-    <header id="top">
-        <div class="columns stack-small">
-            <div class="column">
-                <?=jvbFormatImage($meta->get('image'))?>
-            </div>
-            <div class="column">
-                <h1>
-                    <small><?= (get_term((int)$meta->get('city'), BASE.'city')) ?
-                            get_term((int)$meta->get('city'), BASE.'city')->name :
-                            'Edmonton'?>'s Best Tattoo Shops</small>
-                    <?=$current->name?>
-                </h1>
-                <?= jvbFormatRating($current->term_id, 'term') ?>
-				<?= Render::renderFrom($meta,   'slogan'); ?>
-            </div>
-        </div>
-    </header>
-    <section>
-        <details class="bio-info">
-            <summary class="row x-btw">
-                <h2>Learn More About <?=$current->name?></h2>
-            </summary>
-            <div class="map">
-				<?= Render::renderFrom($meta, 'location'); ?>
-            </div>
-            <div class="short-bio">
-				<?= Render::renderFrom($meta, 'short_bio'); ?>
-            </div>
-
-            <div class="contact">
-                <h3>Contact:</h3>
-                <?php
-                echo jvbRenderContactInfo($current->term_id, 'term');
-                echo jvbRenderLinks($current->term_id, 'term');
-                ?>
-            </div>
-
-            <div id="about">
-				<?= Render::renderFrom($meta, 'bio')?>
-            </div>
-        </details>
-    </section>
-    <section id="contact" class="">
-        <h2>Contact </h2>
-        <?php
-        echo jvbRenderContactInfo($current->term_id, 'term');
-        echo jvbRenderLinks($current->term_id, 'term');
-        ?>
-    </section>
-    <?= jvbRenderHours($current->term_id, 'term')?>
-
-
-    <?php
-    $finished = ob_get_clean();
-    $cache->set($key, $finished);
-    return $finished;
-}
-
-
-function jvbRenderTermSummary()
-{
-    $current = get_queried_object();
-    $cache = Cache::for('term_summary', WEEK_IN_SECONDS)->connect('taxonomy');
-    $key = $current->ID;
-    $cached = $cache->get($key);
-    if ($cached !== false) {
-        return $cached;
-    }
-
-    ob_start();
-	$tax = jvbNoBase($current->taxonomy);
-    switch ($tax) {
-        case 'style':
-            $title = 'Tattoo Artists';
-            break;
-        case 'theme':
-            $title = 'Tattoos';
-            break;
-        default:
-            $title = '';
-    }
-
-    $meta = Meta::forTerm($current->ID);
-    $fields = $meta->getAll();
-
-    ?>
-    <header id="top">
-        <h1><?= get_the_archive_title() ?></h1>
-    </header>
-
-    <?php
-    $finished = ob_get_clean();
-    $cache->set($key, $finished);
-    return $finished;
-}
diff --git a/src/fields/save.js b/src/fields/save.js
deleted file mode 100644
index 8169594..0000000
--- a/src/fields/save.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function save() {
-    return null; // Dynamic block rendered by PHP
-}
diff --git a/src/fields/style.scss b/src/fields/style.scss
deleted file mode 100644
index b182fe9..0000000
--- a/src/fields/style.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-details > div {
-	margin: 1rem 0;
-}
-
-main > header:not(:has(img)) {
-	margin-top: 3rem!important;
-}
-
-header a::before {
-	display: none!important;
-}
-
-header + details {
-	margin: 1.5rem auto 3rem!important;
-	max-width: var(--wide);
-}
-
-main {
-	padding-top: 0!important;
-}
diff --git a/src/fields/view.js b/src/fields/view.js
deleted file mode 100644
index 8b13789..0000000
--- a/src/fields/view.js
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/forms/block.json b/src/forms/block.json
index 7279b38..f790e24 100644
--- a/src/forms/block.json
+++ b/src/forms/block.json
@@ -41,7 +41,7 @@
     },
     "render": "file:./render.php",
     "editorScript": "file:./index.js",
-    "editorStyle": "file:./editor.scss",
+    "editorStyle": "file:./index.scss",
     "style": "file:./style-index.css",
     "viewScript": "file:./view.js"
 }
diff --git a/src/gmbreviews/render.php b/src/gmbreviews/render.php
index 779c1c4..b3d9bbc 100644
--- a/src/gmbreviews/render.php
+++ b/src/gmbreviews/render.php
@@ -1,208 +1 @@
 <?php
-/**
- * GMB Reviews Block - Render Template
- *
- * Displays recent Google My Business reviews with a link to leave a review
- */
-function jvbRenderGMBReviewsBlock(array $attributes): string
-{
-	$count = $attributes['count'] ?? 5;
-	$showRating = $attributes['showRating'] ?? true;
-	$showDate = $attributes['showDate'] ?? true;
-	$showReviewLink = $attributes['showReviewLink'] ?? true;
-	$showViewAllLink = $attributes['showViewAllLink'] ?? true;
-	$showStats = $attributes['showStats'] ?? true;
-	$minStars = $attributes['minStars'] ?? 4; // Only show 4+ star reviews
-	$inheritUser = $attributes['inheritUser']??null;
-	if ($inheritUser) {
-		global $post;
-		$inheritUser = $post->post_author;
-	}else {
-		$inheritUser = null;
-	}
-	try {
-		$gmb = JVB()->connect('gmb', $inheritUser);
-		if (!$gmb->isSetUp()) {
-			error_log('GMB Not set up for: '.(int)$inheritUser);
-			return '';
-		}
-		$gotReviews = $gmb->getReviews();
-		// Get all data
-		$allReviews = $gotReviews['reviews']??[];
-		$reviewUrl = $gmb->getReviewUrl();
-		$viewAllUrl = $gmb->getReviewsViewUrl();
-
-		$average = $gotReviews['averageRating']??null;
-		$total = $gotReviews['totalReviewCount']??null;
-
-		// Filter reviews by minimum stars
-		$reviews = [];
-		if (!empty($allReviews)) {
-			foreach ($allReviews as $review) {
-				$rating = $review['starRating'] ?? 0;
-				if ($rating >= $minStars) {
-					$reviews[] = $review;
-					if (count($reviews) >= $count) {
-						break; // Got enough reviews
-					}
-				}
-			}
-		}
-
-		if (empty($reviews) && empty($reviewUrl) && empty($stats)) {
-			error_log('No reviews to display...');
-			return '';
-		}
-
-		ob_start();
-		?>
-		<div class="gmb-reviews">
-			<div class="row x-mid">
-			<?php
-			if ($showStats && !empty($average) && !empty($total)) {
-				?>
-				<p>
-					<span class="stars" title="<?= $average ?> out of 5 stars">
-						<?php
-						$fullStars = floor($average);
-						$hasHalfStar = ($average - $fullStars) >= 0.5;
-
-						for ($i = 1; $i <= 5; $i++) {
-							if ($i <= $fullStars) {
-								echo jvbIcon('star', ['style' => 'fill']);
-							} elseif ($i == $fullStars + 1 && $hasHalfStar) {
-								echo jvbIcon('star-half', ['style'=> 'fill']);
-							} else {
-								echo  jvbIcon('star', ['style' => 'light']);
-							}
-						}
-						?>
-					</span>
-					<i>Average</i>
-				</p>
-				<?php
-				if ($total > 0) {
-					?>
-					<p><i>{ <?= number_format($total ) . ' ' . _n('Review', 'Reviews', $total, 'jvb')?> Total }</i></p>
-					<?php
-				}
-			?>
-			<?php
-			}
-			?>
-
-
-		</div>
-			<?php
-			if ($showReviewLink && !empty($reviewUrl)) {
-				?>
-				<a href="<?=esc_url($reviewUrl)?>"
-				   class="btn"
-				   target="_blank"
-				   rel="noopener noreferrer">
-					<?= jvbIcon('star', ['style' => 'fill']) ?>
-					Leave Your Review
-				</a>
-				<?php
-			}
-			?>
-
-		<ul>
-			<?php
-			foreach ($reviews as $review) {
-				$reviewer = $review['reviewer']['displayName'] ?? 'Anonymous';
-				$reviewer = strtok($reviewer, ' ');
-				$profilePhoto = $review['reviewer']['profilePhotoUrl'] ?? '';
-				$rating = $review['starRating'] ?? 0;
-				$rating = match($rating) {
-					'FIVE'	=> 5,
-					'FOUR'	=> 4,
-					'THREE'	=> 3,
-					'TWO'	=> 2,
-					'ONE'	=> 1,
-					default =>  $rating
-				};
-				$comment = $review['comment'] ?? '';
-				$date = $review['updateTime'] ?? '';
-				?>
-				<li>
-					<blockquote class="review">
-						<?php
-						echo jvbIcon('quotes',['style' => 'fill']);
-						// Review text
-						if (!empty($comment)) { ?>
-							<div class="content review">
-								<?= apply_filters('wpautop', $comment) ?>
-							</div>
-						<?php } ?>
-						<cite class="row left nowrap">
-							<?php if (!empty($profilePhoto)) { ?>
-								<img src="<?=esc_url($profilePhoto)?>"
-									 alt="<?=esc_attr($reviewer)?>"
-								'loading="lazy">
-							<?php } else { ?>
-								<div class="avatar">
-									<?= jvbIcon('user-circle')?>
-								</div>
-							<?php } ?>
-
-							<div class="row left wrap">
-								<?php if ($showRating && $rating > 0) { ?>
-									<div class="stars" title="<?= $rating ?> out of 5 stars">
-										<?php
-										for ($i = 1; $i <= 5; $i++) {
-											echo ($i <= $rating) ? jvbIcon('star', ['style' => 'fill']) : jvbIcon('star', ['style' => 'light']);
-										} ?>
-									</div>
-								<?php } ?>
-								<p><?= esc_html($reviewer)?></p>
-								<?php
-								// Date
-								if ($showDate && !empty($date)) {
-									$formatted_date = human_time_diff(strtotime($date), current_time('timestamp')) . ' ago';
-									?>
-									<time datetime="<?=esc_attr($date)?>">
-										<?= esc_html($formatted_date) ?>
-									</time>
-								<?php } ?>
-
-							</div>
-						</cite>
-					</blockquote>
-				</li>
-			<?php
-			}
-			?>
-		</ul>
-		<?php
-		// Footer with "See All Reviews" button
-		if ($showViewAllLink && !empty($viewAllUrl)) {
-			?>
-			<div class="footer">
-				<a href=" <?= esc_url($viewAllUrl) ?>"
-					class="btn"
-					target="_blank"
-					rel="noopener noreferrer">
-
-					<?php
-					if ($showStats ) {
-						echo 'See All ' . number_format($total) . ' Reviews';
-					} else {
-						echo ' See All Reviews';
-					}
-					?>
-					<?= jvbIcon('arrow-square-out') ?>
-				</a>
-			</div>
-		<?php
-		}
-		?>
-		</div>
-		<?php
-		return ob_get_clean();
-
-	} catch (\Exception $e) {
-		error_log('[GMB Reviews Block] Error: ' . $e->getMessage());
-		return '';
-	}
-}
diff --git a/src/summary/render.php b/src/summary/render.php
index c2c35fb..b5645eb 100644
--- a/src/summary/render.php
+++ b/src/summary/render.php
@@ -45,7 +45,7 @@
     $meta = Meta::forPost($current->ID);
     $artist = jvbContentFromUser((int)$current->post_author);
 
-	$registrar = Registrar::getInstance($current->post_type));
+	$registrar = Registrar::getInstance($current->post_type);
 	$sections = [];
 	if ($registrar) {
 		$sections = $registrar->getSections();
diff --git a/src/video/block.json b/src/video/block.json
index 29149bf..24561de 100644
--- a/src/video/block.json
+++ b/src/video/block.json
@@ -25,7 +25,7 @@
 			"default": ""
 		},
 		"description": {
-			"type": "rich-text",
+			"type": "string",
 			"default": ""
 		},
 		"posterId": {

--
Gitblit v1.10.0