domma-cms 1.7.2 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.8.0] - 2026-10-15
4
+
5
+ - **Built against domma-js 0.53.0** - see [its release notes](https://github.com/pinpointzero73/domma/releases/tag/v0.53.0).
6
+ - **Smooth typing throughout the CMS.** Apply the shared Domma JS caret glide to editable text fields in the admin, page and code editors, email compose, and public site forms, including dynamically rendered wizard steps and dialogs. Password fields, read-only controls and native picker controls keep their native behaviour.
7
+ - **One browser preference.** Page editor settings offers Automatic, Smooth and Native caret movement for all editing surfaces on the same site. Automatic follows reduced motion; Smooth explicitly enables animation. Selection, undo and composition remain native, with forced-colour mode retaining the native caret.
8
+ - **Less work while typing.** Reuse page and code editor gutter rows when the line count and folding structure stay the same, and coalesce scroll synchronisation into one animation frame.
9
+
3
10
  ## [1.7.2] - 2026-10-15
4
11
 
5
12
  - **Import from WordPress**, a free built-in Tool (Tools › Maintenance). Upload a WordPress export (Tools › Export in WordPress) and see a preview of every page, post, file and menu before anything changes. Pages keep their addresses; posts go to the Blog with categories, tags, featured images and approved comments; media comes from the old site or a zip of `wp-content/uploads`; old addresses, including `?p=123`, redirect to the new ones - and keep redirecting with the importer switched off; Yoast and Rank Math titles and descriptions carry over. Shortcodes and page-builder layouts with no equivalent are listed to rebuild. Run it again and it updates what it made, leaving pages you edited alone unless you choose Overwrite; an import stopped by a restart can be run again to finish it. Each run's report is kept (out of git). Downloads go only to the export's own site, never to private or the server's own addresses, and only on ports 80/443; SVG and anything that is HTML or script is never imported.
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * Domma Tools CSS v0.52.4
2
+ * Domma Tools CSS v0.53.0
3
3
  * Dynamic Object Manipulation & Modeling API
4
4
  * (c) 2026 Darryl Waterhouse & DCBW-IT
5
- * Built: 2026-10-15T17:20:44.118Z
6
- * Commit: a5dee96
5
+ * Built: 2026-10-15T22:14:11.256Z
6
+ * Commit: e15cc27
7
7
  */
8
8
 
9
9
  /*!
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * Domma Tools v0.52.4
2
+ * Domma Tools v0.53.0
3
3
  * Developer tools: Theme Roller & Page Roller
4
4
  * (c) 2026 Darryl Waterhouse & DCBW-IT
5
- * Built: 2026-10-15T17:20:31.284Z
6
- * Commit: a5dee96
5
+ * Built: 2026-10-15T22:13:57.322Z
6
+ * Commit: e15cc27
7
7
  *
8
8
  * Requires: domma.min.js
9
9
  */
package/admin/js/app.js CHANGED
@@ -1,4 +1,4 @@
1
- import{views as K}from"./views/index.js";import{withPluginChrome as O}from"./lib/plugin-chrome.js";import{api as c,getUser as x,isAuthenticated as m,logout as J,sendToLogin as Y}from"./api.js";import{claimDrafts as Q}from"./lib/draft-owner.js";import{isAuthScreen as b,loginHashFor as X}from"./lib/login-arrange.js";import{installHttpInterceptor as Z}from"./http-interceptor.js";import{installResizableSlideovers as tt}from"./lib/slideover-resizable.js";import{installActivityThrobber as et}from"./lib/activity-throbber.js";import{installUpdateNotice as it}from"./lib/update-notice.js";import{isPathAllowed as ot,redirectFor as at}from"./lib/admin-scope.js";import{deliverDesktop as st,desktopActive as nt,notificationSettings as rt}from"./lib/desktop-notify.js";import{avatarUrl as lt}from"./lib/avatar.js";import{installCalculator as ct}from"./lib/calculator.js";import{takeOverviewPass as mt,withDashboardStrip as _}from"./lib/dashboards-strip.js";import{installHotkeys as pt}from"./lib/hotkeys-ui.js";import{applyAdminBrand as V}from"./lib/admin-brand.js";import{installRouterCatchUp as dt}from"./lib/router-catch-up.js";$(()=>{Z(),ct(),it(),et(),tt(),(async()=>{const{applyAdminTheme:t,refreshAdminTheme:i}=await import("./lib/admin-theme.js");m()?await i(c,{init:!0}):t({dommaTheme:"charcoal-dark"},{init:!0})})();let p=null,h=null,l="/",w=!1,g=null;function D(t){if(N[t])return E.toast(`${N[t]} is switched off on this site.`,{type:"info"}),"/";if(t.split("?")[0]==="/my-dashboard")return"/dashboards";const i=y[t]||at(p,t);return i||((t.split("?")[0]||"/")==="/"&&l&&l!=="/"&&!mt()?y[l]||l:null)}const y={},N={};R.use(async(t,i,e)=>{if(b(t.path))return e();if(!m()){Y();return}const o=D(t.path);if(o){R.navigate(o);return}e()});async function f(){try{const t=await c.get("/auth/permissions");p=t.adminScope||null,h=t.adminBrand||null,V(h),l=t.adminHome||"/";const i=t.permissions||[];return w=ot(p,"/settings")&&i.some(e=>e==="settings"||e.startsWith("settings.")),g=i.some(e=>e==="notifications"||e.startsWith("notifications.")),i}catch{return p=null,l="/",h||V(null),w=!1,g=null,[]}}document.addEventListener("dm:admin-home-changed",()=>{f()});let P=null,A=!1;document.addEventListener("dm:sidebar-rebuild",()=>{if(P){A=!0;return}P=(async()=>{do{A=!1;try{await j(await f())}catch{}}while(A)})().finally(()=>{P=null})});async function j(t){const{renderAdminSidebar:i}=await import("./lib/sidebar-renderer.js");await i({mount:"#admin-sidebar",permissions:t,adminScope:p,brand:h})}M.subscribe("router:afterChange",({to:t})=>{b(t.path)&&(u&&(clearInterval(u),u=null),p=null,l="/",w=!1,g=null)});const W=[{path:"/",view:"dashboard",title:"Dashboard - Domma CMS"},{path:"/dashboards",view:"dashboards",title:"Dashboards - Domma CMS"},{path:"/my-dashboard",view:"dashboards",title:"Dashboards - Domma CMS"},{path:"/pages",view:"pages",title:"Pages - Domma CMS"},{path:"/pages/new",view:"pageEditor",title:"New Page - Domma CMS"},{path:"/pages/edit/*",view:"pageEditor",title:"Edit Page - Domma CMS"},{path:"/media",view:"media",title:"Media - Domma CMS"},{path:"/menus",view:"menus",title:"Menus - Domma CMS"},{path:"/context-menus",view:"contextMenus",title:"Context Menus - Domma CMS"},{path:"/context-menus/new",view:"contextMenuEditor",title:"New Context Menu - Domma CMS"},{path:"/context-menus/edit/:slug",view:"contextMenuEditor",title:"Edit Context Menu - Domma CMS"},{path:"/menus/new",view:"menuEditor",title:"New Menu - Domma CMS"},{path:"/menus/edit/:slug",view:"menuEditor",title:"Edit Menu - Domma CMS"},{path:"/menu-locations",view:"menuLocations",title:"Menu Locations - Domma CMS"},{path:"/navigation",view:"menusRedirect",title:"Menus - Domma CMS"},{path:"/layouts",view:"layouts",title:"Layouts - Domma CMS"},{path:"/settings",view:"settings",title:"Settings - Domma CMS"},{path:"/theme",view:"theme",title:"Theme - Domma CMS"},{path:"/users",view:"users",title:"Users - Domma CMS"},{path:"/users/new",view:"userEditor",title:"New User - Domma CMS"},{path:"/users/edit/:id",view:"userEditor",title:"Edit User - Domma CMS"},{path:"/plugins",view:"plugins",title:"Plugins - Domma CMS"},{path:"/plugins/code/:name",view:"pluginCode",title:"Plugin Code - Domma CMS"},{path:"/documentation",view:"documentation",title:"Usage - Domma CMS"},{path:"/tutorials",view:"tutorials",title:"Tutorials - Domma CMS"},{path:"/tutorials/crud",view:"tutorialCrud",title:"Building a CRUD App - Domma CMS"},{path:"/tutorials/plugin",view:"tutorialPlugin",title:"Writing a Tool - Domma CMS"},{path:"/tutorials/forms",view:"tutorialForms",title:"Form Follow-Up - Domma CMS"},{path:"/docs/components",view:"componentsReference",title:"Components Reference - Domma CMS"},{path:"/docs/components-howto",view:"componentsHowto",title:"Components How-To - Domma CMS"},{path:"/docs/components-walkthrough",view:"componentsWalkthrough",title:"Components Walkthrough - Domma CMS"},{path:"/docs/components-rules",view:"componentsRules",title:"Components Rules - Domma CMS"},{path:"/docs/usage/pages",view:"usagePages",title:"Pages - Usage - Domma CMS"},{path:"/docs/usage/media",view:"usageMedia",title:"Media - Usage - Domma CMS"},{path:"/docs/usage/navigation",view:"usageNavigation",title:"Navigation - Usage - Domma CMS"},{path:"/docs/usage/dconfig",view:"usageDconfig",title:"DConfig - Usage - Domma CMS"},{path:"/docs/usage/shortcodes",view:"usageShortcodes",title:"Shortcodes - Usage - Domma CMS"},{path:"/docs/usage/site-settings",view:"usageSiteSettings",title:"Site Settings - Usage - Domma CMS"},{path:"/docs/usage/plugins",view:"usagePlugins",title:"Plugins - Usage - Domma CMS"},{path:"/docs/usage/users-roles",view:"usageUsersRoles",title:"Users & Roles - Usage - Domma CMS"},{path:"/docs/usage/views",view:"usageViews",title:"Views - Usage - Domma CMS"},{path:"/docs/usage/actions",view:"usageActions",title:"Actions - Usage - Domma CMS"},{path:"/docs/usage/cta-shortcode",view:"usageCtaShortcode",title:"CTA Shortcode - Usage - Domma CMS"},{path:"/docs/usage/editions",view:"usageEditions",title:"Editions & Licences - Usage - Domma CMS"},{path:"/docs/usage/collections",view:"usageCollections",title:"Collections & Forms - Usage - Domma CMS"},{path:"/docs/usage/blocks",view:"usageBlocks",title:"Blocks - Usage - Domma CMS"},{path:"/docs/usage/tools",view:"usageTools",title:"Built-in Tools - Usage - Domma CMS"},{path:"/docs/usage/dashboard",view:"usageDashboard",title:"Dashboard - Usage - Domma CMS"},{path:"/docs/plugins",view:"pluginGuides",title:"Plugin Guides - Domma CMS"},{path:"/docs/plugins/*",view:"pluginGuide",title:"Plugin Guide - Domma CMS"},{path:"/docs/api/authentication",view:"apiRefAuthentication",title:"Authentication - API - Domma CMS"},{path:"/docs/api/pages",view:"apiRefPages",title:"Pages - API - Domma CMS"},{path:"/docs/api/settings",view:"apiRefSettings",title:"Settings - API - Domma CMS"},{path:"/docs/api/layouts",view:"apiRefLayouts",title:"Layouts - API - Domma CMS"},{path:"/docs/api/navigation",view:"apiRefNavigation",title:"Navigation - API - Domma CMS"},{path:"/docs/api/media",view:"apiRefMedia",title:"Media - API - Domma CMS"},{path:"/docs/api/users",view:"apiRefUsers",title:"Users - API - Domma CMS"},{path:"/docs/api/plugins",view:"apiRefPlugins",title:"Plugins - API - Domma CMS"},{path:"/docs/api/collections",view:"apiRefCollections",title:"Collections - API - Domma CMS"},{path:"/docs/api/views",view:"apiRefViews",title:"Views API - Domma CMS"},{path:"/docs/api/actions",view:"apiRefActions",title:"Actions API - Domma CMS"},{path:"/docs/api/forms",view:"apiRefForms",title:"Forms API - Domma CMS"},{path:"/docs/api/scaffold",view:"apiRefScaffold",title:"Scaffold API - Domma CMS"},{path:"/docs/api/external",view:"apiRefExternal",title:"External API & Tokens - Domma CMS"},{path:"/docs/api/content",view:"apiRefContent",title:"Content API - Domma CMS"},{path:"/docs/api/builder",view:"apiRefBuilder",title:"API Builder - Domma CMS"},{path:"/api-reference",view:"apiReference",title:"API Reference - Domma CMS"},{path:"/collections",view:"collections",title:"Collections - Domma CMS"},{path:"/collections/new",view:"collectionEditor",title:"New Collection - Domma CMS"},{path:"/collections/edit/:slug",view:"collectionEditor",title:"Edit Collection - Domma CMS"},{path:"/collections/:slug/entries",view:"collectionEntries",title:"Entries - Domma CMS"},{path:"/forms",view:"forms",title:"Forms - Domma CMS"},{path:"/forms/new",view:"formEditor",title:"New Form - Domma CMS"},{path:"/forms/edit/:slug",view:"formEditor",title:"Edit Form - Domma CMS"},{path:"/forms/:slug/submissions",view:"formSubmissions",title:"Submissions - Domma CMS"},{path:"/views",view:"viewsList",title:"Views - Domma CMS"},{path:"/views/new",view:"viewEditor",title:"New View - Domma CMS"},{path:"/views/edit/:slug",view:"viewEditor",title:"Edit View - Domma CMS"},{path:"/views/:slug/preview",view:"viewPreview",title:"View Preview - Domma CMS"},{path:"/actions",view:"actionsList",title:"Actions - Domma CMS"},{path:"/actions/new",view:"actionEditor",title:"New Action - Domma CMS"},{path:"/actions/edit/:slug",view:"actionEditor",title:"Edit Action - Domma CMS"},{path:"/pro/docs",view:"proDocs",title:"Pro Documentation - Domma CMS"},{path:"/blocks",view:"blocks",title:"Blocks - Domma CMS"},{path:"/blocks/new",view:"blockEditor",title:"New Block - Domma CMS"},{path:"/blocks/edit/:name",view:"blockEditor",title:"Edit Block - Domma CMS"},{path:"/components",view:"components",title:"Components - Domma CMS"},{path:"/components/new",view:"componentEditor",title:"New Component - Domma CMS"},{path:"/components/edit/:name",view:"componentEditor",title:"Edit Component - Domma CMS"},{path:"/my-profile",view:"myProfile",title:"My Profile - Domma CMS"},{path:"/roles",view:"roles",title:"Roles & Permissions - Domma CMS"},{path:"/roles/edit/:id",view:"roleEditor",title:"Edit Role - Domma CMS"},{path:"/effects",view:"effects",title:"Effects - Domma CMS"},{path:"/search",view:"search",title:"Search - Domma CMS"},{path:"/content-api",view:"contentApi",title:"Content API - Domma CMS"},{path:"/notes",view:"notes",title:"Notes - Domma CMS"},{path:"/todo",view:"todo",title:"Todo - Domma CMS"},{path:"/calculator",view:"calculator",title:"Calculator - Domma CMS"},{path:"/analytics",view:"analytics",title:"Analytics - Domma CMS"},{path:"/seo",view:"seo",title:"SEO - Domma CMS"},{path:"/seo/:tab",view:"seo",title:"SEO - Domma CMS"},{path:"/wordpress-import",view:"wordpressImport",title:"Import from WordPress - Domma CMS"},{path:"/contacts",view:"contacts",title:"Contacts - Domma CMS"},{path:"/calls/new",view:"callNew",title:"Call now - Domma CMS"},{path:"/system/notifications",view:"notifications",title:"Notifications - Domma CMS"},{path:"/api-tokens",view:"apiTokens",title:"API Tokens - Domma CMS"},{path:"/api-endpoints",view:"apiEndpoints",title:"API Builder - Domma CMS"},{path:"/api-endpoints/new",view:"apiEndpointEditor",title:"New API Endpoint - Domma CMS"},{path:"/api-endpoints/edit/:id",view:"apiEndpointEditor",title:"Edit API Endpoint - Domma CMS"},{path:"/projects",view:"projects",title:"Projects - Domma CMS"},{path:"/projects/new",view:"projects",title:"New Project - Domma CMS"},{path:"/projects/edit/:slug",view:"projects",title:"Edit Project - Domma CMS"},{path:"/projects/:slug/settings",view:"projectSettings",title:"Project settings - Domma CMS"},{path:"/projects/:slug/pages",view:"pages",title:"Project pages - Domma CMS"},{path:"/projects/:slug/collections",view:"collections",title:"Project collections - Domma CMS"},{path:"/projects/:slug/forms",view:"forms",title:"Project forms - Domma CMS"},{path:"/projects/:slug/actions",view:"actionsList",title:"Project actions - Domma CMS"},{path:"/projects/:slug/menus",view:"menus",title:"Project menus - Domma CMS"},{path:"/projects/:slug/blocks",view:"blocks",title:"Project blocks - Domma CMS"},{path:"/projects/:slug/components",view:"components",title:"Project components - Domma CMS"},{path:"/projects/:slug/views",view:"viewsList",title:"Project views - Domma CMS"},{path:"/projects/:slug/roles",view:"roles",title:"Project roles - Domma CMS"},{path:"/projects/:slug/users",view:"users",title:"Project users - Domma CMS"},{path:"/projects/:slug/apis",view:"apiEndpoints",title:"Project APIs - Domma CMS"},{path:"/projects/:slug",view:"projectDetail",title:"Project - Domma CMS"},{path:"/login",view:"login",title:"Sign in - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}},{path:"/reset-password",view:"login",title:"Reset Password - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}}];M.subscribe("router:afterChange",async({to:t,from:i})=>{if(!b(t.path)){if($("#admin-sidebar").show(),$("#admin-topbar").show(),b(i?.path)){$("#topbar-user-name").remove(),import("./lib/admin-theme.js").then(a=>a.refreshAdminTheme(c)),await U();const e=await f(),o=D(t.path);if(o&&R.navigate(o),j(e),rt.read().signInToasts)try{const a=await c.system.notifications.list().catch(()=>[]),n=(Array.isArray(a)?a:[]).filter(s=>s.unread&&["warning","critical"].includes(s.data?.severity)).slice(0,3);for(const s of n){const v=d(s.data?.title||""),T=d((s.data?.body||"").slice(0,120));E.toast(`${v} - ${T}`,{type:s.data?.severity==="critical"?"error":"warning",duration:0})}}catch{}}B()}}),M.subscribe("router:afterChange",()=>{setTimeout(()=>{$(".btn-primary, .btn-danger").length&&Domma.effects.reveal(".btn-primary, .btn-danger",{animation:"fade",stagger:40,duration:300})},50)});const H=["#field-project","#menu-project","#collection-project","#endpoint-project","#action-project","#view-project","#block-project","#component-project","#role-project",'[name="project"]','[name="ownedByProject"]'];function q(t){return/^\/(pages|menus|context-menus|collections|forms|actions|views|blocks|components|users|roles|api-endpoints)\/(new|edit\/)/.test(t)}M.subscribe("router:afterChange",({to:t})=>{const i=t?String(t.path).split("?")[0]:"";if(!t||!q(i))return;const o=new URLSearchParams(location.hash.split("?")[1]||"").get("project");if(!o||!/\/new$/.test(i))return;let a=0;const n=60,s=1500,v=()=>{a+=n;for(const T of H){const C=document.querySelector(T);if(!C)continue;if(Array.from(C.options||[]).find(z=>z.value===o)){C.value=o,C.dispatchEvent(new Event("change",{bubbles:!0}));return}}a<s&&setTimeout(v,n)};setTimeout(v,n)});const L="cms_card_states",k=S.get(L)||{};M.subscribe("router:afterChange",()=>{setTimeout(()=>{$("#view-container .card-collapsible").each(function(){const t=$(this).find(".card-header h2, .card-header h3").first().text().trim();t&&k[t]==="collapsed"&&$(this).addClass("card-collapsed")})},200)}),$("#view-container").on("click",".card-collapsible .card-header",function(t){if($(t.target).closest("button, a").length)return;const i=$(this).closest(".card");i.toggleClass("card-collapsed");const e=$(this).find("h2, h3").first().text().trim();e&&(k[e]=i.hasClass("card-collapsed")?"collapsed":"open",S.set(L,k))}),pt(),document.addEventListener("keydown",t=>{if(!(t.ctrlKey||t.metaKey)||t.key!=="s"||window.location.hash.startsWith("#/login")||window.location.hash.startsWith("#/reset-password"))return;const i=document.querySelector("#view-container .view-header button.btn-primary");i&&(t.preventDefault(),i.click())});const r={...K},G={notes:{displayName:"Notes",icon:"edit-3"},todo:{displayName:"Todo",icon:"check-square"},calculator:{displayName:"Calculator",icon:"calculator"},analytics:{displayName:"Analytics",icon:"chart-bar"},seo:{displayName:"SEO",icon:"search"},wordpressImport:{displayName:"Import from WordPress",icon:"download"},contacts:{displayName:"Contacts",icon:"users"},projects:{displayName:"Projects",icon:"folder"},pages:{displayName:"Pages",icon:"file-text"},media:{displayName:"Media",icon:"image"},menus:{displayName:"Site menus",icon:"menu"},contextMenus:{displayName:"Context Menus",icon:"menu"},theme:{displayName:"Theme",icon:"droplet"},collections:{displayName:"Collections",icon:"database"},forms:{displayName:"Forms",icon:"layout"},viewsList:{displayName:"Views",icon:"eye"},actionsList:{displayName:"Actions",icon:"zap"},apiEndpoints:{displayName:"API Builder",icon:"code"},blocks:{displayName:"Blocks",icon:"box"},components:{displayName:"Components",icon:"component"},notifications:{displayName:"Notifications",icon:"bell"},roles:{displayName:"Roles",icon:"shield"},users:{displayName:"Users",icon:"users"},settings:{displayName:"Site Settings",icon:"settings"},effects:{displayName:"Effects",icon:"sparkles"},layouts:{displayName:"Layouts",icon:"layout"},plugins:{displayName:"Marketplace",icon:"store"},myProfile:{displayName:"My Profile",icon:"user"},apiTokens:{displayName:"API Tokens",icon:"key"},search:{displayName:"Search",icon:"search"},contentApi:{displayName:"Content API",icon:"file-text"},dashboard:{displayName:"Dashboard",icon:"home"},dashboards:{displayName:"Dashboards",icon:"home"},pageEditor:{displayName:"Pages",section:"Edit",icon:"file-text"},menuEditor:{displayName:"Site menus",section:"Edit",icon:"menu"},menuLocations:{displayName:"Site menus",section:"Locations",icon:"map-pin"},contextMenuEditor:{displayName:"Context Menus",section:"Edit",icon:"menu"},collectionEditor:{displayName:"Collections",section:"Edit",icon:"database"},collectionEntries:{displayName:"Collections",section:"Entries",icon:"database"},formEditor:{displayName:"Forms",section:"Edit",icon:"layout"},formSubmissions:{displayName:"Forms",section:"Submissions",icon:"inbox"},viewEditor:{displayName:"Views",section:"Edit",icon:"eye"},viewPreview:{displayName:"Views",section:"Preview",icon:"eye"},actionEditor:{displayName:"Actions",section:"Edit",icon:"zap"},apiEndpointEditor:{displayName:"API Builder",section:"Edit",icon:"code"},blockEditor:{displayName:"Blocks",section:"Edit",icon:"box"},componentEditor:{displayName:"Components",section:"Edit",icon:"component"},roleEditor:{displayName:"Roles",section:"Edit",icon:"shield"},userEditor:{displayName:"Users",section:"Edit",icon:"users"},projectDetail:{displayName:"Projects",section:"Overview",icon:"folder"},projectSettings:{displayName:"Projects",section:"Settings",icon:"folder"},pluginCode:{displayName:"Marketplace",section:"Code",icon:"code"}};for(const[t,i]of Object.entries(G))r[t]&&(r[t]=O(r[t],{plugin:t,licence:"Built in",...i}));r.dashboard=_(r.dashboard);const I=[...W];async function U(){if(m())try{const t=await c.plugins.adminConfig(),i=new Set(I.map(e=>e.path));for(const e of t.routes||[])i.has(e.path)||I.push(e);for(const[e,o]of Object.entries(t.views||{}))try{const a=await import(`/plugins/${o.entry}`);r[e]=O(a[o.exportName],(t.meta||{})[e])}catch{}r.dashboard=_(r.dashboard);for(const[e,{route:o}]of Object.entries(t.takeovers||{}))o&&(y[`/${e}`]=o);for(const[e,{enabled:o,displayName:a}]of Object.entries(t.tools||{}))o===!1&&(N[`/${e}`]=a);for(const{id:e,href:o}of t.css||[])if(!document.getElementById(e)){const a=document.createElement("link");a.id=e,a.rel="stylesheet",a.href=o,document.head.appendChild(a)}}catch{}}function B(){const t=x();if(!t||$("#topbar-user-name").length)return;const e={"super-admin":"Super Admin",admin:"Admin",user:"User"}[t.role]||t.role,o=lt(t);$("#topbar-user").html(`
1
+ import{installSmoothCarets as K}from"./lib/smooth-caret.js";import{views as J}from"./views/index.js";import{withPluginChrome as O}from"./lib/plugin-chrome.js";import{api as c,getUser as x,isAuthenticated as m,logout as Y,sendToLogin as Q}from"./api.js";import{claimDrafts as X}from"./lib/draft-owner.js";import{isAuthScreen as b,loginHashFor as Z}from"./lib/login-arrange.js";import{installHttpInterceptor as tt}from"./http-interceptor.js";import{installResizableSlideovers as et}from"./lib/slideover-resizable.js";import{installActivityThrobber as it}from"./lib/activity-throbber.js";import{installUpdateNotice as ot}from"./lib/update-notice.js";import{isPathAllowed as at,redirectFor as st}from"./lib/admin-scope.js";import{deliverDesktop as nt,desktopActive as rt,notificationSettings as lt}from"./lib/desktop-notify.js";import{avatarUrl as ct}from"./lib/avatar.js";import{installCalculator as mt}from"./lib/calculator.js";import{takeOverviewPass as pt,withDashboardStrip as _}from"./lib/dashboards-strip.js";import{installHotkeys as dt}from"./lib/hotkeys-ui.js";import{applyAdminBrand as V}from"./lib/admin-brand.js";import{installRouterCatchUp as ut}from"./lib/router-catch-up.js";$(()=>{K(document),tt(),mt(),ot(),it(),et(),(async()=>{const{applyAdminTheme:t,refreshAdminTheme:i}=await import("./lib/admin-theme.js");m()?await i(c,{init:!0}):t({dommaTheme:"charcoal-dark"},{init:!0})})();let p=null,h=null,l="/",w=!1,g=null;function D(t){if(N[t])return E.toast(`${N[t]} is switched off on this site.`,{type:"info"}),"/";if(t.split("?")[0]==="/my-dashboard")return"/dashboards";const i=y[t]||st(p,t);return i||((t.split("?")[0]||"/")==="/"&&l&&l!=="/"&&!pt()?y[l]||l:null)}const y={},N={};R.use(async(t,i,e)=>{if(b(t.path))return e();if(!m()){Q();return}const o=D(t.path);if(o){R.navigate(o);return}e()});async function f(){try{const t=await c.get("/auth/permissions");p=t.adminScope||null,h=t.adminBrand||null,V(h),l=t.adminHome||"/";const i=t.permissions||[];return w=at(p,"/settings")&&i.some(e=>e==="settings"||e.startsWith("settings.")),g=i.some(e=>e==="notifications"||e.startsWith("notifications.")),i}catch{return p=null,l="/",h||V(null),w=!1,g=null,[]}}document.addEventListener("dm:admin-home-changed",()=>{f()});let P=null,A=!1;document.addEventListener("dm:sidebar-rebuild",()=>{if(P){A=!0;return}P=(async()=>{do{A=!1;try{await j(await f())}catch{}}while(A)})().finally(()=>{P=null})});async function j(t){const{renderAdminSidebar:i}=await import("./lib/sidebar-renderer.js");await i({mount:"#admin-sidebar",permissions:t,adminScope:p,brand:h})}M.subscribe("router:afterChange",({to:t})=>{b(t.path)&&(u&&(clearInterval(u),u=null),p=null,l="/",w=!1,g=null)});const W=[{path:"/",view:"dashboard",title:"Dashboard - Domma CMS"},{path:"/dashboards",view:"dashboards",title:"Dashboards - Domma CMS"},{path:"/my-dashboard",view:"dashboards",title:"Dashboards - Domma CMS"},{path:"/pages",view:"pages",title:"Pages - Domma CMS"},{path:"/pages/new",view:"pageEditor",title:"New Page - Domma CMS"},{path:"/pages/edit/*",view:"pageEditor",title:"Edit Page - Domma CMS"},{path:"/media",view:"media",title:"Media - Domma CMS"},{path:"/menus",view:"menus",title:"Menus - Domma CMS"},{path:"/context-menus",view:"contextMenus",title:"Context Menus - Domma CMS"},{path:"/context-menus/new",view:"contextMenuEditor",title:"New Context Menu - Domma CMS"},{path:"/context-menus/edit/:slug",view:"contextMenuEditor",title:"Edit Context Menu - Domma CMS"},{path:"/menus/new",view:"menuEditor",title:"New Menu - Domma CMS"},{path:"/menus/edit/:slug",view:"menuEditor",title:"Edit Menu - Domma CMS"},{path:"/menu-locations",view:"menuLocations",title:"Menu Locations - Domma CMS"},{path:"/navigation",view:"menusRedirect",title:"Menus - Domma CMS"},{path:"/layouts",view:"layouts",title:"Layouts - Domma CMS"},{path:"/settings",view:"settings",title:"Settings - Domma CMS"},{path:"/theme",view:"theme",title:"Theme - Domma CMS"},{path:"/users",view:"users",title:"Users - Domma CMS"},{path:"/users/new",view:"userEditor",title:"New User - Domma CMS"},{path:"/users/edit/:id",view:"userEditor",title:"Edit User - Domma CMS"},{path:"/plugins",view:"plugins",title:"Plugins - Domma CMS"},{path:"/plugins/code/:name",view:"pluginCode",title:"Plugin Code - Domma CMS"},{path:"/documentation",view:"documentation",title:"Usage - Domma CMS"},{path:"/tutorials",view:"tutorials",title:"Tutorials - Domma CMS"},{path:"/tutorials/crud",view:"tutorialCrud",title:"Building a CRUD App - Domma CMS"},{path:"/tutorials/plugin",view:"tutorialPlugin",title:"Writing a Tool - Domma CMS"},{path:"/tutorials/forms",view:"tutorialForms",title:"Form Follow-Up - Domma CMS"},{path:"/docs/components",view:"componentsReference",title:"Components Reference - Domma CMS"},{path:"/docs/components-howto",view:"componentsHowto",title:"Components How-To - Domma CMS"},{path:"/docs/components-walkthrough",view:"componentsWalkthrough",title:"Components Walkthrough - Domma CMS"},{path:"/docs/components-rules",view:"componentsRules",title:"Components Rules - Domma CMS"},{path:"/docs/usage/pages",view:"usagePages",title:"Pages - Usage - Domma CMS"},{path:"/docs/usage/media",view:"usageMedia",title:"Media - Usage - Domma CMS"},{path:"/docs/usage/navigation",view:"usageNavigation",title:"Navigation - Usage - Domma CMS"},{path:"/docs/usage/dconfig",view:"usageDconfig",title:"DConfig - Usage - Domma CMS"},{path:"/docs/usage/shortcodes",view:"usageShortcodes",title:"Shortcodes - Usage - Domma CMS"},{path:"/docs/usage/site-settings",view:"usageSiteSettings",title:"Site Settings - Usage - Domma CMS"},{path:"/docs/usage/plugins",view:"usagePlugins",title:"Plugins - Usage - Domma CMS"},{path:"/docs/usage/users-roles",view:"usageUsersRoles",title:"Users & Roles - Usage - Domma CMS"},{path:"/docs/usage/views",view:"usageViews",title:"Views - Usage - Domma CMS"},{path:"/docs/usage/actions",view:"usageActions",title:"Actions - Usage - Domma CMS"},{path:"/docs/usage/cta-shortcode",view:"usageCtaShortcode",title:"CTA Shortcode - Usage - Domma CMS"},{path:"/docs/usage/editions",view:"usageEditions",title:"Editions & Licences - Usage - Domma CMS"},{path:"/docs/usage/collections",view:"usageCollections",title:"Collections & Forms - Usage - Domma CMS"},{path:"/docs/usage/blocks",view:"usageBlocks",title:"Blocks - Usage - Domma CMS"},{path:"/docs/usage/tools",view:"usageTools",title:"Built-in Tools - Usage - Domma CMS"},{path:"/docs/usage/dashboard",view:"usageDashboard",title:"Dashboard - Usage - Domma CMS"},{path:"/docs/plugins",view:"pluginGuides",title:"Plugin Guides - Domma CMS"},{path:"/docs/plugins/*",view:"pluginGuide",title:"Plugin Guide - Domma CMS"},{path:"/docs/api/authentication",view:"apiRefAuthentication",title:"Authentication - API - Domma CMS"},{path:"/docs/api/pages",view:"apiRefPages",title:"Pages - API - Domma CMS"},{path:"/docs/api/settings",view:"apiRefSettings",title:"Settings - API - Domma CMS"},{path:"/docs/api/layouts",view:"apiRefLayouts",title:"Layouts - API - Domma CMS"},{path:"/docs/api/navigation",view:"apiRefNavigation",title:"Navigation - API - Domma CMS"},{path:"/docs/api/media",view:"apiRefMedia",title:"Media - API - Domma CMS"},{path:"/docs/api/users",view:"apiRefUsers",title:"Users - API - Domma CMS"},{path:"/docs/api/plugins",view:"apiRefPlugins",title:"Plugins - API - Domma CMS"},{path:"/docs/api/collections",view:"apiRefCollections",title:"Collections - API - Domma CMS"},{path:"/docs/api/views",view:"apiRefViews",title:"Views API - Domma CMS"},{path:"/docs/api/actions",view:"apiRefActions",title:"Actions API - Domma CMS"},{path:"/docs/api/forms",view:"apiRefForms",title:"Forms API - Domma CMS"},{path:"/docs/api/scaffold",view:"apiRefScaffold",title:"Scaffold API - Domma CMS"},{path:"/docs/api/external",view:"apiRefExternal",title:"External API & Tokens - Domma CMS"},{path:"/docs/api/content",view:"apiRefContent",title:"Content API - Domma CMS"},{path:"/docs/api/builder",view:"apiRefBuilder",title:"API Builder - Domma CMS"},{path:"/api-reference",view:"apiReference",title:"API Reference - Domma CMS"},{path:"/collections",view:"collections",title:"Collections - Domma CMS"},{path:"/collections/new",view:"collectionEditor",title:"New Collection - Domma CMS"},{path:"/collections/edit/:slug",view:"collectionEditor",title:"Edit Collection - Domma CMS"},{path:"/collections/:slug/entries",view:"collectionEntries",title:"Entries - Domma CMS"},{path:"/forms",view:"forms",title:"Forms - Domma CMS"},{path:"/forms/new",view:"formEditor",title:"New Form - Domma CMS"},{path:"/forms/edit/:slug",view:"formEditor",title:"Edit Form - Domma CMS"},{path:"/forms/:slug/submissions",view:"formSubmissions",title:"Submissions - Domma CMS"},{path:"/views",view:"viewsList",title:"Views - Domma CMS"},{path:"/views/new",view:"viewEditor",title:"New View - Domma CMS"},{path:"/views/edit/:slug",view:"viewEditor",title:"Edit View - Domma CMS"},{path:"/views/:slug/preview",view:"viewPreview",title:"View Preview - Domma CMS"},{path:"/actions",view:"actionsList",title:"Actions - Domma CMS"},{path:"/actions/new",view:"actionEditor",title:"New Action - Domma CMS"},{path:"/actions/edit/:slug",view:"actionEditor",title:"Edit Action - Domma CMS"},{path:"/pro/docs",view:"proDocs",title:"Pro Documentation - Domma CMS"},{path:"/blocks",view:"blocks",title:"Blocks - Domma CMS"},{path:"/blocks/new",view:"blockEditor",title:"New Block - Domma CMS"},{path:"/blocks/edit/:name",view:"blockEditor",title:"Edit Block - Domma CMS"},{path:"/components",view:"components",title:"Components - Domma CMS"},{path:"/components/new",view:"componentEditor",title:"New Component - Domma CMS"},{path:"/components/edit/:name",view:"componentEditor",title:"Edit Component - Domma CMS"},{path:"/my-profile",view:"myProfile",title:"My Profile - Domma CMS"},{path:"/roles",view:"roles",title:"Roles & Permissions - Domma CMS"},{path:"/roles/edit/:id",view:"roleEditor",title:"Edit Role - Domma CMS"},{path:"/effects",view:"effects",title:"Effects - Domma CMS"},{path:"/search",view:"search",title:"Search - Domma CMS"},{path:"/content-api",view:"contentApi",title:"Content API - Domma CMS"},{path:"/notes",view:"notes",title:"Notes - Domma CMS"},{path:"/todo",view:"todo",title:"Todo - Domma CMS"},{path:"/calculator",view:"calculator",title:"Calculator - Domma CMS"},{path:"/analytics",view:"analytics",title:"Analytics - Domma CMS"},{path:"/seo",view:"seo",title:"SEO - Domma CMS"},{path:"/seo/:tab",view:"seo",title:"SEO - Domma CMS"},{path:"/wordpress-import",view:"wordpressImport",title:"Import from WordPress - Domma CMS"},{path:"/contacts",view:"contacts",title:"Contacts - Domma CMS"},{path:"/calls/new",view:"callNew",title:"Call now - Domma CMS"},{path:"/system/notifications",view:"notifications",title:"Notifications - Domma CMS"},{path:"/api-tokens",view:"apiTokens",title:"API Tokens - Domma CMS"},{path:"/api-endpoints",view:"apiEndpoints",title:"API Builder - Domma CMS"},{path:"/api-endpoints/new",view:"apiEndpointEditor",title:"New API Endpoint - Domma CMS"},{path:"/api-endpoints/edit/:id",view:"apiEndpointEditor",title:"Edit API Endpoint - Domma CMS"},{path:"/projects",view:"projects",title:"Projects - Domma CMS"},{path:"/projects/new",view:"projects",title:"New Project - Domma CMS"},{path:"/projects/edit/:slug",view:"projects",title:"Edit Project - Domma CMS"},{path:"/projects/:slug/settings",view:"projectSettings",title:"Project settings - Domma CMS"},{path:"/projects/:slug/pages",view:"pages",title:"Project pages - Domma CMS"},{path:"/projects/:slug/collections",view:"collections",title:"Project collections - Domma CMS"},{path:"/projects/:slug/forms",view:"forms",title:"Project forms - Domma CMS"},{path:"/projects/:slug/actions",view:"actionsList",title:"Project actions - Domma CMS"},{path:"/projects/:slug/menus",view:"menus",title:"Project menus - Domma CMS"},{path:"/projects/:slug/blocks",view:"blocks",title:"Project blocks - Domma CMS"},{path:"/projects/:slug/components",view:"components",title:"Project components - Domma CMS"},{path:"/projects/:slug/views",view:"viewsList",title:"Project views - Domma CMS"},{path:"/projects/:slug/roles",view:"roles",title:"Project roles - Domma CMS"},{path:"/projects/:slug/users",view:"users",title:"Project users - Domma CMS"},{path:"/projects/:slug/apis",view:"apiEndpoints",title:"Project APIs - Domma CMS"},{path:"/projects/:slug",view:"projectDetail",title:"Project - Domma CMS"},{path:"/login",view:"login",title:"Sign in - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}},{path:"/reset-password",view:"login",title:"Reset Password - Domma CMS",onEnter:()=>{$("#admin-sidebar").hide(),$("#admin-topbar").hide()}}];M.subscribe("router:afterChange",async({to:t,from:i})=>{if(!b(t.path)){if($("#admin-sidebar").show(),$("#admin-topbar").show(),b(i?.path)){$("#topbar-user-name").remove(),import("./lib/admin-theme.js").then(a=>a.refreshAdminTheme(c)),await U();const e=await f(),o=D(t.path);if(o&&R.navigate(o),j(e),lt.read().signInToasts)try{const a=await c.system.notifications.list().catch(()=>[]),n=(Array.isArray(a)?a:[]).filter(s=>s.unread&&["warning","critical"].includes(s.data?.severity)).slice(0,3);for(const s of n){const v=d(s.data?.title||""),T=d((s.data?.body||"").slice(0,120));E.toast(`${v} - ${T}`,{type:s.data?.severity==="critical"?"error":"warning",duration:0})}}catch{}}B()}}),M.subscribe("router:afterChange",()=>{setTimeout(()=>{$(".btn-primary, .btn-danger").length&&Domma.effects.reveal(".btn-primary, .btn-danger",{animation:"fade",stagger:40,duration:300})},50)});const H=["#field-project","#menu-project","#collection-project","#endpoint-project","#action-project","#view-project","#block-project","#component-project","#role-project",'[name="project"]','[name="ownedByProject"]'];function q(t){return/^\/(pages|menus|context-menus|collections|forms|actions|views|blocks|components|users|roles|api-endpoints)\/(new|edit\/)/.test(t)}M.subscribe("router:afterChange",({to:t})=>{const i=t?String(t.path).split("?")[0]:"";if(!t||!q(i))return;const o=new URLSearchParams(location.hash.split("?")[1]||"").get("project");if(!o||!/\/new$/.test(i))return;let a=0;const n=60,s=1500,v=()=>{a+=n;for(const T of H){const C=document.querySelector(T);if(!C)continue;if(Array.from(C.options||[]).find(z=>z.value===o)){C.value=o,C.dispatchEvent(new Event("change",{bubbles:!0}));return}}a<s&&setTimeout(v,n)};setTimeout(v,n)});const L="cms_card_states",k=S.get(L)||{};M.subscribe("router:afterChange",()=>{setTimeout(()=>{$("#view-container .card-collapsible").each(function(){const t=$(this).find(".card-header h2, .card-header h3").first().text().trim();t&&k[t]==="collapsed"&&$(this).addClass("card-collapsed")})},200)}),$("#view-container").on("click",".card-collapsible .card-header",function(t){if($(t.target).closest("button, a").length)return;const i=$(this).closest(".card");i.toggleClass("card-collapsed");const e=$(this).find("h2, h3").first().text().trim();e&&(k[e]=i.hasClass("card-collapsed")?"collapsed":"open",S.set(L,k))}),dt(),document.addEventListener("keydown",t=>{if(!(t.ctrlKey||t.metaKey)||t.key!=="s"||window.location.hash.startsWith("#/login")||window.location.hash.startsWith("#/reset-password"))return;const i=document.querySelector("#view-container .view-header button.btn-primary");i&&(t.preventDefault(),i.click())});const r={...J},G={notes:{displayName:"Notes",icon:"edit-3"},todo:{displayName:"Todo",icon:"check-square"},calculator:{displayName:"Calculator",icon:"calculator"},analytics:{displayName:"Analytics",icon:"chart-bar"},seo:{displayName:"SEO",icon:"search"},wordpressImport:{displayName:"Import from WordPress",icon:"download"},contacts:{displayName:"Contacts",icon:"users"},projects:{displayName:"Projects",icon:"folder"},pages:{displayName:"Pages",icon:"file-text"},media:{displayName:"Media",icon:"image"},menus:{displayName:"Site menus",icon:"menu"},contextMenus:{displayName:"Context Menus",icon:"menu"},theme:{displayName:"Theme",icon:"droplet"},collections:{displayName:"Collections",icon:"database"},forms:{displayName:"Forms",icon:"layout"},viewsList:{displayName:"Views",icon:"eye"},actionsList:{displayName:"Actions",icon:"zap"},apiEndpoints:{displayName:"API Builder",icon:"code"},blocks:{displayName:"Blocks",icon:"box"},components:{displayName:"Components",icon:"component"},notifications:{displayName:"Notifications",icon:"bell"},roles:{displayName:"Roles",icon:"shield"},users:{displayName:"Users",icon:"users"},settings:{displayName:"Site Settings",icon:"settings"},effects:{displayName:"Effects",icon:"sparkles"},layouts:{displayName:"Layouts",icon:"layout"},plugins:{displayName:"Marketplace",icon:"store"},myProfile:{displayName:"My Profile",icon:"user"},apiTokens:{displayName:"API Tokens",icon:"key"},search:{displayName:"Search",icon:"search"},contentApi:{displayName:"Content API",icon:"file-text"},dashboard:{displayName:"Dashboard",icon:"home"},dashboards:{displayName:"Dashboards",icon:"home"},pageEditor:{displayName:"Pages",section:"Edit",icon:"file-text"},menuEditor:{displayName:"Site menus",section:"Edit",icon:"menu"},menuLocations:{displayName:"Site menus",section:"Locations",icon:"map-pin"},contextMenuEditor:{displayName:"Context Menus",section:"Edit",icon:"menu"},collectionEditor:{displayName:"Collections",section:"Edit",icon:"database"},collectionEntries:{displayName:"Collections",section:"Entries",icon:"database"},formEditor:{displayName:"Forms",section:"Edit",icon:"layout"},formSubmissions:{displayName:"Forms",section:"Submissions",icon:"inbox"},viewEditor:{displayName:"Views",section:"Edit",icon:"eye"},viewPreview:{displayName:"Views",section:"Preview",icon:"eye"},actionEditor:{displayName:"Actions",section:"Edit",icon:"zap"},apiEndpointEditor:{displayName:"API Builder",section:"Edit",icon:"code"},blockEditor:{displayName:"Blocks",section:"Edit",icon:"box"},componentEditor:{displayName:"Components",section:"Edit",icon:"component"},roleEditor:{displayName:"Roles",section:"Edit",icon:"shield"},userEditor:{displayName:"Users",section:"Edit",icon:"users"},projectDetail:{displayName:"Projects",section:"Overview",icon:"folder"},projectSettings:{displayName:"Projects",section:"Settings",icon:"folder"},pluginCode:{displayName:"Marketplace",section:"Code",icon:"code"}};for(const[t,i]of Object.entries(G))r[t]&&(r[t]=O(r[t],{plugin:t,licence:"Built in",...i}));r.dashboard=_(r.dashboard);const I=[...W];async function U(){if(m())try{const t=await c.plugins.adminConfig(),i=new Set(I.map(e=>e.path));for(const e of t.routes||[])i.has(e.path)||I.push(e);for(const[e,o]of Object.entries(t.views||{}))try{const a=await import(`/plugins/${o.entry}`);r[e]=O(a[o.exportName],(t.meta||{})[e])}catch{}r.dashboard=_(r.dashboard);for(const[e,{route:o}]of Object.entries(t.takeovers||{}))o&&(y[`/${e}`]=o);for(const[e,{enabled:o,displayName:a}]of Object.entries(t.tools||{}))o===!1&&(N[`/${e}`]=a);for(const{id:e,href:o}of t.css||[])if(!document.getElementById(e)){const a=document.createElement("link");a.id=e,a.rel="stylesheet",a.href=o,document.head.appendChild(a)}}catch{}}function B(){const t=x();if(!t||$("#topbar-user-name").length)return;const e={"super-admin":"Super Admin",admin:"Admin",user:"User"}[t.role]||t.role,o=ct(t);$("#topbar-user").html(`
2
2
  ${o?`<img id="topbar-avatar" class="topbar-avatar" src="${d(o)}" alt="">`:""}
3
3
  <span id="topbar-user-name" class="topbar-user-name">${d(t.name)}</span>
4
4
  <span class="topbar-role-badge topbar-role-badge--${d(t.role)}">${e}</span>
@@ -20,4 +20,4 @@ import{views as K}from"./views/index.js";import{withPluginChrome as O}from"./lib
20
20
  <span data-icon="log-out"></span>
21
21
  <span>Sign out</span>
22
22
  </a>
23
- `);const a=$("#topbar-bell").get(0);a&&(a.hidden=!0);const n=$("#topbar-settings").get(0);n&&(n.hidden=!w),$("#topbar-logout-btn").on("click",s=>{s.preventDefault(),J()}),Domma.icons.scan("#admin-topbar"),E.tooltip("#topbar-actions [data-tooltip]",{placement:"bottom"}),F(),u||(u=setInterval(F,6e4))}function d(t){return String(t).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}let u=null;async function F(){if(!(!m()||g===!1))try{const{count:t}=await c.system.notifications.unreadCount();$("#topbar-bell").removeAttr("hidden");const i=$("#topbar-bell-badge");t>0?i.text(t>99?"99+":String(t)).removeAttr("hidden"):i.attr("hidden","").text(""),t>0&&nt()&&st(await c.system.notifications.list().catch(()=>[]))}catch{}}(async()=>{if(!m()&&!window.location.hash.startsWith("#/reset-password"))window.location.hash.startsWith("#/login")||(window.location.hash=X(window.location.hash));else if(Q(x()?.id),await U(),x()){const a=await f(),n=(window.location.hash||"#/").slice(1)||"/",s=D(n);s&&(window.location.hash=`#${s}`),await j(a),B()}const t=R._extractParams.bind(R);R._extractParams=function(o,a){const n=a.indexOf("?");if(n!==-1&&(a=a.slice(0,n)),o.endsWith("/*")){const s=o.slice(0,-2);return a.startsWith(s+"/")?{}:null}return t(o,a)};const i=R._renderNotFound.bind(R);let e="";R._renderNotFound=async function(o){return m()&&e!==o&&(e=o,await U(),R._matchRoute(o).route)?(e="",R._handleRouteChange()):(e="",m()&&$("#admin-sidebar").get(0)?.style.display==="none"?(E.toast("That link goes nowhere - here is your home page.",{type:"warning"}),R.navigate("/")):i(o))},dt(R),R.init({container:"#view-container",routes:I,views:r,default:"/",transitions:{enter:"fadeIn",leave:"fadeOut",duration:150}})})()});
23
+ `);const a=$("#topbar-bell").get(0);a&&(a.hidden=!0);const n=$("#topbar-settings").get(0);n&&(n.hidden=!w),$("#topbar-logout-btn").on("click",s=>{s.preventDefault(),Y()}),Domma.icons.scan("#admin-topbar"),E.tooltip("#topbar-actions [data-tooltip]",{placement:"bottom"}),F(),u||(u=setInterval(F,6e4))}function d(t){return String(t).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}let u=null;async function F(){if(!(!m()||g===!1))try{const{count:t}=await c.system.notifications.unreadCount();$("#topbar-bell").removeAttr("hidden");const i=$("#topbar-bell-badge");t>0?i.text(t>99?"99+":String(t)).removeAttr("hidden"):i.attr("hidden","").text(""),t>0&&rt()&&nt(await c.system.notifications.list().catch(()=>[]))}catch{}}(async()=>{if(!m()&&!window.location.hash.startsWith("#/reset-password"))window.location.hash.startsWith("#/login")||(window.location.hash=Z(window.location.hash));else if(X(x()?.id),await U(),x()){const a=await f(),n=(window.location.hash||"#/").slice(1)||"/",s=D(n);s&&(window.location.hash=`#${s}`),await j(a),B()}const t=R._extractParams.bind(R);R._extractParams=function(o,a){const n=a.indexOf("?");if(n!==-1&&(a=a.slice(0,n)),o.endsWith("/*")){const s=o.slice(0,-2);return a.startsWith(s+"/")?{}:null}return t(o,a)};const i=R._renderNotFound.bind(R);let e="";R._renderNotFound=async function(o){return m()&&e!==o&&(e=o,await U(),R._matchRoute(o).route)?(e="",R._handleRouteChange()):(e="",m()&&$("#admin-sidebar").get(0)?.style.display==="none"?(E.toast("That link goes nowhere - here is your home page.",{type:"warning"}),R.navigate("/")):i(o))},ut(R),R.init({container:"#view-container",routes:I,views:r,default:"/",transitions:{enter:"fadeIn",leave:"fadeOut",duration:150}})})()});
@@ -1,6 +1,6 @@
1
- const _=["card","box","grid","row","tabs","accordion","carousel","hero","timeline","slideover","dconfig"],b=new RegExp(`^\\[(${_.join("|")})(\\s[^\\]]*)?\\]`,"i"),k="\u2026",G="\u200B";function j(n,f,o){return`${n.trimEnd()} ${k} [/${f}]${G}${o}`}function $(n,f,o){const c=new RegExp(`^\\[\\/${o}\\]`,"i"),h=new RegExp(`^\\[${o}(\\s[^\\]]*)?\\]`,"i");let d=1;for(let u=f+1;u<n.length;u++){const g=n[u].trimStart();if(h.test(g)&&d++,c.test(g)&&(d--,d===0))return u}return-1}function F(n){const f=[];for(let o=0;o<n.length;o++){const h=n[o].trimStart().match(b);if(!h)continue;const d=h[1].toLowerCase(),u=$(n,o,d);u>o&&f.push({lineIndex:o,tag:d,closeIndex:u})}return f}function B(n){for(;n.firstChild;)n.removeChild(n.firstChild)}export function createFoldingManager(n,f,o={}){const c=new Map;let h=0,d=null;function u(e){d&&d(!0),e(),d&&d(!1)}function g(){return n.value.split(`
2
- `)}function p(){const e=g(),t=F(e),i=new Set(t.map(s=>s.lineIndex)),l=new Set;e.forEach((s,r)=>{c.has(s)&&l.add(r)}),B(f),e.forEach((s,r)=>{const m=document.createElement("span");m.className="editor-line-number-row";const a=document.createElement("span");l.has(r)?(a.className="fold-toggle fold-toggle--folded",a.setAttribute("title","Unfold block"),a.textContent="\u25B8",a.addEventListener("click",()=>w(r))):i.has(r)?(a.className="fold-toggle fold-toggle--open",a.setAttribute("title","Fold block"),a.textContent="\u25BE",a.addEventListener("click",()=>C(r))):a.className="fold-toggle fold-toggle--empty",m.appendChild(a);const E=document.createElement("span");E.className="editor-line-num",E.textContent=String(r+1),m.appendChild(E),f.appendChild(m)}),f.scrollTop=n.scrollTop}function C(e){const t=g(),i=t[e].trimStart().match(b);if(!i)return;const l=i[1].toLowerCase(),s=$(t,e,l);if(s<=e)return;const r=t.slice(e,s+1).join(`
3
- `),m=j(t[e],l,++h);c.set(m,r);const a=[...t.slice(0,e),m,...t.slice(s+1)];u(()=>{n.value=a.join(`
4
- `)}),p(),o.onFoldChange&&o.onFoldChange()}function w(e){const t=g(),i=t[e],l=c.get(i);if(!l)return;c.delete(i);const s=l.split(`
5
- `),r=[...t.slice(0,e),...s,...t.slice(e+1)];u(()=>{n.value=r.join(`
6
- `)}),p(),o.onFoldChange&&o.onFoldChange()}function S(){let e=0;for(;e++<200;){const t=g(),l=F(t).find(s=>!c.has(t[s.lineIndex]));if(!l)break;C(l.lineIndex)}}function L(){let e=0;for(;c.size>0&&e++<200;){const i=g().findIndex(l=>c.has(l));if(i===-1)break;w(i)}}function v(){if(c.size===0)return n.value;let e=n.value,t=!0,i=0;for(;t&&i++<20;){t=!1;for(const[l,s]of c){const r=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),m=e.replace(new RegExp(`^${r}$`,"m"),()=>s);m!==e&&(e=m,t=!0)}}return e}function y(e){const t=g();return t[e]!==void 0&&c.has(t[e])}function A(e){d=e}function R(){p()}function x(){L()}return p(),{foldAt:C,unfoldAt:w,foldAll:S,unfoldAll:L,getUnfoldedContent:v,isFolded:y,setGuard:A,refresh:R,destroy:x}}
1
+ const O=["card","box","grid","row","tabs","accordion","carousel","hero","timeline","slideover","dconfig"],b=new RegExp(`^\\[(${O.join("|")})(\\s[^\\]]*)?\\]`,"i"),j="\u2026",B="\u200B";function D(n,s,o){return`${n.trimEnd()} ${j} [/${s}]${B}${o}`}function y(n,s,o){const i=new RegExp(`^\\[\\/${o}\\]`,"i"),m=new RegExp(`^\\[${o}(\\s[^\\]]*)?\\]`,"i");let d=1;for(let a=s+1;a<n.length;a++){const h=n[a].trimStart();if(m.test(h)&&d++,i.test(h)&&(d--,d===0))return a}return-1}function R(n){const s=[];for(let o=0;o<n.length;o++){const m=n[o].trimStart().match(b);if(!m)continue;const d=m[1].toLowerCase(),a=y(n,o,d);a>o&&s.push({lineIndex:o,tag:d,closeIndex:a})}return s}function M(n){for(;n.firstChild;)n.removeChild(n.firstChild)}export function createFoldingManager(n,s,o={}){const i=new Map;let m=0,d=null;function a(e){d&&d(!0),e(),d&&d(!1)}function h(){return n.value.split(`
2
+ `)}let S=null,$=null;function C(){const e=h(),t=R(e),c=new Set(t.map(u=>u.lineIndex)),l=new Set;e.forEach((u,r)=>{i.has(u)&&l.add(r)});const f=JSON.stringify([e.length,t,[...l]]);f===S&&s.firstChild===$&&s.children.length===e.length||(S=f,M(s),e.forEach((u,r)=>{const p=document.createElement("span");p.className="editor-line-number-row";const g=document.createElement("span");l.has(r)?(g.className="fold-toggle fold-toggle--folded",g.setAttribute("title","Unfold block"),g.textContent="\u25B8",g.addEventListener("click",()=>L(r))):c.has(r)?(g.className="fold-toggle fold-toggle--open",g.setAttribute("title","Fold block"),g.textContent="\u25BE",g.addEventListener("click",()=>w(r))):g.className="fold-toggle fold-toggle--empty",p.appendChild(g);const E=document.createElement("span");E.className="editor-line-num",E.textContent=String(r+1),p.appendChild(E),s.appendChild(p)}),$=s.firstChild,s.scrollTop=n.scrollTop)}function w(e){const t=h(),c=t[e].trimStart().match(b);if(!c)return;const l=c[1].toLowerCase(),f=y(t,e,l);if(f<=e)return;const u=t.slice(e,f+1).join(`
3
+ `),r=D(t[e],l,++m);i.set(r,u);const p=[...t.slice(0,e),r,...t.slice(f+1)];a(()=>{n.value=p.join(`
4
+ `)}),C(),o.onFoldChange&&o.onFoldChange()}function L(e){const t=h(),c=t[e],l=i.get(c);if(!l)return;i.delete(c);const f=l.split(`
5
+ `),u=[...t.slice(0,e),...f,...t.slice(e+1)];a(()=>{n.value=u.join(`
6
+ `)}),C(),o.onFoldChange&&o.onFoldChange()}function v(){let e=0;for(;e++<200;){const t=h(),l=R(t).find(f=>!i.has(t[f.lineIndex]));if(!l)break;w(l.lineIndex)}}function F(){let e=0;for(;i.size>0&&e++<200;){const c=h().findIndex(l=>i.has(l));if(c===-1)break;L(c)}}function A(){if(i.size===0)return n.value;let e=n.value,t=!0,c=0;for(;t&&c++<20;){t=!1;for(const[l,f]of i){const u=l.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=e.replace(new RegExp(`^${u}$`,"m"),()=>f);r!==e&&(e=r,t=!0)}}return e}function x(e){const t=h();return t[e]!==void 0&&i.has(t[e])}function _(e){d=e}function k(){C()}function G(){F()}return C(),{foldAt:w,unfoldAt:L,foldAll:v,unfoldAll:F,getUnfoldedContent:A,isFolded:x,setGuard:_,refresh:k,destroy:G}}
@@ -1,4 +1,4 @@
1
- import{highlight as S}from"./syntax-highlight.js";function T(){if(document.getElementById("dm-simple-editor-style"))return;const r=document.createElement("style");r.id="dm-simple-editor-style",r.textContent=`
1
+ import{highlight as M}from"./syntax-highlight.js";import{attachSmoothCaret as L}from"./smooth-caret.js";function A(){if(document.getElementById("dm-simple-editor-style"))return;const r=document.createElement("style");r.id="dm-simple-editor-style",r.textContent=`
2
2
  .dm-edit-wrap {
3
3
  display: flex;
4
4
  flex-direction: row;
@@ -86,10 +86,10 @@ import{highlight as S}from"./syntax-highlight.js";function T(){if(document.getEl
86
86
  .dm-tok-func { color: #4078f2; }
87
87
  .dm-tok-key { color: #b8762e; }
88
88
  .dm-tok-tag { color: #cc5c66; }
89
- `,document.head.appendChild(r)}export function createSimpleEditor(r,w={}){if(!r)throw new Error("createSimpleEditor: mountEl is required.");const{initialValue:y="",onChange:v=null,language:x=null,autoIndent:C=!1,onCursor:k=null}=w;for(T();r.firstChild;)r.removeChild(r.firstChild);const a=document.createElement("div"),s=document.createElement("div"),e=document.createElement("textarea");a.className="dm-edit-wrap",s.className="dm-edit-gutter",e.className="dm-edit-area",e.spellcheck=!1,e.setAttribute("autocomplete","off"),e.setAttribute("autocorrect","off"),e.setAttribute("autocapitalize","off"),a.appendChild(s);let l=null;if(x){const t=document.createElement("div");t.className="dm-edit-host",l=document.createElement("pre"),l.className="dm-edit-highlight",t.appendChild(l),t.appendChild(e),a.appendChild(t)}else a.appendChild(e);r.appendChild(a);function f(){l&&(l.innerHTML=S(e.value,x))}function p(){const t=e.value.split(`
90
- `).length||1,n=new Array(t);for(let i=0;i<t;i++)n[i]=String(i+1);s.textContent=n.join(`
91
- `);const o=String(t).length;s.style.minWidth=`calc(${o}ch + 1.5rem)`}function u(){requestAnimationFrame(()=>{s.scrollTop=e.scrollTop,l&&(l.scrollTop=e.scrollTop,l.scrollLeft=e.scrollLeft)})}function g(){if(!k)return;const t=e.value.slice(0,e.selectionStart),n=(t.match(/\n/g)||[]).length+1,o=t.length-(t.lastIndexOf(`
92
- `)+1)+1;k({line:n,col:o})}function E(t){if(t.key!=="Enter"||t.isComposing)return;t.preventDefault();const{selectionStart:n,value:o}=e,i=o.lastIndexOf(`
93
- `,n-1)+1,d=(o.slice(i,n).match(/^[ \t]*/)||[""])[0],h=o.slice(0,n).trimEnd().slice(-1),m="{[(".includes(h)?" ":"";e.setRangeText(`
94
- `+d+m,n,e.selectionEnd,"end"),e.dispatchEvent(new Event("input",{bubbles:!0}))}function z(t){if(t.key!=="Tab")return;t.preventDefault();const{selectionStart:n,selectionEnd:o,value:i}=e;if(!t.shiftKey)e.value=i.slice(0,n)+" "+i.slice(o),e.selectionStart=e.selectionEnd=n+2;else{const d=i.lastIndexOf(`
95
- `,n-1)+1,h=i.slice(d,d+2),m=h===" "?2:h[0]===" "?1:0;m>0&&(e.value=i.slice(0,d)+i.slice(d+m),e.selectionStart=e.selectionEnd=Math.max(d,n-m))}e.dispatchEvent(new Event("input",{bubbles:!0}))}const b=[];function c(t,n,o){t.addEventListener(n,o),b.push([t,n,o])}return c(e,"input",()=>{p(),f(),u(),g(),v&&v(e.value)}),c(e,"scroll",u),c(e,"keydown",z),C&&c(e,"keydown",E),c(e,"keyup",()=>{u(),g()}),c(e,"click",g),e.value=y,p(),f(),{textarea:e,gutter:s,getValue(){return e.value},setValue(t){e.value!==t&&(e.value=t??"",p(),f(),u())},focus(){e.focus()},destroy(){for(const[t,n,o]of b)t.removeEventListener(n,o);b.length=0,a.parentNode===r&&r.removeChild(a)}}}
89
+ `,document.head.appendChild(r)}export function createSimpleEditor(r,E={}){if(!r)throw new Error("createSimpleEditor: mountEl is required.");const{initialValue:S="",onChange:x=null,language:y=null,autoIndent:z=!1,onCursor:k=null}=E;for(A();r.firstChild;)r.removeChild(r.firstChild);const a=document.createElement("div"),s=document.createElement("div"),e=document.createElement("textarea");a.className="dm-edit-wrap",s.className="dm-edit-gutter",e.className="dm-edit-area",e.spellcheck=!1,e.setAttribute("autocomplete","off"),e.setAttribute("autocorrect","off"),e.setAttribute("autocapitalize","off"),a.appendChild(s);let l=null;if(y){const t=document.createElement("div");t.className="dm-edit-host",l=document.createElement("pre"),l.className="dm-edit-highlight",t.appendChild(l),t.appendChild(e),a.appendChild(t)}else a.appendChild(e);r.appendChild(a);function p(){l&&(l.innerHTML=M(e.value,y))}let w=0;function g(){const t=e.value.split(`
90
+ `).length||1;if(t===w)return;w=t;const n=new Array(t);for(let i=0;i<t;i++)n[i]=String(i+1);s.textContent=n.join(`
91
+ `);const o=String(t).length;s.style.minWidth=`calc(${o}ch + 1.5rem)`}let m=null;function h(){m===null&&(m=requestAnimationFrame(()=>{m=null,s.scrollTop=e.scrollTop,l&&(l.scrollTop=e.scrollTop,l.scrollLeft=e.scrollLeft)}))}function b(){if(!k)return;const t=e.value.slice(0,e.selectionStart),n=(t.match(/\n/g)||[]).length+1,o=t.length-(t.lastIndexOf(`
92
+ `)+1)+1;k({line:n,col:o})}function F(t){if(t.key!=="Enter"||t.isComposing)return;t.preventDefault();const{selectionStart:n,value:o}=e,i=o.lastIndexOf(`
93
+ `,n-1)+1,d=(o.slice(i,n).match(/^[ \t]*/)||[""])[0],f=o.slice(0,n).trimEnd().slice(-1),u="{[(".includes(f)?" ":"";e.setRangeText(`
94
+ `+d+u,n,e.selectionEnd,"end"),e.dispatchEvent(new Event("input",{bubbles:!0}))}function T(t){if(t.key!=="Tab")return;t.preventDefault();const{selectionStart:n,selectionEnd:o,value:i}=e;if(!t.shiftKey)e.value=i.slice(0,n)+" "+i.slice(o),e.selectionStart=e.selectionEnd=n+2;else{const d=i.lastIndexOf(`
95
+ `,n-1)+1,f=i.slice(d,d+2),u=f===" "?2:f[0]===" "?1:0;u>0&&(e.value=i.slice(0,d)+i.slice(d+u),e.selectionStart=e.selectionEnd=Math.max(d,n-u))}e.dispatchEvent(new Event("input",{bubbles:!0}))}const v=[];function c(t,n,o){t.addEventListener(n,o),v.push([t,n,o])}c(e,"input",()=>{g(),p(),h(),b(),x&&x(e.value)}),c(e,"scroll",h),c(e,"keydown",T),z&&c(e,"keydown",F),c(e,"keyup",()=>{h(),b()}),c(e,"click",b),e.value=S,g(),p();const C=L(e);return{textarea:e,gutter:s,getValue(){return e.value},setValue(t){e.value!==t&&(e.value=t??"",g(),p(),h(),C.refresh())},focus(){e.focus()},destroy(){C.destroy(),m!==null&&cancelAnimationFrame(m);for(const[t,n,o]of v)t.removeEventListener(n,o);v.length=0,a.parentNode===r&&r.removeChild(a)}}}
@@ -0,0 +1 @@
1
+ export{attachSmoothCaret,installSmoothCarets,getCaretPreference,setCaretPreference}from"/public/js/smooth-caret.js";
@@ -1,4 +1,4 @@
1
- import{api as b}from"../api.js";import{CardBuilder as vt}from"../lib/card-builder.js";import{TimelineBuilder as ft}from"../lib/timeline-builder.js";import{attachEditorKeybindings as mt,createToolbar as gt,insertAtCursor as bt}from"../lib/markdown-toolbar.js";import{EffectsBuilder as ht}from"../lib/effects-builder.js";import{attachContextMenu as yt}from"../lib/shortcode-context-menu.js";import{registerCustomInserters as wt}from"../lib/shortcode-insert.js";import{populateThemeSelect as kt}from"../lib/themes.js";import{createFoldingManager as Et}from"../lib/editor-folding.js";import{openScribeComposer as Mt}from"../lib/scribe-composer.js";import{openCrudTutorial as St}from"../lib/crud-tutorial.js";import{addBannerAction as $}from"../lib/plugin-chrome.js";import{helpPopovers as Ke}from"../lib/help-popover.js";import{onceClosed as ye,openMenuAt as Ue}from"../lib/tool-kit.js";import{pickMedia as Tt}from"../lib/media-picker.js";import{openPageClone as Ct}from"../lib/page-clone.js";import{openEditorReference as _e}from"../lib/page-editor-reference.js";import{cleanType as X,DEFAULT_TYPE as Z,EDITOR_FONTS as xt,fontHref as Pt,isDefaultType as Lt,LINE_HEIGHTS as At,SIZES as Ot,typeVars as Je}from"../lib/editor-type.js";import{getProjectFromHash as Dt}from"../lib/project-context.js";import{SCREEN as Rt,bannerSection as Nt,draftIsStale as Ft,draftKey as It,initialProject as Bt,makeDraft as $t,problems as we,readDraft as zt,snapshot as z}from"../lib/page-editor-arrange.js";import{fmtDateTime as Q}from"../lib/dates.js";function ee(s){const r=document.createElement("template");return r.innerHTML=s.trim(),r.content.firstElementChild}const jt=Q,We=s=>Q(s.createdAt)+(s.label?` - ${s.label}`:""),Vt=`
1
+ import{api as g}from"../api.js";import{CardBuilder as gt}from"../lib/card-builder.js";import{TimelineBuilder as bt}from"../lib/timeline-builder.js";import{attachEditorKeybindings as ht,createToolbar as yt,insertAtCursor as wt}from"../lib/markdown-toolbar.js";import{EffectsBuilder as kt}from"../lib/effects-builder.js";import{attachContextMenu as Et}from"../lib/shortcode-context-menu.js";import{registerCustomInserters as Mt}from"../lib/shortcode-insert.js";import{populateThemeSelect as St}from"../lib/themes.js";import{createFoldingManager as Tt}from"../lib/editor-folding.js";import{openScribeComposer as Ct}from"../lib/scribe-composer.js";import{openCrudTutorial as xt}from"../lib/crud-tutorial.js";import{addBannerAction as j}from"../lib/plugin-chrome.js";import{helpPopovers as Ke}from"../lib/help-popover.js";import{onceClosed as ye,openMenuAt as Ue}from"../lib/tool-kit.js";import{pickMedia as Pt}from"../lib/media-picker.js";import{openPageClone as At}from"../lib/page-clone.js";import{openEditorReference as _e}from"../lib/page-editor-reference.js";import{cleanType as Z,DEFAULT_TYPE as Q,EDITOR_FONTS as Lt,fontHref as Ot,isDefaultType as Dt,LINE_HEIGHTS as Rt,SIZES as Nt,typeVars as Je}from"../lib/editor-type.js";import{getProjectFromHash as Ft}from"../lib/project-context.js";import{attachSmoothCaret as We,getCaretPreference as It,setCaretPreference as Bt}from"../lib/smooth-caret.js";import{SCREEN as $t,bannerSection as zt,draftIsStale as jt,draftKey as Vt,initialProject as qt,makeDraft as Ht,problems as we,readDraft as Kt,snapshot as V}from"../lib/page-editor-arrange.js";import{fmtDateTime as ee}from"../lib/dates.js";function te(o){const i=document.createElement("template");return i.innerHTML=o.trim(),i.content.firstElementChild}const Ut=ee,Ge=o=>ee(o.createdAt)+(o.label?` - ${o.label}`:""),_t=`
2
2
  <div class="pe-share">
3
3
  <p class="form-hint" style="margin-top:0">Anyone with the link can view this page even while it is unpublished, without
4
4
  signing in. The link works for this page only, expires on its own, and can be revoked at any time.</p>
@@ -30,7 +30,7 @@ import{api as b}from"../api.js";import{CardBuilder as vt}from"../lib/card-builde
30
30
  .pe-share [hidden] { display: none !important; }
31
31
  .pe-share-row { display: flex; align-items: center; gap: .6rem; padding: .5rem 0; border-bottom: 1px solid var(--dm-border-light); }
32
32
  .pe-share-text { flex: 1 1 auto; min-width: 0; font-size: .82rem; }
33
- </style>`;function Ge(s){const r=Pt(s);if(!r||document.querySelector(`link[data-pe-font="${CSS.escape(s)}"]`))return;const l=Object.assign(document.createElement("link"),{rel:"stylesheet",href:r});l.dataset.peFont=s,document.head.appendChild(l)}const qt=`
33
+ </style>`;function Ye(o){const i=Ot(o);if(!i||document.querySelector(`link[data-pe-font="${CSS.escape(o)}"]`))return;const l=Object.assign(document.createElement("link"),{rel:"stylesheet",href:i});l.dataset.peFont=o,document.head.appendChild(l)}const Jt=`
34
34
  <div class="pe-settings">
35
35
  <p class="pe-settings-note">How the editor looks to you - kept in this browser, for every page.</p>
36
36
  <label class="form-label" for="pe-set-font">Font <span data-help="The lettering in the editor (not on the site). Monospace keeps every character the same width, so shortcodes and Markdown line up."></span></label>
@@ -43,6 +43,13 @@ import{api as b}from"../api.js";import{CardBuilder as vt}from"../lib/card-builde
43
43
  </div>
44
44
  <label class="pe-settings-switch"><input type="checkbox" class="form-switch" data-model="wrap.value"> Wrap long lines
45
45
  <span data-help="Off: a long line runs on and the editor scrolls sideways - each line number is then exactly one line."></span></label>
46
+ <label class="form-label" for="pe-set-caret">Caret movement</label>
47
+ <select id="pe-set-caret" class="form-select" data-model="caret.value">
48
+ <option value="auto">Automatic - follow system motion preference</option>
49
+ <option value="smooth">Smooth</option>
50
+ <option value="native">Native</option>
51
+ </select>
52
+ <p class="pe-settings-note">Smooth enables caret animation across the admin and public site forms in this browser. Automatic follows your system's reduced-motion preference.</p>
46
53
  <div class="pe-settings-sample" aria-label="Sample"># A heading
47
54
  [card title="Shortcodes line up"]
48
55
  The quick brown fox - 0O 1lI {} [] () =&gt; ==
@@ -61,17 +68,17 @@ The quick brown fox - 0O 1lI {} [] () =&gt; ==
61
68
  .pe-settings-sample { white-space: pre-wrap; padding: .75rem 1rem; border-radius: var(--dm-radius-md); border: 1px solid var(--dm-border);
62
69
  background: var(--dm-background-alt); font-family: var(--pe-font); font-size: var(--pe-size); line-height: var(--pe-line); }
63
70
  .pe-settings-actions { display: flex; gap: .5rem; border-top: 1px solid var(--dm-border); padding-top: .75rem; }
64
- </style>`;function Ht(s){const r=E.slideover({title:"Editor settings",size:"sm",position:"right"}),l=ee(`<div>${qt}</div>`),o=X(s.peek()),i={font:M.observable(o.font),size:M.observable(String(o.size)),line:M.observable(String(o.line)),wrap:M.observable(o.wrap)},f=M.computed(()=>X({font:i.font.value,size:i.size.value,line:i.line.value,wrap:i.wrap.value}));i.isDefault=M.computed(()=>Lt(f.value));const p=l.querySelector("#pe-set-font");for(const[v,T]of[["mono","Monospace"],["sans","Other"],["serif",null]]){const F=xt.filter(m=>m.kind===v),V=T?Object.assign(document.createElement("optgroup"),{label:T}):p.querySelector("optgroup:last-of-type");V.append(...F.map(m=>new Option(m.label,m.id))),T&&p.appendChild(V)}l.querySelector("#pe-set-size").append(...Ot.map(v=>new Option(`${v}px`,String(v)))),l.querySelector("#pe-set-line").append(...At.map(v=>new Option({1.3:"Tight",1.45:"Snug",1.6:"Normal",1.8:"Relaxed",2:"Double"}[v]||String(v),String(v))));const c=l.querySelector(".pe-settings-sample"),u=M.effect(()=>{const v=f.value;Ge(v.font);for(const[T,F]of Object.entries(Je(v)))c.style.setProperty(T,F);c.style.whiteSpace=v.wrap?"pre-wrap":"pre",c.style.overflowX=v.wrap?"":"auto",JSON.stringify(v)!==JSON.stringify(X(s.peek()))&&(s.value=v,te("type",v))});i.reset=()=>{i.font.value=Z.font,i.size.value=String(Z.size),i.line.value=String(Z.line),i.wrap.value=Z.wrap},i.done=()=>r.close(),r.element.appendChild(l);const C=M.applyBindings(i,l),d=Ke(l);return ye(r,()=>{C.dispose(),d(),u?.()}),Domma.icons?.scan?.(l),r.open(),r}async function Kt(s){const r=E.slideover({title:"Share preview link",size:"md",position:"right"}),l=ee(`<div>${Vt}</div>`),o={expiry:M.observable("7d"),note:M.observable(""),creating:M.observable(!1),url:M.observable(""),links:M.observable([]),loaded:M.observable(!1),listError:M.observable("")},i=async()=>{try{const p=await b.pages.previewLinks.list(s);o.links.value=p.filter(c=>!c.revokedAt&&!c.expired).map(c=>({id:c.id,title:c.label||"Untitled link",meta:`Expires ${jt(c.expiresAt)} - ${c.useCount===1?"1 view":`${c.useCount||0} views`}`})),o.listError.value=""}catch(p){o.listError.value="Could not load existing links: "+(p.message||"unknown error")}finally{o.loaded.value=!0}};o.create=async()=>{o.creating.value=!0;try{const p=await b.pages.previewLinks.create(s,o.expiry.peek(),o.note.peek().trim());o.url.value=p.url,o.note.value="",E.toast("Share link created.",{type:"success"}),await i(),l.querySelector(".pe-share-url")?.select()}catch(p){E.toast("Could not create link: "+(p.message||"unknown error"),{type:"error"})}finally{o.creating.value=!1}},o.copy=async()=>{try{await navigator.clipboard.writeText(o.url.peek()),E.toast("Link copied to clipboard.",{type:"success"})}catch{l.querySelector(".pe-share-url")?.select(),E.toast("Press Ctrl+C to copy the selected link.",{type:"info"})}},o.revoke=async p=>{if(await E.confirm("Revoke this link? Anyone holding it loses access immediately."))try{await b.pages.previewLinks.revoke(p),E.toast("Link revoked.",{type:"success"}),await i()}catch(c){E.toast("Could not revoke: "+(c.message||"unknown error"),{type:"error"})}};const f=M.applyBindings(o,l);ye(r,()=>f.dispose()),r.element.appendChild(l),r.open(),await i()}function Ut(s){return new Promise(r=>{const l=E.slideover({title:"Save Named Version",size:"sm",position:"right"}),o=ee(`
71
+ </style>`;function Wt(o){const i=E.slideover({title:"Editor settings",size:"sm",position:"right"}),l=te(`<div>${Jt}</div>`),s=Z(o.peek()),r={font:M.observable(s.font),size:M.observable(String(s.size)),line:M.observable(String(s.line)),wrap:M.observable(s.wrap),caret:M.observable(It())},v=M.computed(()=>Z({font:r.font.value,size:r.size.value,line:r.line.value,wrap:r.wrap.value}));r.isDefault=M.computed(()=>Dt(v.value)&&r.caret.value==="auto");const u=M.effect(()=>Bt(r.caret.value)),p=l.querySelector("#pe-set-font");for(const[b,L]of[["mono","Monospace"],["sans","Other"],["serif",null]]){const $=Lt.filter(P=>P.kind===b),m=L?Object.assign(document.createElement("optgroup"),{label:L}):p.querySelector("optgroup:last-of-type");m.append(...$.map(P=>new Option(P.label,P.id))),L&&p.appendChild(m)}l.querySelector("#pe-set-size").append(...Nt.map(b=>new Option(`${b}px`,String(b)))),l.querySelector("#pe-set-line").append(...Rt.map(b=>new Option({1.3:"Tight",1.45:"Snug",1.6:"Normal",1.8:"Relaxed",2:"Double"}[b]||String(b),String(b))));const c=l.querySelector(".pe-settings-sample"),C=M.effect(()=>{const b=v.value;Ye(b.font);for(const[L,$]of Object.entries(Je(b)))c.style.setProperty(L,$);c.style.whiteSpace=b.wrap?"pre-wrap":"pre",c.style.overflowX=b.wrap?"":"auto",JSON.stringify(b)!==JSON.stringify(Z(o.peek()))&&(o.value=b,ae("type",b))});r.reset=()=>{r.font.value=Q.font,r.size.value=String(Q.size),r.line.value=String(Q.line),r.wrap.value=Q.wrap,r.caret.value="auto"},r.done=()=>i.close(),i.element.appendChild(l);const d=M.applyBindings(r,l),h=Ke(l);return ye(i,()=>{d.dispose(),h(),C?.(),u?.()}),Domma.icons?.scan?.(l),i.open(),i}async function Gt(o){const i=E.slideover({title:"Share preview link",size:"md",position:"right"}),l=te(`<div>${_t}</div>`),s={expiry:M.observable("7d"),note:M.observable(""),creating:M.observable(!1),url:M.observable(""),links:M.observable([]),loaded:M.observable(!1),listError:M.observable("")},r=async()=>{try{const u=await g.pages.previewLinks.list(o);s.links.value=u.filter(p=>!p.revokedAt&&!p.expired).map(p=>({id:p.id,title:p.label||"Untitled link",meta:`Expires ${Ut(p.expiresAt)} - ${p.useCount===1?"1 view":`${p.useCount||0} views`}`})),s.listError.value=""}catch(u){s.listError.value="Could not load existing links: "+(u.message||"unknown error")}finally{s.loaded.value=!0}};s.create=async()=>{s.creating.value=!0;try{const u=await g.pages.previewLinks.create(o,s.expiry.peek(),s.note.peek().trim());s.url.value=u.url,s.note.value="",E.toast("Share link created.",{type:"success"}),await r(),l.querySelector(".pe-share-url")?.select()}catch(u){E.toast("Could not create link: "+(u.message||"unknown error"),{type:"error"})}finally{s.creating.value=!1}},s.copy=async()=>{try{await navigator.clipboard.writeText(s.url.peek()),E.toast("Link copied to clipboard.",{type:"success"})}catch{l.querySelector(".pe-share-url")?.select(),E.toast("Press Ctrl+C to copy the selected link.",{type:"info"})}},s.revoke=async u=>{if(await E.confirm("Revoke this link? Anyone holding it loses access immediately."))try{await g.pages.previewLinks.revoke(u),E.toast("Link revoked.",{type:"success"}),await r()}catch(p){E.toast("Could not revoke: "+(p.message||"unknown error"),{type:"error"})}};const v=M.applyBindings(s,l);ye(i,()=>v.dispose()),i.element.appendChild(l),i.open(),await r()}function Yt(o){return new Promise(i=>{const l=E.slideover({title:"Save Named Version",size:"sm",position:"right"}),s=te(`
65
72
  <div style="padding:1rem">
66
73
  <label class="form-label" for="pe-version-label">Version Label</label>
67
74
  <input id="pe-version-label" type="text" class="form-input" style="margin-bottom:.75rem"
68
75
  placeholder="e.g. Initial design, Before restructure" data-model="label.value" data-on-keydown="key">
69
76
  <button type="button" class="btn btn-primary" data-on-click="save" data-bind-disabled="saving.value">Save Version</button>
70
- </div>`);let i=!1;const f={label:M.observable(""),saving:M.observable(!1)};f.save=async()=>{f.saving.value=!0;try{await b.versions.create(s,f.label.peek().trim()||null),E.toast("Named version saved.",{type:"success"}),i=!0,l.close()}catch(c){E.toast("Failed to save version: "+c.message,{type:"error"})}finally{f.saving.value=!1}},f.key=c=>{c.key==="Enter"&&(c.preventDefault(),f.save())};const p=M.applyBindings(f,o);ye(l,()=>{p.dispose(),r(i)}),l.element.appendChild(o),l.open(),setTimeout(()=>o.querySelector("input")?.focus(),100)})}let w=null,Ye=!1;function _t(){Ye||!window.R?.use||(Ye=!0,R.use((s,r,l)=>{const o=r?.path||"",i=s?.path||"",f=Rt.test(o)&&i!==o;return f&&w?.path===o&&w.cloneTarget===i?(w.cloneTarget=null,w.keepDraft(),l()):!f||!w||w.path!==o||!w.dirty()?l():E.confirm("You have unsaved changes to this page. Leave anyway? They are kept as a draft for your next visit.").then(p=>{p?(w?.keepDraft(),l()):history.replaceState(null,"","#"+o)})}),M.subscribe("router:afterChange",({to:s}={})=>{if(w&&(s?.path||"")!==w.path){const r=w;w=null,r.dispose()}}))}function Jt(s){return s.split(`
71
- `).map(r=>r.trimEnd()).join(`
77
+ </div>`);let r=!1;const v={label:M.observable(""),saving:M.observable(!1)};v.save=async()=>{v.saving.value=!0;try{await g.versions.create(o,v.label.peek().trim()||null),E.toast("Named version saved.",{type:"success"}),r=!0,l.close()}catch(p){E.toast("Failed to save version: "+p.message,{type:"error"})}finally{v.saving.value=!1}},v.key=p=>{p.key==="Enter"&&(p.preventDefault(),v.save())};const u=M.applyBindings(v,s);ye(l,()=>{u.dispose(),i(r)}),l.element.appendChild(s),l.open(),setTimeout(()=>s.querySelector("input")?.focus(),100)})}let T=null,Xe=!1;function Xt(){Xe||!window.R?.use||(Xe=!0,R.use((o,i,l)=>{const s=i?.path||"",r=o?.path||"",v=$t.test(s)&&r!==s;return v&&T?.path===s&&T.cloneTarget===r?(T.cloneTarget=null,T.keepDraft(),l()):!v||!T||T.path!==s||!T.dirty()?l():E.confirm("You have unsaved changes to this page. Leave anyway? They are kept as a draft for your next visit.").then(u=>{u?(T?.keepDraft(),l()):history.replaceState(null,"","#"+s)})}),M.subscribe("router:afterChange",({to:o}={})=>{if(T&&(o?.path||"")!==T.path){const i=T;T=null,i.dispose()}}))}function Zt(o){return o.split(`
78
+ `).map(i=>i.trimEnd()).join(`
72
79
  `).replace(/\n{3,}/g,`
73
80
 
74
- `)}const Xe="editor_prefs";function j(){return S.get(Xe)||{viewMode:"split",fullscreen:!1}}function te(s,r){const l=j();l[s]=r,S.set(Xe,l)}const Wt=["edit","details","seo","dconfig","live","history"],Ze=["split","write","preview"],Gt=s=>s.replace(/<\/head>/i,"<style>body.dm-cloaked{opacity:1 !important;transition:none !important}</style></head>");function Qe(s,r,l=()=>{}){let o=0;try{o=s.contentWindow.scrollY||0}catch{}s.addEventListener("load",()=>{try{s.contentWindow.scrollTo(0,o)}catch{}l()},{once:!0}),s.srcdoc=r}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(s){if(_t(),w){const e=w;w=null,e.dispose()}const r=window.location.hash.replace(/^#/,""),l=[],o=e=>(l.push(e),e);let i=()=>!1,f=()=>{};const p={path:r,dirty:()=>i(),keepDraft:()=>f(),dispose:()=>{l.splice(0).forEach(e=>{try{e()}catch{}})}};w=p;const c=s.get(0),u=()=>w===p&&c.isConnected,C=window.location.hash.match(/#\/pages\/edit(\/[^?]*)/),d=C?C[1]:null,v=!!d,T=E.loader(c,{type:"dots"}),[F,V,m,ae,ke,et,tt]=await Promise.all([b.layouts.get().catch(()=>({})),b.settings.get().catch(()=>({})),v?b.pages.get(d).catch(()=>null):null,v?b.pages.list().catch(()=>[]):[],b.projects.list().catch(()=>[]),b.pages.tags().catch(()=>[]),b.listTags.list("pages").then(e=>e.map(t=>t.name)).catch(()=>[])]);if(!u()){T.destroy();return}if(T.destroy(),v&&!m){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}const y=e=>c.querySelector(e);if(kt(y("#field-theme"),{includeDefault:!0}),await ea(y("#field-visibility"),m?.visibility),!u())return;const at=Qt(y("#field-layout"),F,m?.layout||"default");for(const e of ke)y("#field-project").append(new Option(e.name||e.slug,e.slug));const Ee=[...Array.isArray(ae)?ae:[]].sort((e,t)=>(e.title||e.urlPath).localeCompare(t.title||t.urlPath));for(const e of Ee)y("#quick-switch").append(new Option(`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath,!1,e.urlPath===d));const q=j(),a={urlPath:M.observable(d||""),title:M.observable(m?.title||""),description:M.observable(m?.description||""),layout:M.observable(at),status:M.observable(m?.status||"draft"),sortOrder:M.observable(String(m?.sortOrder??99)),showInNav:M.observable(!!m?.showInNav),sidebar:M.observable(!!m?.sidebar),breadcrumbs:M.observable(m?m.breadcrumbs!==!1:!0),bundled:M.observable(!!m?.bundled),tags:M.observable(Array.isArray(m?.tags)?m.tags:[]),adminTags:M.observable(Array.isArray(m?.adminTags)?m.adminTags:[]),category:M.observable(m?.category||""),visibility:M.observable(typeof m?.visibility=="string"&&m.visibility?m.visibility:"public"),project:M.observable(Bt({isEdit:v,page:m,projects:ke,fromHash:Dt()||"",urlPath:d||""})),theme:M.observable(m?.theme||""),seoTitle:M.observable(m?.seo?.title||""),seoDesc:M.observable(m?.seo?.description||""),dconfig:M.observable(m?.dconfig?JSON.stringify(m.dconfig,null,2):""),css:M.observable(""),cssOpened:M.observable(!1)},n={bodyRev:M.observable(0),base:M.observable(""),saving:M.observable(!1),tab:M.observable("edit"),viewMode:M.observable(Ze.includes(q.viewMode)?q.viewMode:"split"),fullscreen:M.observable(!!q.fullscreen),cssMode:M.observable(!1),folded:M.observable(!1),liveStatus:M.observable("Showing unsaved changes"),liveWidth:M.observable("full"),versions:M.observable([]),histLoading:M.observable(!1),histError:M.observable(""),compare:M.observable(null)},k=y("#markdown-editor"),I=y("#css-editor");k.value=m?.content||"";const L=document.createElement("div");L.className="editor-line-numbers editor-line-numbers--foldable",k.parentElement.insertBefore(L,k);const x=Et(k,L,{onFoldChange:()=>{}});let D=!1;x.setGuard(e=>{D=e});const B=()=>x.getUnfoldedContent(),Me=M.observable(X(q.type));o(M.effect(()=>{const e=Me.value,t=y("#editor-body");if(t){Ge(e.font);for(const[g,h]of Object.entries(Je(e)))t.style.setProperty(g,h);t.classList.toggle("pe-nowrap",!e.wrap),k.wrap=e.wrap?"soft":"off",I.wrap=e.wrap?"soft":"off"}}));let Se=null;o(()=>{try{Se?.close()}catch{}});const A=()=>(n.bodyRev.value,{urlPath:a.urlPath.value.trim(),title:a.title.value,description:a.description.value,layout:a.layout.value,status:a.status.value,sortOrder:a.sortOrder.value,showInNav:a.showInNav.value,sidebar:a.sidebar.value,breadcrumbs:a.breadcrumbs.value,bundled:a.bundled.value,tags:a.tags.value,adminTags:a.adminTags.value,category:a.category.value,visibility:a.visibility.value,project:a.project.value,theme:a.theme.value,seoTitle:a.seoTitle.value,seoDesc:a.seoDesc.value,dconfig:a.dconfig.value,body:B(),css:a.cssOpened.value?a.css.value:null}),st=M.computed(()=>z(A())!==n.base.value),ot=M.computed(()=>we({urlPath:a.urlPath.value,dconfig:a.dconfig.value})[0]?.text||""),nt=M.computed(()=>n.versions.value.some(e=>e.checked.value)),rt=M.computed(()=>n.versions.value.length>0&&n.versions.value.every(e=>e.checked.value)),it=M.computed(()=>{const e=n.versions.value.filter(t=>t.checked.value).length;return e>0&&e<n.versions.value.length});i=()=>z(A())!==n.base.peek();let Te=JSON.stringify(a.adminTags.peek());const H=e=>({title:a.title.peek().trim()||"Untitled",description:a.description.peek().trim(),layout:a.layout.peek(),status:a.status.peek(),sortOrder:parseInt(String(a.sortOrder.peek()),10)||99,showInNav:a.showInNav.peek(),sidebar:a.sidebar.peek(),...a.breadcrumbs.peek()?{}:{breadcrumbs:!1},...a.bundled.peek()?{bundled:!0}:{},tags:a.tags.peek(),...v&&JSON.stringify(a.adminTags.peek())===Te?{}:{adminTags:a.adminTags.peek()},category:a.category.peek().trim()||null,visibility:a.visibility.peek()||"public",project:a.project.peek()||"",seo:{title:a.seoTitle.peek().trim(),description:a.seoDesc.peek().trim()},dconfig:e,...a.theme.peek()?{theme:a.theme.peek()}:{}}),se=()=>{const e=a.dconfig.peek().trim();if(!e)return null;try{return JSON.parse(e)}catch{return null}},Ce=()=>a.urlPath.peek().trim()||d||"/",K=y("#markdown-preview");let xe="";b.settings.getCustomCss().then(({css:e})=>{xe=e||""}).catch(()=>{});const Pe=()=>{const e=K?.contentDocument;if(!e?.head)return;const t=a.cssOpened.peek()?a.css.peek():"";if(!t)return;let g=e.getElementById("preview-custom-css");g||(g=e.createElement("style"),g.id="preview-custom-css",e.head.appendChild(g)),g.textContent=t};let oe=null;const U=()=>{clearTimeout(oe),oe=setTimeout(async()=>{if(!(!K||n.viewMode.peek()==="write"))try{const{html:e}=await b.pages.previewFull(Ce(),H(se()),B());u()&&Qe(K,Gt(e),Pe)}catch(e){K.srcdoc='<!doctype html><meta charset="utf-8"><body style="font:14px system-ui;padding:1rem;color:#b91c1c;">Preview failed: '+String(e?.message||"unknown error").replace(/[<&]/g,t=>t==="<"?"&lt;":"&amp;")+"</body>"}},500)},Le=y("#live-preview-frame");let ne=!0,re=null,ie=!1;const le=async()=>{if(!(ie||!Le)){ie=!0,n.liveStatus.value="Rendering\u2026";try{const{html:e}=await b.pages.previewFull(Ce(),H(se()),B());if(!u())return;Qe(Le,e),ne=!1,n.liveStatus.value="Showing unsaved changes"}catch(e){n.liveStatus.value="Preview failed - "+(e?.message||"unknown error")}finally{ie=!1}}},Ae=()=>{ne=!0,n.tab.peek()==="live"&&(clearTimeout(re),re=setTimeout(le,600))};o(()=>{clearTimeout(oe),clearTimeout(re)});const ce=gt(s.find("#markdown-editor"),s.find("#editor-toolbar"),{spacerDefault:V?.layoutOptions?.spacerSize??40});yt(k);const de=c.querySelector(".editor-toolbar-right");de.querySelectorAll(".editor-view-btn[data-mode]").forEach(e=>{const t=e.getAttribute("data-mode");e.classList.remove("active"),e.setAttribute("data-bind-class",`viewMode.value === '${t}' && 'active'`),e.setAttribute("data-on-click",`setMode('${t}')`)}),y("#fullscreen-btn")?.setAttribute("data-on-click","toggleFullscreen");const lt=ee(`
81
+ `)}const Ze="editor_prefs";function q(){return S.get(Ze)||{viewMode:"split",fullscreen:!1}}function ae(o,i){const l=q();l[o]=i,S.set(Ze,l)}const Qt=["edit","details","seo","dconfig","live","history"],Qe=["split","write","preview"],ea=o=>o.replace(/<\/head>/i,"<style>body.dm-cloaked{opacity:1 !important;transition:none !important}</style></head>");function et(o,i,l=()=>{}){let s=0;try{s=o.contentWindow.scrollY||0}catch{}o.addEventListener("load",()=>{try{o.contentWindow.scrollTo(0,s)}catch{}l()},{once:!0}),o.srcdoc=i}export const pageEditorView={templateUrl:"/admin/js/templates/page-editor.html",async onMount(o){if(Xt(),T){const e=T;T=null,e.dispose()}const i=window.location.hash.replace(/^#/,""),l=[],s=e=>(l.push(e),e);let r=()=>!1,v=()=>{};const u={path:i,dirty:()=>r(),keepDraft:()=>v(),dispose:()=>{l.splice(0).forEach(e=>{try{e()}catch{}})}};T=u;const p=o.get(0),c=()=>T===u&&p.isConnected,C=window.location.hash.match(/#\/pages\/edit(\/[^?]*)/),d=C?C[1]:null,h=!!d,b=E.loader(p,{type:"dots"}),[L,$,m,P,ke,tt,at]=await Promise.all([g.layouts.get().catch(()=>({})),g.settings.get().catch(()=>({})),h?g.pages.get(d).catch(()=>null):null,h?g.pages.list().catch(()=>[]):[],g.projects.list().catch(()=>[]),g.pages.tags().catch(()=>[]),g.listTags.list("pages").then(e=>e.map(t=>t.name)).catch(()=>[])]);if(!c()){b.destroy();return}if(b.destroy(),h&&!m){E.toast("Page not found.",{type:"error"}),R.navigate("/pages");return}const w=e=>p.querySelector(e);if(St(w("#field-theme"),{includeDefault:!0}),await na(w("#field-visibility"),m?.visibility),!c())return;const st=oa(w("#field-layout"),L,m?.layout||"default");for(const e of ke)w("#field-project").append(new Option(e.name||e.slug,e.slug));const Ee=[...Array.isArray(P)?P:[]].sort((e,t)=>(e.title||e.urlPath).localeCompare(t.title||t.urlPath));for(const e of Ee)w("#quick-switch").append(new Option(`${e.title||"Untitled"} (${e.urlPath})`,e.urlPath,!1,e.urlPath===d));const H=q(),a={urlPath:M.observable(d||""),title:M.observable(m?.title||""),description:M.observable(m?.description||""),layout:M.observable(st),status:M.observable(m?.status||"draft"),sortOrder:M.observable(String(m?.sortOrder??99)),showInNav:M.observable(!!m?.showInNav),sidebar:M.observable(!!m?.sidebar),breadcrumbs:M.observable(m?m.breadcrumbs!==!1:!0),bundled:M.observable(!!m?.bundled),tags:M.observable(Array.isArray(m?.tags)?m.tags:[]),adminTags:M.observable(Array.isArray(m?.adminTags)?m.adminTags:[]),category:M.observable(m?.category||""),visibility:M.observable(typeof m?.visibility=="string"&&m.visibility?m.visibility:"public"),project:M.observable(qt({isEdit:h,page:m,projects:ke,fromHash:Ft()||"",urlPath:d||""})),theme:M.observable(m?.theme||""),seoTitle:M.observable(m?.seo?.title||""),seoDesc:M.observable(m?.seo?.description||""),dconfig:M.observable(m?.dconfig?JSON.stringify(m.dconfig,null,2):""),css:M.observable(""),cssOpened:M.observable(!1)},n={bodyRev:M.observable(0),base:M.observable(""),saving:M.observable(!1),tab:M.observable("edit"),viewMode:M.observable(Qe.includes(H.viewMode)?H.viewMode:"split"),fullscreen:M.observable(!!H.fullscreen),cssMode:M.observable(!1),folded:M.observable(!1),liveStatus:M.observable("Showing unsaved changes"),liveWidth:M.observable("full"),versions:M.observable([]),histLoading:M.observable(!1),histError:M.observable(""),compare:M.observable(null)},k=w("#markdown-editor"),F=w("#css-editor");k.value=m?.content||"";const ot=We(k),nt=We(F);s(()=>ot.destroy()),s(()=>nt.destroy());const O=document.createElement("div");O.className="editor-line-numbers editor-line-numbers--foldable",k.parentElement.insertBefore(O,k);const x=Tt(k,O,{onFoldChange:()=>{}});let I=!1;x.setGuard(e=>{I=e});const z=()=>x.getUnfoldedContent(),Me=M.observable(Z(H.type));s(M.effect(()=>{const e=Me.value,t=w("#editor-body");if(t){Ye(e.font);for(const[f,y]of Object.entries(Je(e)))t.style.setProperty(f,y);t.classList.toggle("pe-nowrap",!e.wrap),k.wrap=e.wrap?"soft":"off",F.wrap=e.wrap?"soft":"off"}}));let Se=null;s(()=>{try{Se?.close()}catch{}});const D=()=>(n.bodyRev.value,{urlPath:a.urlPath.value.trim(),title:a.title.value,description:a.description.value,layout:a.layout.value,status:a.status.value,sortOrder:a.sortOrder.value,showInNav:a.showInNav.value,sidebar:a.sidebar.value,breadcrumbs:a.breadcrumbs.value,bundled:a.bundled.value,tags:a.tags.value,adminTags:a.adminTags.value,category:a.category.value,visibility:a.visibility.value,project:a.project.value,theme:a.theme.value,seoTitle:a.seoTitle.value,seoDesc:a.seoDesc.value,dconfig:a.dconfig.value,body:z(),css:a.cssOpened.value?a.css.value:null}),rt=M.computed(()=>V(D())!==n.base.value),it=M.computed(()=>we({urlPath:a.urlPath.value,dconfig:a.dconfig.value})[0]?.text||""),lt=M.computed(()=>n.versions.value.some(e=>e.checked.value)),ct=M.computed(()=>n.versions.value.length>0&&n.versions.value.every(e=>e.checked.value)),dt=M.computed(()=>{const e=n.versions.value.filter(t=>t.checked.value).length;return e>0&&e<n.versions.value.length});r=()=>V(D())!==n.base.peek();let Te=JSON.stringify(a.adminTags.peek());const K=e=>({title:a.title.peek().trim()||"Untitled",description:a.description.peek().trim(),layout:a.layout.peek(),status:a.status.peek(),sortOrder:parseInt(String(a.sortOrder.peek()),10)||99,showInNav:a.showInNav.peek(),sidebar:a.sidebar.peek(),...a.breadcrumbs.peek()?{}:{breadcrumbs:!1},...a.bundled.peek()?{bundled:!0}:{},tags:a.tags.peek(),...h&&JSON.stringify(a.adminTags.peek())===Te?{}:{adminTags:a.adminTags.peek()},category:a.category.peek().trim()||null,visibility:a.visibility.peek()||"public",project:a.project.peek()||"",seo:{title:a.seoTitle.peek().trim(),description:a.seoDesc.peek().trim()},dconfig:e,...a.theme.peek()?{theme:a.theme.peek()}:{}}),se=()=>{const e=a.dconfig.peek().trim();if(!e)return null;try{return JSON.parse(e)}catch{return null}},Ce=()=>a.urlPath.peek().trim()||d||"/",U=w("#markdown-preview");let xe="";g.settings.getCustomCss().then(({css:e})=>{xe=e||""}).catch(()=>{});const Pe=()=>{const e=U?.contentDocument;if(!e?.head)return;const t=a.cssOpened.peek()?a.css.peek():"";if(!t)return;let f=e.getElementById("preview-custom-css");f||(f=e.createElement("style"),f.id="preview-custom-css",e.head.appendChild(f)),f.textContent=t};let oe=null;const _=()=>{clearTimeout(oe),oe=setTimeout(async()=>{if(!(!U||n.viewMode.peek()==="write"))try{const{html:e}=await g.pages.previewFull(Ce(),K(se()),z());c()&&et(U,ea(e),Pe)}catch(e){U.srcdoc='<!doctype html><meta charset="utf-8"><body style="font:14px system-ui;padding:1rem;color:#b91c1c;">Preview failed: '+String(e?.message||"unknown error").replace(/[<&]/g,t=>t==="<"?"&lt;":"&amp;")+"</body>"}},500)},Ae=w("#live-preview-frame");let ne=!0,re=null,ie=!1;const le=async()=>{if(!(ie||!Ae)){ie=!0,n.liveStatus.value="Rendering\u2026";try{const{html:e}=await g.pages.previewFull(Ce(),K(se()),z());if(!c())return;et(Ae,e),ne=!1,n.liveStatus.value="Showing unsaved changes"}catch(e){n.liveStatus.value="Preview failed - "+(e?.message||"unknown error")}finally{ie=!1}}},Le=()=>{ne=!0,n.tab.peek()==="live"&&(clearTimeout(re),re=setTimeout(le,600))};s(()=>{clearTimeout(oe),clearTimeout(re)});const ce=yt(o.find("#markdown-editor"),o.find("#editor-toolbar"),{spacerDefault:$?.layoutOptions?.spacerSize??40});Et(k);const de=p.querySelector(".editor-toolbar-right");de.querySelectorAll(".editor-view-btn[data-mode]").forEach(e=>{const t=e.getAttribute("data-mode");e.classList.remove("active"),e.setAttribute("data-bind-class",`viewMode.value === '${t}' && 'active'`),e.setAttribute("data-on-click",`setMode('${t}')`)}),w("#fullscreen-btn")?.setAttribute("data-on-click","toggleFullscreen");const pt=te(`
75
82
  <span class="pe-toolbar-extras" style="display:contents">
76
83
  <button type="button" class="editor-view-btn" data-tip="Edit Custom CSS" data-on-click="toggleCss"
77
84
  data-bind-class="cssMode.value && 'active'"><span>CSS</span></button>
@@ -83,5 +90,5 @@ The quick brown fox - 0O 1lI {} [] () =&gt; ==
83
90
  <span class="pe-fold-icon" hidden data-bind-hidden="!folded.value"><span data-icon="chevrons-right" data-icon-size="10"></span></span>
84
91
  </button>
85
92
  <span class="editor-toolbar-sep"></span>
86
- </span>`);de.prepend(lt);const Oe=e=>(Array.isArray(e)?e:[]).map(t=>({value:t,label:t})),De=y("#field-tags");let _=null;_=De?E.pillbox(De,{data:Oe(et),value:a.tags.peek(),creatable:!0,searchable:!0,placeholder:"Add tag\u2026",onChange:()=>{_&&(a.tags.value=[..._.getValue()])}}):null;const Re=y("#field-admin-tags");let J=null;J=Re?E.pillbox(Re,{data:Oe(tt),value:a.adminTags.peek(),creatable:!0,searchable:!0,placeholder:"Add admin tag\u2026",onChange:()=>{J&&(a.adminTags.value=[...J.getValue()])}}):null;let pe=!1,ue=null;const W=async()=>{pe=!0,n.histLoading.value=!0,n.histError.value="";try{const e=(await b.versions.list(d)).versions||[];if(!u())return;n.versions.value=e.map(t=>({...t,when:Q(t.createdAt),author:t.author||"",label:t.label||"",checked:M.observable(!1)}))}catch(e){n.histError.value="Failed to load versions: "+e.message}finally{n.histLoading.value=!1}},ve=e=>n.versions.peek().find(t=>t.filename===e),fe=async e=>{try{const t=await b.versions.get(d,e.filename);ue=e.filename,n.compare.value={label:We(e),old:t.content,current:B()}}catch(t){E.toast("Failed to load version: "+t.message,{type:"error"})}},Ne=async e=>{if(!(!e||!await E.confirm("Restore this version? The current page content will be overwritten (a pre-restore snapshot will be saved automatically).")))try{await b.versions.restore(d,e),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${d}`),300)}catch(t){E.toast("Restore failed: "+t.message,{type:"error"})}},ct=async e=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await b.versions.delete(d,e.filename),E.toast("Version deleted.",{type:"success"}),await W()}catch(t){E.toast("Failed to delete: "+t.message,{type:"error"})}},Fe=()=>{n.bodyRev.value=n.bodyRev.peek()+1},Ie=()=>{a.cssOpened.peek()||(a.css.value=xe,a.cssOpened.value=!0,mt(I))},Be=e=>{for(const t of["urlPath","title","description","layout","status","sortOrder","category","visibility","project","theme","seoTitle","seoDesc","dconfig"])a[t].value=e[t]==null?"":String(e[t]);for(const t of["showInNav","sidebar","breadcrumbs","bundled"])a[t].value=!!e[t];a.tags.value=Array.isArray(e.tags)?e.tags:[],_?.setValue(a.tags.peek()),Array.isArray(e.adminTags)&&(a.adminTags.value=e.adminTags),J?.setValue(a.adminTags.peek()),x.unfoldAll(),D=!0,k.value=e.body==null?"":String(e.body),D=!1,x.refresh(),e.css!=null&&(Ie(),a.css.value=String(e.css)),Fe()};n.base.value=z(A());const G=It(d||"");f=()=>{if(i())try{S.set(G,$t(A(),n.base.peek()))}catch{}};const me=()=>{try{S.remove?S.remove(G):S.set(G,null)}catch{}},$e=e=>{i()&&(f(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",$e),o(()=>window.removeEventListener("beforeunload",$e));const ze=async()=>{if(n.saving.peek())return;const e=A(),t=we(e);if(t.length){E.toast(t[0].text,{type:"warning"}),c.querySelectorAll("#editor-meta-tabs .tab-item")[Wt.indexOf(t[0].field==="dconfig"?"dconfig":"details")]?.click();return}const g=(e.dconfig||"").trim(),h=H(g?JSON.parse(g):null),P=a.cssOpened.peek();n.saving.value=!0;try{if(v){const O={frontmatter:h,body:e.body};e.urlPath!==d&&(O.newUrlPath=e.urlPath),await b.pages.update(d,O)}else await b.pages.create({urlPath:e.urlPath,frontmatter:h,body:e.body});P&&await b.settings.saveCustomCss(a.css.peek()),E.toast(P?"Page and CSS saved.":"Page saved.",{type:"success"}),me(),Te=JSON.stringify(a.adminTags.peek()),n.base.value=z(A()),v?e.urlPath!==d&&R.navigate(`/pages/edit${e.urlPath}`):R.navigate("/pages")}catch(O){E.toast(`Save failed: ${O.message||"Unknown error"}`,{type:"error"})}finally{n.saving.value=!1}},je=c.querySelector(".dm-plugin-body")||c,dt={...a,...n,dirty:st,problem:ot,anySelected:nt,allSelected:rt,someSelected:it,isEdit:v,savedPath:d||"",hasPages:Ee.length>0},pt={save:()=>ze(),discard:async()=>{!i()||!await E.confirm("Discard the changes you have not saved?")||(Be(JSON.parse(n.base.peek())),me())},switchPage:e=>{const t=e?.target?.value;t&&R.navigate("/pages/edit"+t)},showTab:e=>{n.tab.value=e,e==="live"&&ne&&le(),e==="history"&&v&&!pe&&W()},setMode:e=>{n.cssMode.peek()&&(n.cssMode.value=!1),n.viewMode.value=e,te("viewMode",e),e!=="write"&&U()},toggleFullscreen:()=>{n.fullscreen.value=!n.fullscreen.peek(),te("fullscreen",n.fullscreen.peek())},toggleCss:()=>{n.cssMode.peek()?(n.cssMode.value=!1,n.viewMode.value=Ze.includes(j().viewMode)?j().viewMode:"split",x.refresh()):(Ie(),n.cssMode.value=!0,n.viewMode.value="split")},formatMarkdown:()=>{const e=k.selectionStart,t=Jt(B());x.unfoldAll(),D=!0,k.value=t,D=!1,k.selectionStart=k.selectionEnd=Math.min(e,t.length),k.dispatchEvent(new Event("input")),x.refresh(),E.toast("Markdown formatted.",{type:"success"})},toggleFold:()=>{n.folded.peek()?x.unfoldAll():x.foldAll(),n.folded.value=!n.folded.peek()},setWidth:e=>{n.liveWidth.value=e;const t=y("#live-preview-stage");t&&(t.scrollTop=0)},refreshLive:()=>le(),share:async()=>{if(!v){E.toast("Save the page first - a share link needs a page to point at.",{type:"warning"});return}await Kt(d)},toggleAll:e=>{const t=!!e?.target?.checked;n.versions.peek().forEach(g=>{g.checked.value=t})},deleteSelected:async()=>{const e=n.versions.peek().filter(g=>g.checked.peek()).map(g=>g.filename),t=e.length;if(!(!t||!await E.confirm(`Delete ${t} version${t>1?"s":""}? This cannot be undone.`)))try{await b.versions.bulkDelete(d,e),E.toast(`${t} version${t>1?"s":""} deleted.`,{type:"success"}),await W()}catch(g){E.toast("Delete failed: "+g.message,{type:"error"})}},saveNamed:async()=>{await Ut(d)&&u()&&(n.tab.peek()==="history"?await W():pe=!1)},closeCompare:()=>{n.compare.value=null,ue=null},restoreCompared:()=>Ne(ue)};de.querySelectorAll("[data-tip]").forEach(e=>E.tooltip(e,{content:e.getAttribute("data-tip"),position:"top"}));const ut=M.applyBindings(dt,je,{methods:pt});o(()=>ut.dispose()),E.tabs(y("#editor-meta-tabs"));let ge=null;o(()=>clearTimeout(ge)),k.addEventListener("input",()=>{x.refresh(),L.scrollTop=k.scrollTop,!D&&(clearTimeout(ge),ge=setTimeout(Fe,120),U(),Ae())}),k.addEventListener("scroll",()=>{L.scrollTop=k.scrollTop}),I.addEventListener("scroll",()=>{L.scrollTop=I.scrollTop});let Ve=!0;o(M.effect(()=>{for(const e of Object.keys(a))e!=="css"&&e!=="cssOpened"&&a[e].value;if(n.bodyRev.value,Ve){Ve=!1,U();return}U(),Ae()}));let be=null;if(o(()=>clearTimeout(be)),o(M.effect(()=>{const e=a.css.value;n.cssMode.value&&(Yt(L,e,I),clearTimeout(be),be=setTimeout(Pe,400))})),v){const e=y(".pe-version-list"),t=E.contextMenu(e,{cursor:"glyph",match:"tr[data-file]",inherit:!1,density:"compact",items:g=>{const h=ve(g.dataset.file);return h?[{header:We(h)},{label:"Compare with the editor",icon:"columns",action:()=>fe(h)},{label:"Restore this version\u2026",icon:"rotate-ccw",action:()=>Ne(h.filename)},{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>ct(h)}]:[]}});o(()=>t?.destroy?.()),e.addEventListener("click",g=>{const h=g.target.closest("tr[data-file]");if(!h||g.target.matches("input"))return;const P=g.target.closest(".pe-kebab");if(P){Ue(P);return}const O=ve(h.dataset.file);O&&fe(O)}),e.addEventListener("keydown",g=>{const h=g.target.closest("tr[data-file]");if(h){if(g.key==="F10"&&g.shiftKey)g.preventDefault(),Ue(h);else if(g.key==="Enter"&&g.target===h){const P=ve(h.dataset.file);P&&fe(P)}}})}Xt(y("#editor-body"),y("#editor-divider"),o),wt({image:e=>(n.cssMode.value=!1,Zt(e)),scribe:e=>Mt(e),card:e=>vt.open(e,{onMediaBrowse:()=>b.media.list().catch(()=>[])}),timeline:e=>ft.open(e,{onPreview:async t=>{try{return await b.pages.preview(t)}catch{return null}},onListCollections:()=>b.collections.list().catch(()=>[]),onGetCollection:t=>b.collections.get(t).catch(()=>null)})}),ce.onEffects(e=>ht.open(e)),ce.onHelp(()=>_e()),ce.onTutorial(e=>St(e));const qe=e=>{(e.ctrlKey||e.metaKey)&&!e.shiftKey&&!e.altKey&&e.key.toLowerCase()==="s"&&u()&&(e.preventDefault(),ze())};document.addEventListener("keydown",qe),o(()=>document.removeEventListener("keydown",qe));const Y=c.querySelector(".dm-plugin-banner-name");o(M.effect(()=>{const e=Nt(v,a.title.value,d);if(!u()||(document.title=`${e} - Domma CMS`,!Y))return;const t=Y.lastChild;t&&t.nodeType===3&&Y.querySelector(".dm-plugin-banner-sep")?t.textContent=e:Y.textContent=`Pages \u203A ${e}`})),$(s,{id:"page-editor-back",icon:"arrow-left",title:"Back to Pages",onClick:()=>R.navigate("/pages")}),$(s,{id:"page-editor-help",icon:"help-circle",title:"Editor reference",onClick:()=>_e()}),v&&$(s,{id:"page-editor-view",icon:"external-link",title:"View on the site",onClick:()=>window.open(a.urlPath.peek()||d,"_blank","noopener")});const he=$(s,{id:"page-editor-clone",icon:"copy",title:"Clone page",onClick:()=>{if(!v||n.saving.peek()||!u())return;const e=A(),t=we({...e,urlPath:d});if(t.length){E.toast(t[0].text,{type:"warning"});return}const g=Ct({page:m,frontmatter:{...H(se()),adminTags:a.adminTags.peek()},body:e.body,source:d,pages:ae,onCloned:h=>{u()&&(p.cloneTarget=`/pages/edit${h}`,R.navigate(p.cloneTarget))}});o(()=>g.close())}});he&&(he.disabled=!v,v||(he.title="Save the page before cloning it")),$(s,{id:"page-editor-settings",icon:"settings",title:"Editor settings - font, size, spacing",onClick:()=>{Se=Ht(Me)}}),o(Ke(je,{position:"bottom"})),Domma.icons.scan();let He=null;try{He=S.get(G)}catch{}const N=zt(He);if(N&&(me(),z(N.state)!==n.base.peek())){const e=N.at?` (${Q(N.at)})`:"",t=Ft(N,n.base.peek())?" The saved page has changed since - restoring puts your version back over it (the saved one stays in History).":"";await E.confirm(`You left unsaved changes to this page${e}. Restore them?${t}`)&&u()&&Be(N.state)}}};function Yt(s,r,l){s.replaceChildren(...String(r).split(`
87
- `).map((o,i)=>{const f=document.createElement("span");f.className="editor-line-number-row";const p=document.createElement("span");p.className="fold-toggle fold-toggle--empty";const c=document.createElement("span");return c.className="editor-line-num",c.textContent=String(i+1),f.append(p,c),f})),s.scrollTop=l.scrollTop}function Xt(s,r,l){if(!s||!r)return;const o=15,i=85,f=d=>Math.min(i,Math.max(o,d));let p=f(parseFloat(j().splitRatio)||50);const c=d=>{s.style.setProperty("--dm-editor-split",p+"%"),r.setAttribute("aria-valuenow",String(Math.round(p))),d&&te("splitRatio",p)};c(!1);const u=d=>{const v=s.getBoundingClientRect();v.width&&(p=f((d.clientX-v.left)/v.width*100)),c(!1)},C=()=>{document.removeEventListener("pointermove",u),document.removeEventListener("pointerup",C),s.classList.remove("is-resizing"),r.classList.remove("is-dragging"),c(!0)};l(C),r.addEventListener("pointerdown",d=>{window.matchMedia("(max-width: 768px)").matches||(d.preventDefault(),s.classList.add("is-resizing"),r.classList.add("is-dragging"),document.addEventListener("pointermove",u),document.addEventListener("pointerup",C))}),r.addEventListener("dblclick",()=>{p=50,c(!0)}),r.addEventListener("keydown",d=>{const v=d.shiftKey?10:2;let T=p;if(d.key==="ArrowLeft")T=p-v;else if(d.key==="ArrowRight")T=p+v;else if(d.key==="Home")T=o;else if(d.key==="End")T=i;else if(d.key==="Enter"||d.key===" ")T=50;else return;d.preventDefault(),p=f(T),c(!0)})}async function Zt(s){const r=s.selectionStart,l=s.selectionEnd,o=await Tt({title:"Upload or insert an image"});if(!o||!s.isConnected)return;let i=o.split("/").pop().split("?")[0];try{i=decodeURIComponent(i)}catch{}const f=i.replace(/[\\[\]]/g,"\\$&"),p=o.replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/ /g,"%20");s.setSelectionRange(r,l),bt(s,`![${f}](${p})`),s.dispatchEvent(new Event("input",{bubbles:!0}))}function Qt(s,r,l){const o=Object.entries(r||{});return s?(s.replaceChildren(...o.map(([i,f])=>new Option(f?.label||i,i))),o.some(([i])=>i===l)?l:o[0]?.[0]||l):l}async function ea(s,r){if(!s)return;let l=[];try{const u=await b.get("/collections/roles/entries?limit=100");l=Array.isArray(u)?u:u?.entries||[]}catch{}const o=l.map(u=>({name:u.data?.name,label:u.data?.label||u.data?.name,level:u.data?.level??99})).filter(u=>u.name&&u.level!==0).sort((u,C)=>C.level-u.level),i=(u,C)=>Object.assign(document.createElement("option"),{value:u,textContent:C}),f=()=>{typeof r=="string"&&r&&![...s.options].some(u=>u.value===r)&&s.append(i(r,`${r} (custom)`))};if(!o.length)return f();const p=document.createElement("optgroup");p.label="Role and above",o.forEach(u=>p.append(i(u.name,`${u.label} and above`)));const c=document.createElement("optgroup");c.label="Role only",o.forEach(u=>c.append(i(`=${u.name}`,`${u.label} only`))),s.replaceChildren(i("public","Public - everyone"),p,c,i("private","Private - super-admin only")),f()}
93
+ </span>`);de.prepend(pt);const Oe=e=>(Array.isArray(e)?e:[]).map(t=>({value:t,label:t})),De=w("#field-tags");let J=null;J=De?E.pillbox(De,{data:Oe(tt),value:a.tags.peek(),creatable:!0,searchable:!0,placeholder:"Add tag\u2026",onChange:()=>{J&&(a.tags.value=[...J.getValue()])}}):null;const Re=w("#field-admin-tags");let W=null;W=Re?E.pillbox(Re,{data:Oe(at),value:a.adminTags.peek(),creatable:!0,searchable:!0,placeholder:"Add admin tag\u2026",onChange:()=>{W&&(a.adminTags.value=[...W.getValue()])}}):null;let pe=!1,ue=null;const G=async()=>{pe=!0,n.histLoading.value=!0,n.histError.value="";try{const e=(await g.versions.list(d)).versions||[];if(!c())return;n.versions.value=e.map(t=>({...t,when:ee(t.createdAt),author:t.author||"",label:t.label||"",checked:M.observable(!1)}))}catch(e){n.histError.value="Failed to load versions: "+e.message}finally{n.histLoading.value=!1}},ve=e=>n.versions.peek().find(t=>t.filename===e),fe=async e=>{try{const t=await g.versions.get(d,e.filename);ue=e.filename,n.compare.value={label:Ge(e),old:t.content,current:z()}}catch(t){E.toast("Failed to load version: "+t.message,{type:"error"})}},Ne=async e=>{if(!(!e||!await E.confirm("Restore this version? The current page content will be overwritten (a pre-restore snapshot will be saved automatically).")))try{await g.versions.restore(d,e),E.toast("Page restored. Reloading editor\u2026",{type:"success"}),R.navigate("/pages"),setTimeout(()=>R.navigate(`/pages/edit${d}`),300)}catch(t){E.toast("Restore failed: "+t.message,{type:"error"})}},ut=async e=>{if(await E.confirm("Delete this version? This cannot be undone."))try{await g.versions.delete(d,e.filename),E.toast("Version deleted.",{type:"success"}),await G()}catch(t){E.toast("Failed to delete: "+t.message,{type:"error"})}},Fe=()=>{n.bodyRev.value=n.bodyRev.peek()+1},Ie=()=>{a.cssOpened.peek()||(a.css.value=xe,a.cssOpened.value=!0,ht(F))},Be=e=>{for(const t of["urlPath","title","description","layout","status","sortOrder","category","visibility","project","theme","seoTitle","seoDesc","dconfig"])a[t].value=e[t]==null?"":String(e[t]);for(const t of["showInNav","sidebar","breadcrumbs","bundled"])a[t].value=!!e[t];a.tags.value=Array.isArray(e.tags)?e.tags:[],J?.setValue(a.tags.peek()),Array.isArray(e.adminTags)&&(a.adminTags.value=e.adminTags),W?.setValue(a.adminTags.peek()),x.unfoldAll(),I=!0,k.value=e.body==null?"":String(e.body),I=!1,x.refresh(),e.css!=null&&(Ie(),a.css.value=String(e.css)),Fe()};n.base.value=V(D());const Y=Vt(d||"");v=()=>{if(r())try{S.set(Y,Ht(D(),n.base.peek()))}catch{}};const me=()=>{try{S.remove?S.remove(Y):S.set(Y,null)}catch{}},$e=e=>{r()&&(v(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",$e),s(()=>window.removeEventListener("beforeunload",$e));const ze=async()=>{if(n.saving.peek())return;const e=D(),t=we(e);if(t.length){E.toast(t[0].text,{type:"warning"}),p.querySelectorAll("#editor-meta-tabs .tab-item")[Qt.indexOf(t[0].field==="dconfig"?"dconfig":"details")]?.click();return}const f=(e.dconfig||"").trim(),y=K(f?JSON.parse(f):null),A=a.cssOpened.peek();n.saving.value=!0;try{if(h){const N={frontmatter:y,body:e.body};e.urlPath!==d&&(N.newUrlPath=e.urlPath),await g.pages.update(d,N)}else await g.pages.create({urlPath:e.urlPath,frontmatter:y,body:e.body});A&&await g.settings.saveCustomCss(a.css.peek()),E.toast(A?"Page and CSS saved.":"Page saved.",{type:"success"}),me(),Te=JSON.stringify(a.adminTags.peek()),n.base.value=V(D()),h?e.urlPath!==d&&R.navigate(`/pages/edit${e.urlPath}`):R.navigate("/pages")}catch(N){E.toast(`Save failed: ${N.message||"Unknown error"}`,{type:"error"})}finally{n.saving.value=!1}},je=p.querySelector(".dm-plugin-body")||p,vt={...a,...n,dirty:rt,problem:it,anySelected:lt,allSelected:ct,someSelected:dt,isEdit:h,savedPath:d||"",hasPages:Ee.length>0},ft={save:()=>ze(),discard:async()=>{!r()||!await E.confirm("Discard the changes you have not saved?")||(Be(JSON.parse(n.base.peek())),me())},switchPage:e=>{const t=e?.target?.value;t&&R.navigate("/pages/edit"+t)},showTab:e=>{n.tab.value=e,e==="live"&&ne&&le(),e==="history"&&h&&!pe&&G()},setMode:e=>{n.cssMode.peek()&&(n.cssMode.value=!1),n.viewMode.value=e,ae("viewMode",e),e!=="write"&&_()},toggleFullscreen:()=>{n.fullscreen.value=!n.fullscreen.peek(),ae("fullscreen",n.fullscreen.peek())},toggleCss:()=>{n.cssMode.peek()?(n.cssMode.value=!1,n.viewMode.value=Qe.includes(q().viewMode)?q().viewMode:"split",x.refresh()):(Ie(),n.cssMode.value=!0,n.viewMode.value="split")},formatMarkdown:()=>{const e=k.selectionStart,t=Zt(z());x.unfoldAll(),I=!0,k.value=t,I=!1,k.selectionStart=k.selectionEnd=Math.min(e,t.length),k.dispatchEvent(new Event("input")),x.refresh(),E.toast("Markdown formatted.",{type:"success"})},toggleFold:()=>{n.folded.peek()?x.unfoldAll():x.foldAll(),n.folded.value=!n.folded.peek()},setWidth:e=>{n.liveWidth.value=e;const t=w("#live-preview-stage");t&&(t.scrollTop=0)},refreshLive:()=>le(),share:async()=>{if(!h){E.toast("Save the page first - a share link needs a page to point at.",{type:"warning"});return}await Gt(d)},toggleAll:e=>{const t=!!e?.target?.checked;n.versions.peek().forEach(f=>{f.checked.value=t})},deleteSelected:async()=>{const e=n.versions.peek().filter(f=>f.checked.peek()).map(f=>f.filename),t=e.length;if(!(!t||!await E.confirm(`Delete ${t} version${t>1?"s":""}? This cannot be undone.`)))try{await g.versions.bulkDelete(d,e),E.toast(`${t} version${t>1?"s":""} deleted.`,{type:"success"}),await G()}catch(f){E.toast("Delete failed: "+f.message,{type:"error"})}},saveNamed:async()=>{await Yt(d)&&c()&&(n.tab.peek()==="history"?await G():pe=!1)},closeCompare:()=>{n.compare.value=null,ue=null},restoreCompared:()=>Ne(ue)};de.querySelectorAll("[data-tip]").forEach(e=>E.tooltip(e,{content:e.getAttribute("data-tip"),position:"top"}));const mt=M.applyBindings(vt,je,{methods:ft});s(()=>mt.dispose()),E.tabs(w("#editor-meta-tabs"));let ge=null;s(()=>clearTimeout(ge)),k.addEventListener("input",()=>{x.refresh(),O.scrollTop=k.scrollTop,!I&&(clearTimeout(ge),ge=setTimeout(Fe,120),_(),Le())}),k.addEventListener("scroll",()=>{O.scrollTop=k.scrollTop}),F.addEventListener("scroll",()=>{O.scrollTop=F.scrollTop});let Ve=!0;s(M.effect(()=>{for(const e of Object.keys(a))e!=="css"&&e!=="cssOpened"&&a[e].value;if(n.bodyRev.value,Ve){Ve=!1,_();return}_(),Le()}));let be=null;if(s(()=>clearTimeout(be)),s(M.effect(()=>{const e=a.css.value;n.cssMode.value&&(ta(O,e,F),clearTimeout(be),be=setTimeout(Pe,400))})),h){const e=w(".pe-version-list"),t=E.contextMenu(e,{cursor:"glyph",match:"tr[data-file]",inherit:!1,density:"compact",items:f=>{const y=ve(f.dataset.file);return y?[{header:Ge(y)},{label:"Compare with the editor",icon:"columns",action:()=>fe(y)},{label:"Restore this version\u2026",icon:"rotate-ccw",action:()=>Ne(y.filename)},{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:()=>ut(y)}]:[]}});s(()=>t?.destroy?.()),e.addEventListener("click",f=>{const y=f.target.closest("tr[data-file]");if(!y||f.target.matches("input"))return;const A=f.target.closest(".pe-kebab");if(A){Ue(A);return}const N=ve(y.dataset.file);N&&fe(N)}),e.addEventListener("keydown",f=>{const y=f.target.closest("tr[data-file]");if(y){if(f.key==="F10"&&f.shiftKey)f.preventDefault(),Ue(y);else if(f.key==="Enter"&&f.target===y){const A=ve(y.dataset.file);A&&fe(A)}}})}aa(w("#editor-body"),w("#editor-divider"),s),Mt({image:e=>(n.cssMode.value=!1,sa(e)),scribe:e=>Ct(e),card:e=>gt.open(e,{onMediaBrowse:()=>g.media.list().catch(()=>[])}),timeline:e=>bt.open(e,{onPreview:async t=>{try{return await g.pages.preview(t)}catch{return null}},onListCollections:()=>g.collections.list().catch(()=>[]),onGetCollection:t=>g.collections.get(t).catch(()=>null)})}),ce.onEffects(e=>kt.open(e)),ce.onHelp(()=>_e()),ce.onTutorial(e=>xt(e));const qe=e=>{(e.ctrlKey||e.metaKey)&&!e.shiftKey&&!e.altKey&&e.key.toLowerCase()==="s"&&c()&&(e.preventDefault(),ze())};document.addEventListener("keydown",qe),s(()=>document.removeEventListener("keydown",qe));const X=p.querySelector(".dm-plugin-banner-name");s(M.effect(()=>{const e=zt(h,a.title.value,d);if(!c()||(document.title=`${e} - Domma CMS`,!X))return;const t=X.lastChild;t&&t.nodeType===3&&X.querySelector(".dm-plugin-banner-sep")?t.textContent=e:X.textContent=`Pages \u203A ${e}`})),j(o,{id:"page-editor-back",icon:"arrow-left",title:"Back to Pages",onClick:()=>R.navigate("/pages")}),j(o,{id:"page-editor-help",icon:"help-circle",title:"Editor reference",onClick:()=>_e()}),h&&j(o,{id:"page-editor-view",icon:"external-link",title:"View on the site",onClick:()=>window.open(a.urlPath.peek()||d,"_blank","noopener")});const he=j(o,{id:"page-editor-clone",icon:"copy",title:"Clone page",onClick:()=>{if(!h||n.saving.peek()||!c())return;const e=D(),t=we({...e,urlPath:d});if(t.length){E.toast(t[0].text,{type:"warning"});return}const f=At({page:m,frontmatter:{...K(se()),adminTags:a.adminTags.peek()},body:e.body,source:d,pages:P,onCloned:y=>{c()&&(u.cloneTarget=`/pages/edit${y}`,R.navigate(u.cloneTarget))}});s(()=>f.close())}});he&&(he.disabled=!h,h||(he.title="Save the page before cloning it")),j(o,{id:"page-editor-settings",icon:"settings",title:"Editor settings - font, size, spacing",onClick:()=>{Se=Wt(Me)}}),s(Ke(je,{position:"bottom"})),Domma.icons.scan();let He=null;try{He=S.get(Y)}catch{}const B=Kt(He);if(B&&(me(),V(B.state)!==n.base.peek())){const e=B.at?` (${ee(B.at)})`:"",t=jt(B,n.base.peek())?" The saved page has changed since - restoring puts your version back over it (the saved one stays in History).":"";await E.confirm(`You left unsaved changes to this page${e}. Restore them?${t}`)&&c()&&Be(B.state)}}};function ta(o,i,l){o.replaceChildren(...String(i).split(`
94
+ `).map((s,r)=>{const v=document.createElement("span");v.className="editor-line-number-row";const u=document.createElement("span");u.className="fold-toggle fold-toggle--empty";const p=document.createElement("span");return p.className="editor-line-num",p.textContent=String(r+1),v.append(u,p),v})),o.scrollTop=l.scrollTop}function aa(o,i,l){if(!o||!i)return;const s=15,r=85,v=d=>Math.min(r,Math.max(s,d));let u=v(parseFloat(q().splitRatio)||50);const p=d=>{o.style.setProperty("--dm-editor-split",u+"%"),i.setAttribute("aria-valuenow",String(Math.round(u))),d&&ae("splitRatio",u)};p(!1);const c=d=>{const h=o.getBoundingClientRect();h.width&&(u=v((d.clientX-h.left)/h.width*100)),p(!1)},C=()=>{document.removeEventListener("pointermove",c),document.removeEventListener("pointerup",C),o.classList.remove("is-resizing"),i.classList.remove("is-dragging"),p(!0)};l(C),i.addEventListener("pointerdown",d=>{window.matchMedia("(max-width: 768px)").matches||(d.preventDefault(),o.classList.add("is-resizing"),i.classList.add("is-dragging"),document.addEventListener("pointermove",c),document.addEventListener("pointerup",C))}),i.addEventListener("dblclick",()=>{u=50,p(!0)}),i.addEventListener("keydown",d=>{const h=d.shiftKey?10:2;let b=u;if(d.key==="ArrowLeft")b=u-h;else if(d.key==="ArrowRight")b=u+h;else if(d.key==="Home")b=s;else if(d.key==="End")b=r;else if(d.key==="Enter"||d.key===" ")b=50;else return;d.preventDefault(),u=v(b),p(!0)})}async function sa(o){const i=o.selectionStart,l=o.selectionEnd,s=await Pt({title:"Upload or insert an image"});if(!s||!o.isConnected)return;let r=s.split("/").pop().split("?")[0];try{r=decodeURIComponent(r)}catch{}const v=r.replace(/[\\[\]]/g,"\\$&"),u=s.replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/ /g,"%20");o.setSelectionRange(i,l),wt(o,`![${v}](${u})`),o.dispatchEvent(new Event("input",{bubbles:!0}))}function oa(o,i,l){const s=Object.entries(i||{});return o?(o.replaceChildren(...s.map(([r,v])=>new Option(v?.label||r,r))),s.some(([r])=>r===l)?l:s[0]?.[0]||l):l}async function na(o,i){if(!o)return;let l=[];try{const c=await g.get("/collections/roles/entries?limit=100");l=Array.isArray(c)?c:c?.entries||[]}catch{}const s=l.map(c=>({name:c.data?.name,label:c.data?.label||c.data?.name,level:c.data?.level??99})).filter(c=>c.name&&c.level!==0).sort((c,C)=>C.level-c.level),r=(c,C)=>Object.assign(document.createElement("option"),{value:c,textContent:C}),v=()=>{typeof i=="string"&&i&&![...o.options].some(c=>c.value===i)&&o.append(r(i,`${i} (custom)`))};if(!s.length)return v();const u=document.createElement("optgroup");u.label="Role and above",s.forEach(c=>u.append(r(c.name,`${c.label} and above`)));const p=document.createElement("optgroup");p.label="Role only",s.forEach(c=>p.append(r(`=${c.name}`,`${c.label} only`))),o.replaceChildren(r("public","Public - everyone"),u,p,r("private","Private - super-admin only")),v()}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",
@@ -84,7 +84,7 @@
84
84
  "@fastify/rate-limit": "^10.3.0",
85
85
  "@fastify/static": "9.1.1",
86
86
  "bcryptjs": "^3.0.3",
87
- "domma-js": "0.52.4",
87
+ "domma-js": "0.53.0",
88
88
  "dotenv": "^17.2.3",
89
89
  "fastify": "5.8.5",
90
90
  "gray-matter": "^4.0.3",
@@ -28,6 +28,8 @@ const CARET_ATTR = 'data-dm-font-caret';
28
28
  * @param {object} editor - an `E.editor(..., {mode: 'rich'})` instance
29
29
  * @returns {{destroy: Function}|null} null where the editor or E.dropdown is absent
30
30
  */
31
+ const attachSmoothCaret = (await import('/admin/js/lib/smooth-caret.js').catch(() => ({}))).attachSmoothCaret;
32
+
31
33
  export function installFontControls(editor) {
32
34
  const content = editor?._editorEl;
33
35
  const toolbar = editor?._toolbarEl;
@@ -320,8 +322,10 @@ export function installFontControls(editor) {
320
322
  };
321
323
  window.addEventListener('keydown', onEscape, true);
322
324
 
325
+ const smoothCaret = attachSmoothCaret?.(content);
323
326
  return {
324
327
  destroy() {
328
+ smoothCaret?.destroy();
325
329
  window.removeEventListener('keydown', onEscape, true);
326
330
  scope.removeEventListener('input', tidy, true);
327
331
  for (const menu of menus) {
@@ -1,2 +1,2 @@
1
- import{buildWizardSteps as J}from"/public/js/form-steps.mjs";import{applyFormClasses as T,applySubmitButtons as _,applyWizardButtons as U,resolveSecondaryButton as H,submitWrapperClasses as K}from"/public/js/form-submit.mjs";const j=document.querySelectorAll("[data-form]");j.length&&j.forEach(oe);function F(n){return(n||[]).some(o=>o.logic||Array.isArray(o.triggers)&&o.triggers.length)}function Y(n,o){const t=n.querySelector('[name="'+o+'"], [name="'+o+'[]"]')||n.querySelector('[data-chooser-field="'+o+'"]');if(!t)return null;const e=t.closest("form")||n;let i=t;for(;i.parentNode&&i.parentNode!==e;)i=i.parentNode;return i}export function markInvalidFields(n,o){n.querySelectorAll(".fb-field-invalid").forEach(e=>e.classList.remove("fb-field-invalid"));let t=null;(o||[]).forEach(function(e){const i=Y(n,e.name);i&&(i.classList.add("fb-field-invalid"),t||(t=i))}),t&&t.scrollIntoView&&t.scrollIntoView({behavior:"smooth",block:"center"})}export function showValidationPopup(n){const o=(n.missing||[]).map(e=>"<strong>"+A(e.label)+"</strong> is required.").concat((n.errors||[]).map(A)),t=o.join("<br>");if(typeof E<"u"&&E.alert){E.alert(t,{title:"Please complete this step"});return}window.alert(o.join(`
2
- `).replace(/<[^>]+>/g,""))}function A(n){return String(n).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function q(n,o){let t=!1;n.addEventListener("dm-form-end",function(e){const i=e.detail&&e.detail.validation;if(i&&!i.valid){markInvalidFields(n,i.missing),showValidationPopup(i);return}t||(t=!0,n.classList.add("fb-form-loading"),Promise.resolve(o(e.detail&&e.detail.values||{})).catch(function(){}).finally(function(){t=!1,n.classList.remove("fb-form-loading")}))})}function C(n,o,t){const e=n.querySelector(".fb-form-success, .fb-form-error");e&&e.remove();const i=document.createElement("div");i.className=t==="success"?"fb-form-success":"fb-form-error",i.textContent=o,n.appendChild(i)}function B(n,o){if(n._formLogicRuntime=o,n._formLogicObserver&&(n._formLogicObserver.disconnect(),n._formLogicObserver=null),!n.parentNode||typeof MutationObserver>"u"||n._formLogicObserved)return;n._formLogicObserved=!0;const t=new MutationObserver(function(e){for(const i of e)for(const r of i.removedNodes)if(r===n||r.nodeType===1&&r.contains&&r.contains(n)){n._formLogicRuntime&&n._formLogicRuntime.destroy(),t.disconnect();return}});t.observe(n.parentNode,{childList:!0,subtree:!1}),n._formLogicObserver=t}function $(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function R(n,o){const t={};return n.forEach(function(e){if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const i=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),r=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":i?"chooser":e.type,l={...e.formConfig||{}};l.span==="full"&&o&&(l.span=o);const s={type:r,label:e.label||e.name,required:$(e)?!1:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...l}};e.minLength!==void 0&&(s.minLength=e.minLength),e.maxLength!==void 0&&(s.maxLength=e.maxLength),e.min!==void 0&&(s.min=e.min),e.max!==void 0&&(s.max=e.max),i&&(e.variant&&(s.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(s.multiple=!0),e.density&&(s.density=e.density),e.columns&&(s.columns=e.columns),e.accent&&(s.accent=e.accent),e.accentStyle&&(s.accentStyle=e.accentStyle),e.glow&&(s.glow=!0),e.glowColour&&(s.glowColour=e.glowColour),e.shadow&&(s.shadow=e.shadow),e.shadowColour&&(s.shadowColour=e.shadowColour)),t[e.name]=s}),t}function G(n){const o={};return n.forEach(function(t){if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(o[t.name]=typeof e=="object"?e.value:e)}}),o}function O(n,o){(o||[]).forEach(function(t){if(t.type!=="date"||!t.name)return;const e=n.querySelector('[name="'+t.name+'"]');e&&e.type!=="date"&&(e.type="date")})}const z="padding:.45rem .7rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.85em;flex-shrink:0;line-height:1.2;";function P(n){const o=document.createElement("div");o.style.cssText="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;padding:20px;";const t=document.createElement("div");t.style.cssText="background:var(--dm-surface-overlay,var(--dm-surface));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:10px;width:100%;max-width:560px;max-height:75vh;display:flex;flex-direction:column;gap:.6rem;padding:1rem;box-shadow:var(--dm-shadow-lg,0 12px 40px rgba(0,0,0,.35));";const e=document.createElement("div");e.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;";const i=document.createElement("strong");i.textContent=n;const r=document.createElement("button");r.type="button",r.textContent="\xD7",r.setAttribute("aria-label","Close"),r.style.cssText=z+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(i),e.appendChild(r),t.appendChild(e);const l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(l),o.appendChild(t);const s=c=>{c.key==="Escape"&&a()};function a(){document.removeEventListener("keydown",s),o.remove()}return r.addEventListener("click",a),o.addEventListener("click",c=>{c.target===o&&a()}),document.addEventListener("keydown",s),document.body.appendChild(o),{body:l,close:a}}function Q(n){const{body:o,close:t}=P("Choose an icon"),e=document.createElement("input");e.type="text",e.placeholder="Search icons\u2026",e.className="form-input",e.style.cssText="padding:.45rem .6rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:var(--dm-input-bg,transparent);color:var(--dm-text);",o.appendChild(e);const i=document.createElement("div");i.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(46px,1fr));gap:4px;overflow-y:auto;min-height:0;",o.appendChild(i);const r=window.I&&typeof I.list=="function"?I.list():[],l=r.map(s=>{const a=document.createElement("button");a.type="button",a.title=s,a.dataset.iconName=s,a.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const c=document.createElement("span");return c.setAttribute("data-icon",s),c.setAttribute("data-icon-size","18"),a.appendChild(c),a.addEventListener("mouseenter",()=>{a.style.borderColor="var(--dm-border)"}),a.addEventListener("mouseleave",()=>{a.style.borderColor="transparent"}),a.addEventListener("click",()=>{t(),n(s)}),i.appendChild(a),a});if(!r.length){const s=document.createElement("p");s.textContent="Icon engine unavailable - type an icon name into the field instead.",i.appendChild(s)}window.I?.scan?.(i),e.addEventListener("input",()=>{const s=e.value.trim().toLowerCase();l.forEach(a=>{a.style.display=!s||a.dataset.iconName.includes(s)?"":"none"})}),e.focus()}async function X(){const n=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!n)return{error:"auth"};const o=i=>fetch("/api/media",{headers:{Authorization:"Bearer "+i}});let t;try{if(t=await o(n),t.status===401&&S.get("auth_refresh_token")){const i=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:S.get("auth_refresh_token")})});if(i.ok){const{token:r}=await i.json();S.set("auth_token",r),t=await o(r)}}}catch{return{error:"load"}}if(!t.ok)return{error:t.status===401||t.status===403?"auth":"load"};const e=await t.json().catch(()=>[]);return{files:(Array.isArray(e)?e:[]).filter(i=>/\.(png|jpe?g|gif|webp|svg|avif)$/i.test(i.name||i.url||""))}}function Z(n){const{body:o,close:t}=P("Choose an image"),e=document.createElement("p");e.textContent="Loading media library\u2026",e.style.cssText="margin:0;font-size:.85em;color:var(--dm-text-muted);",o.appendChild(e),X().then(({files:i,error:r})=>{if(r){e.textContent=r==="auth"?"Sign in with media access to browse the library - or paste an image URL into the field.":"Could not load the media library - paste an image URL into the field instead.";return}if(!i.length){e.textContent="No images in the media library yet.";return}e.remove();const l=document.createElement("div");l.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",i.forEach(s=>{const a=document.createElement("button");a.type="button",a.title=s.name||s.url,a.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const c=document.createElement("img");c.src=s.url,c.alt=s.name||"",c.loading="lazy",c.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const m=document.createElement("span");m.textContent=s.name||s.url,m.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",a.appendChild(c),a.appendChild(m),a.addEventListener("click",()=>{t(),n(s.url)}),l.appendChild(a)}),o.appendChild(l)})}function D(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function M(n){const o=document.createElement("div");return o.style.cssText="display:flex;align-items:center;gap:.5rem;",n.parentNode.insertBefore(o,n),o.appendChild(n),n.style.flex="1",n.style.minWidth="0",o}function V(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=z,o}function ee(n){if(!window.I||typeof I.list!="function")return;const o=M(n),t=document.createElement("span");t.style.cssText="display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;flex-shrink:0;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);";const e=()=>{t.textContent="";const r=n.value.trim();if(!r)return;const l=document.createElement("span");l.setAttribute("data-icon",r),l.setAttribute("data-icon-size","16"),t.appendChild(l),window.I?.scan?.(t)};n.addEventListener("input",e),e();const i=V("Browse");i.addEventListener("click",()=>Q(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}function te(n){const o=M(n),t=document.createElement("img");t.alt="",t.style.cssText="width:2rem;height:2rem;flex-shrink:0;object-fit:cover;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);display:none;";const e=()=>{const r=n.value.trim();t.style.display=r?"":"none",r&&(t.src=r)};n.addEventListener("input",e),e();const i=V("Browse");i.addEventListener("click",()=>Z(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}export function enhancePickerFields(n,o){const t=typeof n=="string"?document.querySelector(n):n;t&&(o||[]).forEach(function(e){if(!e.name||e.type!=="icon"&&e.type!=="image")return;const i=t.querySelector('[name="'+e.name+'"]');!i||i.dataset.pickerEnhanced||(i.dataset.pickerEnhanced="1",e.type==="icon"?ee(i):te(i))})}function N(n,o){const t=document.createElement("div");t.className="fb-form-honeypot",t.setAttribute("aria-hidden","true");const e=document.createElement("input");e.name=n.querySelector('[name="website"]')?"_website":"website",t.dataset.hpName=e.name,e.type="text",e.tabIndex=-1,e.autocomplete="url",e.placeholder="https://",t.appendChild(e);const i=document.createElement("input");i.name="_t",i.type="hidden",i.value=o||Date.now(),t.appendChild(i),n.appendChild(t)}function W(n,o){const t=n.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let i=0;o.forEach(function(r){if(r.type==="spacer"){const l=document.createElement("div");l.className="fb-spacer";const s=e[i];if(s)t.insertBefore(l,s);else{const a=t.querySelector('[type="submit"]');a?t.insertBefore(l,a):t.appendChild(l)}}else r.type!=="page-break"&&i++})}function L(n,o){!n||!o||n.querySelectorAll('input[type="file"]').forEach(function(t){t.name&&t.files&&t.files.length&&o.set(t.name,Array.from(t.files))})}function x(n,o,t,e,i,r){const l=i||e,s=l.querySelector(".fb-form-honeypot"),a=s?.querySelector('input[type="text"]')?.value||"",c=s?.querySelector('[name="_t"]')?.value||"",m=Object.assign({},o);delete m._t,s?.dataset.hpName&&delete m[s.dataset.hpName];const d=new Map(r||[]);L(l,d);const u=d.size>0;let p,b;if(u){const h=new FormData;for(const[g,v]of Object.entries(m))v!=null&&(d.has(g)||h.append(g,typeof v=="object"?JSON.stringify(v):String(v)));for(const[g,v]of d)for(const w of v)h.append(g,w,w.name);h.append("_hp",a),h.append("_t",c),p=h,b={}}else{const h=Object.assign({},m,{_hp:a,_t:c});p=JSON.stringify(h),b={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:b,body:p}).then(h=>h.json().then(g=>({ok:h.ok,body:g}))).then(h=>{h.ok&&h.body.ok?(e.textContent="",C(e,h.body.message||t.successMessage||"Thank you.","success")):C(e,h.body.error||"Something went wrong.","error")}).catch(()=>{C(e,"Unable to submit. Please check your connection.","error")})}function ne(n,o,t,e,i){const r=document.createElement("form");r.noValidate=!0,o.forEach(function(a){const c=document.createElement("div");c.className="form-group",c.style.marginBottom="1.25rem",a.name&&(c.dataset.field=a.name);const m=document.createElement("label");if(m.className="form-label",m.textContent=a.label||a.name,a.required){const u=document.createElement("span");u.textContent=" *",u.style.color="var(--dm-danger)",m.appendChild(u)}let d;a.type==="textarea"?(d=document.createElement("textarea"),d.rows=a.formConfig?.rows||4,d.className="form-input"):a.type==="select"?(d=document.createElement("select"),d.className="form-input",(a.options||[]).forEach(function(u){const p=document.createElement("option");p.value=typeof u=="string"?u:u.value??"",p.textContent=typeof u=="string"?u:u.label||p.value,d.appendChild(p)})):(d=document.createElement("input"),d.type=a.type==="icon"||a.type==="image"?"text":a.type||"text",d.className="form-input",a.placeholder&&(d.placeholder=a.placeholder),a.type==="file"&&(a.file?.accept&&(d.accept=a.file.accept),a.multiple&&(d.multiple=!0))),d.name=a.name,d.required=a.required||!1,c.appendChild(m),c.appendChild(d),r.appendChild(c)}),t.honeypot&&N(r);const l=document.createElement("button");if(l.type="submit",l.className="btn btn-primary",l.textContent=t.submitText||"Submit",K(t,"stacked").length||H(t)){const a=document.createElement("div");a.className="form-group form-buttons",a.appendChild(l),r.appendChild(a)}else r.appendChild(l);if(r.addEventListener("submit",function(a){a.preventDefault();const c={};if(o.forEach(function(m){const d=r.querySelector('[name="'+m.name+'"]');d&&(c[m.name]=d.value)}),window.FormLogicEngine&&i){const m=window.FormLogicEngine,d=[],u=[];if(o.forEach(function(p){if(m.evaluateFieldVisibility(p,c)==="hidden"){delete c[p.name];return}const h=m.evaluateFieldRequirement(p,c),g=c[p.name];h&&(!g||!String(g).trim())&&d.push(p.label||p.name);const v=m.validateField(p,g||"",c);v.length&&u.push(v[0].message)}),d.length||u.length){const p=[];d.length&&p.push("Required: "+d.join(", ")),u.length&&p.push(u.join("; ")),C(n,p.join(". "),"error");return}}if(n.dataset.triggerBlocked==="true"){const m=n._formLogicRuntime,d=m&&m.submitBlock?m.submitBlock().reasons:[];C(n,d.join(" ")||"This form cannot be submitted yet.","error");return}n.classList.add("fb-form-loading"),l.disabled=!0,x(e,c,t,n,r).finally(function(){n.classList.remove("fb-form-loading"),l.disabled=!1})}),n.appendChild(r),_(r,t,"stacked"),T(r,t,o),enhancePickerFields(n,o),q(n,function(a){return x(e,a,t,n,r)}),window.FormLogicEngine&&i&&F(o)){const a=new window.FormLogicEngine.FormLogicRuntime(i,n);a.init(),n._formLogicRuntime=a}}function oe(n){const o=n.getAttribute("data-form");o&&fetch("/api/forms/"+o+"/public").then(t=>{if(!t.ok)throw new Error("Form not found: "+o);return t.json()}).then(t=>{const e=t.fields||[],i=t.settings||{},r=document.createElement("div");r.className="fb-form-wrapper",n.appendChild(r);const l=e.some(s=>s.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const s=Number(i.columns)===3?3:2,a=i.layout||"grid";if(l&&Domma.forms.wizard){const c=J(e,t.title),m=c.map(f=>f.fields),d=c.map(function(f){return{title:f.title,description:f.description,fields:R(f.fields,s)}});let u=0,p=null,b=null;const h=Date.now(),g=new Map,v=function(f){const y=window.FormLogicEngine;if(!y||!y.validateFields)return;const k=y.validateFields(r,m[u]||[]);k.valid||(f.preventDefault(),f.stopImmediatePropagation(),markInvalidFields(r,k.missing),showValidationPopup(k))},w=function(){const f=m[u]||e;if(U(r,i),T(r,i,f),O(r,f),enhancePickerFields(r,f),f.some(y=>y.type==="spacer")&&W(r,f),i.honeypot){const y=r.querySelector("form");y&&N(y,h)}window.FormLogicEngine&&F(e)&&(p&&p.destroy(),p=new window.FormLogicEngine.FormLogicRuntime(t,r,{baseValues:b&&b.getStepData?b.getStepData():{}}),p.init(),B(r,p)),r.querySelectorAll(".wizard-next, .wizard-submit").forEach(y=>y.addEventListener("click",v,!0))};b=Domma.forms.wizard(r,{schema:{steps:d},layout:a,columns:s,finishText:i.submitText||"Finish",onStepChange:function(f){L(r,g),u=f,setTimeout(w,0)},onSubmit:function(f){return L(r,g),x(o,f,i,r,null,g)}}),q(r,function(f){return L(r,g),x(o,f,i,r,null,g)}),r.addEventListener("dm-form-trigger",function(f){if(!f.detail||f.detail.type!=="goto-step"||!b||!b.goToStep)return;const y=Number(f.detail.action.step);!isFinite(y)||y<0||y>=d.length||y!==u&&b.goToStep(y)}),Promise.resolve(b).then(w)}else if(Domma.forms.render){const c=R(e,s),m=G(e);q(r,function(u){return x(o,u,i,r,null)});const d=Domma.forms.render(r,c,m,{submitText:i.submitText||"Submit",layout:a,columns:s,onSubmit:function(u){return x(o,u,i,r,null)}});Promise.resolve(d).then(function(){if(_(r,i,a),T(r,i,e),O(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&F(e)){const u=new window.FormLogicEngine.FormLogicRuntime(t,r);u.init(),B(r,u)}if(e.some(u=>u.type==="spacer")&&W(r,e),i.honeypot){const u=r.querySelector("form");u&&N(u)}})}}else ne(r,e.filter(s=>s.type!=="page-break"&&s.type!=="spacer"),i,o,t)}).catch(t=>{const e=document.createElement("p");e.textContent="Form unavailable.",e.style.cssText="color:var(--dm-danger);font-style:italic;",n.appendChild(e),console.warn("[forms]",t.message)})}
1
+ import{installSmoothCarets as J}from"/public/js/smooth-caret.js";import{buildWizardSteps as U}from"/public/js/form-steps.mjs";import{applyFormClasses as T,applySubmitButtons as _,applyWizardButtons as H,resolveSecondaryButton as K,submitWrapperClasses as Y}from"/public/js/form-submit.mjs";J(document);const j=document.querySelectorAll("[data-form]");j.length&&j.forEach(re);function F(n){return(n||[]).some(o=>o.logic||Array.isArray(o.triggers)&&o.triggers.length)}function $(n,o){const t=n.querySelector('[name="'+o+'"], [name="'+o+'[]"]')||n.querySelector('[data-chooser-field="'+o+'"]');if(!t)return null;const e=t.closest("form")||n;let i=t;for(;i.parentNode&&i.parentNode!==e;)i=i.parentNode;return i}export function markInvalidFields(n,o){n.querySelectorAll(".fb-field-invalid").forEach(e=>e.classList.remove("fb-field-invalid"));let t=null;(o||[]).forEach(function(e){const i=$(n,e.name);i&&(i.classList.add("fb-field-invalid"),t||(t=i))}),t&&t.scrollIntoView&&t.scrollIntoView({behavior:"smooth",block:"center"})}export function showValidationPopup(n){const o=(n.missing||[]).map(e=>"<strong>"+A(e.label)+"</strong> is required.").concat((n.errors||[]).map(A)),t=o.join("<br>");if(typeof E<"u"&&E.alert){E.alert(t,{title:"Please complete this step"});return}window.alert(o.join(`
2
+ `).replace(/<[^>]+>/g,""))}function A(n){return String(n).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function q(n,o){let t=!1;n.addEventListener("dm-form-end",function(e){const i=e.detail&&e.detail.validation;if(i&&!i.valid){markInvalidFields(n,i.missing),showValidationPopup(i);return}t||(t=!0,n.classList.add("fb-form-loading"),Promise.resolve(o(e.detail&&e.detail.values||{})).catch(function(){}).finally(function(){t=!1,n.classList.remove("fb-form-loading")}))})}function C(n,o,t){const e=n.querySelector(".fb-form-success, .fb-form-error");e&&e.remove();const i=document.createElement("div");i.className=t==="success"?"fb-form-success":"fb-form-error",i.textContent=o,n.appendChild(i)}function B(n,o){if(n._formLogicRuntime=o,n._formLogicObserver&&(n._formLogicObserver.disconnect(),n._formLogicObserver=null),!n.parentNode||typeof MutationObserver>"u"||n._formLogicObserved)return;n._formLogicObserved=!0;const t=new MutationObserver(function(e){for(const i of e)for(const r of i.removedNodes)if(r===n||r.nodeType===1&&r.contains&&r.contains(n)){n._formLogicRuntime&&n._formLogicRuntime.destroy(),t.disconnect();return}});t.observe(n.parentNode,{childList:!0,subtree:!1}),n._formLogicObserver=t}function G(n){const o=n&&n.logic;return!!(o&&(o.visibility||o.requirement))}function R(n,o){const t={};return n.forEach(function(e){if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const i=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),r=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":i?"chooser":e.type,l={...e.formConfig||{}};l.span==="full"&&o&&(l.span=o);const s={type:r,label:e.label||e.name,required:G(e)?!1:e.required||!1,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{helperText:e.helper},...e.tooltip&&{tooltip:e.tooltip},...l}};e.minLength!==void 0&&(s.minLength=e.minLength),e.maxLength!==void 0&&(s.maxLength=e.maxLength),e.min!==void 0&&(s.min=e.min),e.max!==void 0&&(s.max=e.max),i&&(e.variant&&(s.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(s.multiple=!0),e.density&&(s.density=e.density),e.columns&&(s.columns=e.columns),e.accent&&(s.accent=e.accent),e.accentStyle&&(s.accentStyle=e.accentStyle),e.glow&&(s.glow=!0),e.glowColour&&(s.glowColour=e.glowColour),e.shadow&&(s.shadow=e.shadow),e.shadowColour&&(s.shadowColour=e.shadowColour)),t[e.name]=s}),t}function Q(n){const o={};return n.forEach(function(t){if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(o[t.name]=typeof e=="object"?e.value:e)}}),o}function O(n,o){(o||[]).forEach(function(t){if(t.type!=="date"||!t.name)return;const e=n.querySelector('[name="'+t.name+'"]');e&&e.type!=="date"&&(e.type="date")})}const z="padding:.45rem .7rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:transparent;color:inherit;cursor:pointer;font:inherit;font-size:.85em;flex-shrink:0;line-height:1.2;";function P(n){const o=document.createElement("div");o.style.cssText="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;padding:20px;";const t=document.createElement("div");t.style.cssText="background:var(--dm-surface-overlay,var(--dm-surface));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:10px;width:100%;max-width:560px;max-height:75vh;display:flex;flex-direction:column;gap:.6rem;padding:1rem;box-shadow:var(--dm-shadow-lg,0 12px 40px rgba(0,0,0,.35));";const e=document.createElement("div");e.style.cssText="display:flex;align-items:center;justify-content:space-between;gap:.5rem;";const i=document.createElement("strong");i.textContent=n;const r=document.createElement("button");r.type="button",r.textContent="\xD7",r.setAttribute("aria-label","Close"),r.style.cssText=z+"font-size:1rem;padding:.15rem .55rem;",e.appendChild(i),e.appendChild(r),t.appendChild(e);const l=document.createElement("div");l.style.cssText="display:flex;flex-direction:column;gap:.6rem;overflow:hidden;min-height:0;",t.appendChild(l),o.appendChild(t);const s=c=>{c.key==="Escape"&&a()};function a(){document.removeEventListener("keydown",s),o.remove()}return r.addEventListener("click",a),o.addEventListener("click",c=>{c.target===o&&a()}),document.addEventListener("keydown",s),document.body.appendChild(o),{body:l,close:a}}function X(n){const{body:o,close:t}=P("Choose an icon"),e=document.createElement("input");e.type="text",e.placeholder="Search icons\u2026",e.className="form-input",e.style.cssText="padding:.45rem .6rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);background:var(--dm-input-bg,transparent);color:var(--dm-text);",o.appendChild(e);const i=document.createElement("div");i.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(46px,1fr));gap:4px;overflow-y:auto;min-height:0;",o.appendChild(i);const r=window.I&&typeof I.list=="function"?I.list():[],l=r.map(s=>{const a=document.createElement("button");a.type="button",a.title=s,a.dataset.iconName=s,a.style.cssText="display:flex;align-items:center;justify-content:center;padding:.55rem 0;border:1px solid transparent;border-radius:6px;background:transparent;color:inherit;cursor:pointer;";const c=document.createElement("span");return c.setAttribute("data-icon",s),c.setAttribute("data-icon-size","18"),a.appendChild(c),a.addEventListener("mouseenter",()=>{a.style.borderColor="var(--dm-border)"}),a.addEventListener("mouseleave",()=>{a.style.borderColor="transparent"}),a.addEventListener("click",()=>{t(),n(s)}),i.appendChild(a),a});if(!r.length){const s=document.createElement("p");s.textContent="Icon engine unavailable - type an icon name into the field instead.",i.appendChild(s)}window.I?.scan?.(i),e.addEventListener("input",()=>{const s=e.value.trim().toLowerCase();l.forEach(a=>{a.style.display=!s||a.dataset.iconName.includes(s)?"":"none"})}),e.focus()}async function Z(){const n=typeof S<"u"&&S.get?S.get("auth_token"):null;if(!n)return{error:"auth"};const o=i=>fetch("/api/media",{headers:{Authorization:"Bearer "+i}});let t;try{if(t=await o(n),t.status===401&&S.get("auth_refresh_token")){const i=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:S.get("auth_refresh_token")})});if(i.ok){const{token:r}=await i.json();S.set("auth_token",r),t=await o(r)}}}catch{return{error:"load"}}if(!t.ok)return{error:t.status===401||t.status===403?"auth":"load"};const e=await t.json().catch(()=>[]);return{files:(Array.isArray(e)?e:[]).filter(i=>/\.(png|jpe?g|gif|webp|svg|avif)$/i.test(i.name||i.url||""))}}function ee(n){const{body:o,close:t}=P("Choose an image"),e=document.createElement("p");e.textContent="Loading media library\u2026",e.style.cssText="margin:0;font-size:.85em;color:var(--dm-text-muted);",o.appendChild(e),Z().then(({files:i,error:r})=>{if(r){e.textContent=r==="auth"?"Sign in with media access to browse the library - or paste an image URL into the field.":"Could not load the media library - paste an image URL into the field instead.";return}if(!i.length){e.textContent="No images in the media library yet.";return}e.remove();const l=document.createElement("div");l.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(104px,1fr));gap:8px;overflow-y:auto;min-height:0;",i.forEach(s=>{const a=document.createElement("button");a.type="button",a.title=s.name||s.url,a.style.cssText="display:flex;flex-direction:column;gap:.25rem;padding:.35rem;border:1px solid var(--dm-border);border-radius:8px;background:transparent;color:inherit;cursor:pointer;min-width:0;";const c=document.createElement("img");c.src=s.url,c.alt=s.name||"",c.loading="lazy",c.style.cssText="width:100%;height:72px;object-fit:cover;border-radius:5px;";const m=document.createElement("span");m.textContent=s.name||s.url,m.style.cssText="font-size:.68em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;",a.appendChild(c),a.appendChild(m),a.addEventListener("click",()=>{t(),n(s.url)}),l.appendChild(a)}),o.appendChild(l)})}function D(n,o){n.value=o,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))}function M(n){const o=document.createElement("div");return o.style.cssText="display:flex;align-items:center;gap:.5rem;",n.parentNode.insertBefore(o,n),o.appendChild(n),n.style.flex="1",n.style.minWidth="0",o}function V(n){const o=document.createElement("button");return o.type="button",o.textContent=n,o.style.cssText=z,o}function te(n){if(!window.I||typeof I.list!="function")return;const o=M(n),t=document.createElement("span");t.style.cssText="display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;flex-shrink:0;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);";const e=()=>{t.textContent="";const r=n.value.trim();if(!r)return;const l=document.createElement("span");l.setAttribute("data-icon",r),l.setAttribute("data-icon-size","16"),t.appendChild(l),window.I?.scan?.(t)};n.addEventListener("input",e),e();const i=V("Browse");i.addEventListener("click",()=>X(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}function ne(n){const o=M(n),t=document.createElement("img");t.alt="",t.style.cssText="width:2rem;height:2rem;flex-shrink:0;object-fit:cover;border:1px solid var(--dm-border);border-radius:var(--dm-radius-md,6px);display:none;";const e=()=>{const r=n.value.trim();t.style.display=r?"":"none",r&&(t.src=r)};n.addEventListener("input",e),e();const i=V("Browse");i.addEventListener("click",()=>ee(r=>{D(n,r),e()})),o.appendChild(t),o.appendChild(i)}export function enhancePickerFields(n,o){const t=typeof n=="string"?document.querySelector(n):n;t&&(o||[]).forEach(function(e){if(!e.name||e.type!=="icon"&&e.type!=="image")return;const i=t.querySelector('[name="'+e.name+'"]');!i||i.dataset.pickerEnhanced||(i.dataset.pickerEnhanced="1",e.type==="icon"?te(i):ne(i))})}function N(n,o){const t=document.createElement("div");t.className="fb-form-honeypot",t.setAttribute("aria-hidden","true");const e=document.createElement("input");e.name=n.querySelector('[name="website"]')?"_website":"website",t.dataset.hpName=e.name,e.type="text",e.tabIndex=-1,e.autocomplete="url",e.placeholder="https://",t.appendChild(e);const i=document.createElement("input");i.name="_t",i.type="hidden",i.value=o||Date.now(),t.appendChild(i),n.appendChild(t)}function W(n,o){const t=n.querySelector("form");if(!t)return;const e=Array.from(t.querySelectorAll(".form-group"));let i=0;o.forEach(function(r){if(r.type==="spacer"){const l=document.createElement("div");l.className="fb-spacer";const s=e[i];if(s)t.insertBefore(l,s);else{const a=t.querySelector('[type="submit"]');a?t.insertBefore(l,a):t.appendChild(l)}}else r.type!=="page-break"&&i++})}function L(n,o){!n||!o||n.querySelectorAll('input[type="file"]').forEach(function(t){t.name&&t.files&&t.files.length&&o.set(t.name,Array.from(t.files))})}function x(n,o,t,e,i,r){const l=i||e,s=l.querySelector(".fb-form-honeypot"),a=s?.querySelector('input[type="text"]')?.value||"",c=s?.querySelector('[name="_t"]')?.value||"",m=Object.assign({},o);delete m._t,s?.dataset.hpName&&delete m[s.dataset.hpName];const d=new Map(r||[]);L(l,d);const u=d.size>0;let p,b;if(u){const h=new FormData;for(const[g,v]of Object.entries(m))v!=null&&(d.has(g)||h.append(g,typeof v=="object"?JSON.stringify(v):String(v)));for(const[g,v]of d)for(const w of v)h.append(g,w,w.name);h.append("_hp",a),h.append("_t",c),p=h,b={}}else{const h=Object.assign({},m,{_hp:a,_t:c});p=JSON.stringify(h),b={"Content-Type":"application/json"}}return fetch("/api/forms/submit/"+n,{method:"POST",headers:b,body:p}).then(h=>h.json().then(g=>({ok:h.ok,body:g}))).then(h=>{h.ok&&h.body.ok?(e.textContent="",C(e,h.body.message||t.successMessage||"Thank you.","success")):C(e,h.body.error||"Something went wrong.","error")}).catch(()=>{C(e,"Unable to submit. Please check your connection.","error")})}function oe(n,o,t,e,i){const r=document.createElement("form");r.noValidate=!0,o.forEach(function(a){const c=document.createElement("div");c.className="form-group",c.style.marginBottom="1.25rem",a.name&&(c.dataset.field=a.name);const m=document.createElement("label");if(m.className="form-label",m.textContent=a.label||a.name,a.required){const u=document.createElement("span");u.textContent=" *",u.style.color="var(--dm-danger)",m.appendChild(u)}let d;a.type==="textarea"?(d=document.createElement("textarea"),d.rows=a.formConfig?.rows||4,d.className="form-input"):a.type==="select"?(d=document.createElement("select"),d.className="form-input",(a.options||[]).forEach(function(u){const p=document.createElement("option");p.value=typeof u=="string"?u:u.value??"",p.textContent=typeof u=="string"?u:u.label||p.value,d.appendChild(p)})):(d=document.createElement("input"),d.type=a.type==="icon"||a.type==="image"?"text":a.type||"text",d.className="form-input",a.placeholder&&(d.placeholder=a.placeholder),a.type==="file"&&(a.file?.accept&&(d.accept=a.file.accept),a.multiple&&(d.multiple=!0))),d.name=a.name,d.required=a.required||!1,c.appendChild(m),c.appendChild(d),r.appendChild(c)}),t.honeypot&&N(r);const l=document.createElement("button");if(l.type="submit",l.className="btn btn-primary",l.textContent=t.submitText||"Submit",Y(t,"stacked").length||K(t)){const a=document.createElement("div");a.className="form-group form-buttons",a.appendChild(l),r.appendChild(a)}else r.appendChild(l);if(r.addEventListener("submit",function(a){a.preventDefault();const c={};if(o.forEach(function(m){const d=r.querySelector('[name="'+m.name+'"]');d&&(c[m.name]=d.value)}),window.FormLogicEngine&&i){const m=window.FormLogicEngine,d=[],u=[];if(o.forEach(function(p){if(m.evaluateFieldVisibility(p,c)==="hidden"){delete c[p.name];return}const h=m.evaluateFieldRequirement(p,c),g=c[p.name];h&&(!g||!String(g).trim())&&d.push(p.label||p.name);const v=m.validateField(p,g||"",c);v.length&&u.push(v[0].message)}),d.length||u.length){const p=[];d.length&&p.push("Required: "+d.join(", ")),u.length&&p.push(u.join("; ")),C(n,p.join(". "),"error");return}}if(n.dataset.triggerBlocked==="true"){const m=n._formLogicRuntime,d=m&&m.submitBlock?m.submitBlock().reasons:[];C(n,d.join(" ")||"This form cannot be submitted yet.","error");return}n.classList.add("fb-form-loading"),l.disabled=!0,x(e,c,t,n,r).finally(function(){n.classList.remove("fb-form-loading"),l.disabled=!1})}),n.appendChild(r),_(r,t,"stacked"),T(r,t,o),enhancePickerFields(n,o),q(n,function(a){return x(e,a,t,n,r)}),window.FormLogicEngine&&i&&F(o)){const a=new window.FormLogicEngine.FormLogicRuntime(i,n);a.init(),n._formLogicRuntime=a}}function re(n){const o=n.getAttribute("data-form");o&&fetch("/api/forms/"+o+"/public").then(t=>{if(!t.ok)throw new Error("Form not found: "+o);return t.json()}).then(t=>{const e=t.fields||[],i=t.settings||{},r=document.createElement("div");r.className="fb-form-wrapper",n.appendChild(r);const l=e.some(s=>s.type==="page-break");if(typeof Domma<"u"&&Domma.forms){const s=Number(i.columns)===3?3:2,a=i.layout||"grid";if(l&&Domma.forms.wizard){const c=U(e,t.title),m=c.map(f=>f.fields),d=c.map(function(f){return{title:f.title,description:f.description,fields:R(f.fields,s)}});let u=0,p=null,b=null;const h=Date.now(),g=new Map,v=function(f){const y=window.FormLogicEngine;if(!y||!y.validateFields)return;const k=y.validateFields(r,m[u]||[]);k.valid||(f.preventDefault(),f.stopImmediatePropagation(),markInvalidFields(r,k.missing),showValidationPopup(k))},w=function(){const f=m[u]||e;if(H(r,i),T(r,i,f),O(r,f),enhancePickerFields(r,f),f.some(y=>y.type==="spacer")&&W(r,f),i.honeypot){const y=r.querySelector("form");y&&N(y,h)}window.FormLogicEngine&&F(e)&&(p&&p.destroy(),p=new window.FormLogicEngine.FormLogicRuntime(t,r,{baseValues:b&&b.getStepData?b.getStepData():{}}),p.init(),B(r,p)),r.querySelectorAll(".wizard-next, .wizard-submit").forEach(y=>y.addEventListener("click",v,!0))};b=Domma.forms.wizard(r,{schema:{steps:d},layout:a,columns:s,finishText:i.submitText||"Finish",onStepChange:function(f){L(r,g),u=f,setTimeout(w,0)},onSubmit:function(f){return L(r,g),x(o,f,i,r,null,g)}}),q(r,function(f){return L(r,g),x(o,f,i,r,null,g)}),r.addEventListener("dm-form-trigger",function(f){if(!f.detail||f.detail.type!=="goto-step"||!b||!b.goToStep)return;const y=Number(f.detail.action.step);!isFinite(y)||y<0||y>=d.length||y!==u&&b.goToStep(y)}),Promise.resolve(b).then(w)}else if(Domma.forms.render){const c=R(e,s),m=Q(e);q(r,function(u){return x(o,u,i,r,null)});const d=Domma.forms.render(r,c,m,{submitText:i.submitText||"Submit",layout:a,columns:s,onSubmit:function(u){return x(o,u,i,r,null)}});Promise.resolve(d).then(function(){if(_(r,i,a),T(r,i,e),O(r,e),enhancePickerFields(r,e),window.FormLogicEngine&&F(e)){const u=new window.FormLogicEngine.FormLogicRuntime(t,r);u.init(),B(r,u)}if(e.some(u=>u.type==="spacer")&&W(r,e),i.honeypot){const u=r.querySelector("form");u&&N(u)}})}}else oe(r,e.filter(s=>s.type!=="page-break"&&s.type!=="spacer"),i,o,t)}).catch(t=>{const e=document.createElement("p");e.textContent="Form unavailable.",e.style.cssText="color:var(--dm-danger);font-style:italic;",n.appendChild(e),console.warn("[forms]",t.message)})}
package/public/js/site.js CHANGED
@@ -1 +1 @@
1
- import{decodeBase64Json as P}from"/public/js/utf8-base64.mjs";import{makeBadgeEl as J,applyColour as X,applyPill as oe,applyFloat as ne,applyHighlight as R,applyItemHighlight as ae,itemHighlightAttrs as se,isCurrentItem as U,menuAlign as ie,applyClasses as O,cssClasses as W,applyEntrance as V}from"/public/js/menu-decor.mjs?v=20261014-menu-entrance";import{initFloatingMenus as re}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as G,markInvalidFields as K,showValidationPopup as Q}from"/public/js/forms.js?v=20261009-form-classes";import{buildWizardSteps as ce}from"/public/js/form-steps.mjs";import{applyFormClasses as Z,applySubmitButtons as le,applyWizardButtons as de}from"/public/js/form-submit.mjs";document.addEventListener("click",h=>{const c=h.target?.closest?.(".dm-banner__dismiss");c&&(h.preventDefault(),c.closest(".dm-banner")?.remove())}),$(()=>{const h=window.__CMS_NAV__||{},c=window.__CMS_SITE__||{};if(c.autoTheme?.enabled){let o=function(e){const a=(e||"07:00").split(":");return+a[0]*60+(+a[1]||0)},s=function(){const e=new Date,a=e.getHours()*60+e.getMinutes();return a>=o(n.dayStart)&&a<o(n.nightStart)?n.dayTheme:n.nightTheme},t=function(e){const a=n.apply&&n.apply[e]||{theme:e,custom:""};Domma.theme.set(a.theme);for(const d of[...document.body.classList])d.startsWith("dm-custom-")&&document.body.classList.remove(d);a.custom&&document.body.classList.add(a.custom)};const n=c.autoTheme;t(s()),setInterval(()=>t(s()),6e4)}const x=$("#site-navbar");if(x.length&&h.brand){let s=function(u,p=0){return Array.isArray(u)?u.filter(m=>!(m&&(m.type==="spacer"||m.type==="theme-switcher"))).filter(m=>!(m&&m.type==="separator"&&p===0)).map(m=>m&&m.type==="separator"?{divider:!0}:Array.isArray(m?.items)?{...m,items:s(m.items,p+1)}:m):u};const n={...h.brand},o=n.size&&n.size!=="md"?` navbar-brand-${n.size}`:"";if(n.logo||n.icon||n.tagline){let u="";n.logo?u+=`<img src="${n.logo}" class="navbar-brand-logo" alt="${n.text||""}">`:n.icon&&(u+=`<span data-icon="${n.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),n.text&&(u+=`<span class="navbar-brand-text${o}">${n.text}</span>`),n.tagline&&(u+=`<small class="navbar-brand-tagline">${n.tagline}</small>`),n.html=u}else o&&n.text&&(n.html=`<span class="navbar-brand-text${o}">${n.text}</span>`);const t=s(h.items||[]),e=h.position==="floating",a=h.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:n,items:t,variant:h.variant||"dark",position:e?"static":h.position||"sticky",collapsible:!0,appearOnHover:!!h.appearOnHover}),Domma.icons.scan("#site-navbar");const d=x.get(0),f=()=>{if(!a)return;const p=d.querySelector('a[aria-current="page"]')?.closest(".navbar-dropdown");p&&!p.classList.contains("open")&&p.querySelector(":scope > .navbar-dropdown-toggle")?.click()};d.classList.add(`dm-nav-align-${ie(h)||"centre"}`),a&&x.get(0).classList.add("dm-nav-vertical",h.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left");const i=h.dock||{};a&&!e&&me(d,h.side==="right"),!a&&i.hideOnScroll&&ue(d),R(d,h),V(d,h),O(d,h.class),e&&(ne(x.get(0),h),re(x.get(0).parentNode||document));const l=d.querySelector(".navbar-toggle"),g=d.querySelector(".navbar-collapse");if(l&&g){let u=null;const p=()=>{g.classList.contains("show")&&l.click()},m=()=>{u&&(u.remove(),u=null),document.body.classList.remove("dm-drawer-open")},v=()=>{u||(u=document.createElement("div"),u.className="dm-navbar-backdrop",u.addEventListener("click",p),document.body.appendChild(u),document.body.classList.add("dm-drawer-open"))};l.addEventListener("click",()=>{requestAnimationFrame(()=>{g.classList.contains("show")?(f(),v()):m()})}),g.addEventListener("click",C=>{C.target.closest("a")&&requestAnimationFrame(m)}),document.addEventListener("keydown",C=>{C.key==="Escape"&&g.classList.contains("show")&&p()})}const b=d.querySelector(".navbar-nav");if(b){const u=Array.from(b.children);let p=0;for(const m of h.items||[])if(!(m&&m.type==="separator")){if(m&&m.type==="spacer"){const v=document.createElement("li"),C=["xs","sm","md","lg","xl","flex"].includes(m.size)?m.size:"md";v.className=`dm-menu-spacer dm-menu-spacer--${C}`,v.setAttribute("aria-hidden","true"),b.insertBefore(v,u[p]||null);continue}if(m&&m.type==="theme-switcher"){const v=document.createElement("li");v.className="dm-menu-theme-switcher";const C=document.createElement("span");C.dataset.themeSwitcher="menu",C.dataset.position="inline",v.appendChild(C),b.insertBefore(v,u[p]||null);continue}p++}window.CMSThemeSwitcher?.scan(b)}d.querySelectorAll("[data-path]").forEach(u=>{const p=u.dataset.path.split(".").map(Number),m=p.length>1,v=p.reduce((A,q)=>A?.items?.[q],{items:t});if(!v)return;v.colour&&X(u,v.colour),v.pill&&!m&&oe(u,v.pill),ae(u,v),O(u.closest("li"),v.class);const C=J(v.badge);C&&u.appendChild(C),U(v.url,location.pathname)&&(u.classList.add("active"),u.setAttribute("aria-current","page"))}),f()}const y=$("#site-footer");if(y.length){let e=function(r){return String(r??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},a=function(r){return e(r).replace(/'/g,"&#39;")},d=function(r){if(r&&r.type==="separator")return'<li class="footer-sep"><hr></li>';if(r&&r.type==="spacer")return`<li class="dm-menu-spacer dm-menu-spacer--${["xs","sm","md","lg","xl","flex"].includes(r.size)?r.size:"md"}" aria-hidden="true"></li>`;if(r&&r.type==="theme-switcher")return'<li class="dm-menu-theme-switcher"><span data-theme-switcher="menu" data-position="inline"></span></li>';const M=a(r.url||"#"),L=e(r.text||""),D=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(d).join("")}</ul>`:"",N=se(r),ee=[N.hover&&` data-menu-item-hover="${a(N.hover)}"`,N.active&&` data-menu-item-active="${a(N.active)}"`].filter(Boolean).join(""),te=N.accent?` style="--dm-menu-highlight:${a(N.accent)}"`:"",Y=W(r.class).join(" ");return`<li${Y?` class="${a(Y)}"`:""}><a href="${M}"${ee}${te}>${L}</a>${D}</li>`},f=function(){if(!c.footer)return"";const r=Object.keys(o).filter(L=>n[L]);if(!r.length)return"";const M=W(c.footer.socialClass).join(" ");return`<div class="footer-social">${r.map(L=>{const{label:D,svg:N}=o[L];return`<a href="${n[L]}" target="_blank" rel="noopener noreferrer" aria-label="${D}" class="footer-social-link${M?` ${a(M)}`:""}">${N}</a>`}).join("")}</div>`},b=function(r){if(!r||r.type==="separator"||r.type==="spacer")return"";if(r.type==="theme-switcher")return`<li class="cms-footer-col">${d(r).replace(/^<li[^>]*>|<\/li>$/g,"")}</li>`;const M=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(d).join("")}</ul>`:"",L=g(r)?`<span class="cms-footer-col-title">${e(r.text||"")}</span>`:`<a class="cms-footer-col-title" href="${a(r.url||"#")}">${e(r.text||"")}</a>`,D=["cms-footer-col",...W(r.class)].join(" ");return`<li class="${a(D)}">${L}${M}</li>`},p=function(r,M,L=!1){return(r||[]).forEach(D=>{D&&(D.type==="separator"||D.type==="spacer"||D.type==="theme-switcher")||(L&&g(D)||M.push(D),Array.isArray(D.items)&&D.items.length&&p(D.items,M))}),M};const n=c.social||{},o={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let s='<div class="footer-inner container">';const t=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""},i=["columns","row"].includes(c.footer?.layout)?c.footer.layout:"auto",l=i==="columns"||i==="auto"&&t.primary.some(r=>Array.isArray(r?.items)&&r.items.length),g=r=>l&&!r.url&&Array.isArray(r.items)&&r.items.length>0;if(l){const r=h.brand||{},M=r.text||c.title||"",L=r.logo?`<img src="${a(r.logo)}" class="cms-footer-brand-logo" alt="">`:r.icon?'<span class="cms-footer-brand-icon"></span>':"",D=String(c.footer?.blurb||"").trim();s='<div class="footer-inner footer-inner--columns container"><div class="cms-footer-top">',s+=`<div class="cms-footer-brand">${M||L?`<a class="cms-footer-brand-name" href="${a(r.url||"/")}">${L}<span>${e(M)}</span></a>`:""}${D?`<p class="cms-footer-blurb">${e(D)}</p>`:""}${f()}</div>`,t.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary footer-nav--columns" aria-label="Footer"><ul>${t.primary.map(b).join("")}</ul></nav>`),s+='</div><div class="cms-footer-bottom">',t.copyright&&(s+=`<p class="cms-footer-copyright">${e(t.copyright)}</p>`),t.legal.length&&(s+=`<nav class="footer-nav footer-nav--legal" aria-label="Legal"><ul>${t.legal.map(d).join("")}</ul></nav>`),s+="</div>"}else t.copyright&&(s+=`<p>${e(t.copyright)}</p>`),t.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary"><ul>${t.primary.map(d).join("")}</ul></nav>`),t.legal.length&&(s+=`<nav class="footer-nav footer-nav--legal"><ul>${t.legal.map(d).join("")}</ul></nav>`),s+=f();s+="</div>",y.html(s),window.CMSThemeSwitcher?.scan(y.get(0));const u=y.get(0).querySelector(".cms-footer-brand-icon");u&&h.brand?.icon&&u.setAttribute("data-icon",h.brand.icon),O(y.get(0),c.footer?.class);const m=[...p(t.primary,[],!0),...p(t.legal,[])];y.get(0).querySelectorAll(".footer-nav a").forEach((r,M)=>{const L=m[M];if(!L)return;L.colour&&X(r,L.colour);const D=J(L.badge);D&&r.appendChild(D),U(L.url,location.pathname)&&(r.classList.add("is-active"),r.setAttribute("aria-current","page"))}),R(y.get(0).querySelector(".footer-nav--primary"),{highlight:t.primaryHighlight}),R(y.get(0).querySelector(".footer-nav--legal"),{highlight:t.legalHighlight}),V(y.get(0).querySelector(".footer-nav--primary"),{entrance:t.primaryEntrance}),V(y.get(0).querySelector(".footer-nav--legal"),{entrance:t.legalEntrance}),O(y.get(0).querySelector(".footer-nav--primary"),t.primaryClass),O(y.get(0).querySelector(".footer-nav--legal"),t.legalClass);const C=c.footer?.showMotionToggle!==!1,A=S.get("reduced_motion"),q=c.footer?.motionDefault,z=A!=null?!!A:q==="on"?!0:q==="off"?!1:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),B=c.footer?.motionControl==="checkbox",I=y.get(0).querySelector(".cms-footer-bottom")||y.get(0).querySelector(".footer-inner");if(C&&I){const r=document.createElement("input");r.type="checkbox",r.className=B?"footer-motion-checkbox":"form-switch-input",r.id="dm-motion-switch",r.checked=z,r.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const M=document.createElement("span");M.className=B?"footer-motion-label":"form-switch-label",M.textContent="Reduce motion";const L=document.createElement("label");L.className=B?"footer-motion-check":"form-switch footer-motion-switch",L.title="Reduce motion",L.appendChild(r),L.appendChild(M),I.appendChild(L)}}const k=document.getElementById("site-sidebar");k&&pe(k),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const w=$(".page-body");if(w.length){w.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),w.find(".tabs").each(function(){Domma.elements.tabs(this)}),w.find(".carousel").each(function(){const n={primary:"--dm-primary",secondary:"--dm-secondary",accent:"--dm-primary",text:"--dm-text",surface:"--dm-surface",background:"--dm-background",success:"--dm-success",warning:"--dm-warning",danger:"--dm-danger",info:"--dm-info"},o=f=>{const i=String(f||"").trim();return i?n[i.toLowerCase()]?`var(${n[i.toLowerCase()]})`:CSS.supports("color",i)?i:"":""},s=o(this.dataset.background),t=o(this.dataset.arrowBackground),e=o(this.dataset.arrowColor);s&&(this.style.setProperty("--dm-carousel-background",s),this.classList.add("dm-carousel-custom-background")),t&&this.style.setProperty("--dm-carousel-arrow-background",t),e&&this.style.setProperty("--dm-carousel-arrow-color",e);const a=["top","middle","bottom"].includes(this.dataset.arrowPosition)?this.dataset.arrowPosition:"middle";this.classList.add(`dm-carousel-arrows-${a}`);const d={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide",heightMode:this.dataset.heightMode==="average"?"average":"crop"};if(this.dataset.height){const f=Number(this.dataset.height);Number.isFinite(f)&&f>0&&(d.height=f)}if(this.dataset.animationDuration){const f=parseInt(this.dataset.animationDuration,10);Number.isFinite(f)&&(d.animationDuration=f)}this.dataset.animationEasing&&(d.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(f=>f.cloneNode(!0)),this._dmCarouselOpts=d),this._dmCarousel=Domma.elements.carousel(this,d)}),w.find(".dm-countdown").each(function(){const n={autoStart:!0},o=String(this.dataset.format||"").trim(),s=String(this.dataset.to||"").trim(),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(s),e=t?new Date(+t[1],+t[2]-1,+t[3]).getTime():s?new Date(s).getTime():NaN;Number.isFinite(e)?n.duration=Math.max(0,e-Date.now()):this.dataset.duration&&(n.duration=(parseInt(this.dataset.duration,10)||0)*1e3);const a=/^dd:/i.test(o);n.format=a?"hh:mm:ss":o||(n.duration>=36e5?"hh:mm:ss":"mm:ss");const d=this,f=l=>String(l).padStart(2,"0"),i=l=>{const g=Math.max(0,Math.floor(l/1e3)),b=d.querySelector(".dm-timer-time");b&&(b.textContent=`${f(Math.floor(g/86400))}:${f(Math.floor(g%86400/3600))}:${f(Math.floor(g%3600/60))}:${f(g%60)}`)};a&&(n.onTick=i),Domma.elements.timer(this,n),a&&i(n.duration||0)}),w.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),w.find(".dm-progression").each(function(){const n=Array.from(this.querySelectorAll(".dm-progression-item")).map(t=>{const e={title:t.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:t.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return t.dataset.date&&(e.date=t.dataset.date),t.dataset.status&&(e.status=t.dataset.status),t.dataset.eventIcon&&(e.icon=t.dataset.eventIcon),t.dataset.entryId&&(e._entryId=t.dataset.entryId),e}),o=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",s=Domma.elements.progression(this,{layout:o,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...n.length?{items:n}:{}});if((this.dataset.mode||"timeline")==="timeline"){const t={completed:{label:"Completed",icon:"check-circle",tone:"success"},planned:{label:"Planned",icon:"circle",tone:"secondary"},"in-progress":{label:"In progress",icon:"clock",tone:"primary"},blocked:{label:"Blocked",icon:"alert-circle",tone:"danger"}};this.querySelectorAll(".dm-progression-item").forEach((e,a)=>{const d=n[a];if(!d)return;const f=e.querySelector(".dm-progression-title");if(d.icon&&f){const l=document.createElement("span");l.dataset.icon=d.icon,l.style.cssText="display:inline-flex;vertical-align:middle;margin-right:.4em",l.setAttribute("aria-hidden","true"),f.prepend(l)}const i=t[d.status];if(i&&f){const l=document.createElement("span");l.className=`badge badge-${i.tone} cms-timeline-status`,l.style.cssText="display:inline-flex;align-items:center;gap:.35em;margin:.4rem 0";const g=document.createElement("span");g.dataset.icon=i.icon,g.dataset.iconSize="14",g.setAttribute("aria-hidden","true"),l.append(g,document.createTextNode(i.label)),f.after(l)}})}Domma.icons.scan(this),n.length&&(this._dmCtx={instance:s,items:n})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(n=>{const o=n.dataset.revealMode||"stagger",s=n.dataset.revealAnimation||"slide-up",t=parseInt(n.dataset.revealDuration,10)||400,e=parseInt(n.dataset.revealStagger,10)||60,a=parseInt(n.dataset.revealDelay,10)||0,d=n.dataset.revealDirection==="rtl",f=Array.from(n.children),i={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};f.forEach((l,g)=>{l.style.opacity="0",l.style.transform=i[s]||"",l.style.transition=`opacity ${t}ms ease, transform ${t}ms ease`;const b=d?f.length-1-g:g;l.style.transitionDelay=o==="stagger"?`${a+b*e}ms`:`${a}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const l=new IntersectionObserver(g=>{g.forEach(b=>{b.isIntersecting&&(b.target.offsetWidth,b.target.style.opacity="1",b.target.style.transform="none",l.unobserve(b.target))})},{threshold:.1});f.forEach(g=>l.observe(g))}))}),w.find(".card[data-collapsible]").each(function(){const n=this.querySelector(".card-header");n&&n.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),w.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const n=this.dataset.soTarget,o=document.getElementById(n);if(!o)return;const s=E.slideover({title:o.dataset.soTitle||"",size:o.dataset.soSize||"md",position:o.dataset.soPosition||"right"});o.style.display="",s.setContent(o),s.open()})})}if(typeof $.setup=="function"){const n=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(o=>{try{const s=P(o.dataset.config);Object.assign(n,s)}catch{}}),Object.keys(n).length>0){const o={};for(const[s,t]of Object.entries(n)){const e=t?.events?.click,{confirm:a,toast:d,alert:f,prompt:i,...l}=e||{};a||d||f||i?($(s).on("click",async function(b){if(b.preventDefault(),a&&!await E.confirm(a))return;let u=null;if(!(i&&(u=await E.prompt(i,{inputPlaceholder:l.promptPlaceholder||"",inputValue:l.promptDefault||""}),u===null))){if(l.target){const p=$(l.target);l.toggleClass&&p.toggleClass(l.toggleClass),l.addClass&&p.addClass(l.addClass),l.removeClass&&p.removeClass(l.removeClass),u!==null&&(l.setText&&p.text(u),l.setVal&&p.val(u),l.setAttr&&p.attr(l.setAttr,u))}l.href&&(window.location.href=l.href),d&&E.toast(d,{type:l.toastType||"success"}),f&&E.alert(f)}}),Object.keys(l).length&&(o[s]={...t,events:{...t.events,click:l}})):o[s]=t}$.setup(o)}}w.length&&j(w.get(0))}),window.wireCTAButtons=j;function j(h){h.querySelectorAll(".dm-cta-trigger").forEach(c=>{c.__ctaWired||(c.__ctaWired=!0,c.addEventListener("click",async()=>{const x=c.dataset.action,y=c.dataset.entry,k=c.dataset.confirm;let w=S.get("auth_token");if(!w){E.toast("Please log in to perform this action.",{type:"warning"});return}if(k&&!await E.confirm(k))return;const n=Array.from(c.childNodes).map(s=>s.cloneNode(!0));c.disabled=!0,c.textContent="Running\u2026";const o=s=>fetch(`/api/actions/${x}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify(c.dataset.scope?{entryId:y,scope:c.dataset.scope}:{entryId:y})});try{let s=await o(w);if(s.status===401){const e=S.get("auth_refresh_token");if(e){const a=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(a.ok){const{token:d}=await a.json();S.set("auth_token",d),w=d,s=await o(w)}}}const t=await s.json().catch(()=>({}));if(!s.ok||t.success===!1)throw new Error(t.error||t.message||`Error ${s.status}`);E.toast(t.message||"Action completed.",{type:"success"})}catch(s){E.toast(s.message||"Action failed.",{type:"error"})}finally{c.disabled=!1,c.textContent="",n.forEach(s=>c.appendChild(s)),Domma.icons.scan(c)}}))})}(function(){const c=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!c.length)return;const x=S.get("auth_token");function y(w,n){const o=document.createElement("div");o.className="dm-collection-display dm-collection-empty";const s=document.createElement("p");if(n){s.appendChild(document.createTextNode("Please "));const t=document.createElement("a");t.href="/login",t.textContent="sign in",s.appendChild(t),s.appendChild(document.createTextNode(" to view your entries."))}else s.textContent=w;return o.appendChild(s),o}function k(w,n){const o=document.createElement("template");o.innerHTML=n||"",w.replaceWith(o.content)}c.forEach(async w=>{const n=w.dataset.collectionAttrs;if(!n)return;if(!x){w.replaceChildren(y("",!0));return}const o=s=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify({attrs:n})});try{let s=x,t=await o(s);if(t.status===401){const a=S.get("auth_refresh_token");if(a){const d=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:a})});if(d.ok){const{token:f}=await d.json();S.set("auth_token",f),s=f,t=await o(s)}}}if(!t.ok){const{error:a}=await t.json().catch(()=>({}));w.replaceChildren(y(a||"Unable to load entries.",!1));return}const{html:e}=await t.json();k(w,e),window.DommaCollectionBrowser?.hydrate&&window.DommaCollectionBrowser.hydrate(document)}catch{w.replaceChildren(y("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),j(document.body)},100)})(),(function(){const c=document.querySelectorAll("[data-collection-table]");!c.length||typeof T>"u"||!T.create||c.forEach(x=>{let y;try{y=P(x.dataset.payload)}catch{return}const{columns:k,rows:w,search:n,sortable:o,exportable:s,pageSize:t,empty:e,ctaConfig:a,slug:d,exportCfg:f}=y;if(!k?.length)return;if(a){const g=k.findIndex(b=>b.key==="_cta");g!==-1&&(k[g]={key:"_cta",title:"",render:(b,u)=>{const p=document.createElement("button");if(p.className=`btn btn-${a.style||"primary"} dm-cta-trigger`,p.dataset.action=a.action||"",a.scope&&(p.dataset.scope=a.scope),p.dataset.entry=u._entryId||"",a.confirm&&(p.dataset.confirm=a.confirm),a.icon){const m=document.createElement("span");m.dataset.icon=a.icon,p.appendChild(m),p.appendChild(document.createTextNode(" "))}return p.appendChild(document.createTextNode(a.label||"Run")),p}})}const i="col-table-"+Math.random().toString(36).slice(2,7),l=document.createElement("div");l.id=i,x.replaceChildren(l),T.create("#"+i,{data:w,columns:k,search:n,sortable:o,exportable:s,pageSize:t,emptyMessage:e}),a&&j(l),x._dmTable={columns:k,rows:w,slug:d,exportCfg:f,render(g){T.create("#"+i,{data:g,columns:k,search:n,sortable:o,exportable:s,pageSize:t,emptyMessage:e}),a&&j(l)}}})})(),(function(){const c=document.querySelectorAll("[data-form-inline]");if(!c.length||typeof F>"u")return;function x(o){const s=o&&o.logic;return!!(s&&(s.visibility||s.requirement))}function y(o,s){const t={};return(o||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const a=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),d=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":a?"chooser":e.type,f={...e.formConfig||{}};f.span==="full"&&s&&(f.span=s);const i={type:d,required:x(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...e.tooltip&&{tooltip:e.tooltip},...f}};e.minLength!==void 0&&(i.minLength=e.minLength),e.maxLength!==void 0&&(i.maxLength=e.maxLength),e.min!==void 0&&(i.min=e.min),e.max!==void 0&&(i.max=e.max),a&&(e.variant&&(i.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(i.multiple=!0),e.density&&(i.density=e.density),e.columns&&(i.columns=e.columns),e.accent&&(i.accent=e.accent),e.accentStyle&&(i.accentStyle=e.accentStyle),e.glow&&(i.glow=!0),e.glowColour&&(i.glowColour=e.glowColour),e.shadow&&(i.shadow=e.shadow),e.shadowColour&&(i.shadowColour=e.shadowColour)),t[e.name]=i}),t}function k(o){const s={};return(o||[]).forEach(t=>{if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(s[t.name]=typeof e=="object"?e.value:e)}}),s}function w(o,s){(s||[]).forEach(t=>{if(t.type!=="date"||!t.name)return;const e=o.querySelector(`[name="${t.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function n(o,s,t){let e=o.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",o.appendChild(e)),e.textContent=s,e.style.cssText=t?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}c.forEach(o=>{let s;try{s=P(o.dataset.formInline)}catch{return}const t=s.fields||[],e=s.settings||{},a=Number(e.columns)===3?3:2,d=e.layout||"grid",f=t.some(p=>p.type==="page-break"),i=async p=>{if(o.dataset.triggerBlocked==="true"){const m=o._formLogicRuntime,v=m&&m.submitBlock?m.submitBlock().reasons:[];n(o,v.join(" ")||"This form cannot be submitted yet.",!0);const C=new Error("Blocked by a form trigger");throw C.formSubmitFailed=!0,C}try{const m=o.querySelector(".fb-form-honeypot"),v=m?.querySelector('input[type="text"]')||null,C=m?.querySelector('[name="_t"]')||null,A=Object.assign({},p);delete A._t,m?.dataset.hpName&&delete A[m.dataset.hpName],v!==null&&(A._hp=v.value),C!==null&&(A._t=C.value);const q=await H.post(`/api/forms/submit/${s.slug}`,A);if(q&&q.error){n(o,q.error,!0);const z=new Error(q.error);throw z.formSubmitFailed=!0,z}if(q?.redirect){window.location.href=q.redirect;return}for(;o.firstChild;)o.removeChild(o.firstChild);n(o,q?.message||e.successMessage||"Thank you for your submission.",!1)}catch(m){throw m.formSubmitFailed||n(o,m.message||"Submission failed. Please try again.",!0),m}},l=Date.now();function g(p){const m=p.querySelector("form");if(!m||m.querySelector(".fb-form-honeypot"))return;const v=document.createElement("div");v.className="fb-form-honeypot",v.setAttribute("aria-hidden","true");const C=document.createElement("input");C.name=m.querySelector('[name="website"]')?"_website":"website",v.dataset.hpName=C.name,C.type="text",C.tabIndex=-1,C.autocomplete="url",C.placeholder="https://",v.appendChild(C);const A=document.createElement("input");A.name="_t",A.type="hidden",A.value=l,v.appendChild(A),m.appendChild(v)}function b(p){if(!window.FormLogicEngine||!t.some(v=>v.logic||Array.isArray(v.triggers)&&v.triggers.length))return null;const m=new window.FormLogicEngine.FormLogicRuntime(s,o,p?{baseValues:p}:void 0);if(m.init(),o._formLogicRuntime=m,o._formLogicObserved)return m;if(o._formLogicObserved=!0,o.parentNode&&typeof MutationObserver<"u"){const v=new MutationObserver(function(C){for(const A of C)for(const q of A.removedNodes)if(q===o||q.nodeType===1&&q.contains&&q.contains(o)){o._formLogicRuntime&&o._formLogicRuntime.destroy(),v.disconnect();return}});v.observe(o.parentNode,{childList:!0,subtree:!1}),o._formLogicObserver=v}return m}let u=!1;if(o.addEventListener("dm-form-end",p=>{const m=p.detail?.validation;if(m&&!m.valid){K(o,m.missing),Q(m);return}u||(u=!0,i(p.detail?.values||{}).catch(()=>{}).finally(()=>{u=!1}))}),f&&F.wizard){const p=ce(t,s.title),m=p.map(I=>({title:I.title,description:I.description,fields:y(I.fields,a)})),v=p.map(I=>I.fields);let C=0,A=null,q=null;const z=I=>{const r=window.FormLogicEngine;if(!r||!r.validateFields)return;const M=r.validateFields(o,v[C]||[]);M.valid||(I.preventDefault(),I.stopImmediatePropagation(),K(o,M.missing),Q(M))},B=()=>{const I=v[C]||t;de(o,e),Z(o,e,I),w(o,I),G(o,I),e.honeypot!==!1&&g(o),A&&A.destroy(),A=b(q?.getStepData?q.getStepData():void 0),o.querySelectorAll(".wizard-next, .wizard-submit").forEach(r=>r.addEventListener("click",z,!0))};q=F.wizard(o,{schema:{steps:m},layout:d,columns:a,finishText:e.submitText||"Finish",onSubmit:i,onStepChange:I=>{C=I,setTimeout(B,0)}}),o.addEventListener("dm-form-trigger",I=>{if(I.detail?.type!=="goto-step"||!q?.goToStep)return;const r=Number(I.detail.action.step);!Number.isFinite(r)||r<0||r>=m.length||r!==C&&q.goToStep(r)}),Promise.resolve(q).then(B)}else if(F.render){const p=F.render(o,y(t,a),k(t),{submitText:e.submitText||"Submit",layout:d,columns:a,onSubmit:i});Promise.resolve(p).then(function(){le(o,e,d),Z(o,e,t),w(o,t),G(o,t),e.honeypot!==!1&&g(o),b()})}})})();function me(h,c){const x=document.body,y=x.classList,k=new Set((x.dataset.railSite||"").split(" ").filter(Boolean)),w=()=>window.matchMedia("(min-width: 993px)").matches;h.querySelectorAll(".navbar-link, .navbar-dropdown-toggle").forEach(a=>{const d=a.textContent.trim();d&&(a.setAttribute("title",d),a.querySelector("svg, [data-icon]")||(a.dataset.initial=d.charAt(0).toUpperCase()))});const n=document.createElement("button");n.type="button",n.className="dm-nav-collapse-toggle";const o=()=>{const a=y.contains("dm-vnav-collapsed");n.setAttribute("aria-pressed",String(a)),n.setAttribute("aria-label",a?"Expand menu":"Collapse menu"),n.title=n.getAttribute("aria-label");const d=c?"chevrons-left":"chevrons-right",f=c?"chevrons-right":"chevrons-left";n.innerHTML=`<span data-icon="${a?d:f}"></span>`,window.Domma&&Domma.icons&&Domma.icons.scan(n)},s=a=>{y.toggle("dm-vnav-collapsed",a),S.set("nav_collapsed",a),o()};n.addEventListener("click",()=>s(!y.contains("dm-vnav-collapsed"))),o();const t=h.querySelector(".navbar-container")||h;t.insertBefore(n,t.firstChild?.nextSibling||null);const e=a=>{y.toggle("dm-vnav-autohide",a),y.toggle("dm-vnav-collapsible",!a&&k.has("collapsible")),a?y.remove("dm-vnav-collapsed"):k.has("collapsible")&&S.get("nav_collapsed")===!0&&y.add("dm-vnav-collapsed"),h.classList.remove("dm-nav-revealed"),o()};h.addEventListener("pointerdown",a=>{y.contains("dm-vnav-autohide")&&a.pointerType!=="mouse"&&!h.classList.contains("dm-nav-revealed")&&(h.classList.add("dm-nav-revealed"),a.preventDefault())}),document.addEventListener("pointerdown",a=>{h.contains(a.target)||h.classList.remove("dm-nav-revealed")}),window.E&&typeof E.contextMenu=="function"&&E.contextMenu(h,{items:()=>{const a=y.contains("dm-vnav-autohide"),d=y.contains("dm-vnav-collapsed"),f=S.has("nav_autohide")||S.has("nav_collapsed");return[{header:"Menu"},{label:d?"Expand menu":"Collapse to icons",icon:d?"maximize":"minimize",disabled:!w()||a||!k.has("collapsible"),action:()=>s(!d)},{label:a?"Keep on screen":"Hide when not in use",icon:a?"eye":"eye-off",disabled:!w(),action:()=>{S.set("nav_autohide",!a),e(!a)}},{type:"divider"},{label:"Reset to the site's setting",icon:"refresh",disabled:!f,action:()=>{S.remove("nav_autohide"),S.remove("nav_collapsed"),e(k.has("autohide")),y.toggle("dm-vnav-collapsed",!k.has("autohide")&&k.has("start-collapsed")),o()}}]}})}function ue(h){h.classList.add("dm-nav-scroll-hide");let c=window.scrollY,x=!1;window.addEventListener("scroll",()=>{x||(x=!0,requestAnimationFrame(()=>{x=!1;const y=window.scrollY,k=h.matches(":focus-within")||h.querySelector(".navbar-dropdown.open, .navbar-collapse.show");y>c&&y>h.offsetHeight&&!k?h.classList.add("dm-nav-scrolled-away"):y<c&&h.classList.remove("dm-nav-scrolled-away"),c=y}))},{passive:!0})}function pe(h){let c={};try{c=JSON.parse(h.dataset.contents||"{}")}catch{}const x=h.closest(".site-main"),y=document.querySelector(".site-content"),k=new Set(String(c.exclude||"").split(",").map(i=>i.trim().toLowerCase()).filter(Boolean)),w=i=>!i.closest(".hero, .card, .accordion, .tabs, figure, #site-sidebar"),n=i=>(y?[...y.querySelectorAll(i)]:[]).filter(w).filter(l=>!k.has(l.textContent.trim().toLowerCase())),o=c.headings==="h2"?n("h2"):c.headings==="h3"?n("h3"):c.headings==="h2h3"?n("h2, h3"):n("h2").length?n("h2"):n("h3");if(!o.length){x?.classList.add("no-sidebar-items");return}const s=new Set([...document.querySelectorAll("[id]")].map(i=>i.id)),t=document.createElement("nav");t.className="dm-contents",t.setAttribute("aria-label",c.title||"Page contents"),c.hover&&(t.dataset.menuHover=c.hover),c.selected&&(t.dataset.menuActive=c.selected),c.accent&&t.style.setProperty("--dm-menu-highlight",c.accent.startsWith("#")?c.accent:`var(--dm-${c.accent})`),c.font&&(t.style.fontFamily=c.font),c.fontSize&&(t.style.fontSize=c.fontSize),c.fontWeight&&(t.style.fontWeight=c.fontWeight);const e=document.createElement("div");e.className="dm-contents-head";const a=document.createElement("p");a.className="dm-contents-title",a.textContent=c.title||"",e.appendChild(a),t.appendChild(e);const d=document.createElement("ol");d.className="dm-contents-list"+(c.numbered?" is-numbered":"");const f=[];for(const i of o){if(!i.id){const b=(i.textContent||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"section";let u=b;for(let p=2;s.has(u);p++)u=`${b}-${p}`;s.add(u),i.id=u}const l=document.createElement("li");l.className=`dm-contents-item dm-contents-${i.tagName.toLowerCase()}`;const g=document.createElement("a");g.href=`#${i.id}`,g.textContent=i.textContent.trim(),l.appendChild(g),d.appendChild(l),f.push([i,g])}if(t.appendChild(d),h.replaceChildren(t),c.scrollSpy!==!1&&"IntersectionObserver"in window){const i=new Map,l=()=>{const b=f.find(([u])=>i.get(u))||null;f.forEach(([,u])=>{const p=b&&u===b[1];u.classList.toggle("is-active",!!p),p?u.setAttribute("aria-current","location"):u.removeAttribute("aria-current")})},g=new IntersectionObserver(b=>{b.forEach(u=>i.set(u.target,u.isIntersecting)),l()},{rootMargin:"-80px 0px -60% 0px"});f.forEach(([b])=>g.observe(b))}if(x?.classList.contains("contents-collapsible")){const i=document.createElement("button");i.type="button",i.className="dm-contents-toggle";const l=()=>{const g=x.classList.contains("contents-collapsed");i.setAttribute("aria-expanded",String(!g)),i.setAttribute("aria-label",g?"Show the contents":"Hide the contents"),i.title=i.getAttribute("aria-label"),i.innerHTML=`<span data-icon="${g?"list":"x"}"></span>`,window.Domma?.icons&&Domma.icons.scan(i)};i.addEventListener("click",()=>{S.set("contents_collapsed",x.classList.toggle("contents-collapsed")),l()}),l(),e.insertBefore(i,e.firstChild)}if(x?.classList.contains("contents-floating")&&c.movable){t.classList.add("is-movable");const i=S.get("contents_position");i&&Number.isFinite(i.x)&&Object.assign(h.style,{left:`${i.x}px`,top:`${i.y}px`,right:"auto",bottom:"auto"}),e.addEventListener("pointerdown",l=>{if(l.target.closest("button"))return;const g=h.getBoundingClientRect(),b=l.clientX-g.left,u=l.clientY-g.top,p=v=>{const C=Math.max(0,Math.min(window.innerWidth-g.width,v.clientX-b)),A=Math.max(0,Math.min(window.innerHeight-40,v.clientY-u));Object.assign(h.style,{left:`${C}px`,top:`${A}px`,right:"auto",bottom:"auto"})},m=()=>{document.removeEventListener("pointermove",p),S.set("contents_position",{x:parseInt(h.style.left,10),y:parseInt(h.style.top,10)})};document.addEventListener("pointermove",p),document.addEventListener("pointerup",m,{once:!0})})}window.E&&typeof E.contextMenu=="function"&&E.contextMenu(h,{items:()=>{const i=x?.classList.contains("contents-collapsible"),l=x?.classList.contains("contents-collapsed"),g=f.find(([,b])=>b.classList.contains("is-active"));return[{header:"Contents"},...i?[{label:l?"Show the contents":"Collapse to a button",icon:l?"list":"minimize",action:()=>h.querySelector(".dm-contents-toggle")?.click()}]:[],{label:"Copy a link to this section",icon:"link",disabled:!g,action:async()=>{const b=`${location.origin}${location.pathname}#${g[0].id}`;try{await _.copyToClipboard(b),E.toast("Link copied.",{type:"success"})}catch{E.toast("Could not copy the link.",{type:"error"})}}},{label:"Back to the top",icon:"arrow-up",action:()=>window.scrollTo({top:0,behavior:"smooth"})}]}}),x?.classList.contains("contents-autohide")&&(h.addEventListener("pointerdown",i=>{i.pointerType!=="mouse"&&!h.classList.contains("is-revealed")&&(h.classList.add("is-revealed"),i.preventDefault())}),document.addEventListener("pointerdown",i=>{h.contains(i.target)||h.classList.remove("is-revealed")}))}
1
+ import{installSmoothCarets as oe}from"/public/js/smooth-caret.js";import{decodeBase64Json as P}from"/public/js/utf8-base64.mjs";import{makeBadgeEl as J,applyColour as X,applyPill as ne,applyFloat as ae,applyHighlight as R,applyItemHighlight as se,itemHighlightAttrs as ie,isCurrentItem as U,menuAlign as re,applyClasses as O,cssClasses as W,applyEntrance as V}from"/public/js/menu-decor.mjs?v=20261014-menu-entrance";import{initFloatingMenus as ce}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as G,markInvalidFields as K,showValidationPopup as Q}from"/public/js/forms.js?v=20261015-smooth-caret";import{buildWizardSteps as le}from"/public/js/form-steps.mjs";import{applyFormClasses as Z,applySubmitButtons as de,applyWizardButtons as me}from"/public/js/form-submit.mjs";document.addEventListener("click",h=>{const c=h.target?.closest?.(".dm-banner__dismiss");c&&(h.preventDefault(),c.closest(".dm-banner")?.remove())}),$(()=>{oe(document);const h=window.__CMS_NAV__||{},c=window.__CMS_SITE__||{};if(c.autoTheme?.enabled){let o=function(e){const a=(e||"07:00").split(":");return+a[0]*60+(+a[1]||0)},s=function(){const e=new Date,a=e.getHours()*60+e.getMinutes();return a>=o(n.dayStart)&&a<o(n.nightStart)?n.dayTheme:n.nightTheme},t=function(e){const a=n.apply&&n.apply[e]||{theme:e,custom:""};Domma.theme.set(a.theme);for(const d of[...document.body.classList])d.startsWith("dm-custom-")&&document.body.classList.remove(d);a.custom&&document.body.classList.add(a.custom)};const n=c.autoTheme;t(s()),setInterval(()=>t(s()),6e4)}const x=$("#site-navbar");if(x.length&&h.brand){let s=function(u,p=0){return Array.isArray(u)?u.filter(m=>!(m&&(m.type==="spacer"||m.type==="theme-switcher"))).filter(m=>!(m&&m.type==="separator"&&p===0)).map(m=>m&&m.type==="separator"?{divider:!0}:Array.isArray(m?.items)?{...m,items:s(m.items,p+1)}:m):u};const n={...h.brand},o=n.size&&n.size!=="md"?` navbar-brand-${n.size}`:"";if(n.logo||n.icon||n.tagline){let u="";n.logo?u+=`<img src="${n.logo}" class="navbar-brand-logo" alt="${n.text||""}">`:n.icon&&(u+=`<span data-icon="${n.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),n.text&&(u+=`<span class="navbar-brand-text${o}">${n.text}</span>`),n.tagline&&(u+=`<small class="navbar-brand-tagline">${n.tagline}</small>`),n.html=u}else o&&n.text&&(n.html=`<span class="navbar-brand-text${o}">${n.text}</span>`);const t=s(h.items||[]),e=h.position==="floating",a=h.orientation==="vertical";Domma.elements.navbar("#site-navbar",{brand:n,items:t,variant:h.variant||"dark",position:e?"static":h.position||"sticky",collapsible:!0,appearOnHover:!!h.appearOnHover}),Domma.icons.scan("#site-navbar");const d=x.get(0),f=()=>{if(!a)return;const p=d.querySelector('a[aria-current="page"]')?.closest(".navbar-dropdown");p&&!p.classList.contains("open")&&p.querySelector(":scope > .navbar-dropdown-toggle")?.click()};d.classList.add(`dm-nav-align-${re(h)||"centre"}`),a&&x.get(0).classList.add("dm-nav-vertical",h.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left");const i=h.dock||{};a&&!e&&ue(d,h.side==="right"),!a&&i.hideOnScroll&&pe(d),R(d,h),V(d,h),O(d,h.class),e&&(ae(x.get(0),h),ce(x.get(0).parentNode||document));const l=d.querySelector(".navbar-toggle"),g=d.querySelector(".navbar-collapse");if(l&&g){let u=null;const p=()=>{g.classList.contains("show")&&l.click()},m=()=>{u&&(u.remove(),u=null),document.body.classList.remove("dm-drawer-open")},v=()=>{u||(u=document.createElement("div"),u.className="dm-navbar-backdrop",u.addEventListener("click",p),document.body.appendChild(u),document.body.classList.add("dm-drawer-open"))};l.addEventListener("click",()=>{requestAnimationFrame(()=>{g.classList.contains("show")?(f(),v()):m()})}),g.addEventListener("click",C=>{C.target.closest("a")&&requestAnimationFrame(m)}),document.addEventListener("keydown",C=>{C.key==="Escape"&&g.classList.contains("show")&&p()})}const b=d.querySelector(".navbar-nav");if(b){const u=Array.from(b.children);let p=0;for(const m of h.items||[])if(!(m&&m.type==="separator")){if(m&&m.type==="spacer"){const v=document.createElement("li"),C=["xs","sm","md","lg","xl","flex"].includes(m.size)?m.size:"md";v.className=`dm-menu-spacer dm-menu-spacer--${C}`,v.setAttribute("aria-hidden","true"),b.insertBefore(v,u[p]||null);continue}if(m&&m.type==="theme-switcher"){const v=document.createElement("li");v.className="dm-menu-theme-switcher";const C=document.createElement("span");C.dataset.themeSwitcher="menu",C.dataset.position="inline",v.appendChild(C),b.insertBefore(v,u[p]||null);continue}p++}window.CMSThemeSwitcher?.scan(b)}d.querySelectorAll("[data-path]").forEach(u=>{const p=u.dataset.path.split(".").map(Number),m=p.length>1,v=p.reduce((A,q)=>A?.items?.[q],{items:t});if(!v)return;v.colour&&X(u,v.colour),v.pill&&!m&&ne(u,v.pill),se(u,v),O(u.closest("li"),v.class);const C=J(v.badge);C&&u.appendChild(C),U(v.url,location.pathname)&&(u.classList.add("active"),u.setAttribute("aria-current","page"))}),f()}const y=$("#site-footer");if(y.length){let e=function(r){return String(r??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")},a=function(r){return e(r).replace(/'/g,"&#39;")},d=function(r){if(r&&r.type==="separator")return'<li class="footer-sep"><hr></li>';if(r&&r.type==="spacer")return`<li class="dm-menu-spacer dm-menu-spacer--${["xs","sm","md","lg","xl","flex"].includes(r.size)?r.size:"md"}" aria-hidden="true"></li>`;if(r&&r.type==="theme-switcher")return'<li class="dm-menu-theme-switcher"><span data-theme-switcher="menu" data-position="inline"></span></li>';const M=a(r.url||"#"),L=e(r.text||""),D=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(d).join("")}</ul>`:"",N=ie(r),ee=[N.hover&&` data-menu-item-hover="${a(N.hover)}"`,N.active&&` data-menu-item-active="${a(N.active)}"`].filter(Boolean).join(""),te=N.accent?` style="--dm-menu-highlight:${a(N.accent)}"`:"",Y=W(r.class).join(" ");return`<li${Y?` class="${a(Y)}"`:""}><a href="${M}"${ee}${te}>${L}</a>${D}</li>`},f=function(){if(!c.footer)return"";const r=Object.keys(o).filter(L=>n[L]);if(!r.length)return"";const M=W(c.footer.socialClass).join(" ");return`<div class="footer-social">${r.map(L=>{const{label:D,svg:N}=o[L];return`<a href="${n[L]}" target="_blank" rel="noopener noreferrer" aria-label="${D}" class="footer-social-link${M?` ${a(M)}`:""}">${N}</a>`}).join("")}</div>`},b=function(r){if(!r||r.type==="separator"||r.type==="spacer")return"";if(r.type==="theme-switcher")return`<li class="cms-footer-col">${d(r).replace(/^<li[^>]*>|<\/li>$/g,"")}</li>`;const M=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(d).join("")}</ul>`:"",L=g(r)?`<span class="cms-footer-col-title">${e(r.text||"")}</span>`:`<a class="cms-footer-col-title" href="${a(r.url||"#")}">${e(r.text||"")}</a>`,D=["cms-footer-col",...W(r.class)].join(" ");return`<li class="${a(D)}">${L}${M}</li>`},p=function(r,M,L=!1){return(r||[]).forEach(D=>{D&&(D.type==="separator"||D.type==="spacer"||D.type==="theme-switcher")||(L&&g(D)||M.push(D),Array.isArray(D.items)&&D.items.length&&p(D.items,M))}),M};const n=c.social||{},o={twitter:{label:"X / Twitter",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.742l7.73-8.835L1.254 2.25H8.08l4.259 5.629L18.244 2.25zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>'},facebook:{label:"Facebook",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>'},instagram:{label:"Instagram",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>'},linkedin:{label:"LinkedIn",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>'},github:{label:"GitHub",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>'},youtube:{label:"YouTube",svg:'<svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.495 6.205a3.007 3.007 0 00-2.088-2.088c-1.87-.501-9.396-.501-9.396-.501s-7.507-.01-9.396.501A3.007 3.007 0 00.527 6.205a31.247 31.247 0 00-.522 5.805 31.247 31.247 0 00.522 5.783 3.007 3.007 0 002.088 2.088c1.868.502 9.396.502 9.396.502s7.506 0 9.396-.502a3.007 3.007 0 002.088-2.088 31.247 31.247 0 00.5-5.783 31.247 31.247 0 00-.5-5.805zM9.609 15.601V8.408l6.264 3.602z"/></svg>'}};let s='<div class="footer-inner container">';const t=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""},i=["columns","row"].includes(c.footer?.layout)?c.footer.layout:"auto",l=i==="columns"||i==="auto"&&t.primary.some(r=>Array.isArray(r?.items)&&r.items.length),g=r=>l&&!r.url&&Array.isArray(r.items)&&r.items.length>0;if(l){const r=h.brand||{},M=r.text||c.title||"",L=r.logo?`<img src="${a(r.logo)}" class="cms-footer-brand-logo" alt="">`:r.icon?'<span class="cms-footer-brand-icon"></span>':"",D=String(c.footer?.blurb||"").trim();s='<div class="footer-inner footer-inner--columns container"><div class="cms-footer-top">',s+=`<div class="cms-footer-brand">${M||L?`<a class="cms-footer-brand-name" href="${a(r.url||"/")}">${L}<span>${e(M)}</span></a>`:""}${D?`<p class="cms-footer-blurb">${e(D)}</p>`:""}${f()}</div>`,t.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary footer-nav--columns" aria-label="Footer"><ul>${t.primary.map(b).join("")}</ul></nav>`),s+='</div><div class="cms-footer-bottom">',t.copyright&&(s+=`<p class="cms-footer-copyright">${e(t.copyright)}</p>`),t.legal.length&&(s+=`<nav class="footer-nav footer-nav--legal" aria-label="Legal"><ul>${t.legal.map(d).join("")}</ul></nav>`),s+="</div>"}else t.copyright&&(s+=`<p>${e(t.copyright)}</p>`),t.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary"><ul>${t.primary.map(d).join("")}</ul></nav>`),t.legal.length&&(s+=`<nav class="footer-nav footer-nav--legal"><ul>${t.legal.map(d).join("")}</ul></nav>`),s+=f();s+="</div>",y.html(s),window.CMSThemeSwitcher?.scan(y.get(0));const u=y.get(0).querySelector(".cms-footer-brand-icon");u&&h.brand?.icon&&u.setAttribute("data-icon",h.brand.icon),O(y.get(0),c.footer?.class);const m=[...p(t.primary,[],!0),...p(t.legal,[])];y.get(0).querySelectorAll(".footer-nav a").forEach((r,M)=>{const L=m[M];if(!L)return;L.colour&&X(r,L.colour);const D=J(L.badge);D&&r.appendChild(D),U(L.url,location.pathname)&&(r.classList.add("is-active"),r.setAttribute("aria-current","page"))}),R(y.get(0).querySelector(".footer-nav--primary"),{highlight:t.primaryHighlight}),R(y.get(0).querySelector(".footer-nav--legal"),{highlight:t.legalHighlight}),V(y.get(0).querySelector(".footer-nav--primary"),{entrance:t.primaryEntrance}),V(y.get(0).querySelector(".footer-nav--legal"),{entrance:t.legalEntrance}),O(y.get(0).querySelector(".footer-nav--primary"),t.primaryClass),O(y.get(0).querySelector(".footer-nav--legal"),t.legalClass);const C=c.footer?.showMotionToggle!==!1,A=S.get("reduced_motion"),q=c.footer?.motionDefault,z=A!=null?!!A:q==="on"?!0:q==="off"?!1:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),B=c.footer?.motionControl==="checkbox",I=y.get(0).querySelector(".cms-footer-bottom")||y.get(0).querySelector(".footer-inner");if(C&&I){const r=document.createElement("input");r.type="checkbox",r.className=B?"footer-motion-checkbox":"form-switch-input",r.id="dm-motion-switch",r.checked=z,r.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const M=document.createElement("span");M.className=B?"footer-motion-label":"form-switch-label",M.textContent="Reduce motion";const L=document.createElement("label");L.className=B?"footer-motion-check":"form-switch footer-motion-switch",L.title="Reduce motion",L.appendChild(r),L.appendChild(M),I.appendChild(L)}}const k=document.getElementById("site-sidebar");k&&he(k),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const w=$(".page-body");if(w.length){w.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),w.find(".tabs").each(function(){Domma.elements.tabs(this)}),w.find(".carousel").each(function(){const n={primary:"--dm-primary",secondary:"--dm-secondary",accent:"--dm-primary",text:"--dm-text",surface:"--dm-surface",background:"--dm-background",success:"--dm-success",warning:"--dm-warning",danger:"--dm-danger",info:"--dm-info"},o=f=>{const i=String(f||"").trim();return i?n[i.toLowerCase()]?`var(${n[i.toLowerCase()]})`:CSS.supports("color",i)?i:"":""},s=o(this.dataset.background),t=o(this.dataset.arrowBackground),e=o(this.dataset.arrowColor);s&&(this.style.setProperty("--dm-carousel-background",s),this.classList.add("dm-carousel-custom-background")),t&&this.style.setProperty("--dm-carousel-arrow-background",t),e&&this.style.setProperty("--dm-carousel-arrow-color",e);const a=["top","middle","bottom"].includes(this.dataset.arrowPosition)?this.dataset.arrowPosition:"middle";this.classList.add(`dm-carousel-arrows-${a}`);const d={autoplay:this.dataset.autoplay==="true",interval:parseInt(this.dataset.interval,10)||5e3,loop:this.dataset.loop!=="false",animation:this.dataset.animation||"slide",heightMode:this.dataset.heightMode==="average"?"average":"crop"};if(this.dataset.height){const f=Number(this.dataset.height);Number.isFinite(f)&&f>0&&(d.height=f)}if(this.dataset.animationDuration){const f=parseInt(this.dataset.animationDuration,10);Number.isFinite(f)&&(d.animationDuration=f)}this.dataset.animationEasing&&(d.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(f=>f.cloneNode(!0)),this._dmCarouselOpts=d),this._dmCarousel=Domma.elements.carousel(this,d)}),w.find(".dm-countdown").each(function(){const n={autoStart:!0},o=String(this.dataset.format||"").trim(),s=String(this.dataset.to||"").trim(),t=/^(\d{4})-(\d{2})-(\d{2})$/.exec(s),e=t?new Date(+t[1],+t[2]-1,+t[3]).getTime():s?new Date(s).getTime():NaN;Number.isFinite(e)?n.duration=Math.max(0,e-Date.now()):this.dataset.duration&&(n.duration=(parseInt(this.dataset.duration,10)||0)*1e3);const a=/^dd:/i.test(o);n.format=a?"hh:mm:ss":o||(n.duration>=36e5?"hh:mm:ss":"mm:ss");const d=this,f=l=>String(l).padStart(2,"0"),i=l=>{const g=Math.max(0,Math.floor(l/1e3)),b=d.querySelector(".dm-timer-time");b&&(b.textContent=`${f(Math.floor(g/86400))}:${f(Math.floor(g%86400/3600))}:${f(Math.floor(g%3600/60))}:${f(g%60)}`)};a&&(n.onTick=i),Domma.elements.timer(this,n),a&&i(n.duration||0)}),w.find("[data-tooltip]").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),w.find(".dm-progression").each(function(){const n=Array.from(this.querySelectorAll(".dm-progression-item")).map(t=>{const e={title:t.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:t.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return t.dataset.date&&(e.date=t.dataset.date),t.dataset.status&&(e.status=t.dataset.status),t.dataset.eventIcon&&(e.icon=t.dataset.eventIcon),t.dataset.entryId&&(e._entryId=t.dataset.entryId),e}),o=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",s=Domma.elements.progression(this,{layout:o,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...n.length?{items:n}:{}});if((this.dataset.mode||"timeline")==="timeline"){const t={completed:{label:"Completed",icon:"check-circle",tone:"success"},planned:{label:"Planned",icon:"circle",tone:"secondary"},"in-progress":{label:"In progress",icon:"clock",tone:"primary"},blocked:{label:"Blocked",icon:"alert-circle",tone:"danger"}};this.querySelectorAll(".dm-progression-item").forEach((e,a)=>{const d=n[a];if(!d)return;const f=e.querySelector(".dm-progression-title");if(d.icon&&f){const l=document.createElement("span");l.dataset.icon=d.icon,l.style.cssText="display:inline-flex;vertical-align:middle;margin-right:.4em",l.setAttribute("aria-hidden","true"),f.prepend(l)}const i=t[d.status];if(i&&f){const l=document.createElement("span");l.className=`badge badge-${i.tone} cms-timeline-status`,l.style.cssText="display:inline-flex;align-items:center;gap:.35em;margin:.4rem 0";const g=document.createElement("span");g.dataset.icon=i.icon,g.dataset.iconSize="14",g.setAttribute("aria-hidden","true"),l.append(g,document.createTextNode(i.label)),f.after(l)}})}Domma.icons.scan(this),n.length&&(this._dmCtx={instance:s,items:n})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}document.querySelectorAll(".page-body .row[data-reveal]").forEach(n=>{const o=n.dataset.revealMode||"stagger",s=n.dataset.revealAnimation||"slide-up",t=parseInt(n.dataset.revealDuration,10)||400,e=parseInt(n.dataset.revealStagger,10)||60,a=parseInt(n.dataset.revealDelay,10)||0,d=n.dataset.revealDirection==="rtl",f=Array.from(n.children),i={"slide-up":"translateY(30px)","slide-down":"translateY(-30px)","slide-left":"translateX(30px)","slide-right":"translateX(-30px)",zoom:"scale(0.85)",flip:"perspective(600px) rotateX(15deg)"};f.forEach((l,g)=>{l.style.opacity="0",l.style.transform=i[s]||"",l.style.transition=`opacity ${t}ms ease, transform ${t}ms ease`;const b=d?f.length-1-g:g;l.style.transitionDelay=o==="stagger"?`${a+b*e}ms`:`${a}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const l=new IntersectionObserver(g=>{g.forEach(b=>{b.isIntersecting&&(b.target.offsetWidth,b.target.style.opacity="1",b.target.style.transform="none",l.unobserve(b.target))})},{threshold:.1});f.forEach(g=>l.observe(g))}))}),w.find(".card[data-collapsible]").each(function(){const n=this.querySelector(".card-header");n&&n.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),w.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const n=this.dataset.soTarget,o=document.getElementById(n);if(!o)return;const s=E.slideover({title:o.dataset.soTitle||"",size:o.dataset.soSize||"md",position:o.dataset.soPosition||"right"});o.style.display="",s.setContent(o),s.open()})})}if(typeof $.setup=="function"){const n=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(o=>{try{const s=P(o.dataset.config);Object.assign(n,s)}catch{}}),Object.keys(n).length>0){const o={};for(const[s,t]of Object.entries(n)){const e=t?.events?.click,{confirm:a,toast:d,alert:f,prompt:i,...l}=e||{};a||d||f||i?($(s).on("click",async function(b){if(b.preventDefault(),a&&!await E.confirm(a))return;let u=null;if(!(i&&(u=await E.prompt(i,{inputPlaceholder:l.promptPlaceholder||"",inputValue:l.promptDefault||""}),u===null))){if(l.target){const p=$(l.target);l.toggleClass&&p.toggleClass(l.toggleClass),l.addClass&&p.addClass(l.addClass),l.removeClass&&p.removeClass(l.removeClass),u!==null&&(l.setText&&p.text(u),l.setVal&&p.val(u),l.setAttr&&p.attr(l.setAttr,u))}l.href&&(window.location.href=l.href),d&&E.toast(d,{type:l.toastType||"success"}),f&&E.alert(f)}}),Object.keys(l).length&&(o[s]={...t,events:{...t.events,click:l}})):o[s]=t}$.setup(o)}}w.length&&j(w.get(0))}),window.wireCTAButtons=j;function j(h){h.querySelectorAll(".dm-cta-trigger").forEach(c=>{c.__ctaWired||(c.__ctaWired=!0,c.addEventListener("click",async()=>{const x=c.dataset.action,y=c.dataset.entry,k=c.dataset.confirm;let w=S.get("auth_token");if(!w){E.toast("Please log in to perform this action.",{type:"warning"});return}if(k&&!await E.confirm(k))return;const n=Array.from(c.childNodes).map(s=>s.cloneNode(!0));c.disabled=!0,c.textContent="Running\u2026";const o=s=>fetch(`/api/actions/${x}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify(c.dataset.scope?{entryId:y,scope:c.dataset.scope}:{entryId:y})});try{let s=await o(w);if(s.status===401){const e=S.get("auth_refresh_token");if(e){const a=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(a.ok){const{token:d}=await a.json();S.set("auth_token",d),w=d,s=await o(w)}}}const t=await s.json().catch(()=>({}));if(!s.ok||t.success===!1)throw new Error(t.error||t.message||`Error ${s.status}`);E.toast(t.message||"Action completed.",{type:"success"})}catch(s){E.toast(s.message||"Action failed.",{type:"error"})}finally{c.disabled=!1,c.textContent="",n.forEach(s=>c.appendChild(s)),Domma.icons.scan(c)}}))})}(function(){const c=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!c.length)return;const x=S.get("auth_token");function y(w,n){const o=document.createElement("div");o.className="dm-collection-display dm-collection-empty";const s=document.createElement("p");if(n){s.appendChild(document.createTextNode("Please "));const t=document.createElement("a");t.href="/login",t.textContent="sign in",s.appendChild(t),s.appendChild(document.createTextNode(" to view your entries."))}else s.textContent=w;return o.appendChild(s),o}function k(w,n){const o=document.createElement("template");o.innerHTML=n||"",w.replaceWith(o.content)}c.forEach(async w=>{const n=w.dataset.collectionAttrs;if(!n)return;if(!x){w.replaceChildren(y("",!0));return}const o=s=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify({attrs:n})});try{let s=x,t=await o(s);if(t.status===401){const a=S.get("auth_refresh_token");if(a){const d=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:a})});if(d.ok){const{token:f}=await d.json();S.set("auth_token",f),s=f,t=await o(s)}}}if(!t.ok){const{error:a}=await t.json().catch(()=>({}));w.replaceChildren(y(a||"Unable to load entries.",!1));return}const{html:e}=await t.json();k(w,e),window.DommaCollectionBrowser?.hydrate&&window.DommaCollectionBrowser.hydrate(document)}catch{w.replaceChildren(y("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),j(document.body)},100)})(),(function(){const c=document.querySelectorAll("[data-collection-table]");!c.length||typeof T>"u"||!T.create||c.forEach(x=>{let y;try{y=P(x.dataset.payload)}catch{return}const{columns:k,rows:w,search:n,sortable:o,exportable:s,pageSize:t,empty:e,ctaConfig:a,slug:d,exportCfg:f}=y;if(!k?.length)return;if(a){const g=k.findIndex(b=>b.key==="_cta");g!==-1&&(k[g]={key:"_cta",title:"",render:(b,u)=>{const p=document.createElement("button");if(p.className=`btn btn-${a.style||"primary"} dm-cta-trigger`,p.dataset.action=a.action||"",a.scope&&(p.dataset.scope=a.scope),p.dataset.entry=u._entryId||"",a.confirm&&(p.dataset.confirm=a.confirm),a.icon){const m=document.createElement("span");m.dataset.icon=a.icon,p.appendChild(m),p.appendChild(document.createTextNode(" "))}return p.appendChild(document.createTextNode(a.label||"Run")),p}})}const i="col-table-"+Math.random().toString(36).slice(2,7),l=document.createElement("div");l.id=i,x.replaceChildren(l),T.create("#"+i,{data:w,columns:k,search:n,sortable:o,exportable:s,pageSize:t,emptyMessage:e}),a&&j(l),x._dmTable={columns:k,rows:w,slug:d,exportCfg:f,render(g){T.create("#"+i,{data:g,columns:k,search:n,sortable:o,exportable:s,pageSize:t,emptyMessage:e}),a&&j(l)}}})})(),(function(){const c=document.querySelectorAll("[data-form-inline]");if(!c.length||typeof F>"u")return;function x(o){const s=o&&o.logic;return!!(s&&(s.visibility||s.requirement))}function y(o,s){const t={};return(o||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const a=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),d=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":a?"chooser":e.type,f={...e.formConfig||{}};f.span==="full"&&s&&(f.span=s);const i={type:d,required:x(e)?!1:e.required,label:e.label,options:e.options,formConfig:{...e.placeholder&&{placeholder:e.placeholder},...e.helper&&{hint:e.helper},...e.tooltip&&{tooltip:e.tooltip},...f}};e.minLength!==void 0&&(i.minLength=e.minLength),e.maxLength!==void 0&&(i.maxLength=e.maxLength),e.min!==void 0&&(i.min=e.min),e.max!==void 0&&(i.max=e.max),a&&(e.variant&&(i.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(i.multiple=!0),e.density&&(i.density=e.density),e.columns&&(i.columns=e.columns),e.accent&&(i.accent=e.accent),e.accentStyle&&(i.accentStyle=e.accentStyle),e.glow&&(i.glow=!0),e.glowColour&&(i.glowColour=e.glowColour),e.shadow&&(i.shadow=e.shadow),e.shadowColour&&(i.shadowColour=e.shadowColour)),t[e.name]=i}),t}function k(o){const s={};return(o||[]).forEach(t=>{if(!(!t.name||t.type==="page-break"||t.type==="spacer")&&(t.type==="select"||t.type==="multiselect")&&t.required){const e=(t.options||[])[0];e&&(s[t.name]=typeof e=="object"?e.value:e)}}),s}function w(o,s){(s||[]).forEach(t=>{if(t.type!=="date"||!t.name)return;const e=o.querySelector(`[name="${t.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function n(o,s,t){let e=o.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",o.appendChild(e)),e.textContent=s,e.style.cssText=t?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}c.forEach(o=>{let s;try{s=P(o.dataset.formInline)}catch{return}const t=s.fields||[],e=s.settings||{},a=Number(e.columns)===3?3:2,d=e.layout||"grid",f=t.some(p=>p.type==="page-break"),i=async p=>{if(o.dataset.triggerBlocked==="true"){const m=o._formLogicRuntime,v=m&&m.submitBlock?m.submitBlock().reasons:[];n(o,v.join(" ")||"This form cannot be submitted yet.",!0);const C=new Error("Blocked by a form trigger");throw C.formSubmitFailed=!0,C}try{const m=o.querySelector(".fb-form-honeypot"),v=m?.querySelector('input[type="text"]')||null,C=m?.querySelector('[name="_t"]')||null,A=Object.assign({},p);delete A._t,m?.dataset.hpName&&delete A[m.dataset.hpName],v!==null&&(A._hp=v.value),C!==null&&(A._t=C.value);const q=await H.post(`/api/forms/submit/${s.slug}`,A);if(q&&q.error){n(o,q.error,!0);const z=new Error(q.error);throw z.formSubmitFailed=!0,z}if(q?.redirect){window.location.href=q.redirect;return}for(;o.firstChild;)o.removeChild(o.firstChild);n(o,q?.message||e.successMessage||"Thank you for your submission.",!1)}catch(m){throw m.formSubmitFailed||n(o,m.message||"Submission failed. Please try again.",!0),m}},l=Date.now();function g(p){const m=p.querySelector("form");if(!m||m.querySelector(".fb-form-honeypot"))return;const v=document.createElement("div");v.className="fb-form-honeypot",v.setAttribute("aria-hidden","true");const C=document.createElement("input");C.name=m.querySelector('[name="website"]')?"_website":"website",v.dataset.hpName=C.name,C.type="text",C.tabIndex=-1,C.autocomplete="url",C.placeholder="https://",v.appendChild(C);const A=document.createElement("input");A.name="_t",A.type="hidden",A.value=l,v.appendChild(A),m.appendChild(v)}function b(p){if(!window.FormLogicEngine||!t.some(v=>v.logic||Array.isArray(v.triggers)&&v.triggers.length))return null;const m=new window.FormLogicEngine.FormLogicRuntime(s,o,p?{baseValues:p}:void 0);if(m.init(),o._formLogicRuntime=m,o._formLogicObserved)return m;if(o._formLogicObserved=!0,o.parentNode&&typeof MutationObserver<"u"){const v=new MutationObserver(function(C){for(const A of C)for(const q of A.removedNodes)if(q===o||q.nodeType===1&&q.contains&&q.contains(o)){o._formLogicRuntime&&o._formLogicRuntime.destroy(),v.disconnect();return}});v.observe(o.parentNode,{childList:!0,subtree:!1}),o._formLogicObserver=v}return m}let u=!1;if(o.addEventListener("dm-form-end",p=>{const m=p.detail?.validation;if(m&&!m.valid){K(o,m.missing),Q(m);return}u||(u=!0,i(p.detail?.values||{}).catch(()=>{}).finally(()=>{u=!1}))}),f&&F.wizard){const p=le(t,s.title),m=p.map(I=>({title:I.title,description:I.description,fields:y(I.fields,a)})),v=p.map(I=>I.fields);let C=0,A=null,q=null;const z=I=>{const r=window.FormLogicEngine;if(!r||!r.validateFields)return;const M=r.validateFields(o,v[C]||[]);M.valid||(I.preventDefault(),I.stopImmediatePropagation(),K(o,M.missing),Q(M))},B=()=>{const I=v[C]||t;me(o,e),Z(o,e,I),w(o,I),G(o,I),e.honeypot!==!1&&g(o),A&&A.destroy(),A=b(q?.getStepData?q.getStepData():void 0),o.querySelectorAll(".wizard-next, .wizard-submit").forEach(r=>r.addEventListener("click",z,!0))};q=F.wizard(o,{schema:{steps:m},layout:d,columns:a,finishText:e.submitText||"Finish",onSubmit:i,onStepChange:I=>{C=I,setTimeout(B,0)}}),o.addEventListener("dm-form-trigger",I=>{if(I.detail?.type!=="goto-step"||!q?.goToStep)return;const r=Number(I.detail.action.step);!Number.isFinite(r)||r<0||r>=m.length||r!==C&&q.goToStep(r)}),Promise.resolve(q).then(B)}else if(F.render){const p=F.render(o,y(t,a),k(t),{submitText:e.submitText||"Submit",layout:d,columns:a,onSubmit:i});Promise.resolve(p).then(function(){de(o,e,d),Z(o,e,t),w(o,t),G(o,t),e.honeypot!==!1&&g(o),b()})}})})();function ue(h,c){const x=document.body,y=x.classList,k=new Set((x.dataset.railSite||"").split(" ").filter(Boolean)),w=()=>window.matchMedia("(min-width: 993px)").matches;h.querySelectorAll(".navbar-link, .navbar-dropdown-toggle").forEach(a=>{const d=a.textContent.trim();d&&(a.setAttribute("title",d),a.querySelector("svg, [data-icon]")||(a.dataset.initial=d.charAt(0).toUpperCase()))});const n=document.createElement("button");n.type="button",n.className="dm-nav-collapse-toggle";const o=()=>{const a=y.contains("dm-vnav-collapsed");n.setAttribute("aria-pressed",String(a)),n.setAttribute("aria-label",a?"Expand menu":"Collapse menu"),n.title=n.getAttribute("aria-label");const d=c?"chevrons-left":"chevrons-right",f=c?"chevrons-right":"chevrons-left";n.innerHTML=`<span data-icon="${a?d:f}"></span>`,window.Domma&&Domma.icons&&Domma.icons.scan(n)},s=a=>{y.toggle("dm-vnav-collapsed",a),S.set("nav_collapsed",a),o()};n.addEventListener("click",()=>s(!y.contains("dm-vnav-collapsed"))),o();const t=h.querySelector(".navbar-container")||h;t.insertBefore(n,t.firstChild?.nextSibling||null);const e=a=>{y.toggle("dm-vnav-autohide",a),y.toggle("dm-vnav-collapsible",!a&&k.has("collapsible")),a?y.remove("dm-vnav-collapsed"):k.has("collapsible")&&S.get("nav_collapsed")===!0&&y.add("dm-vnav-collapsed"),h.classList.remove("dm-nav-revealed"),o()};h.addEventListener("pointerdown",a=>{y.contains("dm-vnav-autohide")&&a.pointerType!=="mouse"&&!h.classList.contains("dm-nav-revealed")&&(h.classList.add("dm-nav-revealed"),a.preventDefault())}),document.addEventListener("pointerdown",a=>{h.contains(a.target)||h.classList.remove("dm-nav-revealed")}),window.E&&typeof E.contextMenu=="function"&&E.contextMenu(h,{items:()=>{const a=y.contains("dm-vnav-autohide"),d=y.contains("dm-vnav-collapsed"),f=S.has("nav_autohide")||S.has("nav_collapsed");return[{header:"Menu"},{label:d?"Expand menu":"Collapse to icons",icon:d?"maximize":"minimize",disabled:!w()||a||!k.has("collapsible"),action:()=>s(!d)},{label:a?"Keep on screen":"Hide when not in use",icon:a?"eye":"eye-off",disabled:!w(),action:()=>{S.set("nav_autohide",!a),e(!a)}},{type:"divider"},{label:"Reset to the site's setting",icon:"refresh",disabled:!f,action:()=>{S.remove("nav_autohide"),S.remove("nav_collapsed"),e(k.has("autohide")),y.toggle("dm-vnav-collapsed",!k.has("autohide")&&k.has("start-collapsed")),o()}}]}})}function pe(h){h.classList.add("dm-nav-scroll-hide");let c=window.scrollY,x=!1;window.addEventListener("scroll",()=>{x||(x=!0,requestAnimationFrame(()=>{x=!1;const y=window.scrollY,k=h.matches(":focus-within")||h.querySelector(".navbar-dropdown.open, .navbar-collapse.show");y>c&&y>h.offsetHeight&&!k?h.classList.add("dm-nav-scrolled-away"):y<c&&h.classList.remove("dm-nav-scrolled-away"),c=y}))},{passive:!0})}function he(h){let c={};try{c=JSON.parse(h.dataset.contents||"{}")}catch{}const x=h.closest(".site-main"),y=document.querySelector(".site-content"),k=new Set(String(c.exclude||"").split(",").map(i=>i.trim().toLowerCase()).filter(Boolean)),w=i=>!i.closest(".hero, .card, .accordion, .tabs, figure, #site-sidebar"),n=i=>(y?[...y.querySelectorAll(i)]:[]).filter(w).filter(l=>!k.has(l.textContent.trim().toLowerCase())),o=c.headings==="h2"?n("h2"):c.headings==="h3"?n("h3"):c.headings==="h2h3"?n("h2, h3"):n("h2").length?n("h2"):n("h3");if(!o.length){x?.classList.add("no-sidebar-items");return}const s=new Set([...document.querySelectorAll("[id]")].map(i=>i.id)),t=document.createElement("nav");t.className="dm-contents",t.setAttribute("aria-label",c.title||"Page contents"),c.hover&&(t.dataset.menuHover=c.hover),c.selected&&(t.dataset.menuActive=c.selected),c.accent&&t.style.setProperty("--dm-menu-highlight",c.accent.startsWith("#")?c.accent:`var(--dm-${c.accent})`),c.font&&(t.style.fontFamily=c.font),c.fontSize&&(t.style.fontSize=c.fontSize),c.fontWeight&&(t.style.fontWeight=c.fontWeight);const e=document.createElement("div");e.className="dm-contents-head";const a=document.createElement("p");a.className="dm-contents-title",a.textContent=c.title||"",e.appendChild(a),t.appendChild(e);const d=document.createElement("ol");d.className="dm-contents-list"+(c.numbered?" is-numbered":"");const f=[];for(const i of o){if(!i.id){const b=(i.textContent||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"section";let u=b;for(let p=2;s.has(u);p++)u=`${b}-${p}`;s.add(u),i.id=u}const l=document.createElement("li");l.className=`dm-contents-item dm-contents-${i.tagName.toLowerCase()}`;const g=document.createElement("a");g.href=`#${i.id}`,g.textContent=i.textContent.trim(),l.appendChild(g),d.appendChild(l),f.push([i,g])}if(t.appendChild(d),h.replaceChildren(t),c.scrollSpy!==!1&&"IntersectionObserver"in window){const i=new Map,l=()=>{const b=f.find(([u])=>i.get(u))||null;f.forEach(([,u])=>{const p=b&&u===b[1];u.classList.toggle("is-active",!!p),p?u.setAttribute("aria-current","location"):u.removeAttribute("aria-current")})},g=new IntersectionObserver(b=>{b.forEach(u=>i.set(u.target,u.isIntersecting)),l()},{rootMargin:"-80px 0px -60% 0px"});f.forEach(([b])=>g.observe(b))}if(x?.classList.contains("contents-collapsible")){const i=document.createElement("button");i.type="button",i.className="dm-contents-toggle";const l=()=>{const g=x.classList.contains("contents-collapsed");i.setAttribute("aria-expanded",String(!g)),i.setAttribute("aria-label",g?"Show the contents":"Hide the contents"),i.title=i.getAttribute("aria-label"),i.innerHTML=`<span data-icon="${g?"list":"x"}"></span>`,window.Domma?.icons&&Domma.icons.scan(i)};i.addEventListener("click",()=>{S.set("contents_collapsed",x.classList.toggle("contents-collapsed")),l()}),l(),e.insertBefore(i,e.firstChild)}if(x?.classList.contains("contents-floating")&&c.movable){t.classList.add("is-movable");const i=S.get("contents_position");i&&Number.isFinite(i.x)&&Object.assign(h.style,{left:`${i.x}px`,top:`${i.y}px`,right:"auto",bottom:"auto"}),e.addEventListener("pointerdown",l=>{if(l.target.closest("button"))return;const g=h.getBoundingClientRect(),b=l.clientX-g.left,u=l.clientY-g.top,p=v=>{const C=Math.max(0,Math.min(window.innerWidth-g.width,v.clientX-b)),A=Math.max(0,Math.min(window.innerHeight-40,v.clientY-u));Object.assign(h.style,{left:`${C}px`,top:`${A}px`,right:"auto",bottom:"auto"})},m=()=>{document.removeEventListener("pointermove",p),S.set("contents_position",{x:parseInt(h.style.left,10),y:parseInt(h.style.top,10)})};document.addEventListener("pointermove",p),document.addEventListener("pointerup",m,{once:!0})})}window.E&&typeof E.contextMenu=="function"&&E.contextMenu(h,{items:()=>{const i=x?.classList.contains("contents-collapsible"),l=x?.classList.contains("contents-collapsed"),g=f.find(([,b])=>b.classList.contains("is-active"));return[{header:"Contents"},...i?[{label:l?"Show the contents":"Collapse to a button",icon:l?"list":"minimize",action:()=>h.querySelector(".dm-contents-toggle")?.click()}]:[],{label:"Copy a link to this section",icon:"link",disabled:!g,action:async()=>{const b=`${location.origin}${location.pathname}#${g[0].id}`;try{await _.copyToClipboard(b),E.toast("Link copied.",{type:"success"})}catch{E.toast("Could not copy the link.",{type:"error"})}}},{label:"Back to the top",icon:"arrow-up",action:()=>window.scrollTo({top:0,behavior:"smooth"})}]}}),x?.classList.contains("contents-autohide")&&(h.addEventListener("pointerdown",i=>{i.pointerType!=="mouse"&&!h.classList.contains("is-revealed")&&(h.classList.add("is-revealed"),i.preventDefault())}),document.addEventListener("pointerdown",i=>{h.contains(i.target)||h.classList.remove("is-revealed")}))}
@@ -0,0 +1 @@
1
+ const r=Object.freeze({refresh(){},destroy(){}}),t=()=>globalThis.Domma?.smoothCaret;export const attachSmoothCaret=e=>t()?.attach(e)||r,installSmoothCarets=e=>t()?.install(e)||r,getCaretPreference=()=>t()?.getPreference()||"auto",setCaretPreference=e=>t()?.setPreference(e);
@@ -173,7 +173,7 @@
173
173
  </script>
174
174
 
175
175
  <!-- Site initialisation -->
176
- <script src="/public/js/site.js?v=20261015-menu-current-branch" type="module"></script>
176
+ <script src="/public/js/site.js?v=20261015-smooth-caret" type="module"></script>
177
177
  <script src="/public/js/collection-context.js?v=20261010-utf8-payloads" type="module"></script>
178
178
  {{ctxMenusModule}}
179
179
 
@@ -188,7 +188,7 @@
188
188
 
189
189
  <!-- Core Forms (logic engine must load before renderer) -->
190
190
  <script src="/public/js/form-logic-engine.js?v=20260927-submit-btn"></script>
191
- <script src="/public/js/forms.js?v=20261009-form-classes" type="module"></script>
191
+ <script src="/public/js/forms.js?v=20261015-smooth-caret" type="module"></script>
192
192
 
193
193
  <!-- Core effects runtime -->
194
194
  <script src="/public/js/effects.js?v=20261015-occasions"></script>