domma-cms 1.13.2 → 1.15.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 +8 -0
- package/admin/js/lib/shortcode-context-menu.js +2 -2
- package/admin/js/lib/shortcode-insert.js +1 -1
- package/admin/js/lib/shortcode-preview.js +1 -1
- package/admin/js/lib/shortcode-registry.js +2 -2
- package/admin/js/lib/site-settings-arrange.js +3 -3
- package/admin/js/templates/docs/usage-shortcodes.html +9 -1
- package/admin/js/templates/docs/usage-site-settings.html +13 -2
- package/admin/js/templates/menu-editor.html +1 -1
- package/admin/js/templates/settings.html +96 -22
- package/admin/js/views/settings.js +3 -3
- package/docs/DommaFeatures.md +3 -1
- package/docs/configuration.md +53 -8
- package/docs/markdown-shortcodes.md +2 -0
- package/package.json +1 -1
- package/public/css/motion.css +1 -0
- package/public/js/motion-control.mjs +1 -0
- package/public/js/site.js +1 -1
- package/server/routes/api/settings.js +23 -2
- package/server/services/motionSettings.js +107 -0
- package/server/services/renderer.js +34 -6
- package/server/templates/page.html +2 -2
package/public/js/site.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{applyMobileMenu as ae,initCarouselPopup as ie}from"/public/js/mobile-ui.mjs?v=20261016-mobile-options";import{installSmoothCarets as re}from"/public/js/smooth-caret.js";import{decodeBase64Json as W}from"/public/js/utf8-base64.mjs";import{makeBadgeEl as U,applyColour as G,applyPill as ce,applyFloat as le,applyHighlight as V,applyItemHighlight as de,itemHighlightAttrs as me,isCurrentItem as K,menuAlign as ue,applyClasses as P,cssClasses as Y,applyEntrance as X}from"/public/js/menu-decor.mjs?v=20261014-menu-entrance";import{applyMenuLook as pe}from"/public/js/menu-cards.mjs?v=20261029-glider-layout";import{initPageMotion as fe}from"/public/js/page-motion.mjs?v=20261029-page-motion";import{applyFooterShowcase as he}from"/public/js/footer-showcase.mjs?v=20261029-footer-showcase";import{initFloatingMenus as ge}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as Q,markInvalidFields as Z,showValidationPopup as ee}from"/public/js/forms.js?v=20261025-forms-files-total";import{buildWizardSteps as ye}from"/public/js/form-steps.mjs";import{applyFormClasses as te,applySubmitButtons as ve,applyWizardButtons as be}from"/public/js/form-submit.mjs";import{captureFileFields as oe,destroyDropzones as we,fileBlueprint as Ce,restoreFileFields as Se,setFileLimits as xe,splitFiles as ke,submitBody as Le,totalTooLarge as $e,wireFileFields as Ee}from"/public/js/form-files.mjs";document.addEventListener("click",u=>{const i=u.target?.closest?.(".dm-banner__dismiss");i&&(u.preventDefault(),i.closest(".dm-banner")?.remove())}),$(()=>{re(document);const u=window.__CMS_NAV__||{},i=window.__CMS_SITE__||{};if(i.autoTheme?.enabled){let t=function(e){const n=(e||"07:00").split(":");return+n[0]*60+(+n[1]||0)},s=function(){const e=new Date,n=e.getHours()*60+e.getMinutes();return n>=t(l.dayStart)&&n<t(l.nightStart)?l.dayTheme:l.nightTheme},o=function(e){const n=l.apply&&l.apply[e]||{theme:e,custom:""};Domma.theme.set(n.theme);for(const m of[...document.body.classList])m.startsWith("dm-custom-")&&document.body.classList.remove(m);n.custom&&document.body.classList.add(n.custom)};const l=i.autoTheme;o(s()),setInterval(()=>o(s()),6e4)}const L=$("#site-navbar");if(L.length&&u.brand){let s=function(p,v=0){return Array.isArray(p)?p.filter(f=>!(f&&(f.type==="spacer"||f.type==="theme-switcher"))).filter(f=>!(f&&f.type==="separator"&&v===0)).map(f=>f&&f.type==="separator"?{divider:!0}:Array.isArray(f?.items)?{...f,items:s(f.items,v+1)}:f):p};const l={...u.brand},t=l.size&&l.size!=="md"?` navbar-brand-${l.size}`:"";if(l.logo||l.icon||l.tagline){let p="";l.logo?p+=`<img src="${l.logo}" class="navbar-brand-logo" alt="${l.text||""}">`:l.icon&&(p+=`<span data-icon="${l.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),l.text&&(p+=`<span class="navbar-brand-text${t}">${l.text}</span>`),l.tagline&&(p+=`<small class="navbar-brand-tagline">${l.tagline}</small>`),l.html=p}else t&&l.text&&(l.html=`<span class="navbar-brand-text${t}">${l.text}</span>`);const o=s(u.items||[]),e=u.position==="floating",n=u.orientation==="vertical";L.get(0).querySelector(":scope > .cms-nojs-links")?.remove(),Domma.elements.navbar("#site-navbar",{brand:l,items:o,variant:u.variant||"dark",position:e?"static":u.position||"sticky",collapsible:!0,appearOnHover:!!u.appearOnHover}),Domma.icons.scan("#site-navbar");const m=L.get(0);ae(m,u.mobile);const b=()=>{if(!n)return;const v=m.querySelector('a[aria-current="page"]')?.closest(".navbar-dropdown");v&&!v.classList.contains("open")&&v.querySelector(":scope > .navbar-dropdown-toggle")?.click()};m.classList.add(`dm-nav-align-${ue(u)||"centre"}`),n&&L.get(0).classList.add("dm-nav-vertical",u.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left");const a=u.dock||{};n&&!e&&Ae(m,u.side==="right"),!n&&a.hideOnScroll&&Te(m),V(m,u),X(m,u),P(m,u.class),e&&(le(L.get(0),u),ge(L.get(0).parentNode||document));const c=m.querySelector(".navbar-toggle"),g=m.querySelector(".navbar-collapse");if(c&&g){let p=null;const v=()=>{g.classList.contains("show")&&c.click()},f=()=>{p&&(p.remove(),p=null),document.body.classList.remove("dm-drawer-open")},d=()=>{p||(p=document.createElement("div"),p.className="dm-navbar-backdrop",p.addEventListener("click",v),document.body.appendChild(p),document.body.classList.add("dm-drawer-open"))};c.addEventListener("click",()=>{requestAnimationFrame(()=>{g.classList.contains("show")?(b(),d()):f()})}),g.addEventListener("click",y=>{y.target.closest("a")&&requestAnimationFrame(f)}),document.addEventListener("keydown",y=>{y.key==="Escape"&&g.classList.contains("show")&&v()})}const w=m.querySelector(".navbar-nav");if(w){const p=Array.from(w.children);let v=0;for(const f of u.items||[])if(!(f&&f.type==="separator")){if(f&&f.type==="spacer"){const d=document.createElement("li"),y=["xs","sm","md","lg","xl","flex"].includes(f.size)?f.size:"md";d.className=`dm-menu-spacer dm-menu-spacer--${y}`,d.setAttribute("aria-hidden","true"),w.insertBefore(d,p[v]||null);continue}if(f&&f.type==="theme-switcher"){const d=document.createElement("li");d.className="dm-menu-theme-switcher";const y=document.createElement("span");y.dataset.themeSwitcher="menu",y.dataset.position="inline",d.appendChild(y),w.insertBefore(d,p[v]||null);continue}v++}window.CMSThemeSwitcher?.scan(w)}m.querySelectorAll("[data-path]").forEach(p=>{const v=p.dataset.path.split(".").map(Number),f=v.length>1,d=v.reduce((C,D)=>C?.items?.[D],{items:o});if(!d)return;d.colour&&G(p,d.colour),d.pill&&!f&&ce(p,d.pill),de(p,d),P(p.closest("li"),d.class);const y=U(d.badge);y&&p.appendChild(y),K(d.url,location.pathname)&&(p.classList.add("active"),p.setAttribute("aria-current","page"))}),pe(m,u,o),b()}const h=$("#site-footer");if(h.length){let e=function(r){return String(r??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")},n=function(r){return e(r).replace(/'/g,"'")},m=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 N=n(r.url||"#"),k=e(r.text||""),M=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(m).join("")}</ul>`:"",j=me(r),ne=[j.hover&&` data-menu-item-hover="${n(j.hover)}"`,j.active&&` data-menu-item-active="${n(j.active)}"`].filter(Boolean).join(""),se=j.accent?` style="--dm-menu-highlight:${n(j.accent)}"`:"",J=Y(r.class).join(" ");return`<li${J?` class="${n(J)}"`:""}><a href="${N}"${ne}${se}>${k}</a>${M}</li>`},a=function(){if(!i.footer)return"";const r=Object.keys(t).filter(k=>l[k]);if(!r.length)return"";const N=Y(i.footer.socialClass).join(" ");return`<div class="footer-social">${r.map(k=>{const{label:M,svg:j}=t[k];return`<a href="${l[k]}" target="_blank" rel="noopener noreferrer" aria-label="${M}" class="footer-social-link${N?` ${n(N)}`:""}">${j}</a>`}).join("")}</div>`},p=function(r){if(!r||r.type==="separator"||r.type==="spacer")return"";if(r.type==="theme-switcher")return`<li class="cms-footer-col">${m(r).replace(/^<li[^>]*>|<\/li>$/g,"")}</li>`;const N=Array.isArray(r.items)&&r.items.length?`<ul>${r.items.map(m).join("")}</ul>`:"",k=w(r)?`<span class="cms-footer-col-title">${e(r.text||"")}</span>`:`<a class="cms-footer-col-title" href="${n(r.url||"#")}">${e(r.text||"")}</a>`,M=["cms-footer-col",...Y(r.class)].join(" ");return`<li class="${n(M)}">${k}${N}</li>`},d=function(r,N,k=!1){return(r||[]).forEach(M=>{M&&(M.type==="separator"||M.type==="spacer"||M.type==="theme-switcher")||(k&&w(M)||N.push(M),Array.isArray(M.items)&&M.items.length&&d(M.items,N))}),N};const l=i.social||{},t={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 o=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""},b=(()=>{const r=i.cookieConsent;if(!r||r.showSettingsLink===!1)return"";const N=k=>(k||[]).some(M=>M&&(M.url==="#cookie-settings"||N(M.items)));return N(o.primary)||N(o.legal)?"":`<li class="cms-cookie-settings"><a href="#cookie-settings">${e(r.settingsLinkText||"Cookie settings")}</a></li>`})(),c=["columns","row"].includes(i.footer?.layout)?i.footer.layout:"auto",g=i.footer?.look==="showcase"||c==="columns"||c==="auto"&&o.primary.some(r=>Array.isArray(r?.items)&&r.items.length),w=r=>g&&!r.url&&Array.isArray(r.items)&&r.items.length>0;if(g){const r=u.brand||{},N=r.text||i.title||"",k=r.logo?`<img src="${n(r.logo)}" class="cms-footer-brand-logo" alt="">`:r.icon?'<span class="cms-footer-brand-icon"></span>':"",M=String(i.footer?.blurb||"").trim();s='<div class="footer-inner footer-inner--columns container"><div class="cms-footer-top">',s+=`<div class="cms-footer-brand">${N||k?`<a class="cms-footer-brand-name" href="${n(r.url||"/")}">${k}<span>${e(N)}</span></a>`:""}${M?`<p class="cms-footer-blurb">${e(M)}</p>`:""}${a()}</div>`,o.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary footer-nav--columns" aria-label="Footer"><ul>${o.primary.map(p).join("")}</ul></nav>`),s+='</div><div class="cms-footer-bottom">',o.copyright&&(s+=`<p class="cms-footer-copyright">${e(o.copyright)}</p>`),(o.legal.length||b)&&(s+=`<nav class="footer-nav footer-nav--legal" aria-label="Legal"><ul>${o.legal.map(m).join("")}${b}</ul></nav>`),s+="</div>"}else o.copyright&&(s+=`<p>${e(o.copyright)}</p>`),o.primary.length&&(s+=`<nav class="footer-nav footer-nav--primary"><ul>${o.primary.map(m).join("")}</ul></nav>`),(o.legal.length||b)&&(s+=`<nav class="footer-nav footer-nav--legal"><ul>${o.legal.map(m).join("")}${b}</ul></nav>`),s+=a();s+="</div>",h.get(0).querySelector(":scope > .cms-nojs-links")?.remove();const v=h.get(0).querySelector(":scope > .cms-footer-blocks");v?.remove(),h.html(s),v&&h.get(0).prepend(v),window.CMSThemeSwitcher?.scan(h.get(0));const f=h.get(0).querySelector(".cms-footer-brand-icon");f&&u.brand?.icon&&f.setAttribute("data-icon",u.brand.icon),P(h.get(0),i.footer?.class),g&&he(h.get(0),i);const y=[...d(o.primary,[],!0),...d(o.legal,[])];h.get(0).querySelectorAll(".footer-nav a").forEach((r,N)=>{const k=y[N];if(!k)return;k.colour&&G(r,k.colour);const M=U(k.badge);M&&r.appendChild(M),K(k.url,location.pathname)&&(r.classList.add("is-active"),r.setAttribute("aria-current","page"))}),V(h.get(0).querySelector(".footer-nav--primary"),{highlight:o.primaryHighlight}),V(h.get(0).querySelector(".footer-nav--legal"),{highlight:o.legalHighlight}),X(h.get(0).querySelector(".footer-nav--primary"),{entrance:o.primaryEntrance}),X(h.get(0).querySelector(".footer-nav--legal"),{entrance:o.legalEntrance}),P(h.get(0).querySelector(".footer-nav--primary"),o.primaryClass),P(h.get(0).querySelector(".footer-nav--legal"),o.legalClass);const D=i.footer?.showMotionToggle!==!1,z=S.get("reduced_motion"),B=i.footer?.motionDefault,O=z!=null?!!z:B==="on"?!0:B==="off"?!1:!!(window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches),A=i.footer?.motionControl==="checkbox",I=h.get(0).querySelector(".cms-footer-bottom")||h.get(0).querySelector(".footer-inner");if(D&&I){const r=document.createElement("input");r.type="checkbox",r.className=A?"footer-motion-checkbox":"form-switch-input",r.id="dm-motion-switch",r.checked=O,r.addEventListener("change",function(){S.set("reduced_motion",this.checked),window.location.reload()});const N=document.createElement("span");N.className=A?"footer-motion-label":"form-switch-label",N.textContent="Reduce motion";const k=document.createElement("label");k.className=A?"footer-motion-check":"form-switch footer-motion-switch",k.title="Reduce motion",k.appendChild(r),k.appendChild(N),I.appendChild(k)}}const q=document.getElementById("site-sidebar");q&&_e(q),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const x=$(".page-body");if(x.length){x.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),x.find(".tabs").each(function(){Domma.elements.tabs(this)}),x.find(".carousel").each(function(){const t={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"},s=a=>{const c=String(a||"").trim();return c?t[c.toLowerCase()]?`var(${t[c.toLowerCase()]})`:CSS.supports("color",c)?c:"":""},o=s(this.dataset.background),e=s(this.dataset.arrowBackground),n=s(this.dataset.arrowColor);o&&(this.style.setProperty("--dm-carousel-background",o),this.classList.add("dm-carousel-custom-background")),e&&this.style.setProperty("--dm-carousel-arrow-background",e),n&&this.style.setProperty("--dm-carousel-arrow-color",n);const m=["top","middle","bottom"].includes(this.dataset.arrowPosition)?this.dataset.arrowPosition:"middle";this.classList.add(`dm-carousel-arrows-${m}`);const b={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 a=Number(this.dataset.height);Number.isFinite(a)&&a>0&&(b.height=a)}if(this.dataset.animationDuration){const a=parseInt(this.dataset.animationDuration,10);Number.isFinite(a)&&(b.animationDuration=a)}this.dataset.animationEasing&&(b.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(a=>a.cloneNode(!0)),this._dmCarouselOpts=b),this._dmCarousel=Domma.elements.carousel(this,b),ie(this)}),x.find(".dm-countdown").each(function(){const t={autoStart:!0},s=String(this.dataset.format||"").trim(),o=String(this.dataset.to||"").trim(),e=/^(\d{4})-(\d{2})-(\d{2})$/.exec(o),n=e?new Date(+e[1],+e[2]-1,+e[3]).getTime():o?new Date(o).getTime():NaN;Number.isFinite(n)?t.duration=Math.max(0,n-Date.now()):this.dataset.duration&&(t.duration=(parseInt(this.dataset.duration,10)||0)*1e3);const m=/^dd:/i.test(s);t.format=m?"hh:mm:ss":s||(t.duration>=36e5?"hh:mm:ss":"mm:ss");const b=this,a=g=>String(g).padStart(2,"0"),c=g=>{const w=Math.max(0,Math.floor(g/1e3)),p=b.querySelector(".dm-timer-time");p&&(p.textContent=`${a(Math.floor(w/86400))}:${a(Math.floor(w%86400/3600))}:${a(Math.floor(w%3600/60))}:${a(w%60)}`)};m&&(t.onTick=c),Domma.elements.timer(this,t),m&&c(t.duration||0)}),x.find("[data-tooltip]:not(.dm-range-slider)").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),x.find(".dm-progression").each(function(){const t=Array.from(this.querySelectorAll(".dm-progression-item")).map(e=>{const n={title:e.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:e.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return e.dataset.date&&(n.date=e.dataset.date),e.dataset.status&&(n.status=e.dataset.status),e.dataset.eventIcon&&(n.icon=e.dataset.eventIcon),e.dataset.entryId&&(n._entryId=e.dataset.entryId),n}),s=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",o=Domma.elements.progression(this,{layout:s,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...t.length?{items:t}:{}});if((this.dataset.mode||"timeline")==="timeline"){const e={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((n,m)=>{const b=t[m];if(!b)return;const a=n.querySelector(".dm-progression-title");if(b.icon&&a){const g=document.createElement("span");g.dataset.icon=b.icon,g.style.cssText="display:inline-flex;vertical-align:middle;margin-right:.4em",g.setAttribute("aria-hidden","true"),a.prepend(g)}const c=e[b.status];if(c&&a){const g=document.createElement("span");g.className=`badge badge-${c.tone} cms-timeline-status`,g.style.cssText="display:inline-flex;align-items:center;gap:.35em;margin:.4rem 0";const w=document.createElement("span");w.dataset.icon=c.icon,w.dataset.iconSize="14",w.setAttribute("aria-hidden","true"),g.append(w,document.createTextNode(c.label)),a.after(g)}})}Domma.icons.scan(this),t.length&&(this._dmCtx={instance:o,items:t})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}const l=matchMedia("(prefers-reduced-motion: reduce)").matches||document.documentElement.classList.contains("dm-reduced-motion");document.querySelectorAll(".page-body .row[data-reveal]").forEach(t=>{const s=t.dataset.revealMode||"stagger",o=t.dataset.revealAnimation||"slide-up",e=parseInt(t.dataset.revealDuration,10)||(o.startsWith("swoosh")?700:400),n=parseInt(t.dataset.revealStagger,10)||(o.startsWith("swoosh")?90:60),m=parseInt(t.dataset.revealDelay,10)||0,b=t.dataset.revealDirection==="rtl",a=t.dataset.revealReplay==="true",c=Array.from(t.children);if(l&&o.startsWith("swoosh"))return;const g={"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)",swoosh:"translateY(36px) scale(0.96)"},w=d=>o!=="swoosh-sides"?g[o]||"":c.length>1&&d===0?"translateX(-64px) rotate(-1.5deg)":c.length>1&&d===c.length-1?"translateX(64px) rotate(1.5deg)":"translateY(40px) scale(0.94)",p=o.startsWith("swoosh"),v=p?"cubic-bezier(.2,.8,.2,1)":"ease",f=(d,y)=>{d.style.opacity="0",d.style.transform=w(y),p&&(d.style.filter="blur(10px)")};c.forEach((d,y)=>{f(d,y),d.style.transition=`opacity ${e}ms ${v}, transform ${e}ms ${v}`+(p?`, filter ${e}ms ${v}`:"");const C=b?c.length-1-y:y;d.style.transitionDelay=s==="stagger"?`${m+C*n}ms`:`${m}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const d=new IntersectionObserver(y=>{y.forEach(C=>{if(C.isIntersecting){if(C.target.offsetWidth,C.target.style.opacity="1",C.target.style.transform="",p&&(C.target.style.filter=""),!a){d.unobserve(C.target);const D=C.target;D.addEventListener("transitionend",function z(B){B.target!==D||B.propertyName!=="opacity"||(D.removeEventListener("transitionend",z),D.style.transition="",D.style.transitionDelay="")})}}else a&&C.boundingClientRect.top>0&&f(C.target,c.indexOf(C.target))})},{threshold:.1});c.forEach(y=>d.observe(y))}))}),fe(document.querySelector(".page-body")||document),x.find(".card[data-collapsible]").each(function(){const t=this.querySelector(".card-header");t&&t.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),x.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const t=this.dataset.soTarget,s=document.getElementById(t);if(!s)return;const o=E.slideover({title:s.dataset.soTitle||"",size:s.dataset.soSize||"md",position:s.dataset.soPosition||"right"});s.style.display="",o.setContent(s),o.open()})})}if(typeof $.setup=="function"){const l=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(t=>{try{const s=W(t.dataset.config);Object.assign(l,s)}catch{}}),Object.keys(l).length>0){const t={};for(const[s,o]of Object.entries(l)){const e=o?.events?.click,{confirm:n,toast:m,alert:b,prompt:a,...c}=e||{};if(n||m||b||a){$(s).on("click",async function(N){if(N.preventDefault(),n&&!await E.confirm(n))return;let k=null;if(!(a&&(k=await E.prompt(a,{inputPlaceholder:c.promptPlaceholder||"",inputValue:c.promptDefault||""}),k===null))){{const M=$(c.target||this);c.toggleClass&&M.toggleClass(c.toggleClass),c.addClass&&M.addClass(c.addClass),c.removeClass&&M.removeClass(c.removeClass),k!==null&&(c.setText&&M.text(k),c.setVal&&M.val(k),c.setAttr&&M.attr(c.setAttr,k))}c.href&&(window.location.href=c.href),m&&E.toast(m,{type:c.toastType||"success"}),b&&E.alert(b)}});const{target:w,toggleClass:p,addClass:v,removeClass:f,setText:d,setVal:y,setAttr:C,href:D,toastType:z,promptPlaceholder:B,promptDefault:O,...A}=c,I={...o.events};Object.keys(A).length?I.click=w?{target:w,...A}:A:delete I.click;const r={...o,events:I};Object.keys(I).length||delete r.events,Object.keys(r).length&&(t[s]=r)}else t[s]=o}$.setup(t)}}x.length&&R(x.get(0))}),window.wireCTAButtons=R;function R(u){u.querySelectorAll(".dm-cta-trigger").forEach(i=>{i.__ctaWired||(i.__ctaWired=!0,i.addEventListener("click",async()=>{const L=i.dataset.action,h=i.dataset.entry,q=i.dataset.confirm;let x=S.get("auth_token");if(!x){E.toast("Please log in to perform this action.",{type:"warning"});return}if(q&&!await E.confirm(q))return;const l=Array.from(i.childNodes).map(s=>s.cloneNode(!0));i.disabled=!0,i.textContent="Running\u2026";const t=s=>fetch(`/api/actions/${L}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify(i.dataset.scope?{entryId:h,scope:i.dataset.scope}:{entryId:h})});try{let s=await t(x);if(s.status===401){const e=S.get("auth_refresh_token");if(e){const n=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(n.ok){const{token:m}=await n.json();S.set("auth_token",m),x=m,s=await t(x)}}}const o=await s.json().catch(()=>({}));if(!s.ok||o.success===!1)throw new Error(o.error||o.message||`Error ${s.status}`);E.toast(o.message||"Action completed.",{type:"success"})}catch(s){E.toast(s.message||"Action failed.",{type:"error"})}finally{i.disabled=!1,i.textContent="",l.forEach(s=>i.appendChild(s)),Domma.icons.scan(i)}}))})}(function(){const i=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!i.length)return;const L=S.get("auth_token");function h(x,l){const t=document.createElement("div");t.className="dm-collection-display dm-collection-empty";const s=document.createElement("p");if(l){s.appendChild(document.createTextNode("Please "));const o=document.createElement("a");o.href="/login",o.textContent="sign in",s.appendChild(o),s.appendChild(document.createTextNode(" to view your entries."))}else s.textContent=x;return t.appendChild(s),t}function q(x,l){const t=document.createElement("template");t.innerHTML=l||"",x.replaceWith(t.content)}i.forEach(async x=>{const l=x.dataset.collectionAttrs;if(!l)return;if(!L){x.replaceChildren(h("",!0));return}const t=s=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify({attrs:l})});try{let s=L,o=await t(s);if(o.status===401){const n=S.get("auth_refresh_token");if(n){const m=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:n})});if(m.ok){const{token:b}=await m.json();S.set("auth_token",b),s=b,o=await t(s)}}}if(!o.ok){const{error:n}=await o.json().catch(()=>({}));x.replaceChildren(h(n||"Unable to load entries.",!1));return}const{html:e}=await o.json();q(x,e),window.DommaCollectionBrowser?.hydrate&&window.DommaCollectionBrowser.hydrate(document)}catch{x.replaceChildren(h("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),R(document.body)},100)})(),(function(){const i=document.querySelectorAll("[data-collection-table]");!i.length||typeof T>"u"||!T.create||i.forEach(L=>{let h;try{h=W(L.dataset.payload)}catch{return}const{columns:q,rows:x,search:l,sortable:t,exportable:s,pageSize:o,empty:e,ctaConfig:n,slug:m,exportCfg:b}=h;if(!q?.length)return;if(n){const g=q.findIndex(w=>w.key==="_cta");g!==-1&&(q[g]={key:"_cta",title:"",render:(w,p)=>{const v=document.createElement("button");if(v.className=`btn btn-${n.style||"primary"} dm-cta-trigger`,v.dataset.action=n.action||"",n.scope&&(v.dataset.scope=n.scope),v.dataset.entry=p._entryId||"",n.confirm&&(v.dataset.confirm=n.confirm),n.icon){const f=document.createElement("span");f.dataset.icon=n.icon,v.appendChild(f),v.appendChild(document.createTextNode(" "))}return v.appendChild(document.createTextNode(n.label||"Run")),v}})}const a="col-table-"+Math.random().toString(36).slice(2,7),c=document.createElement("div");c.id=a,L.replaceChildren(c),T.create("#"+a,{data:x,columns:q,search:l,sortable:t,exportable:s,pageSize:o,emptyMessage:e}),n&&R(c),L._dmTable={columns:q,rows:x,slug:m,exportCfg:b,render(g){T.create("#"+a,{data:g,columns:q,search:l,sortable:t,exportable:s,pageSize:o,emptyMessage:e}),n&&R(c)}}})})(),(function(){const i=document.querySelectorAll("[data-form-inline]");if(!i.length||typeof F>"u")return;function L(t){const s=t&&t.logic;return!!(s&&(s.visibility||s.requirement))}function h(t,s){const o={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const n=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),m=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":n?"chooser":e.type,b={...e.formConfig||{}};b.span==="full"&&s&&(b.span=s);const a={type:m,required:L(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},...b}};e.minLength!==void 0&&(a.minLength=e.minLength),e.maxLength!==void 0&&(a.maxLength=e.maxLength),e.min!==void 0&&(a.min=e.min),e.max!==void 0&&(a.max=e.max),n&&(e.variant&&(a.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(a.multiple=!0),e.density&&(a.density=e.density),e.columns&&(a.columns=e.columns),e.accent&&(a.accent=e.accent),e.accentStyle&&(a.accentStyle=e.accentStyle),e.glow&&(a.glow=!0),e.glowColour&&(a.glowColour=e.glowColour),e.shadow&&(a.shadow=e.shadow),e.shadowColour&&(a.shadowColour=e.shadowColour)),o[e.name]=e.type==="file"?Ce(e,a):a}),o}function q(t){const s={};return(t||[]).forEach(o=>{if(!(!o.name||o.type==="page-break"||o.type==="spacer")&&(o.type==="select"||o.type==="multiselect")&&o.required){const e=(o.options||[])[0];e&&(s[o.name]=typeof e=="object"?e.value:e)}}),s}function x(t,s){(s||[]).forEach(o=>{if(o.type!=="date"||!o.name)return;const e=t.querySelector(`[name="${o.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function l(t,s,o){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=s,e.style.cssText=o?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}i.forEach(t=>{let s;try{s=W(t.dataset.formInline)}catch{return}t.querySelector(":scope > .cms-form-embed-summary")?.remove();const o=s.fields||[],e=s.settings||{},n=Number(e.columns)===3?3:2,m=e.layout||"grid",b=o.some(f=>f.type==="page-break"),a=new Map;xe(t,s.fileLimits,a),Ee(t,o);const c=async f=>{if(t.dataset.triggerBlocked==="true"){const d=t._formLogicRuntime,y=d&&d.submitBlock?d.submitBlock().reasons:[];l(t,y.join(" ")||"This form cannot be submitted yet.",!0);const C=new Error("Blocked by a form trigger");throw C.formSubmitFailed=!0,C}try{const d=t.querySelector(".fb-form-honeypot"),y=d?.querySelector('input[type="text"]')||null,C=d?.querySelector('[name="_t"]')||null,D=Object.assign({},f);delete D._t,d?.dataset.hpName&&delete D[d.dataset.hpName],y!==null&&(D._hp=y.value),C!==null&&(D._t=C.value);const z=new Map(a);oe(t,z);const B=ke(D,o,z),O=$e(t,B.files);if(O){l(t,O,!0);const I=new Error(O);throw I.formSubmitFailed=!0,I}const A=await H.post(`/api/forms/submit/${s.slug}`,B.files.size?Le(B.values,B.files).body:B.values);if(A&&A.error){l(t,A.error,!0);const I=new Error(A.error);throw I.formSubmitFailed=!0,I}if(A?.redirect){window.location.href=A.redirect;return}for(we(t);t.firstChild;)t.removeChild(t.firstChild);l(t,A?.message||e.successMessage||"Thank you for your submission.",!1)}catch(d){throw d.formSubmitFailed||l(t,d.message||"Submission failed. Please try again.",!0),d}},g=Date.now();function w(f){const d=f.querySelector("form");if(!d||d.querySelector(".fb-form-honeypot"))return;const y=document.createElement("div");y.className="fb-form-honeypot",y.setAttribute("aria-hidden","true");const C=document.createElement("input");C.name=d.querySelector('[name="website"]')?"_website":"website",y.dataset.hpName=C.name,C.type="text",C.tabIndex=-1,C.autocomplete="url",C.placeholder="https://",y.appendChild(C);const D=document.createElement("input");D.name="_t",D.type="hidden",D.value=g,y.appendChild(D),d.appendChild(y)}function p(f){if(!window.FormLogicEngine||!o.some(y=>y.logic||Array.isArray(y.triggers)&&y.triggers.length))return null;const d=new window.FormLogicEngine.FormLogicRuntime(s,t,f?{baseValues:f}:void 0);if(d.init(),t._formLogicRuntime=d,t._formLogicObserved)return d;if(t._formLogicObserved=!0,t.parentNode&&typeof MutationObserver<"u"){const y=new MutationObserver(function(C){for(const D of C)for(const z of D.removedNodes)if(z===t||z.nodeType===1&&z.contains&&z.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),y.disconnect();return}});y.observe(t.parentNode,{childList:!0,subtree:!1}),t._formLogicObserver=y}return d}let v=!1;if(t.addEventListener("dm-form-end",f=>{const d=f.detail?.validation;if(d&&!d.valid){Z(t,d.missing),ee(d);return}v||(v=!0,c(f.detail?.values||{}).catch(()=>{}).finally(()=>{v=!1}))}),b&&F.wizard){const f=ye(o,s.title),d=f.map(A=>({title:A.title,description:A.description,fields:h(A.fields,n)})),y=f.map(A=>A.fields);let C=0,D=null,z=null;const B=A=>{const I=window.FormLogicEngine;if(!I||!I.validateFields)return;const r=I.validateFields(t,y[C]||[]);r.valid||(A.preventDefault(),A.stopImmediatePropagation(),Z(t,r.missing),ee(r))},O=()=>{const A=y[C]||o;be(t,e),te(t,e,A),x(t,A),Q(t,A),Se(t,a),e.honeypot!==!1&&w(t),D&&D.destroy(),D=p(z?.getStepData?z.getStepData():void 0),t.querySelectorAll(".wizard-next, .wizard-submit").forEach(I=>I.addEventListener("click",B,!0))};z=F.wizard(t,{schema:{steps:d},layout:m,columns:n,finishText:e.submitText||"Finish",onSubmit:c,onStepChange:A=>{oe(t,a),C=A,setTimeout(O,0)}}),t.addEventListener("dm-form-trigger",A=>{if(A.detail?.type!=="goto-step"||!z?.goToStep)return;const I=Number(A.detail.action.step);!Number.isFinite(I)||I<0||I>=d.length||I!==C&&z.goToStep(I)}),Promise.resolve(z).then(O)}else if(F.render){const f=F.render(t,h(o,n),q(o),{submitText:e.submitText||"Submit",layout:m,columns:n,onSubmit:c});Promise.resolve(f).then(function(){ve(t,e,m),te(t,e,o),x(t,o),Q(t,o),e.honeypot!==!1&&w(t),p()})}})})();function Ae(u,i){const L=document.body,h=L.classList,q=new Set((L.dataset.railSite||"").split(" ").filter(Boolean)),x=()=>window.matchMedia("(min-width: 993px)").matches;u.querySelectorAll(".navbar-link, .navbar-dropdown-toggle").forEach(n=>{const m=n.textContent.trim();m&&(n.setAttribute("title",m),n.querySelector("svg, [data-icon]")||(n.dataset.initial=m.charAt(0).toUpperCase()))});const l=document.createElement("button");l.type="button",l.className="dm-nav-collapse-toggle";const t=()=>{const n=h.contains("dm-vnav-collapsed");l.setAttribute("aria-pressed",String(n)),l.setAttribute("aria-label",n?"Expand menu":"Collapse menu"),l.title=l.getAttribute("aria-label");const m=i?"chevrons-left":"chevrons-right",b=i?"chevrons-right":"chevrons-left";l.innerHTML=`<span data-icon="${n?m:b}"></span>`,window.Domma&&Domma.icons&&Domma.icons.scan(l)},s=n=>{h.toggle("dm-vnav-collapsed",n),S.set("nav_collapsed",n),t()};l.addEventListener("click",()=>s(!h.contains("dm-vnav-collapsed"))),t();const o=u.querySelector(".navbar-container")||u;o.insertBefore(l,o.firstChild?.nextSibling||null);const e=n=>{h.toggle("dm-vnav-autohide",n),h.toggle("dm-vnav-collapsible",!n&&q.has("collapsible")),n?h.remove("dm-vnav-collapsed"):q.has("collapsible")&&S.get("nav_collapsed")===!0&&h.add("dm-vnav-collapsed"),u.classList.remove("dm-nav-revealed"),t()};u.addEventListener("pointerdown",n=>{h.contains("dm-vnav-autohide")&&n.pointerType!=="mouse"&&!u.classList.contains("dm-nav-revealed")&&(u.classList.add("dm-nav-revealed"),n.preventDefault())}),document.addEventListener("pointerdown",n=>{u.contains(n.target)||u.classList.remove("dm-nav-revealed")}),window.E&&typeof E.contextMenu=="function"&&E.contextMenu(u,{items:()=>{const n=h.contains("dm-vnav-autohide"),m=h.contains("dm-vnav-collapsed"),b=S.has("nav_autohide")||S.has("nav_collapsed");return[{header:"Menu"},{label:m?"Expand menu":"Collapse to icons",icon:m?"maximize":"minimize",disabled:!x()||n||!q.has("collapsible"),action:()=>s(!m)},{label:n?"Keep on screen":"Hide when not in use",icon:n?"eye":"eye-off",disabled:!x(),action:()=>{S.set("nav_autohide",!n),e(!n)}},{type:"divider"},{label:"Reset to the site's setting",icon:"refresh",disabled:!b,action:()=>{S.remove("nav_autohide"),S.remove("nav_collapsed"),e(q.has("autohide")),h.toggle("dm-vnav-collapsed",!q.has("autohide")&&q.has("start-collapsed")),t()}}]}})}function Te(u){u.classList.add("dm-nav-scroll-hide");let i=window.scrollY,L=!1;window.addEventListener("scroll",()=>{L||(L=!0,requestAnimationFrame(()=>{L=!1;const h=window.scrollY,q=u.matches(":focus-within")||u.querySelector(".navbar-dropdown.open, .navbar-collapse.show");h>i&&h>u.offsetHeight&&!q?u.classList.add("dm-nav-scrolled-away"):h<i&&u.classList.remove("dm-nav-scrolled-away"),i=h}))},{passive:!0})}function _e(u){let i={};try{i=JSON.parse(u.dataset.contents||"{}")}catch{}const L=u.closest(".site-main"),h=document.querySelector(".site-content"),q=new Set(String(i.exclude||"").split(",").map(a=>a.trim().toLowerCase()).filter(Boolean)),x=a=>!a.closest(".hero, .card, .accordion, .tabs, figure, #site-sidebar"),l=a=>(h?[...h.querySelectorAll(a)]:[]).filter(x).filter(c=>!q.has(c.textContent.trim().toLowerCase())),t=i.headings==="h2"?l("h2"):i.headings==="h3"?l("h3"):i.headings==="h2h3"?l("h2, h3"):l("h2").length?l("h2"):l("h3");if(!t.length){L?.classList.add("no-sidebar-items");return}const s=new Set([...document.querySelectorAll("[id]")].map(a=>a.id)),o=document.createElement("nav");o.className="dm-contents",o.setAttribute("aria-label",i.title||"Page contents"),i.hover&&(o.dataset.menuHover=i.hover),i.selected&&(o.dataset.menuActive=i.selected),i.accent&&o.style.setProperty("--dm-menu-highlight",i.accent.startsWith("#")?i.accent:`var(--dm-${i.accent})`),i.font&&(o.style.fontFamily=i.font),i.fontSize&&(o.style.fontSize=i.fontSize),i.fontWeight&&(o.style.fontWeight=i.fontWeight);const e=document.createElement("div");e.className="dm-contents-head";const n=document.createElement("p");n.className="dm-contents-title",n.textContent=i.title||"",e.appendChild(n),o.appendChild(e);const m=document.createElement("ol");m.className="dm-contents-list"+(i.numbered?" is-numbered":"");const b=[];for(const a of t){if(!a.id){const w=(a.textContent||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"section";let p=w;for(let v=2;s.has(p);v++)p=`${w}-${v}`;s.add(p),a.id=p}const c=document.createElement("li");c.className=`dm-contents-item dm-contents-${a.tagName.toLowerCase()}`;const g=document.createElement("a");g.href=`#${a.id}`,g.textContent=a.textContent.trim(),c.appendChild(g),m.appendChild(c),b.push([a,g])}if(o.appendChild(m),u.replaceChildren(o),i.scrollSpy!==!1&&"IntersectionObserver"in window){const a=new Map,c=()=>{const w=b.find(([p])=>a.get(p))||null;b.forEach(([,p])=>{const v=w&&p===w[1];p.classList.toggle("is-active",!!v),v?p.setAttribute("aria-current","location"):p.removeAttribute("aria-current")})},g=new IntersectionObserver(w=>{w.forEach(p=>a.set(p.target,p.isIntersecting)),c()},{rootMargin:"-80px 0px -60% 0px"});b.forEach(([w])=>g.observe(w))}if(L?.classList.contains("contents-collapsible")){const a=document.createElement("button");a.type="button",a.className="dm-contents-toggle";const c=()=>{const g=L.classList.contains("contents-collapsed");a.setAttribute("aria-expanded",String(!g)),a.setAttribute("aria-label",g?"Show the contents":"Hide the contents"),a.title=a.getAttribute("aria-label"),a.innerHTML=`<span data-icon="${g?"list":"x"}"></span>`,window.Domma?.icons&&Domma.icons.scan(a)};a.addEventListener("click",()=>{S.set("contents_collapsed",L.classList.toggle("contents-collapsed")),c()}),c(),e.insertBefore(a,e.firstChild)}if(L?.classList.contains("contents-floating")&&i.movable){o.classList.add("is-movable");const a=S.get("contents_position");a&&Number.isFinite(a.x)&&Object.assign(u.style,{left:`${a.x}px`,top:`${a.y}px`,right:"auto",bottom:"auto"}),e.addEventListener("pointerdown",c=>{if(c.target.closest("button"))return;const g=u.getBoundingClientRect(),w=c.clientX-g.left,p=c.clientY-g.top,v=d=>{const y=Math.max(0,Math.min(window.innerWidth-g.width,d.clientX-w)),C=Math.max(0,Math.min(window.innerHeight-40,d.clientY-p));Object.assign(u.style,{left:`${y}px`,top:`${C}px`,right:"auto",bottom:"auto"})},f=()=>{document.removeEventListener("pointermove",v),S.set("contents_position",{x:parseInt(u.style.left,10),y:parseInt(u.style.top,10)})};document.addEventListener("pointermove",v),document.addEventListener("pointerup",f,{once:!0})})}window.E&&typeof E.contextMenu=="function"&&E.contextMenu(u,{items:()=>{const a=L?.classList.contains("contents-collapsible"),c=L?.classList.contains("contents-collapsed"),g=b.find(([,w])=>w.classList.contains("is-active"));return[{header:"Contents"},...a?[{label:c?"Show the contents":"Collapse to a button",icon:c?"list":"minimize",action:()=>u.querySelector(".dm-contents-toggle")?.click()}]:[],{label:"Copy a link to this section",icon:"link",disabled:!g,action:async()=>{const w=`${location.origin}${location.pathname}#${g[0].id}`;try{await _.copyToClipboard(w),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"})}]}}),L?.classList.contains("contents-autohide")&&(u.addEventListener("pointerdown",a=>{a.pointerType!=="mouse"&&!u.classList.contains("is-revealed")&&(u.classList.add("is-revealed"),a.preventDefault())}),document.addEventListener("pointerdown",a=>{u.contains(a.target)||u.classList.remove("is-revealed")}))}
|
|
1
|
+
import{applyMobileMenu as oe,initCarouselPopup as ne}from"/public/js/mobile-ui.mjs?v=20261016-mobile-options";import{installSmoothCarets as se}from"/public/js/smooth-caret.js";import{decodeBase64Json as W}from"/public/js/utf8-base64.mjs";import{makeBadgeEl as J,applyColour as U,applyPill as ae,applyFloat as ie,applyHighlight as V,applyItemHighlight as re,itemHighlightAttrs as ce,isCurrentItem as G,menuAlign as le,applyClasses as j,cssClasses as Y,applyEntrance as X}from"/public/js/menu-decor.mjs?v=20261014-menu-entrance";import{applyMenuLook as de}from"/public/js/menu-cards.mjs?v=20261029-glider-layout";import{initPageMotion as me}from"/public/js/page-motion.mjs?v=20261029-page-motion";import{applyFooterShowcase as ue}from"/public/js/footer-showcase.mjs?v=20261029-footer-showcase";import{initFloatingMenus as pe}from"/public/js/menu-float.js?v=20260829-float-panel";import{enhancePickerFields as K,markInvalidFields as Q,showValidationPopup as Z}from"/public/js/forms.js?v=20261025-forms-files-total";import{buildWizardSteps as fe}from"/public/js/form-steps.mjs";import{mountMotionControl as he}from"/public/js/motion-control.mjs?v=20261029-motion-under-switcher";import{applyFormClasses as ee,applySubmitButtons as ge,applyWizardButtons as ye}from"/public/js/form-submit.mjs";import{captureFileFields as te,destroyDropzones as ve,fileBlueprint as be,restoreFileFields as we,setFileLimits as Ce,splitFiles as Se,submitBody as xe,totalTooLarge as ke,wireFileFields as Le}from"/public/js/form-files.mjs";document.addEventListener("click",u=>{const r=u.target?.closest?.(".dm-banner__dismiss");r&&(u.preventDefault(),r.closest(".dm-banner")?.remove())}),$(()=>{se(document);const u=window.__CMS_NAV__||{},r=window.__CMS_SITE__||{};if(r.autoTheme?.enabled){let s=function(o){const c=(o||"07:00").split(":");return+c[0]*60+(+c[1]||0)},n=function(){const o=new Date,c=o.getHours()*60+o.getMinutes();return c>=s(t.dayStart)&&c<s(t.nightStart)?t.dayTheme:t.nightTheme},e=function(o){const c=t.apply&&t.apply[o]||{theme:o,custom:""};Domma.theme.set(c.theme);for(const f of[...document.body.classList])f.startsWith("dm-custom-")&&document.body.classList.remove(f);c.custom&&document.body.classList.add(c.custom)};const t=r.autoTheme;e(n()),setInterval(()=>e(n()),6e4)}const L=$("#site-navbar");if(L.length&&u.brand){let n=function(m,w=0){return Array.isArray(m)?m.filter(d=>!(d&&(d.type==="spacer"||d.type==="theme-switcher"))).filter(d=>!(d&&d.type==="separator"&&w===0)).map(d=>d&&d.type==="separator"?{divider:!0}:Array.isArray(d?.items)?{...d,items:n(d.items,w+1)}:d):m};const t={...u.brand},s=t.size&&t.size!=="md"?` navbar-brand-${t.size}`:"";if(t.logo||t.icon||t.tagline){let m="";t.logo?m+=`<img src="${t.logo}" class="navbar-brand-logo" alt="${t.text||""}">`:t.icon&&(m+=`<span data-icon="${t.icon}" style="width:1.1em;height:1.1em;margin-right:.35em;vertical-align:middle;"></span>`),t.text&&(m+=`<span class="navbar-brand-text${s}">${t.text}</span>`),t.tagline&&(m+=`<small class="navbar-brand-tagline">${t.tagline}</small>`),t.html=m}else s&&t.text&&(t.html=`<span class="navbar-brand-text${s}">${t.text}</span>`);const e=n(u.items||[]),o=u.position==="floating",c=u.orientation==="vertical";L.get(0).querySelector(":scope > .cms-nojs-links")?.remove(),Domma.elements.navbar("#site-navbar",{brand:t,items:e,variant:u.variant||"dark",position:o?"static":u.position||"sticky",collapsible:!0,appearOnHover:!!u.appearOnHover}),Domma.icons.scan("#site-navbar");const f=L.get(0);oe(f,u.mobile);const a=()=>{if(!c)return;const w=f.querySelector('a[aria-current="page"]')?.closest(".navbar-dropdown");w&&!w.classList.contains("open")&&w.querySelector(":scope > .navbar-dropdown-toggle")?.click()};f.classList.add(`dm-nav-align-${le(u)||"centre"}`),c&&L.get(0).classList.add("dm-nav-vertical",u.side==="right"?"dm-nav-vertical-right":"dm-nav-vertical-left");const h=u.dock||{};c&&!o&&$e(f,u.side==="right"),!c&&h.hideOnScroll&&Ee(f),V(f,u),X(f,u),j(f,u.class),o&&(ie(L.get(0),u),pe(L.get(0).parentNode||document));const l=f.querySelector(".navbar-toggle"),y=f.querySelector(".navbar-collapse");if(l&&y){let m=null;const w=()=>{y.classList.contains("show")&&l.click()},d=()=>{m&&(m.remove(),m=null),document.body.classList.remove("dm-drawer-open")},p=()=>{m||(m=document.createElement("div"),m.className="dm-navbar-backdrop",m.addEventListener("click",w),document.body.appendChild(m),document.body.classList.add("dm-drawer-open"))};l.addEventListener("click",()=>{requestAnimationFrame(()=>{y.classList.contains("show")?(a(),p()):d()})}),y.addEventListener("click",v=>{v.target.closest("a")&&requestAnimationFrame(d)}),document.addEventListener("keydown",v=>{v.key==="Escape"&&y.classList.contains("show")&&w()})}const C=f.querySelector(".navbar-nav");if(C){const m=Array.from(C.children);let w=0;for(const d of u.items||[])if(!(d&&d.type==="separator")){if(d&&d.type==="spacer"){const p=document.createElement("li"),v=["xs","sm","md","lg","xl","flex"].includes(d.size)?d.size:"md";p.className=`dm-menu-spacer dm-menu-spacer--${v}`,p.setAttribute("aria-hidden","true"),C.insertBefore(p,m[w]||null);continue}if(d&&d.type==="theme-switcher"){const p=document.createElement("li");p.className="dm-menu-theme-switcher";const v=document.createElement("span");v.dataset.themeSwitcher="menu",v.dataset.position="inline",p.appendChild(v),C.insertBefore(p,m[w]||null);continue}w++}window.CMSThemeSwitcher?.scan(C)}f.querySelectorAll("[data-path]").forEach(m=>{const w=m.dataset.path.split(".").map(Number),d=w.length>1,p=w.reduce((A,i)=>A?.items?.[i],{items:e});if(!p)return;p.colour&&U(m,p.colour),p.pill&&!d&&ae(m,p.pill),re(m,p),j(m.closest("li"),p.class);const v=J(p.badge);v&&m.appendChild(v),G(p.url,location.pathname)&&(m.classList.add("active"),m.setAttribute("aria-current","page"))}),de(f,u,e),a()}let k=null;const x=$("#site-footer");if(x.length){let o=function(i){return String(i??"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")},c=function(i){return o(i).replace(/'/g,"'")},f=function(i){if(i&&i.type==="separator")return'<li class="footer-sep"><hr></li>';if(i&&i.type==="spacer")return`<li class="dm-menu-spacer dm-menu-spacer--${["xs","sm","md","lg","xl","flex"].includes(i.size)?i.size:"md"}" aria-hidden="true"></li>`;if(i&&i.type==="theme-switcher")return'<li class="dm-menu-theme-switcher"><span data-theme-switcher="menu" data-position="inline"></span></li>';const M=c(i.url||"#"),q=o(i.text||""),g=Array.isArray(i.items)&&i.items.length?`<ul>${i.items.map(f).join("")}</ul>`:"",D=ce(i),N=[D.hover&&` data-menu-item-hover="${c(D.hover)}"`,D.active&&` data-menu-item-active="${c(D.active)}"`].filter(Boolean).join(""),O=D.accent?` style="--dm-menu-highlight:${c(D.accent)}"`:"",R=Y(i.class).join(" ");return`<li${R?` class="${c(R)}"`:""}><a href="${M}"${N}${O}>${q}</a>${g}</li>`},h=function(){if(!r.footer)return"";const i=Object.keys(s).filter(q=>t[q]);if(!i.length)return"";const M=Y(r.footer.socialClass).join(" ");return`<div class="footer-social">${i.map(q=>{const{label:g,svg:D}=s[q];return`<a href="${t[q]}" target="_blank" rel="noopener noreferrer" aria-label="${g}" class="footer-social-link${M?` ${c(M)}`:""}">${D}</a>`}).join("")}</div>`},m=function(i){if(!i||i.type==="separator"||i.type==="spacer")return"";if(i.type==="theme-switcher")return`<li class="cms-footer-col">${f(i).replace(/^<li[^>]*>|<\/li>$/g,"")}</li>`;const M=Array.isArray(i.items)&&i.items.length?`<ul>${i.items.map(f).join("")}</ul>`:"",q=C(i)?`<span class="cms-footer-col-title">${o(i.text||"")}</span>`:`<a class="cms-footer-col-title" href="${c(i.url||"#")}">${o(i.text||"")}</a>`,g=["cms-footer-col",...Y(i.class)].join(" ");return`<li class="${c(g)}">${q}${M}</li>`},p=function(i,M,q=!1){return(i||[]).forEach(g=>{g&&(g.type==="separator"||g.type==="spacer"||g.type==="theme-switcher")||(q&&C(g)||M.push(g),Array.isArray(g.items)&&g.items.length&&p(g.items,M))}),M};const t=r.social||{},s={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 n='<div class="footer-inner container">';const e=window.__CMS_FOOTER__||{primary:[],legal:[],copyright:""},a=(()=>{const i=r.cookieConsent;if(!i||i.showSettingsLink===!1)return"";const M=q=>(q||[]).some(g=>g&&(g.url==="#cookie-settings"||M(g.items)));return M(e.primary)||M(e.legal)?"":`<li class="cms-cookie-settings"><a href="#cookie-settings">${o(i.settingsLinkText||"Cookie settings")}</a></li>`})(),l=["columns","row"].includes(r.footer?.layout)?r.footer.layout:"auto",y=r.footer?.look==="showcase"||l==="columns"||l==="auto"&&e.primary.some(i=>Array.isArray(i?.items)&&i.items.length),C=i=>y&&!i.url&&Array.isArray(i.items)&&i.items.length>0;if(y){const i=u.brand||{},M=i.text||r.title||"",q=i.logo?`<img src="${c(i.logo)}" class="cms-footer-brand-logo" alt="">`:i.icon?'<span class="cms-footer-brand-icon"></span>':"",g=String(r.footer?.blurb||"").trim();n='<div class="footer-inner footer-inner--columns container"><div class="cms-footer-top">',n+=`<div class="cms-footer-brand">${M||q?`<a class="cms-footer-brand-name" href="${c(i.url||"/")}">${q}<span>${o(M)}</span></a>`:""}${g?`<p class="cms-footer-blurb">${o(g)}</p>`:""}${h()}</div>`,e.primary.length&&(n+=`<nav class="footer-nav footer-nav--primary footer-nav--columns" aria-label="Footer"><ul>${e.primary.map(m).join("")}</ul></nav>`),n+='</div><div class="cms-footer-bottom">',e.copyright&&(n+=`<p class="cms-footer-copyright">${o(e.copyright)}</p>`),(e.legal.length||a)&&(n+=`<nav class="footer-nav footer-nav--legal" aria-label="Legal"><ul>${e.legal.map(f).join("")}${a}</ul></nav>`),n+="</div>"}else e.copyright&&(n+=`<p>${o(e.copyright)}</p>`),e.primary.length&&(n+=`<nav class="footer-nav footer-nav--primary"><ul>${e.primary.map(f).join("")}</ul></nav>`),(e.legal.length||a)&&(n+=`<nav class="footer-nav footer-nav--legal"><ul>${e.legal.map(f).join("")}${a}</ul></nav>`),n+=h();n+="</div>",x.get(0).querySelector(":scope > .cms-nojs-links")?.remove();const w=x.get(0).querySelector(":scope > .cms-footer-blocks");w?.remove(),x.html(n),w&&x.get(0).prepend(w),window.CMSThemeSwitcher?.scan(x.get(0));const d=x.get(0).querySelector(".cms-footer-brand-icon");d&&u.brand?.icon&&d.setAttribute("data-icon",u.brand.icon),j(x.get(0),r.footer?.class),y&&ue(x.get(0),r);const v=[...p(e.primary,[],!0),...p(e.legal,[])];x.get(0).querySelectorAll(".footer-nav a").forEach((i,M)=>{const q=v[M];if(!q)return;q.colour&&U(i,q.colour);const g=J(q.badge);g&&i.appendChild(g),G(q.url,location.pathname)&&(i.classList.add("is-active"),i.setAttribute("aria-current","page"))}),V(x.get(0).querySelector(".footer-nav--primary"),{highlight:e.primaryHighlight}),V(x.get(0).querySelector(".footer-nav--legal"),{highlight:e.legalHighlight}),X(x.get(0).querySelector(".footer-nav--primary"),{entrance:e.primaryEntrance}),X(x.get(0).querySelector(".footer-nav--legal"),{entrance:e.legalEntrance}),j(x.get(0).querySelector(".footer-nav--primary"),e.primaryClass),j(x.get(0).querySelector(".footer-nav--legal"),e.legalClass),k=x.get(0).querySelector(".cms-footer-bottom")||x.get(0).querySelector(".footer-inner")}he(r.motion||{enabled:r.footer?.showMotionToggle!==!1,default:r.footer?.motionDefault,placement:"footer",control:r.footer?.motionControl,label:"Reduce motion"},{footer:k,navbar:document.querySelector("#site-navbar .navbar-container")?.closest("#site-navbar")||null});const I=document.getElementById("site-sidebar");I&&Ae(I),Domma.icons.scan(),Domma.syntax?.scan&&Domma.syntax.scan();const b=$(".page-body");if(b.length){b.find(".accordion").each(function(){Domma.elements.accordion(this,{allowMultiple:this.dataset.multi==="true"})}),b.find(".tabs").each(function(){Domma.elements.tabs(this)}),b.find(".carousel").each(function(){const s={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"},n=h=>{const l=String(h||"").trim();return l?s[l.toLowerCase()]?`var(${s[l.toLowerCase()]})`:CSS.supports("color",l)?l:"":""},e=n(this.dataset.background),o=n(this.dataset.arrowBackground),c=n(this.dataset.arrowColor);e&&(this.style.setProperty("--dm-carousel-background",e),this.classList.add("dm-carousel-custom-background")),o&&this.style.setProperty("--dm-carousel-arrow-background",o),c&&this.style.setProperty("--dm-carousel-arrow-color",c);const f=["top","middle","bottom"].includes(this.dataset.arrowPosition)?this.dataset.arrowPosition:"middle";this.classList.add(`dm-carousel-arrows-${f}`);const a={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 h=Number(this.dataset.height);Number.isFinite(h)&&h>0&&(a.height=h)}if(this.dataset.animationDuration){const h=parseInt(this.dataset.animationDuration,10);Number.isFinite(h)&&(a.animationDuration=h)}this.dataset.animationEasing&&(a.animationEasing=this.dataset.animationEasing),this.dataset.ctx&&(this._dmCtxSlides=Array.from(this.querySelectorAll(".carousel-slide")).map(h=>h.cloneNode(!0)),this._dmCarouselOpts=a),this._dmCarousel=Domma.elements.carousel(this,a),ne(this)}),b.find(".dm-countdown").each(function(){const s={autoStart:!0},n=String(this.dataset.format||"").trim(),e=String(this.dataset.to||"").trim(),o=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e),c=o?new Date(+o[1],+o[2]-1,+o[3]).getTime():e?new Date(e).getTime():NaN;Number.isFinite(c)?s.duration=Math.max(0,c-Date.now()):this.dataset.duration&&(s.duration=(parseInt(this.dataset.duration,10)||0)*1e3);const f=/^dd:/i.test(n);s.format=f?"hh:mm:ss":n||(s.duration>=36e5?"hh:mm:ss":"mm:ss");const a=this,h=y=>String(y).padStart(2,"0"),l=y=>{const C=Math.max(0,Math.floor(y/1e3)),m=a.querySelector(".dm-timer-time");m&&(m.textContent=`${h(Math.floor(C/86400))}:${h(Math.floor(C%86400/3600))}:${h(Math.floor(C%3600/60))}:${h(C%60)}`)};f&&(s.onTick=l),Domma.elements.timer(this,s),f&&l(s.duration||0)}),b.find("[data-tooltip]:not(.dm-range-slider)").each(function(){Domma.elements.tooltip(this,{content:$(this).data("tooltip"),position:$(this).data("tooltip-position")||"top"})}),b.find(".dm-progression").each(function(){const s=Array.from(this.querySelectorAll(".dm-progression-item")).map(o=>{const c={title:o.querySelector(".dm-progression-item-title")?.textContent?.trim()||"",description:o.querySelector(".dm-progression-item-body")?.innerHTML?.trim()||""};return o.dataset.date&&(c.date=o.dataset.date),o.dataset.status&&(c.status=o.dataset.status),o.dataset.eventIcon&&(c.icon=o.dataset.eventIcon),o.dataset.entryId&&(c._entryId=o.dataset.entryId),c}),n=this.dataset.layout==="centred"?"centered":this.dataset.layout||"vertical",e=Domma.elements.progression(this,{layout:n,theme:this.dataset.theme||"minimal",mode:this.dataset.mode||"timeline",statusIcons:!0,allowHtml:!0,...s.length?{items:s}:{}});if((this.dataset.mode||"timeline")==="timeline"){const o={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((c,f)=>{const a=s[f];if(!a)return;const h=c.querySelector(".dm-progression-title");if(a.icon&&h){const y=document.createElement("span");y.dataset.icon=a.icon,y.style.cssText="display:inline-flex;vertical-align:middle;margin-right:.4em",y.setAttribute("aria-hidden","true"),h.prepend(y)}const l=o[a.status];if(l&&h){const y=document.createElement("span");y.className=`badge badge-${l.tone} cms-timeline-status`,y.style.cssText="display:inline-flex;align-items:center;gap:.35em;margin:.4rem 0";const C=document.createElement("span");C.dataset.icon=l.icon,C.dataset.iconSize="14",C.setAttribute("aria-hidden","true"),y.append(C,document.createTextNode(l.label)),h.after(y)}})}Domma.icons.scan(this),s.length&&(this._dmCtx={instance:e,items:s})});try{Domma.effects.reveal(".page-body .hero",{animation:"slide-up",duration:480,threshold:.06,stagger:60,once:!1})}catch{}const t=matchMedia("(prefers-reduced-motion: reduce)").matches||document.documentElement.classList.contains("dm-reduced-motion");document.querySelectorAll(".page-body .row[data-reveal]").forEach(s=>{const n=s.dataset.revealMode||"stagger",e=s.dataset.revealAnimation||"slide-up",o=parseInt(s.dataset.revealDuration,10)||(e.startsWith("swoosh")?700:400),c=parseInt(s.dataset.revealStagger,10)||(e.startsWith("swoosh")?90:60),f=parseInt(s.dataset.revealDelay,10)||0,a=s.dataset.revealDirection==="rtl",h=s.dataset.revealReplay==="true",l=Array.from(s.children);if(t&&e.startsWith("swoosh"))return;const y={"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)",swoosh:"translateY(36px) scale(0.96)"},C=p=>e!=="swoosh-sides"?y[e]||"":l.length>1&&p===0?"translateX(-64px) rotate(-1.5deg)":l.length>1&&p===l.length-1?"translateX(64px) rotate(1.5deg)":"translateY(40px) scale(0.94)",m=e.startsWith("swoosh"),w=m?"cubic-bezier(.2,.8,.2,1)":"ease",d=(p,v)=>{p.style.opacity="0",p.style.transform=C(v),m&&(p.style.filter="blur(10px)")};l.forEach((p,v)=>{d(p,v),p.style.transition=`opacity ${o}ms ${w}, transform ${o}ms ${w}`+(m?`, filter ${o}ms ${w}`:"");const A=a?l.length-1-v:v;p.style.transitionDelay=n==="stagger"?`${f+A*c}ms`:`${f}ms`}),requestAnimationFrame(()=>requestAnimationFrame(()=>{const p=new IntersectionObserver(v=>{v.forEach(A=>{if(A.isIntersecting){if(A.target.offsetWidth,A.target.style.opacity="1",A.target.style.transform="",m&&(A.target.style.filter=""),!h){p.unobserve(A.target);const i=A.target;i.addEventListener("transitionend",function M(q){q.target!==i||q.propertyName!=="opacity"||(i.removeEventListener("transitionend",M),i.style.transition="",i.style.transitionDelay="")})}}else h&&A.boundingClientRect.top>0&&d(A.target,l.indexOf(A.target))})},{threshold:.1});l.forEach(v=>p.observe(v))}))}),me(document.querySelector(".page-body")||document),b.find(".card[data-collapsible]").each(function(){const s=this.querySelector(".card-header");s&&s.addEventListener("click",()=>this.classList.toggle("is-collapsed"))}),b.find(".dm-so-trigger").each(function(){this.addEventListener("click",()=>{const s=this.dataset.soTarget,n=document.getElementById(s);if(!n)return;const e=E.slideover({title:n.dataset.soTitle||"",size:n.dataset.soSize||"md",position:n.dataset.soPosition||"right"});n.style.display="",e.setContent(n),e.open()})})}if(typeof $.setup=="function"){const t=Object.assign({},window.__CMS_DCONFIG__||{});if(document.querySelectorAll(".dm-page-config[data-config]").forEach(s=>{try{const n=W(s.dataset.config);Object.assign(t,n)}catch{}}),Object.keys(t).length>0){const s={};for(const[n,e]of Object.entries(t)){const o=e?.events?.click,{confirm:c,toast:f,alert:a,prompt:h,...l}=o||{};if(c||f||a||h){$(n).on("click",async function(R){if(R.preventDefault(),c&&!await E.confirm(c))return;let z=null;if(!(h&&(z=await E.prompt(h,{inputPlaceholder:l.promptPlaceholder||"",inputValue:l.promptDefault||""}),z===null))){{const B=$(l.target||this);l.toggleClass&&B.toggleClass(l.toggleClass),l.addClass&&B.addClass(l.addClass),l.removeClass&&B.removeClass(l.removeClass),z!==null&&(l.setText&&B.text(z),l.setVal&&B.val(z),l.setAttr&&B.attr(l.setAttr,z))}l.href&&(window.location.href=l.href),f&&E.toast(f,{type:l.toastType||"success"}),a&&E.alert(a)}});const{target:C,toggleClass:m,addClass:w,removeClass:d,setText:p,setVal:v,setAttr:A,href:i,toastType:M,promptPlaceholder:q,promptDefault:g,...D}=l,N={...e.events};Object.keys(D).length?N.click=C?{target:C,...D}:D:delete N.click;const O={...e,events:N};Object.keys(N).length||delete O.events,Object.keys(O).length&&(s[n]=O)}else s[n]=e}$.setup(s)}}b.length&&P(b.get(0))}),window.wireCTAButtons=P;function P(u){u.querySelectorAll(".dm-cta-trigger").forEach(r=>{r.__ctaWired||(r.__ctaWired=!0,r.addEventListener("click",async()=>{const L=r.dataset.action,k=r.dataset.entry,x=r.dataset.confirm;let I=S.get("auth_token");if(!I){E.toast("Please log in to perform this action.",{type:"warning"});return}if(x&&!await E.confirm(x))return;const b=Array.from(r.childNodes).map(s=>s.cloneNode(!0));r.disabled=!0,r.textContent="Running\u2026";const t=s=>fetch(`/api/actions/${L}/public`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify(r.dataset.scope?{entryId:k,scope:r.dataset.scope}:{entryId:k})});try{let s=await t(I);if(s.status===401){const e=S.get("auth_refresh_token");if(e){const o=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e})});if(o.ok){const{token:c}=await o.json();S.set("auth_token",c),I=c,s=await t(I)}}}const n=await s.json().catch(()=>({}));if(!s.ok||n.success===!1)throw new Error(n.error||n.message||`Error ${s.status}`);E.toast(n.message||"Action completed.",{type:"success"})}catch(s){E.toast(s.message||"Action failed.",{type:"error"})}finally{r.disabled=!1,r.textContent="",b.forEach(s=>r.appendChild(s)),Domma.icons.scan(r)}}))})}(function(){const r=document.querySelectorAll('.dm-collection-hydrate[data-collection-scope="mine"]');if(!r.length)return;const L=S.get("auth_token");function k(I,b){const t=document.createElement("div");t.className="dm-collection-display dm-collection-empty";const s=document.createElement("p");if(b){s.appendChild(document.createTextNode("Please "));const n=document.createElement("a");n.href="/login",n.textContent="sign in",s.appendChild(n),s.appendChild(document.createTextNode(" to view your entries."))}else s.textContent=I;return t.appendChild(s),t}function x(I,b){const t=document.createElement("template");t.innerHTML=b||"",I.replaceWith(t.content)}r.forEach(async I=>{const b=I.dataset.collectionAttrs;if(!b)return;if(!L){I.replaceChildren(k("",!0));return}const t=s=>fetch("/api/collections/render-scope",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${s}`},body:JSON.stringify({attrs:b})});try{let s=L,n=await t(s);if(n.status===401){const o=S.get("auth_refresh_token");if(o){const c=await fetch("/api/auth/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:o})});if(c.ok){const{token:f}=await c.json();S.set("auth_token",f),s=f,n=await t(s)}}}if(!n.ok){const{error:o}=await n.json().catch(()=>({}));I.replaceChildren(k(o||"Unable to load entries.",!1));return}const{html:e}=await n.json();x(I,e),window.DommaCollectionBrowser?.hydrate&&window.DommaCollectionBrowser.hydrate(document)}catch{I.replaceChildren(k("Unable to load entries.",!1))}}),setTimeout(()=>{typeof Domma<"u"&&Domma.icons?.scan&&Domma.icons.scan(),typeof Domma<"u"&&Domma.syntax?.scan&&Domma.syntax.scan(),P(document.body)},100)})(),(function(){const r=document.querySelectorAll("[data-collection-table]");!r.length||typeof T>"u"||!T.create||r.forEach(L=>{let k;try{k=W(L.dataset.payload)}catch{return}const{columns:x,rows:I,search:b,sortable:t,exportable:s,pageSize:n,empty:e,ctaConfig:o,slug:c,exportCfg:f}=k;if(!x?.length)return;if(o){const l=x.findIndex(y=>y.key==="_cta");l!==-1&&(x[l]={key:"_cta",title:"",render:(y,C)=>{const m=document.createElement("button");if(m.className=`btn btn-${o.style||"primary"} dm-cta-trigger`,m.dataset.action=o.action||"",o.scope&&(m.dataset.scope=o.scope),m.dataset.entry=C._entryId||"",o.confirm&&(m.dataset.confirm=o.confirm),o.icon){const w=document.createElement("span");w.dataset.icon=o.icon,m.appendChild(w),m.appendChild(document.createTextNode(" "))}return m.appendChild(document.createTextNode(o.label||"Run")),m}})}const a="col-table-"+Math.random().toString(36).slice(2,7),h=document.createElement("div");h.id=a,L.replaceChildren(h),T.create("#"+a,{data:I,columns:x,search:b,sortable:t,exportable:s,pageSize:n,emptyMessage:e}),o&&P(h),L._dmTable={columns:x,rows:I,slug:c,exportCfg:f,render(l){T.create("#"+a,{data:l,columns:x,search:b,sortable:t,exportable:s,pageSize:n,emptyMessage:e}),o&&P(h)}}})})(),(function(){const r=document.querySelectorAll("[data-form-inline]");if(!r.length||typeof F>"u")return;function L(t){const s=t&&t.logic;return!!(s&&(s.visibility||s.requirement))}function k(t,s){const n={};return(t||[]).forEach(e=>{if(e.type==="page-break"||e.type==="spacer"||!e.name)return;const o=e.type==="chooser"||!!(e.variant&&["select","radio","checkbox-group"].includes(e.type)),c=e.type==="checkbox"?"boolean":e.type==="date"||e.type==="icon"||e.type==="image"?"string":o?"chooser":e.type,f={...e.formConfig||{}};f.span==="full"&&s&&(f.span=s);const a={type:c,required:L(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&&(a.minLength=e.minLength),e.maxLength!==void 0&&(a.maxLength=e.maxLength),e.min!==void 0&&(a.min=e.min),e.max!==void 0&&(a.max=e.max),o&&(e.variant&&(a.variant=e.variant),(e.multiple||e.type==="checkbox-group")&&(a.multiple=!0),e.density&&(a.density=e.density),e.columns&&(a.columns=e.columns),e.accent&&(a.accent=e.accent),e.accentStyle&&(a.accentStyle=e.accentStyle),e.glow&&(a.glow=!0),e.glowColour&&(a.glowColour=e.glowColour),e.shadow&&(a.shadow=e.shadow),e.shadowColour&&(a.shadowColour=e.shadowColour)),n[e.name]=e.type==="file"?be(e,a):a}),n}function x(t){const s={};return(t||[]).forEach(n=>{if(!(!n.name||n.type==="page-break"||n.type==="spacer")&&(n.type==="select"||n.type==="multiselect")&&n.required){const e=(n.options||[])[0];e&&(s[n.name]=typeof e=="object"?e.value:e)}}),s}function I(t,s){(s||[]).forEach(n=>{if(n.type!=="date"||!n.name)return;const e=t.querySelector(`[name="${n.name}"]`);e&&e.type!=="date"&&(e.type="date")})}function b(t,s,n){let e=t.querySelector(".cms-form-message");e||(e=document.createElement("p"),e.className="cms-form-message",t.appendChild(e)),e.textContent=s,e.style.cssText=n?"color:var(--dm-danger);margin-top:.75rem;":"color:var(--dm-success);margin-top:.75rem;"}r.forEach(t=>{let s;try{s=W(t.dataset.formInline)}catch{return}t.querySelector(":scope > .cms-form-embed-summary")?.remove();const n=s.fields||[],e=s.settings||{},o=Number(e.columns)===3?3:2,c=e.layout||"grid",f=n.some(w=>w.type==="page-break"),a=new Map;Ce(t,s.fileLimits,a),Le(t,n);const h=async w=>{if(t.dataset.triggerBlocked==="true"){const d=t._formLogicRuntime,p=d&&d.submitBlock?d.submitBlock().reasons:[];b(t,p.join(" ")||"This form cannot be submitted yet.",!0);const v=new Error("Blocked by a form trigger");throw v.formSubmitFailed=!0,v}try{const d=t.querySelector(".fb-form-honeypot"),p=d?.querySelector('input[type="text"]')||null,v=d?.querySelector('[name="_t"]')||null,A=Object.assign({},w);delete A._t,d?.dataset.hpName&&delete A[d.dataset.hpName],p!==null&&(A._hp=p.value),v!==null&&(A._t=v.value);const i=new Map(a);te(t,i);const M=Se(A,n,i),q=ke(t,M.files);if(q){b(t,q,!0);const D=new Error(q);throw D.formSubmitFailed=!0,D}const g=await H.post(`/api/forms/submit/${s.slug}`,M.files.size?xe(M.values,M.files).body:M.values);if(g&&g.error){b(t,g.error,!0);const D=new Error(g.error);throw D.formSubmitFailed=!0,D}if(g?.redirect){window.location.href=g.redirect;return}for(ve(t);t.firstChild;)t.removeChild(t.firstChild);b(t,g?.message||e.successMessage||"Thank you for your submission.",!1)}catch(d){throw d.formSubmitFailed||b(t,d.message||"Submission failed. Please try again.",!0),d}},l=Date.now();function y(w){const d=w.querySelector("form");if(!d||d.querySelector(".fb-form-honeypot"))return;const p=document.createElement("div");p.className="fb-form-honeypot",p.setAttribute("aria-hidden","true");const v=document.createElement("input");v.name=d.querySelector('[name="website"]')?"_website":"website",p.dataset.hpName=v.name,v.type="text",v.tabIndex=-1,v.autocomplete="url",v.placeholder="https://",p.appendChild(v);const A=document.createElement("input");A.name="_t",A.type="hidden",A.value=l,p.appendChild(A),d.appendChild(p)}function C(w){if(!window.FormLogicEngine||!n.some(p=>p.logic||Array.isArray(p.triggers)&&p.triggers.length))return null;const d=new window.FormLogicEngine.FormLogicRuntime(s,t,w?{baseValues:w}:void 0);if(d.init(),t._formLogicRuntime=d,t._formLogicObserved)return d;if(t._formLogicObserved=!0,t.parentNode&&typeof MutationObserver<"u"){const p=new MutationObserver(function(v){for(const A of v)for(const i of A.removedNodes)if(i===t||i.nodeType===1&&i.contains&&i.contains(t)){t._formLogicRuntime&&t._formLogicRuntime.destroy(),p.disconnect();return}});p.observe(t.parentNode,{childList:!0,subtree:!1}),t._formLogicObserver=p}return d}let m=!1;if(t.addEventListener("dm-form-end",w=>{const d=w.detail?.validation;if(d&&!d.valid){Q(t,d.missing),Z(d);return}m||(m=!0,h(w.detail?.values||{}).catch(()=>{}).finally(()=>{m=!1}))}),f&&F.wizard){const w=fe(n,s.title),d=w.map(g=>({title:g.title,description:g.description,fields:k(g.fields,o)})),p=w.map(g=>g.fields);let v=0,A=null,i=null;const M=g=>{const D=window.FormLogicEngine;if(!D||!D.validateFields)return;const N=D.validateFields(t,p[v]||[]);N.valid||(g.preventDefault(),g.stopImmediatePropagation(),Q(t,N.missing),Z(N))},q=()=>{const g=p[v]||n;ye(t,e),ee(t,e,g),I(t,g),K(t,g),we(t,a),e.honeypot!==!1&&y(t),A&&A.destroy(),A=C(i?.getStepData?i.getStepData():void 0),t.querySelectorAll(".wizard-next, .wizard-submit").forEach(D=>D.addEventListener("click",M,!0))};i=F.wizard(t,{schema:{steps:d},layout:c,columns:o,finishText:e.submitText||"Finish",onSubmit:h,onStepChange:g=>{te(t,a),v=g,setTimeout(q,0)}}),t.addEventListener("dm-form-trigger",g=>{if(g.detail?.type!=="goto-step"||!i?.goToStep)return;const D=Number(g.detail.action.step);!Number.isFinite(D)||D<0||D>=d.length||D!==v&&i.goToStep(D)}),Promise.resolve(i).then(q)}else if(F.render){const w=F.render(t,k(n,o),x(n),{submitText:e.submitText||"Submit",layout:c,columns:o,onSubmit:h});Promise.resolve(w).then(function(){ge(t,e,c),ee(t,e,n),I(t,n),K(t,n),e.honeypot!==!1&&y(t),C()})}})})();function $e(u,r){const L=document.body,k=L.classList,x=new Set((L.dataset.railSite||"").split(" ").filter(Boolean)),I=()=>window.matchMedia("(min-width: 993px)").matches;u.querySelectorAll(".navbar-link, .navbar-dropdown-toggle").forEach(o=>{const c=o.textContent.trim();c&&(o.setAttribute("title",c),o.querySelector("svg, [data-icon]")||(o.dataset.initial=c.charAt(0).toUpperCase()))});const b=document.createElement("button");b.type="button",b.className="dm-nav-collapse-toggle";const t=()=>{const o=k.contains("dm-vnav-collapsed");b.setAttribute("aria-pressed",String(o)),b.setAttribute("aria-label",o?"Expand menu":"Collapse menu"),b.title=b.getAttribute("aria-label");const c=r?"chevrons-left":"chevrons-right",f=r?"chevrons-right":"chevrons-left";b.innerHTML=`<span data-icon="${o?c:f}"></span>`,window.Domma&&Domma.icons&&Domma.icons.scan(b)},s=o=>{k.toggle("dm-vnav-collapsed",o),S.set("nav_collapsed",o),t()};b.addEventListener("click",()=>s(!k.contains("dm-vnav-collapsed"))),t();const n=u.querySelector(".navbar-container")||u;n.insertBefore(b,n.firstChild?.nextSibling||null);const e=o=>{k.toggle("dm-vnav-autohide",o),k.toggle("dm-vnav-collapsible",!o&&x.has("collapsible")),o?k.remove("dm-vnav-collapsed"):x.has("collapsible")&&S.get("nav_collapsed")===!0&&k.add("dm-vnav-collapsed"),u.classList.remove("dm-nav-revealed"),t()};u.addEventListener("pointerdown",o=>{k.contains("dm-vnav-autohide")&&o.pointerType!=="mouse"&&!u.classList.contains("dm-nav-revealed")&&(u.classList.add("dm-nav-revealed"),o.preventDefault())}),document.addEventListener("pointerdown",o=>{u.contains(o.target)||u.classList.remove("dm-nav-revealed")}),window.E&&typeof E.contextMenu=="function"&&E.contextMenu(u,{items:()=>{const o=k.contains("dm-vnav-autohide"),c=k.contains("dm-vnav-collapsed"),f=S.has("nav_autohide")||S.has("nav_collapsed");return[{header:"Menu"},{label:c?"Expand menu":"Collapse to icons",icon:c?"maximize":"minimize",disabled:!I()||o||!x.has("collapsible"),action:()=>s(!c)},{label:o?"Keep on screen":"Hide when not in use",icon:o?"eye":"eye-off",disabled:!I(),action:()=>{S.set("nav_autohide",!o),e(!o)}},{type:"divider"},{label:"Reset to the site's setting",icon:"refresh",disabled:!f,action:()=>{S.remove("nav_autohide"),S.remove("nav_collapsed"),e(x.has("autohide")),k.toggle("dm-vnav-collapsed",!x.has("autohide")&&x.has("start-collapsed")),t()}}]}})}function Ee(u){u.classList.add("dm-nav-scroll-hide");let r=window.scrollY,L=!1;window.addEventListener("scroll",()=>{L||(L=!0,requestAnimationFrame(()=>{L=!1;const k=window.scrollY,x=u.matches(":focus-within")||u.querySelector(".navbar-dropdown.open, .navbar-collapse.show");k>r&&k>u.offsetHeight&&!x?u.classList.add("dm-nav-scrolled-away"):k<r&&u.classList.remove("dm-nav-scrolled-away"),r=k}))},{passive:!0})}function Ae(u){let r={};try{r=JSON.parse(u.dataset.contents||"{}")}catch{}const L=u.closest(".site-main"),k=document.querySelector(".site-content"),x=new Set(String(r.exclude||"").split(",").map(a=>a.trim().toLowerCase()).filter(Boolean)),I=a=>!a.closest(".hero, .card, .accordion, .tabs, figure, #site-sidebar"),b=a=>(k?[...k.querySelectorAll(a)]:[]).filter(I).filter(h=>!x.has(h.textContent.trim().toLowerCase())),t=r.headings==="h2"?b("h2"):r.headings==="h3"?b("h3"):r.headings==="h2h3"?b("h2, h3"):b("h2").length?b("h2"):b("h3");if(!t.length){L?.classList.add("no-sidebar-items");return}const s=new Set([...document.querySelectorAll("[id]")].map(a=>a.id)),n=document.createElement("nav");n.className="dm-contents",n.setAttribute("aria-label",r.title||"Page contents"),r.hover&&(n.dataset.menuHover=r.hover),r.selected&&(n.dataset.menuActive=r.selected),r.accent&&n.style.setProperty("--dm-menu-highlight",r.accent.startsWith("#")?r.accent:`var(--dm-${r.accent})`),r.font&&(n.style.fontFamily=r.font),r.fontSize&&(n.style.fontSize=r.fontSize),r.fontWeight&&(n.style.fontWeight=r.fontWeight);const e=document.createElement("div");e.className="dm-contents-head";const o=document.createElement("p");o.className="dm-contents-title",o.textContent=r.title||"",e.appendChild(o),n.appendChild(e);const c=document.createElement("ol");c.className="dm-contents-list"+(r.numbered?" is-numbered":"");const f=[];for(const a of t){if(!a.id){const y=(a.textContent||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"section";let C=y;for(let m=2;s.has(C);m++)C=`${y}-${m}`;s.add(C),a.id=C}const h=document.createElement("li");h.className=`dm-contents-item dm-contents-${a.tagName.toLowerCase()}`;const l=document.createElement("a");l.href=`#${a.id}`,l.textContent=a.textContent.trim(),h.appendChild(l),c.appendChild(h),f.push([a,l])}if(n.appendChild(c),u.replaceChildren(n),r.scrollSpy!==!1&&"IntersectionObserver"in window){const a=new Map,h=()=>{const y=f.find(([C])=>a.get(C))||null;f.forEach(([,C])=>{const m=y&&C===y[1];C.classList.toggle("is-active",!!m),m?C.setAttribute("aria-current","location"):C.removeAttribute("aria-current")})},l=new IntersectionObserver(y=>{y.forEach(C=>a.set(C.target,C.isIntersecting)),h()},{rootMargin:"-80px 0px -60% 0px"});f.forEach(([y])=>l.observe(y))}if(L?.classList.contains("contents-collapsible")){const a=document.createElement("button");a.type="button",a.className="dm-contents-toggle";const h=()=>{const l=L.classList.contains("contents-collapsed");a.setAttribute("aria-expanded",String(!l)),a.setAttribute("aria-label",l?"Show the contents":"Hide the contents"),a.title=a.getAttribute("aria-label"),a.innerHTML=`<span data-icon="${l?"list":"x"}"></span>`,window.Domma?.icons&&Domma.icons.scan(a)};a.addEventListener("click",()=>{S.set("contents_collapsed",L.classList.toggle("contents-collapsed")),h()}),h(),e.insertBefore(a,e.firstChild)}if(L?.classList.contains("contents-floating")&&r.movable){n.classList.add("is-movable");const a=S.get("contents_position");a&&Number.isFinite(a.x)&&Object.assign(u.style,{left:`${a.x}px`,top:`${a.y}px`,right:"auto",bottom:"auto"}),e.addEventListener("pointerdown",h=>{if(h.target.closest("button"))return;const l=u.getBoundingClientRect(),y=h.clientX-l.left,C=h.clientY-l.top,m=d=>{const p=Math.max(0,Math.min(window.innerWidth-l.width,d.clientX-y)),v=Math.max(0,Math.min(window.innerHeight-40,d.clientY-C));Object.assign(u.style,{left:`${p}px`,top:`${v}px`,right:"auto",bottom:"auto"})},w=()=>{document.removeEventListener("pointermove",m),S.set("contents_position",{x:parseInt(u.style.left,10),y:parseInt(u.style.top,10)})};document.addEventListener("pointermove",m),document.addEventListener("pointerup",w,{once:!0})})}window.E&&typeof E.contextMenu=="function"&&E.contextMenu(u,{items:()=>{const a=L?.classList.contains("contents-collapsible"),h=L?.classList.contains("contents-collapsed"),l=f.find(([,y])=>y.classList.contains("is-active"));return[{header:"Contents"},...a?[{label:h?"Show the contents":"Collapse to a button",icon:h?"list":"minimize",action:()=>u.querySelector(".dm-contents-toggle")?.click()}]:[],{label:"Copy a link to this section",icon:"link",disabled:!l,action:async()=>{const y=`${location.origin}${location.pathname}#${l[0].id}`;try{await _.copyToClipboard(y),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"})}]}}),L?.classList.contains("contents-autohide")&&(u.addEventListener("pointerdown",a=>{a.pointerType!=="mouse"&&!u.classList.contains("is-revealed")&&(u.classList.add("is-revealed"),a.preventDefault())}),document.addEventListener("pointerdown",a=>{u.contains(a.target)||u.classList.remove("is-revealed")}))}
|
|
@@ -20,6 +20,7 @@ import {fileURLToPath} from 'url';
|
|
|
20
20
|
import * as cache from '../../services/cache/index.js';
|
|
21
21
|
import {normaliseAdminPath} from '../../services/roles.js';
|
|
22
22
|
import {cssClassProblems} from '../../../public/js/css-classes.mjs';
|
|
23
|
+
import {motionFooterMirror, normaliseMotionSettings} from '../../services/motionSettings.js';
|
|
23
24
|
import {invalidateMeasurementId, measurementIdOf, normaliseMeasurementId} from '../../services/googleAnalytics.js';
|
|
24
25
|
|
|
25
26
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -124,7 +125,9 @@ export async function settingsRoutes(fastify) {
|
|
|
124
125
|
// Designer classes on <body>, every page (Site Settings > Appearance).
|
|
125
126
|
'bodyClass',
|
|
126
127
|
// Google Analytics (Site Settings > Analytics) - services/googleAnalytics.js.
|
|
127
|
-
'googleAnalytics'
|
|
128
|
+
'googleAnalytics',
|
|
129
|
+
// The "Reduce motion" control (Site Settings > Reduce motion) - services/motionSettings.js.
|
|
130
|
+
'motion'
|
|
128
131
|
]);
|
|
129
132
|
const unknownKeys = Object.keys(data).filter(k => !ALLOWED_KEYS.has(k));
|
|
130
133
|
if (unknownKeys.length > 0) {
|
|
@@ -141,7 +144,7 @@ export async function settingsRoutes(fastify) {
|
|
|
141
144
|
}
|
|
142
145
|
// Designer classes - the same rules as menus and forms (css-classes.mjs).
|
|
143
146
|
for (const [label, value] of [['Body CSS classes', data.bodyClass], ['Footer CSS classes', data.footer?.class],
|
|
144
|
-
['Social link CSS classes', data.footer?.socialClass]]) {
|
|
147
|
+
['Social link CSS classes', data.footer?.socialClass], ['Reduce motion CSS classes', data.motion?.class]]) {
|
|
145
148
|
const problems = cssClassProblems(value);
|
|
146
149
|
if (problems.length) return reply.status(400).send({error: `${label}: ${problems[0]}.`});
|
|
147
150
|
}
|
|
@@ -184,6 +187,24 @@ export async function settingsRoutes(fastify) {
|
|
|
184
187
|
merged[k] = v;
|
|
185
188
|
}
|
|
186
189
|
}
|
|
190
|
+
// The Reduce motion control: stored whitelisted, with the footer keys it used to live
|
|
191
|
+
// under kept in step for older readers. A client that still writes only those footer
|
|
192
|
+
// keys (fleet tooling) moves the block with them, so its change is not overruled.
|
|
193
|
+
if ('motion' in data) {
|
|
194
|
+
if (data.motion !== null && (typeof data.motion !== 'object' || Array.isArray(data.motion))) {
|
|
195
|
+
return reply.status(400).send({error: 'Reduce motion: send an object.'});
|
|
196
|
+
}
|
|
197
|
+
merged.motion = normaliseMotionSettings(merged.motion, merged.footer);
|
|
198
|
+
merged.footer = {...merged.footer, ...motionFooterMirror(merged.motion)};
|
|
199
|
+
} else if (merged.motion && data.footer && typeof data.footer === 'object') {
|
|
200
|
+
const legacy = {showMotionToggle: 'enabled', motionDefault: 'default', motionControl: 'control'};
|
|
201
|
+
const moved = Object.entries(legacy).filter(([k]) => k in data.footer);
|
|
202
|
+
if (moved.length) {
|
|
203
|
+
const next = {...merged.motion};
|
|
204
|
+
for (const [k, key] of moved) next[key] = k === 'showMotionToggle' ? data.footer[k] !== false : data.footer[k];
|
|
205
|
+
merged.motion = normaliseMotionSettings(next, merged.footer);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
187
208
|
// Never erase smtp.pass with the empty string that the GET endpoint injects for safety
|
|
188
209
|
if (merged.smtp && merged.smtp.pass === '' && existing.smtp?.pass) {
|
|
189
210
|
merged.smtp = {...merged.smtp, pass: existing.smtp.pass};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "Reduce motion" control - `site.json` `motion` (Site Settings > Reduce motion).
|
|
3
|
+
*
|
|
4
|
+
* One pure normaliser, shared by the renderer (both render paths: the page's
|
|
5
|
+
* bootstrap default and the object site.js draws the control from) and the
|
|
6
|
+
* settings route (what is stored). Whitelisted and clamped rather than merged,
|
|
7
|
+
* because the result is written into the source of every public page.
|
|
8
|
+
*
|
|
9
|
+
* Until it had a tab of its own the control lived in the footer settings: `footer.showMotionToggle`,
|
|
10
|
+
* `footer.motionDefault` and `footer.motionControl`. A site with no `motion`
|
|
11
|
+
* block - or one missing a key - falls back to those, key by key, so every
|
|
12
|
+
* existing site renders exactly as before with no migration. The admin keeps
|
|
13
|
+
* writing them as a mirror for older readers and fleet tooling.
|
|
14
|
+
*
|
|
15
|
+
* No I/O here; tested in tests/services/motion-settings.test.js.
|
|
16
|
+
*/
|
|
17
|
+
import {cssClasses} from '../../public/js/css-classes.mjs';
|
|
18
|
+
|
|
19
|
+
/** Today's behaviour: shown, in the footer, as a switch, following the device. */
|
|
20
|
+
export const MOTION_DEFAULTS = Object.freeze({
|
|
21
|
+
enabled: true,
|
|
22
|
+
default: 'system',
|
|
23
|
+
placement: 'footer',
|
|
24
|
+
control: 'switch',
|
|
25
|
+
triggerStyle: 'icon',
|
|
26
|
+
label: 'Reduce motion',
|
|
27
|
+
// Bottom left: clear of Search (right-centre) and Back to top (bottom right)
|
|
28
|
+
// at their defaults. public/js/motion-control.mjs stacks it clear of them
|
|
29
|
+
// anyway when a site moves one into the same corner.
|
|
30
|
+
position: 'BL',
|
|
31
|
+
offsetX: 32,
|
|
32
|
+
offsetY: 32,
|
|
33
|
+
iconSize: 52,
|
|
34
|
+
iconRadius: 26,
|
|
35
|
+
class: ''
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const MOTION_DEFAULT_CHOICES = ['system', 'off', 'on'];
|
|
39
|
+
export const MOTION_PLACEMENTS = ['footer', 'floating', 'navbar'];
|
|
40
|
+
export const MOTION_CONTROLS = ['switch', 'checkbox'];
|
|
41
|
+
export const MOTION_TRIGGER_STYLES = ['icon', 'icon-text'];
|
|
42
|
+
/** The breadcrumb corners - the Placement card's corner picker. */
|
|
43
|
+
export const MOTION_POSITIONS = ['TL', 'TR', 'BL', 'BR'];
|
|
44
|
+
export const MOTION_LABEL_MAX = 40;
|
|
45
|
+
/** The same limits as Search's floating disc (services/search.js). */
|
|
46
|
+
export const MOTION_ICON_SIZE_MIN = 32;
|
|
47
|
+
export const MOTION_ICON_SIZE_MAX = 96;
|
|
48
|
+
export const MOTION_OFFSET_MAX = 500;
|
|
49
|
+
|
|
50
|
+
const pick = (value, list, fallback) => (list.includes(value) ? value : fallback);
|
|
51
|
+
|
|
52
|
+
function num(value, fallback, min, max) {
|
|
53
|
+
const n = typeof value === 'number' ? value : (typeof value === 'string' && value.trim() ? Number(value) : NaN);
|
|
54
|
+
if (!Number.isFinite(n)) return fallback;
|
|
55
|
+
return Math.min(max, Math.max(min, Math.round(n)));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The settings a page and the admin act on.
|
|
60
|
+
*
|
|
61
|
+
* @param {object} [raw] - site.json `motion` (absent or partial is fine)
|
|
62
|
+
* @param {object} [footer] - site.json `footer`, for the keys the control used to live under
|
|
63
|
+
* @returns {object} every key of MOTION_DEFAULTS, nothing else
|
|
64
|
+
*/
|
|
65
|
+
export function normaliseMotionSettings(raw, footer) {
|
|
66
|
+
const m = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {};
|
|
67
|
+
const f = footer && typeof footer === 'object' ? footer : {};
|
|
68
|
+
const has = (k) => m[k] !== undefined && m[k] !== null;
|
|
69
|
+
|
|
70
|
+
const enabledRaw = has('enabled') ? m.enabled : f.showMotionToggle;
|
|
71
|
+
const defaultRaw = has('default') ? m.default : f.motionDefault;
|
|
72
|
+
const controlRaw = has('control') ? m.control : f.motionControl;
|
|
73
|
+
|
|
74
|
+
const label = typeof m.label === 'string' && m.label.trim()
|
|
75
|
+
? m.label.trim().replace(/\s+/g, ' ').slice(0, MOTION_LABEL_MAX)
|
|
76
|
+
: MOTION_DEFAULTS.label;
|
|
77
|
+
|
|
78
|
+
// The radius is clamped against the size (half of it is already a circle) - Search's rule.
|
|
79
|
+
const iconSize = num(m.iconSize, MOTION_DEFAULTS.iconSize, MOTION_ICON_SIZE_MIN, MOTION_ICON_SIZE_MAX);
|
|
80
|
+
const maxRadius = Math.floor(iconSize / 2);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
// Absent means shown, as footer.showMotionToggle always did.
|
|
84
|
+
enabled: enabledRaw !== false,
|
|
85
|
+
default: pick(defaultRaw, MOTION_DEFAULT_CHOICES, MOTION_DEFAULTS.default),
|
|
86
|
+
placement: pick(m.placement, MOTION_PLACEMENTS, MOTION_DEFAULTS.placement),
|
|
87
|
+
control: pick(controlRaw, MOTION_CONTROLS, MOTION_DEFAULTS.control),
|
|
88
|
+
triggerStyle: pick(m.triggerStyle, MOTION_TRIGGER_STYLES, MOTION_DEFAULTS.triggerStyle),
|
|
89
|
+
label,
|
|
90
|
+
position: pick(m.position, MOTION_POSITIONS, MOTION_DEFAULTS.position),
|
|
91
|
+
offsetX: num(m.offsetX, MOTION_DEFAULTS.offsetX, 0, MOTION_OFFSET_MAX),
|
|
92
|
+
offsetY: num(m.offsetY, MOTION_DEFAULTS.offsetY, 0, MOTION_OFFSET_MAX),
|
|
93
|
+
iconSize,
|
|
94
|
+
iconRadius: Math.min(maxRadius, num(m.iconRadius, MOTION_DEFAULTS.iconRadius, 0, maxRadius)),
|
|
95
|
+
class: cssClasses(typeof m.class === 'string' ? m.class : '').join(' ')
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** The settings for a site.json. */
|
|
100
|
+
export function motionSettingsOf(site) {
|
|
101
|
+
return normaliseMotionSettings(site?.motion, site?.footer);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** The footer keys older readers look at, kept in step with a `motion` block. */
|
|
105
|
+
export function motionFooterMirror(settings) {
|
|
106
|
+
return {showMotionToggle: settings.enabled, motionDefault: settings.default, motionControl: settings.control};
|
|
107
|
+
}
|
|
@@ -16,6 +16,7 @@ import {getProjectForPage} from './projects.js';
|
|
|
16
16
|
import {resolveContextMenusForPage} from './contextMenus.js';
|
|
17
17
|
import {buildCustomThemeStyleTag, buildOverrideStyleTag, getThemeTokenMap, listThemeIds, loadThemeConfig, resolveThemeClasses} from './themeSettings.js';
|
|
18
18
|
import {getSearchSettings} from './search.js';
|
|
19
|
+
import {motionSettingsOf} from './motionSettings.js';
|
|
19
20
|
import {isToolEnabled} from './tools.js';
|
|
20
21
|
import {consentSettingsFor, measurementIdOf} from './googleAnalytics.js';
|
|
21
22
|
import {fmtDateTime} from './dates.js';
|
|
@@ -209,10 +210,30 @@ export async function buildFooterBlocks(site, ctx = {}) {
|
|
|
209
210
|
return cols.length ? `<div class="cms-footer-blocks">${cols.join('')}</div>` : '';
|
|
210
211
|
}
|
|
211
212
|
|
|
213
|
+
const MOTION_ASSET_V = '20261029-motion-under-switcher';
|
|
214
|
+
|
|
212
215
|
/** The site's reduced-motion default for visitors who have not chosen: 'system', 'off' or 'on'. */
|
|
213
216
|
function motionDefaultOf(site) {
|
|
214
|
-
|
|
215
|
-
|
|
217
|
+
return motionSettingsOf(site).default;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* The "Reduce motion" control (site.json `motion`, Site Settings > Reduce motion):
|
|
222
|
+
* the whitelisted settings for window.__CMS_SITE__.motion - site.js draws the
|
|
223
|
+
* control from them (public/js/motion-control.mjs) - and its stylesheet. The
|
|
224
|
+
* old footer keys still count where `motion` says nothing (motionSettings.js).
|
|
225
|
+
*
|
|
226
|
+
* Both render paths need this - the standing trap in this file.
|
|
227
|
+
*
|
|
228
|
+
* @param {object} site - site.json
|
|
229
|
+
* @returns {{siteFields: {motion: object}, headTag: string}}
|
|
230
|
+
*/
|
|
231
|
+
export function buildMotionAssets(site) {
|
|
232
|
+
const motion = motionSettingsOf(site);
|
|
233
|
+
return {
|
|
234
|
+
siteFields: {motion},
|
|
235
|
+
headTag: motion.enabled ? `<link rel="stylesheet" href="/public/css/motion.css?v=${MOTION_ASSET_V}">` : ''
|
|
236
|
+
};
|
|
216
237
|
}
|
|
217
238
|
|
|
218
239
|
/** The override a page's [navbar] tag left in its html (the first one), or null. */
|
|
@@ -450,6 +471,7 @@ export async function renderPage(page, opts = {}) {
|
|
|
450
471
|
|
|
451
472
|
const themeView = await buildThemeView(page);
|
|
452
473
|
const searchAssets = buildSearchAssets();
|
|
474
|
+
const motionAssets = buildMotionAssets(site);
|
|
453
475
|
const footerBlocksHtml = preset.footer !== false ? await buildFooterBlocks(site, {user: opts.user || null, urlPath: menuCtx.urlPath, project: menuCtx.project, tags: opts.cacheTags}) : '';
|
|
454
476
|
const switcherAssets = buildThemeSwitcherAssets(themeView.cfg, {
|
|
455
477
|
html: `${page.html || ''}${overlayMenus}${footerBlocksHtml}`,
|
|
@@ -547,6 +569,8 @@ export async function renderPage(page, opts = {}) {
|
|
|
547
569
|
footerScript: footerJson ? `window.__CMS_FOOTER__ = ${footerJson};` : '',
|
|
548
570
|
ctxMenusScript: ctxMenusScript,
|
|
549
571
|
ctxMenusModule: ctxMenusModule,
|
|
572
|
+
// Every `<` escaped, not only `</script>`: a label holding `<!--<script` would
|
|
573
|
+
// otherwise put the parser in script-data-escaped state and swallow the page.
|
|
550
574
|
siteJson: JSON.stringify(Object.assign(
|
|
551
575
|
{
|
|
552
576
|
title: site.title,
|
|
@@ -561,13 +585,14 @@ export async function renderPage(page, opts = {}) {
|
|
|
561
585
|
site.backToTop?.enabled ? { backToTop: site.backToTop } : {},
|
|
562
586
|
site.goToBottom?.enabled ? { goToBottom: site.goToBottom } : {},
|
|
563
587
|
consentAssets.siteFields,
|
|
588
|
+
motionAssets.siteFields,
|
|
564
589
|
autoTheme ? {autoTheme} : {}
|
|
565
|
-
)).replace(
|
|
590
|
+
)).replace(/</g, '\\u003c'),
|
|
566
591
|
headInject: [injection.head, navbarFontLink].filter(Boolean).join('\n'),
|
|
567
592
|
// Theme overrides land BEFORE content/custom.css: the overrides are
|
|
568
593
|
// generated, custom.css is hand-written, and the hand-written one stays
|
|
569
594
|
// the last word.
|
|
570
|
-
headInjectLate: [injection.headLate, searchAssets.headTag, switcherAssets.headTag, themeView.customThemeStyleTag, themeView.overrideStyleTag, customCssTag, navbarStyleTag]
|
|
595
|
+
headInjectLate: [injection.headLate, searchAssets.headTag, motionAssets.headTag, switcherAssets.headTag, themeView.customThemeStyleTag, themeView.overrideStyleTag, customCssTag, navbarStyleTag]
|
|
571
596
|
.filter(Boolean).join('\n'),
|
|
572
597
|
bodyEndInject: [
|
|
573
598
|
// Draft banner - first, so it is the topmost fixed element and a
|
|
@@ -1256,6 +1281,7 @@ export async function renderBlogPage(templatePath, data = {}, seoMeta = {}) {
|
|
|
1256
1281
|
// other is the standing trap in this file.
|
|
1257
1282
|
const themeView = await buildThemeView({});
|
|
1258
1283
|
const searchAssets = buildSearchAssets();
|
|
1284
|
+
const motionAssets = buildMotionAssets(site);
|
|
1259
1285
|
const footerBlocksHtml = await buildFooterBlocks(site, {user, urlPath: seoMeta.urlPath || '/', project: menuCtx.project ?? null});
|
|
1260
1286
|
const switcherAssets = buildThemeSwitcherAssets(themeView.cfg, {
|
|
1261
1287
|
html: `${renderedFragment || ''}${overlayMenus}${footerBlocksHtml}`,
|
|
@@ -1340,6 +1366,7 @@ export async function renderBlogPage(templatePath, data = {}, seoMeta = {}) {
|
|
|
1340
1366
|
footerScript: footerJson ? `window.__CMS_FOOTER__ = ${footerJson};` : '',
|
|
1341
1367
|
ctxMenusScript: ctxMenusScript,
|
|
1342
1368
|
ctxMenusModule: ctxMenusModule,
|
|
1369
|
+
// Every `<` escaped, as on the page path above.
|
|
1343
1370
|
siteJson: JSON.stringify({
|
|
1344
1371
|
title: site.title,
|
|
1345
1372
|
footer: site.footer
|
|
@@ -1349,13 +1376,14 @@ export async function renderBlogPage(templatePath, data = {}, seoMeta = {}) {
|
|
|
1349
1376
|
}
|
|
1350
1377
|
: site.footer,
|
|
1351
1378
|
social: site.social || null,
|
|
1379
|
+
...motionAssets.siteFields,
|
|
1352
1380
|
...(bare ? {} : consentAssets.siteFields)
|
|
1353
|
-
}).replace(
|
|
1381
|
+
}).replace(/</g, '\\u003c'),
|
|
1354
1382
|
headInject: [bare ? '' : injection.head, navbarFontLink].filter(Boolean).join('\n'),
|
|
1355
1383
|
// Theme overrides land BEFORE content/custom.css: the overrides are
|
|
1356
1384
|
// generated, custom.css is hand-written, and the hand-written one stays
|
|
1357
1385
|
// the last word.
|
|
1358
|
-
headInjectLate: [bare ? '' : injection.headLate, searchAssets.headTag, switcherAssets.headTag, themeView.customThemeStyleTag, themeView.overrideStyleTag, customCssTag, navbarStyleTag]
|
|
1386
|
+
headInjectLate: [bare ? '' : injection.headLate, searchAssets.headTag, motionAssets.headTag, switcherAssets.headTag, themeView.customThemeStyleTag, themeView.overrideStyleTag, customCssTag, navbarStyleTag]
|
|
1359
1387
|
.filter(Boolean).join('\n'),
|
|
1360
1388
|
bodyEndInject: [
|
|
1361
1389
|
overlayMenus,
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
_stored = JSON.parse(localStorage.getItem('domma:reduced_motion'));
|
|
113
113
|
} catch (e) {
|
|
114
114
|
}
|
|
115
|
-
// No choice of the visitor's yet: the site's default (Site Settings >
|
|
115
|
+
// No choice of the visitor's yet: the site's default (Site Settings > Reduce motion) -
|
|
116
116
|
// 'on' or 'off' decide it; 'system' (or nothing) leaves it to the device.
|
|
117
117
|
if (_stored === null || _stored === undefined) {
|
|
118
118
|
var _def = '{{motionDefault}}';
|
|
@@ -188,7 +188,7 @@
|
|
|
188
188
|
<script src="/public/js/form-logic-engine.js?v=20261025-dropzone-disable" defer></script>
|
|
189
189
|
|
|
190
190
|
<!-- Site initialisation -->
|
|
191
|
-
<script src="/public/js/site.js?v=20261029-
|
|
191
|
+
<script src="/public/js/site.js?v=20261029-reduce-motion" type="module"></script>
|
|
192
192
|
<script src="/public/js/collection-context.js?v=20261010-utf8-payloads" type="module"></script>
|
|
193
193
|
{{ctxMenusModule}}
|
|
194
194
|
|