domma-cms 0.97.0 → 0.98.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.
@@ -1 +1 @@
1
- .dashboard-layout{display:flex;flex-direction:column;height:100vh;min-height:100vh;overflow:hidden}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden}.dashboard-main{flex:1;min-width:0;overflow-y:auto}#admin-sidebar.dashboard-sidebar{display:flex;flex-direction:column;flex-shrink:0;overflow:hidden}#admin-sidebar .dm-admin-sidebar{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--dm-border) transparent}#admin-sidebar .dm-admin-sidebar::-webkit-scrollbar{width:8px}#admin-sidebar .dm-admin-sidebar::-webkit-scrollbar-track{background:transparent}#admin-sidebar .dm-admin-sidebar::-webkit-scrollbar-thumb{background:var(--dm-border);border-radius:4px}#admin-sidebar .dm-admin-sidebar::-webkit-scrollbar-thumb:hover{background:var(--dm-text-muted)}.view-container{padding:1.5rem 2rem;max-width:1200px}.view-container:has(>.dm-plugin-shell){max-width:100%}.view-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;gap:1rem}.view-header h1{font-size:1.5rem;font-weight:700;margin:0;display:flex;align-items:center;gap:.5rem}.view-header-actions{display:flex;gap:.75rem;flex-wrap:wrap}.view-header-actions .btn-primary,.view-header-actions .btn-success,.view-header-actions .btn-danger{margin-left:.5rem}.stat-card .card-body{display:flex;align-items:center;gap:1rem}.stat-icon{width:44px;height:44px;border-radius:8px;background:color-mix(in srgb,var(--dm-primary) 14%,transparent);color:var(--dm-primary, #5b8cff);display:flex;align-items:center;justify-content:center;font-size:1.25rem;flex-shrink:0}.stat-icon--success{background:color-mix(in srgb,var(--dm-success) 15%,transparent);color:var(--dm-success)}.stat-icon--warning{background:color-mix(in srgb,var(--dm-warning) 15%,transparent);color:var(--dm-warning)}.stat-value{font-size:1.75rem;font-weight:700;line-height:1}.stat-label{font-size:.8rem;color:var(--dm-text-muted, #888);margin-top:.25rem}.toolbar{display:flex;align-items:center;gap:.75rem}.form-check-label{display:flex;align-items:center;gap:.5rem;cursor:pointer;font-size:.9rem}.form-hint{display:block;font-size:.8rem;color:var(--dm-text-muted, #888);margin-top:.25rem}.dashboard-main:has(#editor-meta-tabs){overflow:hidden}.view-container:has(#editor-meta-tabs){display:flex;flex-direction:column;height:calc(100dvh - 60px);max-width:100%;padding-bottom:0}.view-container:has(#editor-meta-tabs)>.dm-plugin-shell{flex:1;min-height:0;display:flex;flex-direction:column}.view-container:has(#editor-meta-tabs)>.dm-plugin-shell>.dm-plugin-banner,.view-container:has(#editor-meta-tabs) .pex-bar{flex:none}.view-container:has(#editor-meta-tabs)>.dm-plugin-shell>.dm-plugin-body{flex:1;min-height:0;display:flex;flex-direction:column}.view-container:has(#block-editor-body){max-width:100%}.view-container:has(#ep-editor-tabs){max-width:100%}.ep-editor-grid{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,1fr) minmax(0,1.3fr);gap:1rem;align-items:start}.ep-editor-grid>.ep-tryit-col,.ep-editor-grid>.ep-results-col{position:sticky;top:1rem;display:flex;flex-direction:column;gap:1rem;min-width:0}@media(max-width:1500px){.ep-editor-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.ep-editor-grid>:first-child{grid-column:1 / -1}.ep-editor-grid>.ep-tryit-col,.ep-editor-grid>.ep-results-col{position:static}}@media(max-width:1024px){.ep-editor-grid{grid-template-columns:minmax(0,1fr)}}#editor-meta-tabs{flex:1;min-height:0;display:flex;flex-direction:column}#editor-meta-tabs .tab-content{flex:1;min-height:0;overflow:hidden}#editor-meta-tabs .tab-panel{height:100%;overflow-y:auto}#editor-meta-tabs .tab-panel:has(.editor-card),#live-preview-panel{overflow:hidden}.live-preview-bar{display:flex;align-items:center;gap:var(--dm-space-4);flex-wrap:wrap;padding:var(--dm-space-2) 0;border-bottom:1px solid var(--dm-border);margin-bottom:var(--dm-space-2)}.live-preview-widths{display:inline-flex;border:1px solid var(--dm-border);border-radius:var(--dm-radius-sm);overflow:hidden}.live-preview-width{display:inline-flex;align-items:center;justify-content:center;padding:.3rem .55rem;border:none;background:transparent;color:inherit;cursor:pointer;line-height:1}.live-preview-width+.live-preview-width{border-left:1px solid var(--dm-border)}.live-preview-width:hover{background:var(--dm-hover-bg)}.live-preview-width.active{background:var(--dm-active-bg)}.live-preview-status{flex:1 1 auto;font-size:.8rem;opacity:.75}.live-preview-actions{display:flex;gap:var(--dm-space-1)}.live-preview-wrap{display:flex;flex-direction:column;height:100%;min-height:0}.live-preview-wrap>.live-preview-bar{flex:none}.live-preview-stage{display:flex;justify-content:center;flex:1;min-height:0;overflow:auto;background:var(--dm-background-alt);border-radius:var(--dm-radius-md)}.page-live-preview-frame{display:block;width:100%;max-width:100%;height:100%;border:none;border-radius:6px;background:var(--dm-background);transition:max-width .18s ease}.page-live-preview-frame[data-width="1024"]{max-width:1024px}.page-live-preview-frame[data-width="390"]{max-width:390px}.page-live-preview-frame[data-width="1024"],.page-live-preview-frame[data-width="390"]{border-left:1px solid var(--dm-border);border-right:1px solid var(--dm-border)}.editor-card{display:flex;flex-direction:column;height:100%}.editor-card .card-body{display:flex;flex-direction:column;flex:1;min-height:0;padding:0!important}.editor-toolbar{display:flex;align-items:center;gap:2px;padding:6px 10px;border-bottom:1px solid var(--dm-border, rgba(255, 255, 255, .08));flex-wrap:wrap;flex-shrink:0}.editor-toolbar-btn{background:none;border:none;color:var(--dm-text-muted, #888);padding:6px 8px;border-radius:4px;cursor:pointer;display:flex;align-items:center;transition:color .15s,background .15s}.editor-toolbar-btn:hover{color:var(--dm-text, #eee);background:var(--dm-hover-bg)}.editor-toolbar-sep{width:1px;height:20px;background:var(--dm-border, rgba(255, 255, 255, .08));margin:0 4px;flex-shrink:0}.editor-toolbar-right{margin-left:auto;display:flex;align-items:center;gap:2px}.editor-view-btn{background:none;border:none;color:var(--dm-text-muted, #888);padding:6px 8px;border-radius:4px;cursor:pointer;display:flex;align-items:center;transition:color .15s,background .15s}.editor-view-btn:hover{color:var(--dm-text, #eee);background:var(--dm-hover-bg)}.editor-view-btn.active{color:var(--dm-primary, #5b8cff);background:color-mix(in srgb,var(--dm-primary) 14%,transparent)}.editor-body{display:flex;flex:1;min-height:0;--dm-editor-split: 50%}@media(min-width:769px){.editor-body:not(.editor-mode-write):not(.editor-mode-preview) .editor-pane--write{flex:0 0 var(--dm-editor-split, 50%)}.editor-body:not(.editor-mode-write):not(.editor-mode-preview) .editor-pane--preview{flex:1 1 0}}.editor-pane{flex:1;display:flex;flex-direction:column;min-width:0}.editor-pane--write,.editor-pane--preview{overflow:hidden}.editor-pane--write{flex-direction:row}.editor-line-numbers{padding:1rem .6rem 1rem .75rem;background:var(--dm-background-alt, rgba(0, 0, 0, .15));border-right:1px solid var(--dm-border, rgba(255, 255, 255, .08));color:var(--dm-text-muted, #666);font-family:Fira Code,Courier New,monospace;font-size:.9rem;line-height:1.6;text-align:right;user-select:none;white-space:pre;overflow:hidden;flex-shrink:0;min-width:2.5rem}.editor-line-numbers--foldable{padding:1rem 0;min-width:3rem;white-space:normal;text-align:left;display:flex;flex-direction:column}.editor-line-number-row{display:flex;align-items:center;justify-content:flex-end;padding-right:.6rem;gap:.15rem}.fold-toggle{display:inline-flex;align-items:center;justify-content:center;width:1em;font-size:.6rem;cursor:default;color:transparent}.fold-toggle--open,.fold-toggle--folded{cursor:pointer;color:var(--dm-text-muted, #666);transition:color .1s}.fold-toggle--open:hover,.fold-toggle--folded:hover{color:var(--dm-primary, #4a9eff)}.editor-line-num{min-width:1.5rem;text-align:right}.editor-mode-write .editor-pane--preview,.editor-mode-write .editor-divider,.editor-mode-preview .editor-pane--write,.editor-mode-preview .editor-divider{display:none}.editor-divider{width:7px;background:linear-gradient(to right,transparent 0,transparent 3px,var(--dm-border, rgba(255,255,255,.08)) 3px,var(--dm-border, rgba(255,255,255,.08)) 4px,transparent 4px,transparent 100%);cursor:col-resize;flex-shrink:0;touch-action:none;transition:background .12s ease}.editor-divider:hover,.editor-divider:focus-visible,.editor-divider.is-dragging{background:linear-gradient(to right,transparent 0,transparent 2px,var(--dm-primary, #5b8cff) 2px,var(--dm-primary, #5b8cff) 5px,transparent 5px,transparent 100%);outline:none}.editor-body.is-resizing .editor-pane{pointer-events:none}.editor-body.is-resizing{cursor:col-resize;user-select:none}.editor-textarea{flex:1;resize:none;border:none;border-radius:0;background:transparent;font-family:Fira Code,Courier New,monospace;font-size:.9rem;padding:1rem;outline:none;color:inherit;line-height:1.6}#editor-body .editor-textarea,#editor-body .editor-line-numbers{font-family:var(--pe-font, "Fira Code", "Courier New", monospace);font-size:var(--pe-size, .9rem);line-height:var(--pe-line, 1.6)}#editor-body.pe-nowrap .editor-textarea{white-space:pre;overflow-x:auto}.editor-preview{flex:1;display:block;width:100%;border:none;background:var(--dm-background)}.editor-fullscreen{position:fixed;inset:0;z-index:1000;border-radius:0;margin:0}.editor-fullscreen .card-body{height:100vh}.media-picker-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:.75rem;max-height:400px;overflow-y:auto;padding:.25rem}.media-picker-item{cursor:pointer;border:2px solid transparent;border-radius:6px;overflow:hidden;transition:border-color .15s}.media-picker-item:hover{border-color:var(--dm-primary, #5b8cff)}.media-picker-item img{width:100%;height:80px;object-fit:cover;display:block}.media-picker-item span{display:block;font-size:.75rem;padding:4px 6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.docs-body h3{margin-top:1.25rem;margin-bottom:.5rem}.docs-body p{margin-bottom:.5rem;line-height:1.6}.docs-body ol,.docs-body ul{margin-bottom:.75rem;padding-left:1.25rem}.docs-body li{margin-bottom:.25rem}.docs-body hr{margin:1.25rem 0;border-color:var(--dm-border, rgba(255, 255, 255, .08))}.docs-body .table{margin-bottom:.75rem}.docs-body h2{margin-top:1.75rem;margin-bottom:.6rem;padding-bottom:.3rem;border-bottom:1px solid var(--dm-border)}.docs-body h2:first-child{margin-top:0}.docs-body blockquote{margin:.75rem 0;padding:.5rem .9rem;border-left:3px solid var(--dm-primary);background:var(--dm-surface);border-radius:var(--dm-radius, 6px)}.docs-body pre{margin-bottom:.75rem;overflow-x:auto}.pg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:1rem;margin-top:1.5rem}.pg-grid>.card.pg-card{display:block;margin:0;text-decoration:none}.pg-card h3{margin-top:0}.pg-card .text-muted,.pg-card-pages{margin-bottom:0}.pg-card-pages{margin-top:.5rem;font-size:.8rem;color:var(--dm-text-muted)}.pg-actions{display:flex;gap:.5rem;flex-wrap:wrap}.pg-meta{margin-bottom:.75rem}.pg-pages{display:flex;flex-wrap:wrap;gap:.35rem;margin-bottom:1rem}.pg-body{max-width:80ch}.nav-items-header,.nav-item-row{display:flex;gap:.5rem;align-items:center;padding:.35rem .75rem}.nav-items-header{border-bottom:1px solid var(--dm-border, rgba(255,255,255,.08));padding-bottom:.4rem;margin-bottom:.25rem}.nav-item-row{border-bottom:1px solid var(--dm-border, rgba(255,255,255,.04))}.nav-item-row:last-child{border-bottom:none}.nav-col-indent{width:18px;flex-shrink:0;color:var(--dm-text-muted, #888);text-align:center;font-size:.85rem}.nav-col-main{flex:2;min-width:0}.nav-col-icon{flex:0 0 90px}.nav-col-parent{flex:2;min-width:0}.nav-col-action{flex-shrink:0}.nav-item-row--child{background:color-mix(in srgb,var(--dm-text) 3%,transparent)}.nav-col-action{display:flex;align-items:center;gap:.25rem}.nav-item-row--hidden{opacity:.45}.nav-item-row--hidden .item-text,.nav-item-row--hidden .footer-link-text{text-decoration:line-through}.btn-toggle-hidden{color:var(--dm-text-muted, #888)}.btn-toggle-hidden.active{color:var(--dm-warning, #f59e0b)}.fb-field-card.fb-drag-over{outline:2px dashed var(--dm-primary, #6366f1);outline-offset:-2px}.btn-ghost span[data-icon=trash]{color:var(--dm-danger, #dc2626)}.view-container:has(.fb-fields-layout){max-width:none}.fb-fields-layout{display:grid;grid-template-columns:minmax(0,6fr) minmax(320px,4fr);gap:1.25rem;align-items:start}.fb-preview-pane{position:sticky;top:1rem;min-width:0}@media(max-width:1100px){.fb-fields-layout{grid-template-columns:1fr}.fb-preview-pane{position:static}}.toggle-label{display:flex;align-items:center;gap:.4rem;font-size:.9rem;cursor:pointer;margin-right:1rem}.preset-toggles{display:flex;flex-wrap:wrap;margin-top:.75rem}.presets-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}@media(max-width:900px){.presets-grid{grid-template-columns:repeat(2,1fr)}}@media(max-width:600px){.presets-grid{grid-template-columns:1fr}}.card-header{padding:.5rem 1rem}.card-header h2{margin:0;font-size:.9rem;font-weight:600;letter-spacing:.02em}.preset-card .card-header{display:flex;align-items:center;justify-content:space-between}.preset-card .card-header h3{margin:0;font-size:1rem}.media-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:1rem}.media-card{background:var(--dm-card-bg, rgba(255,255,255,.04));border:1px solid var(--dm-border, rgba(255,255,255,.08));border-radius:8px;overflow:hidden}.media-preview{height:130px;display:flex;align-items:center;justify-content:center;background:#0003;overflow:hidden}.media-thumb{width:100%;height:100%;object-fit:cover}.media-thumb--file{font-size:2rem;color:var(--dm-text-muted, #888)}.media-info{padding:.5rem .75rem;display:flex;flex-direction:column;gap:.15rem}.media-name{font-size:.8rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:default}.media-rename-input{width:100%;font-size:.8rem;font-weight:500;padding:.1rem .25rem;border:1px solid var(--dm-primary, #7c6af7);border-radius:3px;background:var(--dm-input-bg, transparent);color:inherit;outline:none}.media-size{font-size:.75rem;color:var(--dm-text-muted, #888)}.media-actions{padding:.5rem .75rem;display:flex;gap:.4rem;border-top:1px solid var(--dm-border, rgba(255,255,255,.08))}#admin-topbar{height:60px;display:flex;align-items:center;gap:1rem;padding:0 1.25rem;background:var(--dm-navbar-bg, rgba(0,0,0,.3));border-bottom:1px solid var(--dm-border, rgba(255,255,255,.08));position:sticky;top:0;z-index:200;flex-shrink:0}.topbar-brand{display:flex;align-items:center;gap:.5rem;font-weight:700;font-size:.95rem;color:inherit;flex-shrink:0;margin-right:.5rem}.topbar-brand span[data-icon],.topbar-brand svg{color:var(--dm-primary, #5b8cff);width:22px;height:22px}.topbar-brand-text{opacity:.85}.topbar-brand-logo{height:28px;width:auto;display:inline-block;vertical-align:middle;margin-right:.4em;object-fit:contain}.topbar-user{display:flex;align-items:center;gap:.6rem;flex:1}.topbar-user-name{font-size:.875rem;font-weight:500}.topbar-avatar{width:1.75rem;height:1.75rem;border-radius:50%;object-fit:cover;flex-shrink:0}.topbar-role-badge{font-size:.7rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;padding:.15rem .45rem;border-radius:4px}.topbar-role-badge--admin{background:color-mix(in srgb,var(--dm-primary) 15%,transparent);color:var(--dm-primary)}.topbar-role-badge--manager{background:color-mix(in srgb,var(--dm-success) 15%,transparent);color:var(--dm-success)}.topbar-role-badge--editor{background:color-mix(in srgb,var(--dm-warning) 15%,transparent);color:var(--dm-warning)}.topbar-role-badge--subscriber{background:color-mix(in srgb,var(--dm-text-muted) 15%,transparent);color:var(--dm-text-muted)}.topbar-actions{display:flex;align-items:center;gap:.5rem;flex-shrink:0}.topbar-action-link{display:flex;align-items:center;gap:.35rem;font-size:.875rem;color:var(--dm-text-muted, #888);text-decoration:none;padding:.4rem .65rem;border-radius:6px;transition:color .15s,background .15s}.topbar-action-link:hover{color:var(--dm-text, #eee);background:var(--dm-hover-bg)}.topbar-action-link span[data-icon],.topbar-action-link svg{width:16px;height:16px}.topbar-signout{display:flex;align-items:center;gap:.35rem;font-size:.875rem}.topbar-signout span[data-icon],.topbar-signout svg{width:16px;height:16px}.login-wrap{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;padding:1rem;background:var(--dm-background, #0f1117);z-index:100;overflow-y:auto}.login-card{width:100%;max-width:460px}.ob-done-icon{font-size:3rem;color:var(--dm-success);margin-bottom:1rem;text-align:center}.btn-skip{display:block;text-align:center;margin-top:.75rem;font-size:.85rem;color:var(--dm-text-muted, #888);text-decoration:none}.btn-skip:hover{text-decoration:underline}.theme-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:.6rem}.theme-swatch{border:2px solid var(--dm-border, rgba(255,255,255,.1));border-radius:8px;overflow:hidden;cursor:pointer;transition:border-color .15s,transform .1s}.theme-swatch:hover{border-color:var(--dm-primary, #5b8cff);transform:translateY(-1px)}.theme-swatch.selected{border-color:var(--dm-primary, #5b8cff);box-shadow:0 0 0 2px var(--dm-primary, #5b8cff)}.theme-swatch-preview{height:52px;position:relative;display:flex;align-items:flex-end;padding:.35rem}.theme-swatch-accent{width:28px;height:6px;border-radius:3px}.theme-swatch-label{display:flex;justify-content:space-between;align-items:center;padding:.3rem .45rem;font-size:.7rem;background:var(--dm-card-bg, rgba(255,255,255,.04))}.theme-swatch-mode{color:var(--dm-text-muted, #888);font-size:.65rem}.login-logo{display:flex;align-items:center;gap:.75rem;margin-bottom:1.75rem;font-size:1.5rem}.login-logo span[data-icon]{font-size:2rem;color:var(--dm-primary, #5b8cff)}.login-logo h1{margin:0;font-size:1.5rem;font-weight:700}.login-card [hidden]{display:none!important}.login-heading{font-size:1.1rem;font-weight:600;margin-bottom:1.25rem}.login-rules{margin:.25rem 0 .75rem;padding-left:1.1rem;color:var(--dm-danger);font-size:.85rem}.login-rules li+li{margin-top:.2rem}.login-small{font-size:.8rem;margin-top:.75rem}.login-icon-warn{color:var(--dm-warning)}.pwf{position:relative;display:block}.pwf>input{width:100%;padding-right:2.5rem}.pwf-toggle{position:absolute;top:50%;right:.35rem;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:0;border-radius:var(--dm-radius-sm);background:transparent;color:var(--dm-text-muted);cursor:pointer}.pwf-toggle:hover,.pwf-toggle:focus-visible{color:var(--dm-text);background:var(--dm-hover-bg)}.pwf-toggle svg{width:16px;height:16px}.pwf-toggle [data-icon=eye-off],.pwf.is-shown .pwf-toggle [data-icon=eye]{display:none}.pwf.is-shown .pwf-toggle [data-icon=eye-off]{display:inline-block}.pwf-caps{display:block;margin-top:.25rem;color:var(--dm-warning);font-size:.8rem}.pwf-caps[hidden]{display:none}.btn-block{width:100%}.plugins-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:1rem}.plugin-card{display:flex;flex-direction:column;--plugin-accent: var(--dm-primary, #5b8cff);position:relative;overflow:hidden;background-image:radial-gradient(120% 90% at 100% 0%,color-mix(in srgb,var(--plugin-accent) 13%,transparent) 0%,color-mix(in srgb,var(--plugin-accent) 4%,transparent) 42%,transparent 72%)}.plugin-card .plugin-icon{background:color-mix(in srgb,var(--plugin-accent) 16%,transparent);color:var(--plugin-accent)}.plugin-watermark{position:absolute;top:-34px;right:-30px;width:148px;height:148px;display:block;color:var(--plugin-accent);opacity:.09;pointer-events:none;z-index:0}.plugin-card>.card-body,.plugin-card>.plugin-footer{position:relative;z-index:1}.plugin-card:has(.badge-secondary) .plugin-watermark{opacity:.05}@media(prefers-reduced-motion:no-preference){.plugin-card{transition:background-image .2s ease}}.plugin-card .card-body{flex:1}.plugin-header{display:flex;align-items:flex-start;gap:.75rem;margin-bottom:.75rem;flex-wrap:wrap}.plugin-icon{width:40px;height:40px;border-radius:8px;background:color-mix(in srgb,var(--dm-primary) 14%,transparent);color:var(--dm-primary, #5b8cff);display:flex;align-items:center;justify-content:center;flex-shrink:0}.plugin-meta{flex:1 1 140px;min-width:0}.plugin-name{font-weight:600;margin-bottom:.15rem}.plugin-version{font-size:.75rem;color:var(--dm-text-muted, #888)}.plugin-desc{font-size:.875rem;color:var(--dm-text-muted, #888);margin-bottom:1rem}.plugin-footer{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-top:1px solid var(--dm-border, rgba(255,255,255,.08))}.plugin-footer-actions{display:flex;align-items:center;gap:.5rem}#admin-sidebar .sidebar-link{position:relative!important}#admin-sidebar .sidebar-badge{position:absolute!important;right:.75rem!important;top:50%!important;transform:translateY(-50%)!important;margin-left:0!important;padding-left:.45rem!important;padding-right:.45rem!important}#admin-sidebar .sidebar-text{padding-right:2rem!important}#admin-sidebar.sidebar-dark{background:var(--dm-surface);border-color:var(--dm-border)}#admin-sidebar.sidebar-dark .sidebar-header{background:var(--dm-surface-raised);border-color:var(--dm-border)}#admin-sidebar.sidebar-dark .sidebar-header-title{color:var(--dm-text)}#admin-sidebar.sidebar-dark .sidebar-link{color:var(--dm-text-muted)}#admin-sidebar.sidebar-dark .sidebar-link:hover{color:var(--dm-text);background:var(--dm-surface-overlay)}#admin-sidebar.sidebar-dark .sidebar-link.active{color:var(--dm-primary);background:color-mix(in srgb,var(--dm-primary) 14%,transparent);border-left-color:var(--dm-primary)}#admin-sidebar.sidebar-dark .sidebar-heading{color:var(--dm-text-muted)}#admin-sidebar.sidebar-dark .sidebar-divider{background:var(--dm-border)}#admin-sidebar.sidebar-dark .sidebar-footer{background:var(--dm-surface-raised);border-color:var(--dm-border)}.sidebar-heading--collapsible{display:flex!important;align-items:center;justify-content:space-between;cursor:pointer;user-select:none}.sidebar-heading-toggle{display:flex;align-items:center;opacity:.5;flex-shrink:0;transition:transform .2s ease}.sidebar-heading--collapsible.is-collapsed .sidebar-heading-toggle{transform:rotate(-90deg)}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.p-0{padding:0!important}.text-muted{color:var(--dm-text-muted, #888)}@media(max-width:768px){.view-container{padding:1rem}.editor-body{flex-direction:column}.editor-divider{width:auto;height:1px;cursor:default;background:var(--dm-border, rgba(255,255,255,.08))}}.image-editor{display:flex;flex-direction:column;gap:0}.image-editor-toolbar{display:flex;flex-direction:row;align-items:center;gap:.25rem;padding:.5rem .75rem;border-bottom:1px solid var(--dm-border, rgba(255, 255, 255, .1))}.image-editor-sep{display:inline-block;width:1px;height:1.5rem;background:var(--dm-border, rgba(255, 255, 255, .15));margin:0 .25rem;flex-shrink:0}.editor-toolbar-btn.active{color:var(--dm-primary, #7c6af7);background:color-mix(in srgb,var(--dm-primary, #7c6af7) 15%,transparent)}.editor-toolbar-caret{font-size:.6rem;line-height:1;margin-left:2px;opacity:.6}.editor-toolbar-dropdown{position:absolute;z-index:1000;background:var(--dm-surface, #1e1e2e);border:1px solid var(--dm-border, rgba(255, 255, 255, .1));border-radius:8px;box-shadow:0 8px 24px #0006;padding:4px;min-width:160px;max-height:70vh;overflow-y:auto}.editor-toolbar-dropdown-heading{padding:6px 10px 3px;color:var(--dm-text-muted, #8a8a9a);font-size:.66rem;text-transform:uppercase;letter-spacing:.06em}.editor-toolbar-dropdown-item{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:none;border:none;color:var(--dm-text, #ddd);padding:7px 10px;border-radius:5px;cursor:pointer;font-size:.85rem;transition:background .12s,color .12s}.editor-toolbar-dropdown-item:hover{background:var(--dm-hover-bg);color:var(--dm-text, #fff)}.editor-toolbar-dropdown-item span[data-icon],.editor-toolbar-dropdown-item svg{width:15px;height:15px;flex-shrink:0;opacity:.75}.editor-toolbar{position:relative}.editor-effects-dropdown-menu{position:absolute;top:100%;z-index:1000;background:var(--dm-surface, #1e1e2e);border:1px solid var(--dm-border, rgba(255, 255, 255, .1));border-radius:8px;box-shadow:0 8px 24px #0006;padding:6px;min-width:180px;max-height:340px;overflow-y:auto}.editor-effects-category{padding:6px 8px 3px;font-size:.7rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--dm-text-muted, #888)}.editor-effects-item{display:block;width:100%;text-align:left;background:none;border:none;color:var(--dm-text, #ddd);padding:6px 10px;border-radius:5px;cursor:pointer;font-size:.85rem;transition:background .12s,color .12s}.editor-effects-item:hover{background:var(--dm-hover-bg);color:var(--dm-text, #fff)}.editor-icon-picker{position:absolute;z-index:1000;background:var(--dm-surface, #1e1e2e);border:1px solid var(--dm-border, rgba(255, 255, 255, .1));border-radius:8px;box-shadow:0 8px 24px #0006;padding:8px;width:320px}.editor-icon-picker-search{width:100%;margin-bottom:8px;font-size:.8rem}.editor-spacer-picker{position:absolute;z-index:9999;background:var(--dm-surface, #1e1e2e);border:1px solid var(--dm-border, #333);border-radius:8px;padding:12px;width:240px;box-shadow:0 8px 24px #00000073}.editor-spacer-picker-label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--dm-text-muted, #888);margin-bottom:10px}.editor-spacer-picker-row{display:flex;align-items:center;gap:10px;margin-bottom:12px}.editor-spacer-slider{flex:1;accent-color:var(--dm-primary, #6366f1);cursor:pointer}.editor-spacer-slider-value{font-size:13px;font-weight:600;min-width:38px;text-align:right;color:var(--dm-text, #cdd6f4)}.editor-spacer-insert-btn{width:100%}.editor-icon-picker-size-row{display:flex;align-items:center;gap:8px;padding:0 8px 8px}.editor-icon-picker-size-row label{font-size:11px;color:var(--dm-text-muted, #888);white-space:nowrap}.editor-icon-picker-size{width:70px;font-size:12px;padding:3px 6px}.editor-icon-picker-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(52px,1fr));gap:2px;max-height:280px;overflow-y:auto}.editor-icon-picker-item{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:6px 2px;border-radius:5px;cursor:pointer;background:none;border:none;color:var(--dm-text, #ddd);font-size:.58rem;text-align:center;gap:4px;overflow:hidden;transition:background .12s,color .12s}.editor-icon-picker-item:hover{background:var(--dm-hover-bg);color:var(--dm-text, #fff)}.editor-icon-picker-item span[data-icon],.editor-icon-picker-item svg{width:16px;height:16px;flex-shrink:0}.editor-icon-picker-item>span:last-child{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.2}.editor-icon-picker-empty{grid-column:1 / -1;text-align:center;color:var(--dm-text-muted, #888);font-size:.8rem;padding:1.5rem}.image-editor-canvas{min-height:320px;max-height:520px;background:#111;overflow:hidden;display:flex;align-items:center;justify-content:center}.image-editor-canvas img{display:block;max-width:100%;max-height:520px}.image-editor-resize{display:flex;flex-direction:row;align-items:center;gap:.5rem;padding:.6rem .75rem;border-top:1px solid var(--dm-border, rgba(255, 255, 255, .1));font-size:.85rem}.image-editor-resize label{font-weight:600;color:var(--dm-text-muted, #888);font-size:.8rem}.image-editor-resize .form-input{width:5rem;padding:.25rem .5rem;font-size:.85rem}.image-editor-footer{display:flex;flex-direction:row;align-items:center;justify-content:space-between;padding:.75rem;border-top:1px solid var(--dm-border, rgba(255, 255, 255, .1));gap:.5rem}.image-editor-effects{border-top:1px solid var(--dm-border, rgba(255, 255, 255, .1))}.image-editor-tab-bar{display:flex;flex-direction:row;overflow-x:auto;border-bottom:1px solid var(--dm-border, rgba(255, 255, 255, .1));scrollbar-width:none}.image-editor-tab-bar::-webkit-scrollbar{display:none}.image-editor-tab-btn{display:inline-flex;align-items:center;gap:.35rem;padding:.5rem .85rem;font-size:.8rem;font-weight:500;border:none;border-bottom:2px solid transparent;background:transparent;cursor:pointer;color:var(--dm-text-muted, #888);white-space:nowrap;transition:color .15s,border-color .15s;flex-shrink:0}.image-editor-tab-btn:hover{color:var(--dm-text, #eee)}.image-editor-tab-btn.active{color:var(--dm-primary, #7c6af7);border-bottom-color:var(--dm-primary, #7c6af7)}.image-editor-tab-panel{padding:.75rem;max-height:200px;overflow-y:auto}.ie-presets-grid{display:flex;flex-wrap:wrap;gap:.35rem;margin-bottom:.5rem}.ie-preset-btn.active{color:var(--dm-primary, #7c6af7);background:color-mix(in srgb,var(--dm-primary, #7c6af7) 15%,transparent);border-color:var(--dm-primary, #7c6af7)}.ie-server-note{font-size:.73rem;color:var(--dm-text-muted, #888);font-style:italic;margin:.25rem 0 0;line-height:1.4}.ie-slider-row{display:flex;align-items:center;gap:.5rem;margin-bottom:.4rem}.ie-slider-label{width:6rem;font-size:.8rem;color:var(--dm-text-muted, #888);font-weight:600;flex-shrink:0}.ie-slider{flex:1;accent-color:var(--dm-primary, #7c6af7);cursor:pointer}.ie-slider-val{width:3rem;font-size:.8rem;text-align:right;color:var(--dm-text, #eee);flex-shrink:0}.ie-select{flex:1;font-size:.85rem;padding:.25rem .5rem}.ie-colour-input{width:40px;height:28px;padding:0;border:1px solid var(--dm-border, rgba(255, 255, 255, .15));border-radius:4px;cursor:pointer;background:transparent;flex-shrink:0}.ie-wm-preview-row{display:flex;align-items:center;gap:.5rem;margin:.4rem 0}.ie-wm-preview-img{width:48px;height:48px;object-fit:contain;border-radius:4px;background:var(--dm-surface-raised, rgba(255, 255, 255, .06));flex-shrink:0}.ie-wm-preview-name{font-size:.8rem;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text, #eee)}.ie-media-picker{padding:.25rem 0}.ie-media-picker-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(80px,1fr));gap:.5rem;max-height:300px;overflow-y:auto}.ie-media-thumb{display:flex;flex-direction:column;align-items:center;gap:.25rem;padding:.4rem;border-radius:6px;cursor:pointer;border:2px solid transparent;transition:border-color .15s,background .15s}.ie-media-thumb:hover{background:var(--dm-surface-raised, rgba(255, 255, 255, .08));border-color:var(--dm-primary, #7c6af7)}.ie-media-thumb img{width:72px;height:72px;object-fit:cover;border-radius:4px}.ie-media-thumb-name{font-size:.7rem;color:var(--dm-text-muted, #888);text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:72px}.dm-slideover-left,.dm-slideover-right{width:min(40rem,95vw)!important;min-width:min(36rem,100vw)!important;max-width:100vw!important}.dm-slideover-resizer{position:absolute;top:0;bottom:0;width:6px;cursor:col-resize;z-index:2;background:transparent}.dm-slideover-right>.dm-slideover-resizer{left:0}.dm-slideover-left>.dm-slideover-resizer{right:0}.dm-slideover-resizer:hover,.is-resizing>.dm-slideover-resizer{background:var(--dm-primary);opacity:.7}.dm-slideover.is-resizing{user-select:none;transition:none!important}.dm-slideover-header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1.25rem;border-bottom:1px solid var(--dm-border, #333);flex-shrink:0}.dm-slideover-title{margin:0;font-size:1rem;font-weight:600}.dm-slideover-close{padding:.2rem .35rem!important;line-height:1;font-size:.75rem}.dm-slideover-body{flex:1;overflow:auto;overscroll-behavior:contain;min-height:0;padding:1.5rem!important;box-sizing:border-box}.dm-slideover-body:empty{flex:0 0 auto;padding:0!important}.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-body):not(.dm-slideover-close){padding:1.5rem!important;box-sizing:border-box;flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain}.dm-slideover-body,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close){scrollbar-width:thin;scrollbar-color:var(--dm-border) transparent}.dm-slideover-body::-webkit-scrollbar,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close)::-webkit-scrollbar{width:8px;height:8px}.dm-slideover-body::-webkit-scrollbar-track,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close)::-webkit-scrollbar-track{background:transparent}.dm-slideover-body::-webkit-scrollbar-thumb,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close)::-webkit-scrollbar-thumb{background:var(--dm-border);border-radius:4px}.dm-slideover-body::-webkit-scrollbar-thumb:hover,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close)::-webkit-scrollbar-thumb:hover{background:var(--dm-text-muted)}.dm-slideover-body>div{padding-left:0!important;padding-right:0!important}.dm-slideover-body>button.btn:last-child{margin-top:.5rem}.dconfig-textarea{font-family:monospace;min-height:100px;resize:vertical}.dm-editor-line-numbers{white-space:pre}.dm-code-inline{font-family:Fira Code,Courier New,monospace;font-size:.82em;padding:.15em .35em;border-radius:3px;background:var(--dm-background-alt, rgba(0, 0, 0, .18));color:var(--dm-text, inherit);border:1px solid var(--dm-border, rgba(255, 255, 255, .08))}.dm-code-block{font-family:Fira Code,Courier New,monospace;font-size:.82rem;line-height:1.6;padding:.65rem .9rem;border-radius:6px;background:var(--dm-background-alt, rgba(0, 0, 0, .18));color:var(--dm-text, inherit);border:1px solid var(--dm-border, rgba(255, 255, 255, .08));white-space:pre;overflow-x:auto;display:block;margin:.4rem 0}.tabs-centered{text-align:center}.tabs-centered .tab-list{display:inline-flex}.tabs-centered .tab-content{text-align:left}@media(max-width:768px){.view-header{flex-direction:column;align-items:flex-start}.theme-grid{grid-template-columns:repeat(2,1fr)}.nav-item-row{flex-wrap:wrap}.nav-col-icon,.nav-col-parent{display:none}#admin-topbar{padding:0 .75rem}.topbar-brand-text{display:none}.image-editor-toolbar{flex-wrap:wrap}}#topbar-bell{position:relative}.topbar-action-link[hidden],.topbar-bell-badge[hidden]{display:none}.topbar-bell-badge{position:absolute;top:2px;right:2px;min-width:16px;height:16px;padding:0 4px;background:var(--dm-danger, #dc2626);color:var(--dm-danger-text, #fff);font-size:10px;font-weight:700;line-height:16px;border-radius:9999px;text-align:center;pointer-events:none}.cb-scaffolder{padding:1rem 1.1rem;background:var(--dm-background-alt);border:1px solid var(--dm-primary);border-radius:8px;color:var(--dm-text)}.cb-scaffolder-head{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}.cb-scaffolder-head .cb-icon{flex-shrink:0;color:var(--dm-primary)}.cb-scaffolder-head h2{margin:0;font-size:1.05rem;font-weight:700;color:var(--dm-text)}.cb-scaffolder-blurb{margin:0 0 .75rem;font-size:.88rem;line-height:1.5;color:var(--dm-text-muted)}.cb-recipe-list{display:flex;flex-direction:column;gap:.5rem}.cb-recipe-card{display:flex;align-items:flex-start;gap:.75rem;text-align:left;padding:.75rem 1rem;background:var(--dm-surface);border:1px solid var(--dm-border);border-radius:6px;cursor:pointer;transition:border-color .12s;width:100%;color:var(--dm-text)}.cb-recipe-card:hover{border-color:var(--dm-primary)}.cb-recipe-card .cb-icon{flex-shrink:0;font-size:1.5rem;color:var(--dm-primary);margin-top:.1rem}.cb-recipe-meta{flex:1}.cb-recipe-name{font-weight:600;margin-bottom:.15rem;font-size:.95rem;color:var(--dm-text)}.cb-recipe-desc{font-size:.83rem;line-height:1.45;color:var(--dm-text-muted)}.cb-apply-panel{padding:1rem 1.1rem;background:var(--dm-surface);border:1px solid var(--dm-primary);border-radius:8px;color:var(--dm-text)}.cb-apply-head{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}.cb-apply-head .cb-icon{color:var(--dm-primary);font-size:1.4rem}.cb-apply-head h3{margin:0;font-size:1rem;font-weight:600;color:var(--dm-text)}.cb-apply-desc,.cb-apply-hint{margin:.25rem 0 .75rem;font-size:.85rem;line-height:1.5;color:var(--dm-text-muted)}.cb-apply-hint{font-size:.75rem;margin-top:.2rem}.cb-apply-field{margin-bottom:.6rem}.cb-apply-field label{display:block;font-size:.82rem;font-weight:600;margin-bottom:.2rem;color:var(--dm-text)}.cb-apply-field input{width:100%;padding:.4rem .55rem;border:1px solid var(--dm-border);border-radius:4px;font-size:.88rem;background:var(--dm-surface);color:var(--dm-text)}.cb-apply-status{margin:.5rem 0;font-size:.85rem;min-height:1.2rem;color:var(--dm-text)}.cb-apply-status.cb-error{color:var(--dm-danger, #dc2626)}.cb-apply-buttons{display:flex;gap:.5rem;justify-content:flex-end;margin-top:.5rem}.cb-success-panel{padding:1rem 1.1rem;background:var(--dm-surface);border:1px solid var(--dm-success, #16a34a);border-radius:8px;color:var(--dm-text)}.cb-success-panel .cb-icon{color:var(--dm-success, #16a34a);font-size:1.4rem}.cb-success-summary{margin:.25rem 0 .5rem;padding-left:1.2rem;font-size:.86rem;line-height:1.6;color:var(--dm-text)}.cb-success-warning{margin:.5rem 0;padding:.5rem .75rem;background:var(--dm-background-alt);border-left:3px solid var(--dm-warning, #eab308);border-radius:0 4px 4px 0;font-size:.82rem;color:var(--dm-text-muted)}.cb-success-snippet-label{margin:0 0 .25rem;font-size:.82rem;font-weight:600;color:var(--dm-text)}.cb-success-actions{display:flex;gap:.5rem;margin-top:.5rem;flex-wrap:wrap}.cb-code{position:relative}.cb-code pre{background:var(--dm-background-alt);color:var(--dm-text);display:block;padding:.6rem 2.4rem .6rem .75rem;white-space:pre;overflow-x:auto;margin:0;border-radius:6px;font-size:.82em;font-family:monospace;line-height:1.45}.cb-code .cb-copy{position:absolute;top:.35rem;right:.35rem;background:none;border:none;cursor:pointer;opacity:.45;padding:.2rem;line-height:1;color:var(--dm-text)}.cb-code .cb-copy:hover{opacity:1}.cb-intro{padding:.75rem 1rem;border-left:3px solid var(--dm-primary);background:var(--dm-background-alt);border-radius:0 6px 6px 0}.cb-intro p{margin:0;font-size:.92rem;line-height:1.5;color:var(--dm-text)}.cb-tutorial-link{display:flex;align-items:center;gap:.6rem;padding:.65rem .85rem;border:1px solid var(--dm-border);border-radius:6px;text-decoration:none;color:var(--dm-text);font-size:.88rem;transition:border-color .12s}.cb-tutorial-link:hover{border-color:var(--dm-primary)}.cb-tutorial-link .cb-icon{flex-shrink:0;color:var(--dm-primary)}.cb-tutorial-link .cb-arrow{color:var(--dm-text-muted);font-size:1.1rem;margin-left:auto}.menu-tree-row{display:grid;grid-template-columns:26px 1.4fr 1.4fr .9fr .7fr .9fr repeat(6,auto);gap:6px;align-items:center;padding:4px 0;transition:opacity .15s ease}.menu-tree-row--hidden{opacity:.5}.menu-tree-row--tool .me-tool-badge{margin-left:.4rem;font-size:.7rem;vertical-align:middle}.menu-tree-row--default .me-row-label{font-style:italic;opacity:.8}.menu-tree-grip{cursor:grab;color:var(--dm-text-muted)}.menu-tree-grip:hover{color:var(--dm-text)}.menu-tree{padding:8px 0}.menu-tree-row--separator{display:grid;grid-template-columns:26px minmax(80px,1fr) repeat(7,auto);gap:6px;align-items:center;padding:2px 0;opacity:.85}.menu-tree-row--separator:hover{opacity:1}.menu-tree-row--separator .me-sep-line{display:flex;align-items:center;gap:10px;width:100%}.menu-tree-row--separator .me-sep-line:before,.menu-tree-row--separator .me-sep-line:after{content:"";flex:1;border-top:1px dashed var(--dm-border, rgba(128, 128, 128, .55))}.menu-tree-row--separator .me-sep-label{font-size:.66rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--dm-text-muted, #8a8a8a);white-space:nowrap}.dm-admin-sidebar .sidebar-divider{border:0;border-top:1px solid var(--dm-border, rgba(128, 128, 128, .5));margin:.5rem .75rem;opacity:.8}.dm-admin-sidebar .sidebar-spacer--xs{height:var(--dm-space-1, .25rem)}.dm-admin-sidebar .sidebar-spacer--sm{height:var(--dm-space-2, .5rem)}.dm-admin-sidebar .sidebar-spacer--md{height:var(--dm-space-4, 1rem)}.dm-admin-sidebar .sidebar-spacer--lg{height:var(--dm-space-6, 1.5rem)}.dm-admin-sidebar .sidebar-spacer--xl{height:var(--dm-space-10, 2.5rem)}.dm-admin-sidebar .sidebar-spacer--flex{flex:1 1 auto;min-height:var(--dm-space-4, 1rem)}.dm-admin-sidebar--has-flex-spacer{display:flex;flex-direction:column;min-height:100%}.menu-tree-row--spacer{display:grid;grid-template-columns:26px minmax(80px,1fr) repeat(7,auto);gap:6px;align-items:center;padding:2px 0;opacity:.85}.menu-tree-row--spacer:hover{opacity:1}.menu-tree-row--spacer .me-spacer-line{display:flex;align-items:center;gap:8px;width:100%}.menu-tree-row--spacer .me-spacer-line:before,.menu-tree-row--spacer .me-spacer-line:after{content:"";flex:1;border-top:1px dotted var(--dm-border, rgba(128, 128, 128, .55))}.menu-tree-row--spacer .me-spacer-label{font-size:.66rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--dm-text-muted, #8a8a8a);white-space:nowrap}.menu-tree-row--spacer .me-spacer-size{width:auto;min-width:5.5rem;height:26px;padding:0 .35rem;font-size:.75rem}.menu-tree-row .me-icon-wrap{display:flex;gap:2px}.menu-tree-row .me-icon-wrap .me-icon{flex:1;min-width:0}.menu-tree-row .me-icon-wrap .me-icon-pick{flex-shrink:0;padding:.2rem .45rem;font-size:.85em}.dm-admin-sidebar{display:flex;flex-direction:column;gap:2px;padding:8px 0;font-size:.875rem}.dm-admin-sidebar details{margin:0}.dm-admin-sidebar details>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:.5rem;padding:.4rem .75rem;border-radius:4px;user-select:none;font-size:.78rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--dm-text-muted, #888)}.dm-admin-sidebar details details>summary{font-size:.875rem;font-weight:500;text-transform:none;letter-spacing:0;color:inherit}.dm-admin-sidebar .dm-menu-badge{font-size:.7rem;font-weight:600}.dm-admin-sidebar details>summary::-webkit-details-marker{display:none}.dm-admin-sidebar details>summary:after{content:"\25b8";margin-left:auto;transition:transform .15s ease;color:var(--dm-text-muted, #999);font-size:.85em}.dm-admin-sidebar details[open]>summary:after{transform:rotate(90deg)}.dm-admin-sidebar details>div{padding-left:1rem;border-left:1px solid var(--dm-border-light, rgba(0, 0, 0, .08));margin-left:.95rem}.dm-admin-sidebar .sidebar-link{display:flex;align-items:center;gap:.5rem;padding:.35rem .75rem;text-decoration:none;color:var(--dm-text, inherit);border-radius:4px}.dm-admin-sidebar .sidebar-link:hover,.dm-admin-sidebar details>summary:hover{background:var(--dm-hover-bg, rgba(0, 0, 0, .05))}.dm-admin-sidebar .sidebar-link.active{background:var(--dm-active-bg, rgba(0, 0, 0, .08));font-weight:600}.dm-admin-sidebar .sidebar-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dm-admin-sidebar [data-icon]{flex-shrink:0}.dm-admin-sidebar-header{position:sticky;top:0;z-index:2;background:var(--dm-surface);display:flex;align-items:center;gap:.5rem;padding:.65rem .85rem;margin:0 0 .5rem;font-weight:600;font-size:.95rem;letter-spacing:.01em;color:var(--dm-text, inherit);border-bottom:1px solid var(--dm-border-light, rgba(0, 0, 0, .08))}.dm-admin-sidebar--dark .dm-admin-sidebar-header{background:#1a1d24}.dm-admin-sidebar--light .dm-admin-sidebar-header{background:#fff}.dm-admin-sidebar-header [data-icon]{color:var(--dm-text-muted, #999)}.dm-admin-sidebar-header .dm-admin-sidebar-arrange{margin-left:auto;padding:.2rem .35rem;color:var(--dm-text-muted, #999);line-height:1}.dm-admin-sidebar-header .dm-admin-sidebar-arrange:hover,.dm-admin-sidebar-header .dm-admin-sidebar-arrange:focus-visible{color:var(--dm-text)}.dm-admin-sidebar.is-arranging>:not(.dm-admin-sidebar-header):not(.sb-arrange):not(style){display:none!important}.dm-admin-sidebar.is-arranging .dm-admin-sidebar-arrange{display:none}.sb-arrange{box-sizing:border-box;max-width:100vw;padding:0 .5rem 1rem;animation:sb-arrange-in .18s cubic-bezier(.2,.8,.2,1)}@keyframes sb-arrange-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}.sb-arrange-bar{position:sticky;top:2.6rem;z-index:2;display:flex;align-items:center;gap:.4rem;padding:.4rem .25rem;background:inherit}.sb-arrange-title{font-weight:600;margin-right:auto}.sb-arrange-hint{margin:0 .25rem .5rem;font-size:.78rem;line-height:1.35;color:var(--dm-text-muted)}.sb-arr-row{display:flex;align-items:center;gap:.45rem;padding:.35rem .4rem .35rem calc(.4rem + var(--sb-arr-depth, 0) * 1rem);border-radius:var(--dm-radius-sm, 4px);cursor:grab;user-select:none;font-size:.9rem}.sb-arr-row:hover{background:color-mix(in srgb,var(--dm-text) 6%,transparent)}.sb-arr-row:focus-visible{outline:2px solid var(--dm-primary);outline-offset:-2px}.sb-arr-row--folder .sb-arr-text{font-weight:600}.sb-arr-row--hidden .sb-arr-text,.sb-arr-row--hidden .sb-arr-icon{opacity:.45;text-decoration:line-through}.sb-arr-row--structural .sb-arr-text{font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;color:var(--dm-text-muted)}.sb-arr-grip{color:var(--dm-text-muted);flex:none}.sb-arr-icon{width:16px;flex:none}.sb-arr-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sb-arr-hide{flex:none;display:inline-flex;padding:.15rem;border:0;border-radius:var(--dm-radius-sm, 4px);background:transparent;color:var(--dm-text-muted);cursor:pointer}.sb-arr-hide:hover,.sb-arr-hide:focus-visible{color:var(--dm-text);background:color-mix(in srgb,var(--dm-text) 8%,transparent)}.sb-arr-lock{flex:none;color:var(--dm-text-muted);opacity:.6}.dm-admin-sidebar .sidebar-badge{margin-left:auto;padding:0 .4rem;min-width:1.25rem;height:1.1rem;line-height:1.1rem;text-align:center;font-size:.7rem;font-weight:600;border-radius:999px;background:var(--dm-active-bg, rgba(0, 0, 0, .12));color:var(--dm-text-muted, #888)}.dm-admin-sidebar .sidebar-link.active .sidebar-badge{background:var(--dm-primary, #4a86e8);color:var(--dm-primary-text, #fff)}.dm-admin-sidebar .sidebar-children{overflow:hidden;transition:max-height .22s ease,opacity .18s ease}.dm-admin-sidebar details:not([open])>.sidebar-children{opacity:0}.dm-admin-sidebar{position:relative}.dm-admin-sidebar-handle{position:absolute;top:0;right:0;width:6px;height:100%;cursor:col-resize;background:transparent;z-index:10;transition:background .15s}.dm-admin-sidebar-handle:hover,.dm-admin-sidebar-handle:active{background:var(--dm-primary, #4a86e8);opacity:.35}.dm-admin-sidebar--dark{background:#1a1d24;color:#e3e6eb}.dm-admin-sidebar--dark .sidebar-link,.dm-admin-sidebar--dark summary{color:#e3e6eb}.dm-admin-sidebar--dark .sidebar-link:hover,.dm-admin-sidebar--dark details>summary:hover{background:#ffffff0f}.dm-admin-sidebar--dark .sidebar-link.active{background:#4a86e840}.dm-admin-sidebar--dark .sidebar-badge{background:#ffffff1f;color:#cbd0d8}.dm-admin-sidebar--light{background:#fff;color:#1a1d24;border-right:1px solid rgba(0,0,0,.08)}.dm-admin-sidebar--light .sidebar-link,.dm-admin-sidebar--light summary{color:#1a1d24}.dm-admin-sidebar--light .sidebar-link:hover,.dm-admin-sidebar--light details>summary:hover{background:#0000000a}.dm-admin-sidebar--light .sidebar-link.active{background:#4a86e826}.dm-admin-sidebar--transparent{background:transparent}.page-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin:0 0 1.25rem;padding-bottom:.75rem;border-bottom:1px solid var(--dm-border-light, rgba(0, 0, 0, .08))}.page-header h2{margin:0;display:flex;align-items:center;gap:.5rem;font-size:1.4rem;line-height:1.2}.page-header h2 [data-icon]{color:var(--dm-text-muted, #888)}.header-actions{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.card+.card,.card+p,p+.card,.card+.toolbar,.toolbar+.card,.card+.grid{margin-top:1rem}.toolbar{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;margin:0 0 1rem}.btn+.btn,.btn+a.btn,a.btn+.btn,a.btn+a.btn{margin-left:.35rem}[style*=inline-flex] .btn+.btn,[style*=inline-flex] .btn+a.btn,[style*=inline-flex] a.btn+.btn{margin-left:0}.card-body>[id$=-form],.card-body>form{margin:.25rem 0}.card-header{display:flex;align-items:center;gap:.5rem}.card-header h3{margin:0;font-size:1.05rem}.card-header [data-icon]{color:var(--dm-text-muted, #888)}.page-header+p.text-muted{margin:-.5rem 0 1rem}.dm-pe-grid{gap:.75rem 1rem}.dm-pe-grid .form-group{display:flex;flex-direction:column;gap:.25rem;margin:0}.dm-pe-grid .form-group.col-span-2{grid-column:1 / -1}.dm-pe-grid label{font-size:.85rem;font-weight:600;color:var(--dm-text, inherit)}.dm-pe-grid label .required{color:var(--dm-danger, #c33);margin-left:2px}.dm-pe-grid .form-hint{font-size:.75rem;color:var(--dm-text-muted, #888);margin-top:.1rem}.dm-pe-grid .form-input{width:100%;padding:.4rem .6rem}.dm-pe-grid textarea.form-input{resize:vertical;min-height:2.5rem}.dm-menu-badge{display:inline-block;margin-left:6px;padding:1px 7px;font-size:.7em;font-weight:700;line-height:1.4;border-radius:999px;background:var(--dm-text-muted);color:var(--dm-text-inverse, #fff);vertical-align:middle}.menu-tree-row--slim{display:grid;grid-template-columns:26px 1fr auto repeat(9,auto);gap:6px;align-items:center}.menu-tree-row--slim .me-row-label{font-weight:600}.menu-tree-row--slim .me-row-url{color:var(--dm-text-muted);font-size:.85em}.me-pages-picker{display:flex;gap:6px;align-items:center;margin-bottom:6px}.me-pages-picker .form-input{flex:1;min-width:0}.me-colour-control{display:flex;gap:6px;align-items:center}.me-colour-control .me-colour-hex{width:48px;height:32px;padding:2px;flex:none}.me-bind-summary{padding:.6rem .8rem;border:1px solid var(--dm-border, rgba(128, 128, 128, .35));border-radius:var(--dm-radius-md, 6px);background:color-mix(in srgb,var(--dm-text) 4%,transparent);font-size:.9em}.me-bind-summary code{font-size:.9em}.me-item-form{display:flex;flex-direction:column;gap:10px;padding:4px 2px}.me-item-form .form-field{display:flex;flex-direction:column;gap:4px}.me-item-form .form-label{font-size:.85em;color:var(--dm-text-muted)}.me-form-section{margin:12px 0 2px;padding-top:10px;border-top:1px solid var(--dm-border-light, rgba(0,0,0,.15));font-size:.78em;text-transform:uppercase;letter-spacing:.06em;color:var(--dm-text-muted)}.me-item-form .me-form-section:first-child{margin-top:0;padding-top:0;border-top:0}.me-item-form .me-colour-hex{width:48px;height:32px;padding:2px}.me-item-form .me-field-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}.me-item-form .me-field-grid .form-field{margin:0}.me-item-form .me-icon-field{display:flex;align-items:center;gap:8px}.me-item-form .me-icon-field .form-input{flex:1}.me-item-form .me-icon-preview{width:24px;height:24px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;color:var(--dm-text-muted)}#admin-sidebar.dm-menu-floating{border:1px solid var(--dm-border);border-radius:var(--dm-radius-md, 8px);box-shadow:var(--dm-shadow-lg);overflow:hidden}@media(max-width:768px){#admin-sidebar.dm-menu-floating{position:static!important;inset:auto!important;max-height:none!important;transform:none!important}.dashboard-wrapper{padding-left:0!important;padding-right:0!important}}[data-logic-section]{border:1px solid var(--dm-border);border-radius:var(--dm-radius-md, 6px);padding:.9rem 1rem 1rem;margin-bottom:1rem;background:color-mix(in srgb,var(--dm-text) 3%,transparent)}[data-logic-section] .fb-logic-cond-row,[data-logic-section] .fb-logic-val-rule{padding:.55rem .65rem;border-radius:var(--dm-radius-sm, 4px);border:1px solid var(--dm-border);background:var(--dm-surface, transparent)}[data-logic-section] .fb-logic-cond-row:last-of-type,[data-logic-section] .fb-logic-val-rule:last-of-type{margin-bottom:.75rem}[data-logic-section]>.btn{margin-top:.15rem}[data-logic-section] textarea{min-height:5rem}.project-filter-notice{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap;margin:0 0 1rem;padding:.6rem .85rem;border:1px solid var(--dm-border);border-left:3px solid var(--dm-info, var(--dm-primary));border-radius:var(--dm-radius-md, 6px);background:color-mix(in srgb,var(--dm-info, var(--dm-primary)) 6%,transparent);font-size:.85rem;color:var(--dm-text-muted)}.project-filter-notice a{color:var(--dm-primary);font-weight:600}.ctx-help{display:inline-flex;align-items:center;justify-content:center;width:1.05rem;height:1.05rem;margin-left:.35rem;padding:0;border:1px solid var(--dm-border-dark, var(--dm-border));border-radius:var(--dm-radius-full, 9999px);background:transparent;color:var(--dm-text-muted);font-size:.68rem;font-weight:700;line-height:1;cursor:pointer;vertical-align:middle;flex-shrink:0}.ctx-help:hover,.ctx-help:focus-visible{border-color:var(--dm-primary);color:var(--dm-primary);outline:none}.card-header h3 .ctx-help{align-self:center}.ctx-preview-card{position:sticky;top:1rem}@media(max-width:1100px){.ctx-workspace>.col-8,.ctx-workspace>.col-4{flex:0 0 auto;width:100%}.ctx-preview-card{position:static}}.dm-plugin-shell{border:1px solid var(--dm-border);border-radius:var(--dm-radius-lg, 12px);background:var(--dm-surface);overflow:hidden}.dm-plugin-banner{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;padding:.7rem 1rem;background:var(--dm-background-alt);border-bottom:1px solid var(--dm-border)}.dm-plugin-banner-identity{display:flex;align-items:center;gap:.55rem;min-width:0;margin-right:auto}.dm-plugin-banner-actions{display:flex;align-items:center;gap:.25rem;flex:0 0 auto;margin-right:.15rem;padding-right:.4rem;border-right:1px solid var(--dm-border)}.dm-plugin-banner-action{padding:.25rem .4rem;line-height:1;color:var(--dm-text-muted)}.dm-plugin-banner-action:hover{color:var(--dm-primary)}.dm-plugin-banner-icon{display:inline-flex;align-items:center;color:var(--dm-primary);flex:0 0 auto}.dm-plugin-banner-name{margin:0;font-size:1.05rem;font-weight:600;letter-spacing:.01em;color:var(--dm-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dm-activity{display:inline-flex;align-items:center;flex:0 0 auto;margin-left:.35rem}.dm-activity domma-loader{display:inline-block;line-height:0}.dm-activity[hidden]{display:none!important}#admin-topbar>.dm-activity{margin:0 .75rem 0 0}.dm-plugin-banner-parent{font-weight:500;color:var(--dm-text-muted)}.dm-plugin-banner-sep{margin:0 .4rem;color:var(--dm-text-muted)}.dm-plugin-banner-facts{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap}.dm-plugin-fact{font-size:.72rem;line-height:1.6;padding:1px 8px;border-radius:999px;border:1px solid var(--dm-border);color:var(--dm-text-muted);background:var(--dm-surface);white-space:nowrap}.dm-plugin-fact--version{font-variant-numeric:tabular-nums;color:var(--dm-text)}.dm-plugin-fact--licence.is-included{color:var(--dm-info);border-color:var(--dm-info)}.dm-plugin-fact--licence.is-licensed{color:var(--dm-success);border-color:var(--dm-success)}.dm-plugin-fact--expiry{font-variant-numeric:tabular-nums}.dm-plugin-fact--expiry.is-warning{color:var(--dm-warning);border-color:var(--dm-warning)}.dm-plugin-fact--expiry.is-danger{color:var(--dm-danger);border-color:var(--dm-danger)}.dm-plugin-body{padding:1rem}.dm-plugin-body .card.dm-plugin-unwrap{border:0;background:none;box-shadow:none;margin:0}.dm-plugin-body .card.dm-plugin-unwrap>.card-body{padding:0}.dm-plugin-body>.p-4{padding:0}@media(max-width:640px){.dm-plugin-banner{align-items:flex-start;flex-direction:column;gap:.5rem}.dm-plugin-body{padding:.75rem}}.analytics-filter{max-width:240px}.dm-help-btn{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;margin-left:.3rem;padding:0;border:0;background:none;line-height:1;color:var(--dm-text-muted);opacity:.75;cursor:pointer}.dm-help-btn:hover,.dm-help-btn:focus-visible{color:var(--dm-primary);opacity:1}.dm-help-pop{position:fixed;z-index:10050;max-width:300px;padding:.6rem .75rem;background:var(--dm-surface, var(--dm-background));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:var(--dm-radius-md);box-shadow:0 8px 24px #00000040;font-size:.85rem;line-height:1.45;text-align:left;font-weight:400}.dm-help-pop strong{display:block;margin-bottom:.2rem;font-weight:600}.dm-help-pop p{margin:0}.dm-admin-sidebar .sidebar-badge[data-badge-label]{cursor:help}.dm-admin-sidebar .sidebar-badge--danger,.dm-admin-sidebar .sidebar-link.active .sidebar-badge--danger{background:var(--dm-danger, #dc2626);color:#fff}.dm-admin-sidebar .sidebar-badge--live{background:color-mix(in srgb,var(--dm-success, #16a34a) 20%,transparent);color:var(--dm-success, #16a34a)}#admin-sidebar .sidebar-badge--live{padding-left:1.05rem!important}#admin-sidebar summary>.sidebar-badge--sum{position:static!important;transform:none!important;margin-left:auto!important;margin-right:.45rem;text-transform:none;letter-spacing:0}#admin-sidebar summary:has(>.sidebar-badge--sum):after{margin-left:0}#admin-sidebar details[open]>summary>.sidebar-badge--sum{display:none}.dm-admin-sidebar .sidebar-badge--live:before{content:"";position:absolute;left:.4rem;top:50%;width:.4rem;height:.4rem;margin-top:-.2rem;border-radius:50%;background:currentColor;animation:dm-badge-pulse 2s ease-in-out infinite}@keyframes dm-badge-pulse{50%{opacity:.35}}@media(prefers-reduced-motion:reduce){.dm-admin-sidebar .sidebar-badge--live:before{animation:none}}.dm-badge-pop{width:290px;max-width:calc(100vw - 16px);font-size:.8rem;pointer-events:none}.dm-badge-pop-title{display:block;font-size:.85rem}.dm-badge-pop-sub{margin:.1rem 0 .5rem;color:var(--dm-text-muted)}.dm-badge-pop-rows{display:grid;grid-template-columns:1fr auto;gap:.2rem .75rem;margin:0 0 .5rem;padding:.45rem 0;border-top:1px solid var(--dm-border);border-bottom:1px solid var(--dm-border)}.dm-badge-pop-rows dt{color:var(--dm-text-muted)}.dm-badge-pop-rows dd{margin:0;text-align:right;font-weight:600;font-variant-numeric:tabular-nums}.dm-badge-pop-items{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.4rem}.dm-badge-pop-items li{display:flex;flex-direction:column;min-width:0}.dm-badge-pop-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dm-badge-pop-meta{font-size:.72rem;color:var(--dm-text-muted)}.dm-badge-pop .is-danger,.dm-badge-pop li.is-danger .dm-badge-pop-meta{color:var(--dm-danger, #dc2626)}.dm-badge-pop-empty{margin:0;color:var(--dm-text-muted)}.dm-plugin-body,.dm-slideover{font-family:var(--dm-font-sans, inherit)}.dm-plugin-body :is(button,input,select,textarea,.btn,.form-input,.form-select,.form-textarea),.dm-slideover :is(button,input,select,textarea,.btn,.form-input,.form-select,.form-textarea){font-family:inherit}.dm-plugin-body :is(input,select,textarea,.form-input,.form-select,.form-textarea):not(.form-input-lg),.dm-slideover :is(input,select,textarea,.form-input,.form-select,.form-textarea):not(.form-input-lg){font-size:var(--dm-text-sm)}.dm-plugin-body .form-input-lg{font-size:var(--dm-text-base)}.dm-plugin-body :is(.font-mono,code,pre,kbd),.dm-slideover :is(.font-mono,code,pre,kbd){font-family:var(--dm-font-mono, monospace)}.dm-plugin-body .form-label,.dm-slideover .form-label{font-size:var(--dm-text-sm)}.related-box{display:flex;flex-direction:column;gap:.6rem;border-top:1px solid var(--dm-border);padding-top:.75rem}.related-box[hidden]{display:none}.related-head{display:flex;align-items:center;gap:.4rem}.related-head strong{flex:1}.related-list{list-style:none;margin:.3rem 0 0;padding:0;display:flex;flex-direction:column;gap:.25rem}.related-list li{display:flex;flex-direction:column}.related-list li.is-past{opacity:.7}.related-meta,.related-note,.related-loading{color:var(--dm-text-muted);font-size:var(--dm-text-xs);margin:0}.login-challenge{display:flex;flex-direction:column;gap:.6rem;margin-bottom:.75rem}.login-challenge #challenge-code{font-size:1.25rem;letter-spacing:.2em;text-align:center}.login-trust{display:flex;align-items:center;gap:.45rem;font-size:.875rem}.login-enrol{display:flex;flex-direction:column;align-items:center;gap:.6rem;margin-bottom:1rem}.login-enrol img{background:#fff;padding:.5rem;border-radius:.5rem}.login-secret{display:flex;flex-direction:column;align-items:center;gap:.25rem;text-align:center}.login-secret code{font-size:.95rem;letter-spacing:.08em;word-break:break-all}.usx-secret{display:flex;flex-direction:column;gap:.75rem;padding:1rem}.usx-secret-link{display:block;padding:.6rem .75rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-sm);background:var(--dm-background-alt);word-break:break-all;font-size:.8rem;user-select:all}.usx-secret-actions{display:flex;align-items:center;justify-content:flex-end;gap:.5rem}.usx-secret-actions .btn{display:inline-flex;align-items:center;gap:.35rem}.usx-secret-note{margin-right:auto;color:var(--dm-success)}.usx-secret-foot{color:var(--dm-text-muted);font-size:.8rem;margin:0}.uex-reset{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem .5rem;margin-top:.5rem}.uex-reset>small:first-child{flex-basis:100%;color:var(--dm-text-muted)}.uex-reset .btn{display:inline-flex;align-items:center;gap:.35rem}.uex-reset-open{flex-basis:100%;color:var(--dm-info)}
1
+ .dashboard-layout{display:flex;flex-direction:column;height:100vh;min-height:100vh;overflow:hidden}.dashboard-wrapper{display:flex;flex:1;min-height:0;overflow:hidden}.dashboard-main{flex:1;min-width:0;overflow-y:auto}#admin-sidebar.dashboard-sidebar{display:flex;flex-direction:column;flex-shrink:0;overflow:hidden}#admin-sidebar .dm-admin-sidebar{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--dm-border) transparent}#admin-sidebar .dm-admin-sidebar::-webkit-scrollbar{width:8px}#admin-sidebar .dm-admin-sidebar::-webkit-scrollbar-track{background:transparent}#admin-sidebar .dm-admin-sidebar::-webkit-scrollbar-thumb{background:var(--dm-border);border-radius:4px}#admin-sidebar .dm-admin-sidebar::-webkit-scrollbar-thumb:hover{background:var(--dm-text-muted)}.view-container{padding:1.5rem 2rem;max-width:1200px}.view-container:has(>.dm-plugin-shell){max-width:100%}.view-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:1.5rem;gap:1rem}.view-header h1{font-size:1.5rem;font-weight:700;margin:0;display:flex;align-items:center;gap:.5rem}.view-header-actions{display:flex;gap:.75rem;flex-wrap:wrap}.view-header-actions .btn-primary,.view-header-actions .btn-success,.view-header-actions .btn-danger{margin-left:.5rem}.stat-card .card-body{display:flex;align-items:center;gap:1rem}.stat-icon{width:44px;height:44px;border-radius:8px;background:color-mix(in srgb,var(--dm-primary) 14%,transparent);color:var(--dm-primary, #5b8cff);display:flex;align-items:center;justify-content:center;font-size:1.25rem;flex-shrink:0}.stat-icon--success{background:color-mix(in srgb,var(--dm-success) 15%,transparent);color:var(--dm-success)}.stat-icon--warning{background:color-mix(in srgb,var(--dm-warning) 15%,transparent);color:var(--dm-warning)}.stat-value{font-size:1.75rem;font-weight:700;line-height:1}.stat-label{font-size:.8rem;color:var(--dm-text-muted, #888);margin-top:.25rem}.toolbar{display:flex;align-items:center;gap:.75rem}.form-check-label{display:flex;align-items:center;gap:.5rem;cursor:pointer;font-size:.9rem}.form-hint{display:block;font-size:.8rem;color:var(--dm-text-muted, #888);margin-top:.25rem}.dashboard-main:has(#editor-meta-tabs){overflow:hidden}.view-container:has(#editor-meta-tabs){display:flex;flex-direction:column;height:calc(100dvh - 60px);max-width:100%;padding-bottom:0}.view-container:has(#editor-meta-tabs)>.dm-plugin-shell{flex:1;min-height:0;display:flex;flex-direction:column}.view-container:has(#editor-meta-tabs)>.dm-plugin-shell>.dm-plugin-banner,.view-container:has(#editor-meta-tabs) .pex-bar{flex:none}.view-container:has(#editor-meta-tabs)>.dm-plugin-shell>.dm-plugin-body{flex:1;min-height:0;display:flex;flex-direction:column}.view-container:has(#block-editor-body){max-width:100%}.view-container:has(#ep-editor-tabs){max-width:100%}.ep-editor-grid{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(0,1fr) minmax(0,1.3fr);gap:1rem;align-items:start}.ep-editor-grid>.ep-tryit-col,.ep-editor-grid>.ep-results-col{position:sticky;top:1rem;display:flex;flex-direction:column;gap:1rem;min-width:0}@media(max-width:1500px){.ep-editor-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.ep-editor-grid>:first-child{grid-column:1 / -1}.ep-editor-grid>.ep-tryit-col,.ep-editor-grid>.ep-results-col{position:static}}@media(max-width:1024px){.ep-editor-grid{grid-template-columns:minmax(0,1fr)}}#editor-meta-tabs{flex:1;min-height:0;display:flex;flex-direction:column}#editor-meta-tabs .tab-content{flex:1;min-height:0;overflow:hidden}#editor-meta-tabs .tab-panel{height:100%;overflow-y:auto}#editor-meta-tabs .tab-panel:has(.editor-card),#live-preview-panel{overflow:hidden}.live-preview-bar{display:flex;align-items:center;gap:var(--dm-space-4);flex-wrap:wrap;padding:var(--dm-space-2) 0;border-bottom:1px solid var(--dm-border);margin-bottom:var(--dm-space-2)}.live-preview-widths{display:inline-flex;border:1px solid var(--dm-border);border-radius:var(--dm-radius-sm);overflow:hidden}.live-preview-width{display:inline-flex;align-items:center;justify-content:center;padding:.3rem .55rem;border:none;background:transparent;color:inherit;cursor:pointer;line-height:1}.live-preview-width+.live-preview-width{border-left:1px solid var(--dm-border)}.live-preview-width:hover{background:var(--dm-hover-bg)}.live-preview-width.active{background:var(--dm-active-bg)}.live-preview-status{flex:1 1 auto;font-size:.8rem;opacity:.75}.live-preview-actions{display:flex;gap:var(--dm-space-1)}.live-preview-wrap{display:flex;flex-direction:column;height:100%;min-height:0}.live-preview-wrap>.live-preview-bar{flex:none}.live-preview-stage{display:flex;justify-content:center;flex:1;min-height:0;overflow:auto;background:var(--dm-background-alt);border-radius:var(--dm-radius-md)}.page-live-preview-frame{display:block;width:100%;max-width:100%;height:100%;border:none;border-radius:6px;background:var(--dm-background);transition:max-width .18s ease}.page-live-preview-frame[data-width="1024"]{max-width:1024px}.page-live-preview-frame[data-width="390"]{max-width:390px}.page-live-preview-frame[data-width="1024"],.page-live-preview-frame[data-width="390"]{border-left:1px solid var(--dm-border);border-right:1px solid var(--dm-border)}.editor-card{display:flex;flex-direction:column;height:100%}.editor-card .card-body{display:flex;flex-direction:column;flex:1;min-height:0;padding:0!important}.editor-toolbar{display:flex;align-items:center;gap:2px;padding:6px 10px;border-bottom:1px solid var(--dm-border, rgba(255, 255, 255, .08));flex-wrap:wrap;flex-shrink:0}.editor-toolbar-btn{background:none;border:none;color:var(--dm-text-muted, #888);padding:6px 8px;border-radius:4px;cursor:pointer;display:flex;align-items:center;transition:color .15s,background .15s}.editor-toolbar-btn:hover{color:var(--dm-text, #eee);background:var(--dm-hover-bg)}.editor-toolbar-sep{width:1px;height:20px;background:var(--dm-border, rgba(255, 255, 255, .08));margin:0 4px;flex-shrink:0}.editor-toolbar-right{margin-left:auto;display:flex;align-items:center;gap:2px}.editor-view-btn{background:none;border:none;color:var(--dm-text-muted, #888);padding:6px 8px;border-radius:4px;cursor:pointer;display:flex;align-items:center;transition:color .15s,background .15s}.editor-view-btn:hover{color:var(--dm-text, #eee);background:var(--dm-hover-bg)}.editor-view-btn.active{color:var(--dm-primary, #5b8cff);background:color-mix(in srgb,var(--dm-primary) 14%,transparent)}.editor-body{display:flex;flex:1;min-height:0;--dm-editor-split: 50%}@media(min-width:769px){.editor-body:not(.editor-mode-write):not(.editor-mode-preview) .editor-pane--write{flex:0 0 var(--dm-editor-split, 50%)}.editor-body:not(.editor-mode-write):not(.editor-mode-preview) .editor-pane--preview{flex:1 1 0}}.editor-pane{flex:1;display:flex;flex-direction:column;min-width:0}.editor-pane--write,.editor-pane--preview{overflow:hidden}.editor-pane--write{flex-direction:row}.editor-line-numbers{padding:1rem .6rem 1rem .75rem;background:var(--dm-background-alt, rgba(0, 0, 0, .15));border-right:1px solid var(--dm-border, rgba(255, 255, 255, .08));color:var(--dm-text-muted, #666);font-family:Fira Code,Courier New,monospace;font-size:.9rem;line-height:1.6;text-align:right;user-select:none;white-space:pre;overflow:hidden;flex-shrink:0;min-width:2.5rem}.editor-line-numbers--foldable{padding:1rem 0;min-width:3rem;white-space:normal;text-align:left;display:flex;flex-direction:column}.editor-line-number-row{display:flex;align-items:center;justify-content:flex-end;padding-right:.6rem;gap:.15rem}.fold-toggle{display:inline-flex;align-items:center;justify-content:center;width:1em;font-size:.6rem;cursor:default;color:transparent}.fold-toggle--open,.fold-toggle--folded{cursor:pointer;color:var(--dm-text-muted, #666);transition:color .1s}.fold-toggle--open:hover,.fold-toggle--folded:hover{color:var(--dm-primary, #4a9eff)}.editor-line-num{min-width:1.5rem;text-align:right}.editor-mode-write .editor-pane--preview,.editor-mode-write .editor-divider,.editor-mode-preview .editor-pane--write,.editor-mode-preview .editor-divider{display:none}.editor-divider{width:7px;background:linear-gradient(to right,transparent 0,transparent 3px,var(--dm-border, rgba(255,255,255,.08)) 3px,var(--dm-border, rgba(255,255,255,.08)) 4px,transparent 4px,transparent 100%);cursor:col-resize;flex-shrink:0;touch-action:none;transition:background .12s ease}.editor-divider:hover,.editor-divider:focus-visible,.editor-divider.is-dragging{background:linear-gradient(to right,transparent 0,transparent 2px,var(--dm-primary, #5b8cff) 2px,var(--dm-primary, #5b8cff) 5px,transparent 5px,transparent 100%);outline:none}.editor-body.is-resizing .editor-pane{pointer-events:none}.editor-body.is-resizing{cursor:col-resize;user-select:none}.editor-textarea{flex:1;resize:none;border:none;border-radius:0;background:transparent;font-family:Fira Code,Courier New,monospace;font-size:.9rem;padding:1rem;outline:none;color:inherit;line-height:1.6}#editor-body .editor-textarea,#editor-body .editor-line-numbers{font-family:var(--pe-font, "Fira Code", "Courier New", monospace);font-size:var(--pe-size, .9rem);line-height:var(--pe-line, 1.6)}#editor-body.pe-nowrap .editor-textarea{white-space:pre;overflow-x:auto}.editor-preview{flex:1;display:block;width:100%;border:none;background:var(--dm-background)}.editor-fullscreen{position:fixed;inset:0;z-index:1000;border-radius:0;margin:0}.editor-fullscreen .card-body{height:100vh}.media-picker-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:.75rem;max-height:400px;overflow-y:auto;padding:.25rem}.media-picker-item{cursor:pointer;border:2px solid transparent;border-radius:6px;overflow:hidden;transition:border-color .15s}.media-picker-item:hover{border-color:var(--dm-primary, #5b8cff)}.media-picker-item img{width:100%;height:80px;object-fit:cover;display:block}.media-picker-item span{display:block;font-size:.75rem;padding:4px 6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.docs-body h3{margin-top:1.25rem;margin-bottom:.5rem}.docs-body p{margin-bottom:.5rem;line-height:1.6}.docs-body ol,.docs-body ul{margin-bottom:.75rem;padding-left:1.25rem}.docs-body li{margin-bottom:.25rem}.docs-body hr{margin:1.25rem 0;border-color:var(--dm-border, rgba(255, 255, 255, .08))}.docs-body .table{margin-bottom:.75rem}.docs-body h2{margin-top:1.75rem;margin-bottom:.6rem;padding-bottom:.3rem;border-bottom:1px solid var(--dm-border)}.docs-body h2:first-child{margin-top:0}.docs-body blockquote{margin:.75rem 0;padding:.5rem .9rem;border-left:3px solid var(--dm-primary);background:var(--dm-surface);border-radius:var(--dm-radius, 6px)}.docs-body pre{margin-bottom:.75rem;overflow-x:auto}.pg-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:1rem;margin-top:1.5rem}.pg-grid>.card.pg-card{display:block;margin:0;text-decoration:none}.pg-card h3{margin-top:0}.pg-card .text-muted,.pg-card-pages{margin-bottom:0}.pg-card-pages{margin-top:.5rem;font-size:.8rem;color:var(--dm-text-muted)}.pg-actions{display:flex;gap:.5rem;flex-wrap:wrap}.pg-meta{margin-bottom:.75rem}.pg-pages{display:flex;flex-wrap:wrap;gap:.35rem;margin-bottom:1rem}.pg-body{max-width:80ch}.nav-items-header,.nav-item-row{display:flex;gap:.5rem;align-items:center;padding:.35rem .75rem}.nav-items-header{border-bottom:1px solid var(--dm-border, rgba(255,255,255,.08));padding-bottom:.4rem;margin-bottom:.25rem}.nav-item-row{border-bottom:1px solid var(--dm-border, rgba(255,255,255,.04))}.nav-item-row:last-child{border-bottom:none}.nav-col-indent{width:18px;flex-shrink:0;color:var(--dm-text-muted, #888);text-align:center;font-size:.85rem}.nav-col-main{flex:2;min-width:0}.nav-col-icon{flex:0 0 90px}.nav-col-parent{flex:2;min-width:0}.nav-col-action{flex-shrink:0}.nav-item-row--child{background:color-mix(in srgb,var(--dm-text) 3%,transparent)}.nav-col-action{display:flex;align-items:center;gap:.25rem}.nav-item-row--hidden{opacity:.45}.nav-item-row--hidden .item-text,.nav-item-row--hidden .footer-link-text{text-decoration:line-through}.btn-toggle-hidden{color:var(--dm-text-muted, #888)}.btn-toggle-hidden.active{color:var(--dm-warning, #f59e0b)}.fb-drag-grip{flex-shrink:0;display:inline-flex;align-items:center;color:var(--dm-text-muted);cursor:grab}.fb-drag-grip:hover{color:var(--dm-text)}.btn-ghost span[data-icon=trash]{color:var(--dm-danger, #dc2626)}.view-container:has(.fb-fields-layout){max-width:none}.fb-fields-layout{display:grid;grid-template-columns:minmax(0,6fr) minmax(320px,4fr);gap:1.25rem;align-items:start}.fb-preview-pane{position:sticky;top:1rem;min-width:0}@media(max-width:1100px){.fb-fields-layout{grid-template-columns:1fr}.fb-preview-pane{position:static}}.toggle-label{display:flex;align-items:center;gap:.4rem;font-size:.9rem;cursor:pointer;margin-right:1rem}.preset-toggles{display:flex;flex-wrap:wrap;margin-top:.75rem}.presets-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}@media(max-width:900px){.presets-grid{grid-template-columns:repeat(2,1fr)}}@media(max-width:600px){.presets-grid{grid-template-columns:1fr}}.card-header{padding:.5rem 1rem}.card-header h2{margin:0;font-size:.9rem;font-weight:600;letter-spacing:.02em}.preset-card .card-header{display:flex;align-items:center;justify-content:space-between}.preset-card .card-header h3{margin:0;font-size:1rem}.media-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:1rem}.media-card{background:var(--dm-card-bg, rgba(255,255,255,.04));border:1px solid var(--dm-border, rgba(255,255,255,.08));border-radius:8px;overflow:hidden}.media-preview{height:130px;display:flex;align-items:center;justify-content:center;background:#0003;overflow:hidden}.media-thumb{width:100%;height:100%;object-fit:cover}.media-thumb--file{font-size:2rem;color:var(--dm-text-muted, #888)}.media-info{padding:.5rem .75rem;display:flex;flex-direction:column;gap:.15rem}.media-name{font-size:.8rem;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:default}.media-rename-input{width:100%;font-size:.8rem;font-weight:500;padding:.1rem .25rem;border:1px solid var(--dm-primary, #7c6af7);border-radius:3px;background:var(--dm-input-bg, transparent);color:inherit;outline:none}.media-size{font-size:.75rem;color:var(--dm-text-muted, #888)}.media-actions{padding:.5rem .75rem;display:flex;gap:.4rem;border-top:1px solid var(--dm-border, rgba(255,255,255,.08))}#admin-topbar{height:60px;display:flex;align-items:center;gap:1rem;padding:0 1.25rem;background:var(--dm-navbar-bg, rgba(0,0,0,.3));border-bottom:1px solid var(--dm-border, rgba(255,255,255,.08));position:sticky;top:0;z-index:200;flex-shrink:0}.topbar-brand{display:flex;align-items:center;gap:.5rem;font-weight:700;font-size:.95rem;color:inherit;flex-shrink:0;margin-right:.5rem}.topbar-brand span[data-icon],.topbar-brand svg{color:var(--dm-primary, #5b8cff);width:22px;height:22px}.topbar-brand-text{opacity:.85}.topbar-brand-logo{height:28px;width:auto;display:inline-block;vertical-align:middle;margin-right:.4em;object-fit:contain}.topbar-user{display:flex;align-items:center;gap:.6rem;flex:1}.topbar-user-name{font-size:.875rem;font-weight:500}.topbar-avatar{width:1.75rem;height:1.75rem;border-radius:50%;object-fit:cover;flex-shrink:0}.topbar-role-badge{font-size:.7rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;padding:.15rem .45rem;border-radius:4px}.topbar-role-badge--admin{background:color-mix(in srgb,var(--dm-primary) 15%,transparent);color:var(--dm-primary)}.topbar-role-badge--manager{background:color-mix(in srgb,var(--dm-success) 15%,transparent);color:var(--dm-success)}.topbar-role-badge--editor{background:color-mix(in srgb,var(--dm-warning) 15%,transparent);color:var(--dm-warning)}.topbar-role-badge--subscriber{background:color-mix(in srgb,var(--dm-text-muted) 15%,transparent);color:var(--dm-text-muted)}.topbar-actions{display:flex;align-items:center;gap:.5rem;flex-shrink:0}.topbar-action-link{display:flex;align-items:center;gap:.35rem;font-size:.875rem;color:var(--dm-text-muted, #888);text-decoration:none;padding:.4rem .65rem;border-radius:6px;transition:color .15s,background .15s}.topbar-action-link:hover{color:var(--dm-text, #eee);background:var(--dm-hover-bg)}.topbar-action-link span[data-icon],.topbar-action-link svg{width:16px;height:16px}.topbar-signout{display:flex;align-items:center;gap:.35rem;font-size:.875rem}.topbar-signout span[data-icon],.topbar-signout svg{width:16px;height:16px}.login-wrap{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;padding:1rem;background:var(--dm-background, #0f1117);z-index:100;overflow-y:auto}.login-card{width:100%;max-width:460px}.ob-done-icon{font-size:3rem;color:var(--dm-success);margin-bottom:1rem;text-align:center}.btn-skip{display:block;text-align:center;margin-top:.75rem;font-size:.85rem;color:var(--dm-text-muted, #888);text-decoration:none}.btn-skip:hover{text-decoration:underline}.theme-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:.6rem}.theme-swatch{border:2px solid var(--dm-border, rgba(255,255,255,.1));border-radius:8px;overflow:hidden;cursor:pointer;transition:border-color .15s,transform .1s}.theme-swatch:hover{border-color:var(--dm-primary, #5b8cff);transform:translateY(-1px)}.theme-swatch.selected{border-color:var(--dm-primary, #5b8cff);box-shadow:0 0 0 2px var(--dm-primary, #5b8cff)}.theme-swatch-preview{height:52px;position:relative;display:flex;align-items:flex-end;padding:.35rem}.theme-swatch-accent{width:28px;height:6px;border-radius:3px}.theme-swatch-label{display:flex;justify-content:space-between;align-items:center;padding:.3rem .45rem;font-size:.7rem;background:var(--dm-card-bg, rgba(255,255,255,.04))}.theme-swatch-mode{color:var(--dm-text-muted, #888);font-size:.65rem}.login-logo{display:flex;align-items:center;gap:.75rem;margin-bottom:1.75rem;font-size:1.5rem}.login-logo span[data-icon]{font-size:2rem;color:var(--dm-primary, #5b8cff)}.login-logo h1{margin:0;font-size:1.5rem;font-weight:700}.login-card [hidden]{display:none!important}.login-heading{font-size:1.1rem;font-weight:600;margin-bottom:1.25rem}.login-rules{margin:.25rem 0 .75rem;padding-left:1.1rem;color:var(--dm-danger);font-size:.85rem}.login-rules li+li{margin-top:.2rem}.login-small{font-size:.8rem;margin-top:.75rem}.login-icon-warn{color:var(--dm-warning)}.pwf{position:relative;display:block}.pwf>input{width:100%;padding-right:2.5rem}.pwf-toggle{position:absolute;top:50%;right:.35rem;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;border:0;border-radius:var(--dm-radius-sm);background:transparent;color:var(--dm-text-muted);cursor:pointer}.pwf-toggle:hover,.pwf-toggle:focus-visible{color:var(--dm-text);background:var(--dm-hover-bg)}.pwf-toggle svg{width:16px;height:16px}.pwf-toggle [data-icon=eye-off],.pwf.is-shown .pwf-toggle [data-icon=eye]{display:none}.pwf.is-shown .pwf-toggle [data-icon=eye-off]{display:inline-block}.pwf-caps{display:block;margin-top:.25rem;color:var(--dm-warning);font-size:.8rem}.pwf-caps[hidden]{display:none}.btn-block{width:100%}.plugins-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:1rem}.plugin-card{display:flex;flex-direction:column;--plugin-accent: var(--dm-primary, #5b8cff);position:relative;overflow:hidden;background-image:radial-gradient(120% 90% at 100% 0%,color-mix(in srgb,var(--plugin-accent) 13%,transparent) 0%,color-mix(in srgb,var(--plugin-accent) 4%,transparent) 42%,transparent 72%)}.plugin-card .plugin-icon{background:color-mix(in srgb,var(--plugin-accent) 16%,transparent);color:var(--plugin-accent)}.plugin-watermark{position:absolute;top:-34px;right:-30px;width:148px;height:148px;display:block;color:var(--plugin-accent);opacity:.09;pointer-events:none;z-index:0}.plugin-card>.card-body,.plugin-card>.plugin-footer{position:relative;z-index:1}.plugin-card:has(.badge-secondary) .plugin-watermark{opacity:.05}@media(prefers-reduced-motion:no-preference){.plugin-card{transition:background-image .2s ease}}.plugin-card .card-body{flex:1}.plugin-header{display:flex;align-items:flex-start;gap:.75rem;margin-bottom:.75rem;flex-wrap:wrap}.plugin-icon{width:40px;height:40px;border-radius:8px;background:color-mix(in srgb,var(--dm-primary) 14%,transparent);color:var(--dm-primary, #5b8cff);display:flex;align-items:center;justify-content:center;flex-shrink:0}.plugin-meta{flex:1 1 140px;min-width:0}.plugin-name{font-weight:600;margin-bottom:.15rem}.plugin-version{font-size:.75rem;color:var(--dm-text-muted, #888)}.plugin-desc{font-size:.875rem;color:var(--dm-text-muted, #888);margin-bottom:1rem}.plugin-footer{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;border-top:1px solid var(--dm-border, rgba(255,255,255,.08))}.plugin-footer-actions{display:flex;align-items:center;gap:.5rem}#admin-sidebar .sidebar-link{position:relative!important}#admin-sidebar .sidebar-badge{position:absolute!important;right:.75rem!important;top:50%!important;transform:translateY(-50%)!important;margin-left:0!important;padding-left:.45rem!important;padding-right:.45rem!important}#admin-sidebar .sidebar-text{padding-right:2rem!important}#admin-sidebar.sidebar-dark{background:var(--dm-surface);border-color:var(--dm-border)}#admin-sidebar.sidebar-dark .sidebar-header{background:var(--dm-surface-raised);border-color:var(--dm-border)}#admin-sidebar.sidebar-dark .sidebar-header-title{color:var(--dm-text)}#admin-sidebar.sidebar-dark .sidebar-link{color:var(--dm-text-muted)}#admin-sidebar.sidebar-dark .sidebar-link:hover{color:var(--dm-text);background:var(--dm-surface-overlay)}#admin-sidebar.sidebar-dark .sidebar-link.active{color:var(--dm-primary);background:color-mix(in srgb,var(--dm-primary) 14%,transparent);border-left-color:var(--dm-primary)}#admin-sidebar.sidebar-dark .sidebar-heading{color:var(--dm-text-muted)}#admin-sidebar.sidebar-dark .sidebar-divider{background:var(--dm-border)}#admin-sidebar.sidebar-dark .sidebar-footer{background:var(--dm-surface-raised);border-color:var(--dm-border)}.sidebar-heading--collapsible{display:flex!important;align-items:center;justify-content:space-between;cursor:pointer;user-select:none}.sidebar-heading-toggle{display:flex;align-items:center;opacity:.5;flex-shrink:0;transition:transform .2s ease}.sidebar-heading--collapsible.is-collapsed .sidebar-heading-toggle{transform:rotate(-90deg)}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.p-0{padding:0!important}.text-muted{color:var(--dm-text-muted, #888)}@media(max-width:768px){.view-container{padding:1rem}.editor-body{flex-direction:column}.editor-divider{width:auto;height:1px;cursor:default;background:var(--dm-border, rgba(255,255,255,.08))}}.image-editor{display:flex;flex-direction:column;gap:0}.image-editor-toolbar{display:flex;flex-direction:row;align-items:center;gap:.25rem;padding:.5rem .75rem;border-bottom:1px solid var(--dm-border, rgba(255, 255, 255, .1))}.image-editor-sep{display:inline-block;width:1px;height:1.5rem;background:var(--dm-border, rgba(255, 255, 255, .15));margin:0 .25rem;flex-shrink:0}.editor-toolbar-btn.active{color:var(--dm-primary, #7c6af7);background:color-mix(in srgb,var(--dm-primary, #7c6af7) 15%,transparent)}.editor-toolbar-caret{font-size:.6rem;line-height:1;margin-left:2px;opacity:.6}.editor-toolbar-dropdown{position:absolute;z-index:1000;background:var(--dm-surface, #1e1e2e);border:1px solid var(--dm-border, rgba(255, 255, 255, .1));border-radius:8px;box-shadow:0 8px 24px #0006;padding:4px;min-width:160px;max-height:70vh;overflow-y:auto}.editor-toolbar-dropdown-heading{padding:6px 10px 3px;color:var(--dm-text-muted, #8a8a9a);font-size:.66rem;text-transform:uppercase;letter-spacing:.06em}.editor-toolbar-dropdown-item{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:none;border:none;color:var(--dm-text, #ddd);padding:7px 10px;border-radius:5px;cursor:pointer;font-size:.85rem;transition:background .12s,color .12s}.editor-toolbar-dropdown-item:hover{background:var(--dm-hover-bg);color:var(--dm-text, #fff)}.editor-toolbar-dropdown-item span[data-icon],.editor-toolbar-dropdown-item svg{width:15px;height:15px;flex-shrink:0;opacity:.75}.editor-toolbar{position:relative}.editor-effects-dropdown-menu{position:absolute;top:100%;z-index:1000;background:var(--dm-surface, #1e1e2e);border:1px solid var(--dm-border, rgba(255, 255, 255, .1));border-radius:8px;box-shadow:0 8px 24px #0006;padding:6px;min-width:180px;max-height:340px;overflow-y:auto}.editor-effects-category{padding:6px 8px 3px;font-size:.7rem;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--dm-text-muted, #888)}.editor-effects-item{display:block;width:100%;text-align:left;background:none;border:none;color:var(--dm-text, #ddd);padding:6px 10px;border-radius:5px;cursor:pointer;font-size:.85rem;transition:background .12s,color .12s}.editor-effects-item:hover{background:var(--dm-hover-bg);color:var(--dm-text, #fff)}.editor-icon-picker{position:absolute;z-index:1000;background:var(--dm-surface, #1e1e2e);border:1px solid var(--dm-border, rgba(255, 255, 255, .1));border-radius:8px;box-shadow:0 8px 24px #0006;padding:8px;width:320px}.editor-icon-picker-search{width:100%;margin-bottom:8px;font-size:.8rem}.editor-spacer-picker{position:absolute;z-index:9999;background:var(--dm-surface, #1e1e2e);border:1px solid var(--dm-border, #333);border-radius:8px;padding:12px;width:240px;box-shadow:0 8px 24px #00000073}.editor-spacer-picker-label{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--dm-text-muted, #888);margin-bottom:10px}.editor-spacer-picker-row{display:flex;align-items:center;gap:10px;margin-bottom:12px}.editor-spacer-slider{flex:1;accent-color:var(--dm-primary, #6366f1);cursor:pointer}.editor-spacer-slider-value{font-size:13px;font-weight:600;min-width:38px;text-align:right;color:var(--dm-text, #cdd6f4)}.editor-spacer-insert-btn{width:100%}.editor-icon-picker-size-row{display:flex;align-items:center;gap:8px;padding:0 8px 8px}.editor-icon-picker-size-row label{font-size:11px;color:var(--dm-text-muted, #888);white-space:nowrap}.editor-icon-picker-size{width:70px;font-size:12px;padding:3px 6px}.editor-icon-picker-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(52px,1fr));gap:2px;max-height:280px;overflow-y:auto}.editor-icon-picker-item{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:6px 2px;border-radius:5px;cursor:pointer;background:none;border:none;color:var(--dm-text, #ddd);font-size:.58rem;text-align:center;gap:4px;overflow:hidden;transition:background .12s,color .12s}.editor-icon-picker-item:hover{background:var(--dm-hover-bg);color:var(--dm-text, #fff)}.editor-icon-picker-item span[data-icon],.editor-icon-picker-item svg{width:16px;height:16px;flex-shrink:0}.editor-icon-picker-item>span:last-child{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.2}.editor-icon-picker-empty{grid-column:1 / -1;text-align:center;color:var(--dm-text-muted, #888);font-size:.8rem;padding:1.5rem}.image-editor-canvas{min-height:320px;max-height:520px;background:#111;overflow:hidden;display:flex;align-items:center;justify-content:center}.image-editor-canvas img{display:block;max-width:100%;max-height:520px}.image-editor-resize{display:flex;flex-direction:row;align-items:center;gap:.5rem;padding:.6rem .75rem;border-top:1px solid var(--dm-border, rgba(255, 255, 255, .1));font-size:.85rem}.image-editor-resize label{font-weight:600;color:var(--dm-text-muted, #888);font-size:.8rem}.image-editor-resize .form-input{width:5rem;padding:.25rem .5rem;font-size:.85rem}.image-editor-footer{display:flex;flex-direction:row;align-items:center;justify-content:space-between;padding:.75rem;border-top:1px solid var(--dm-border, rgba(255, 255, 255, .1));gap:.5rem}.image-editor-effects{border-top:1px solid var(--dm-border, rgba(255, 255, 255, .1))}.image-editor-tab-bar{display:flex;flex-direction:row;overflow-x:auto;border-bottom:1px solid var(--dm-border, rgba(255, 255, 255, .1));scrollbar-width:none}.image-editor-tab-bar::-webkit-scrollbar{display:none}.image-editor-tab-btn{display:inline-flex;align-items:center;gap:.35rem;padding:.5rem .85rem;font-size:.8rem;font-weight:500;border:none;border-bottom:2px solid transparent;background:transparent;cursor:pointer;color:var(--dm-text-muted, #888);white-space:nowrap;transition:color .15s,border-color .15s;flex-shrink:0}.image-editor-tab-btn:hover{color:var(--dm-text, #eee)}.image-editor-tab-btn.active{color:var(--dm-primary, #7c6af7);border-bottom-color:var(--dm-primary, #7c6af7)}.image-editor-tab-panel{padding:.75rem;max-height:200px;overflow-y:auto}.ie-presets-grid{display:flex;flex-wrap:wrap;gap:.35rem;margin-bottom:.5rem}.ie-preset-btn.active{color:var(--dm-primary, #7c6af7);background:color-mix(in srgb,var(--dm-primary, #7c6af7) 15%,transparent);border-color:var(--dm-primary, #7c6af7)}.ie-server-note{font-size:.73rem;color:var(--dm-text-muted, #888);font-style:italic;margin:.25rem 0 0;line-height:1.4}.ie-slider-row{display:flex;align-items:center;gap:.5rem;margin-bottom:.4rem}.ie-slider-label{width:6rem;font-size:.8rem;color:var(--dm-text-muted, #888);font-weight:600;flex-shrink:0}.ie-slider{flex:1;accent-color:var(--dm-primary, #7c6af7);cursor:pointer}.ie-slider-val{width:3rem;font-size:.8rem;text-align:right;color:var(--dm-text, #eee);flex-shrink:0}.ie-select{flex:1;font-size:.85rem;padding:.25rem .5rem}.ie-colour-input{width:40px;height:28px;padding:0;border:1px solid var(--dm-border, rgba(255, 255, 255, .15));border-radius:4px;cursor:pointer;background:transparent;flex-shrink:0}.ie-wm-preview-row{display:flex;align-items:center;gap:.5rem;margin:.4rem 0}.ie-wm-preview-img{width:48px;height:48px;object-fit:contain;border-radius:4px;background:var(--dm-surface-raised, rgba(255, 255, 255, .06));flex-shrink:0}.ie-wm-preview-name{font-size:.8rem;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text, #eee)}.ie-media-picker{padding:.25rem 0}.ie-media-picker-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(80px,1fr));gap:.5rem;max-height:300px;overflow-y:auto}.ie-media-thumb{display:flex;flex-direction:column;align-items:center;gap:.25rem;padding:.4rem;border-radius:6px;cursor:pointer;border:2px solid transparent;transition:border-color .15s,background .15s}.ie-media-thumb:hover{background:var(--dm-surface-raised, rgba(255, 255, 255, .08));border-color:var(--dm-primary, #7c6af7)}.ie-media-thumb img{width:72px;height:72px;object-fit:cover;border-radius:4px}.ie-media-thumb-name{font-size:.7rem;color:var(--dm-text-muted, #888);text-align:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:72px}.dm-slideover-left,.dm-slideover-right{width:min(40rem,95vw)!important;min-width:min(36rem,100vw)!important;max-width:100vw!important}.dm-slideover-resizer{position:absolute;top:0;bottom:0;width:6px;cursor:col-resize;z-index:2;background:transparent}.dm-slideover-right>.dm-slideover-resizer{left:0}.dm-slideover-left>.dm-slideover-resizer{right:0}.dm-slideover-resizer:hover,.is-resizing>.dm-slideover-resizer{background:var(--dm-primary);opacity:.7}.dm-slideover.is-resizing{user-select:none;transition:none!important}.dm-slideover-header{display:flex;align-items:center;justify-content:space-between;padding:1rem 1.25rem;border-bottom:1px solid var(--dm-border, #333);flex-shrink:0}.dm-slideover-title{margin:0;font-size:1rem;font-weight:600}.dm-slideover-close{padding:.2rem .35rem!important;line-height:1;font-size:.75rem}.dm-slideover-body{flex:1;overflow:auto;overscroll-behavior:contain;min-height:0;padding:1.5rem!important;box-sizing:border-box}.dm-slideover-body:empty{flex:0 0 auto;padding:0!important}.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-body):not(.dm-slideover-close){padding:1.5rem!important;box-sizing:border-box;flex:1 1 auto;min-height:0;overflow:auto;overscroll-behavior:contain}.dm-slideover-body,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close){scrollbar-width:thin;scrollbar-color:var(--dm-border) transparent}.dm-slideover-body::-webkit-scrollbar,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close)::-webkit-scrollbar{width:8px;height:8px}.dm-slideover-body::-webkit-scrollbar-track,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close)::-webkit-scrollbar-track{background:transparent}.dm-slideover-body::-webkit-scrollbar-thumb,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close)::-webkit-scrollbar-thumb{background:var(--dm-border);border-radius:4px}.dm-slideover-body::-webkit-scrollbar-thumb:hover,.dm-slideover>div:not(.dm-slideover-header):not(.dm-slideover-close)::-webkit-scrollbar-thumb:hover{background:var(--dm-text-muted)}.dm-slideover-body>div{padding-left:0!important;padding-right:0!important}.dm-slideover-body>button.btn:last-child{margin-top:.5rem}.dconfig-textarea{font-family:monospace;min-height:100px;resize:vertical}.dm-editor-line-numbers{white-space:pre}.dm-code-inline{font-family:Fira Code,Courier New,monospace;font-size:.82em;padding:.15em .35em;border-radius:3px;background:var(--dm-background-alt, rgba(0, 0, 0, .18));color:var(--dm-text, inherit);border:1px solid var(--dm-border, rgba(255, 255, 255, .08))}.dm-code-block{font-family:Fira Code,Courier New,monospace;font-size:.82rem;line-height:1.6;padding:.65rem .9rem;border-radius:6px;background:var(--dm-background-alt, rgba(0, 0, 0, .18));color:var(--dm-text, inherit);border:1px solid var(--dm-border, rgba(255, 255, 255, .08));white-space:pre;overflow-x:auto;display:block;margin:.4rem 0}.tabs-centered{text-align:center}.tabs-centered .tab-list{display:inline-flex}.tabs-centered .tab-content{text-align:left}@media(max-width:768px){.view-header{flex-direction:column;align-items:flex-start}.theme-grid{grid-template-columns:repeat(2,1fr)}.nav-item-row{flex-wrap:wrap}.nav-col-icon,.nav-col-parent{display:none}#admin-topbar{padding:0 .75rem}.topbar-brand-text{display:none}.image-editor-toolbar{flex-wrap:wrap}}#topbar-bell{position:relative}.topbar-action-link[hidden],.topbar-bell-badge[hidden]{display:none}.topbar-bell-badge{position:absolute;top:2px;right:2px;min-width:16px;height:16px;padding:0 4px;background:var(--dm-danger, #dc2626);color:var(--dm-danger-text, #fff);font-size:10px;font-weight:700;line-height:16px;border-radius:9999px;text-align:center;pointer-events:none}.cb-scaffolder{padding:1rem 1.1rem;background:var(--dm-background-alt);border:1px solid var(--dm-primary);border-radius:8px;color:var(--dm-text)}.cb-scaffolder-head{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}.cb-scaffolder-head .cb-icon{flex-shrink:0;color:var(--dm-primary)}.cb-scaffolder-head h2{margin:0;font-size:1.05rem;font-weight:700;color:var(--dm-text)}.cb-scaffolder-blurb{margin:0 0 .75rem;font-size:.88rem;line-height:1.5;color:var(--dm-text-muted)}.cb-recipe-list{display:flex;flex-direction:column;gap:.5rem}.cb-recipe-card{display:flex;align-items:flex-start;gap:.75rem;text-align:left;padding:.75rem 1rem;background:var(--dm-surface);border:1px solid var(--dm-border);border-radius:6px;cursor:pointer;transition:border-color .12s;width:100%;color:var(--dm-text)}.cb-recipe-card:hover{border-color:var(--dm-primary)}.cb-recipe-card .cb-icon{flex-shrink:0;font-size:1.5rem;color:var(--dm-primary);margin-top:.1rem}.cb-recipe-meta{flex:1}.cb-recipe-name{font-weight:600;margin-bottom:.15rem;font-size:.95rem;color:var(--dm-text)}.cb-recipe-desc{font-size:.83rem;line-height:1.45;color:var(--dm-text-muted)}.cb-apply-panel{padding:1rem 1.1rem;background:var(--dm-surface);border:1px solid var(--dm-primary);border-radius:8px;color:var(--dm-text)}.cb-apply-head{display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem}.cb-apply-head .cb-icon{color:var(--dm-primary);font-size:1.4rem}.cb-apply-head h3{margin:0;font-size:1rem;font-weight:600;color:var(--dm-text)}.cb-apply-desc,.cb-apply-hint{margin:.25rem 0 .75rem;font-size:.85rem;line-height:1.5;color:var(--dm-text-muted)}.cb-apply-hint{font-size:.75rem;margin-top:.2rem}.cb-apply-field{margin-bottom:.6rem}.cb-apply-field label{display:block;font-size:.82rem;font-weight:600;margin-bottom:.2rem;color:var(--dm-text)}.cb-apply-field input{width:100%;padding:.4rem .55rem;border:1px solid var(--dm-border);border-radius:4px;font-size:.88rem;background:var(--dm-surface);color:var(--dm-text)}.cb-apply-status{margin:.5rem 0;font-size:.85rem;min-height:1.2rem;color:var(--dm-text)}.cb-apply-status.cb-error{color:var(--dm-danger, #dc2626)}.cb-apply-buttons{display:flex;gap:.5rem;justify-content:flex-end;margin-top:.5rem}.cb-success-panel{padding:1rem 1.1rem;background:var(--dm-surface);border:1px solid var(--dm-success, #16a34a);border-radius:8px;color:var(--dm-text)}.cb-success-panel .cb-icon{color:var(--dm-success, #16a34a);font-size:1.4rem}.cb-success-summary{margin:.25rem 0 .5rem;padding-left:1.2rem;font-size:.86rem;line-height:1.6;color:var(--dm-text)}.cb-success-warning{margin:.5rem 0;padding:.5rem .75rem;background:var(--dm-background-alt);border-left:3px solid var(--dm-warning, #eab308);border-radius:0 4px 4px 0;font-size:.82rem;color:var(--dm-text-muted)}.cb-success-snippet-label{margin:0 0 .25rem;font-size:.82rem;font-weight:600;color:var(--dm-text)}.cb-success-actions{display:flex;gap:.5rem;margin-top:.5rem;flex-wrap:wrap}.cb-code{position:relative}.cb-code pre{background:var(--dm-background-alt);color:var(--dm-text);display:block;padding:.6rem 2.4rem .6rem .75rem;white-space:pre;overflow-x:auto;margin:0;border-radius:6px;font-size:.82em;font-family:monospace;line-height:1.45}.cb-code .cb-copy{position:absolute;top:.35rem;right:.35rem;background:none;border:none;cursor:pointer;opacity:.45;padding:.2rem;line-height:1;color:var(--dm-text)}.cb-code .cb-copy:hover{opacity:1}.cb-intro{padding:.75rem 1rem;border-left:3px solid var(--dm-primary);background:var(--dm-background-alt);border-radius:0 6px 6px 0}.cb-intro p{margin:0;font-size:.92rem;line-height:1.5;color:var(--dm-text)}.cb-tutorial-link{display:flex;align-items:center;gap:.6rem;padding:.65rem .85rem;border:1px solid var(--dm-border);border-radius:6px;text-decoration:none;color:var(--dm-text);font-size:.88rem;transition:border-color .12s}.cb-tutorial-link:hover{border-color:var(--dm-primary)}.cb-tutorial-link .cb-icon{flex-shrink:0;color:var(--dm-primary)}.cb-tutorial-link .cb-arrow{color:var(--dm-text-muted);font-size:1.1rem;margin-left:auto}.menu-tree-row{display:grid;grid-template-columns:26px 1.4fr 1.4fr .9fr .7fr .9fr repeat(6,auto);gap:6px;align-items:center;padding:4px 0;transition:opacity .15s ease}.menu-tree-row--hidden{opacity:.5}.menu-tree-row--tool .me-tool-badge{margin-left:.4rem;font-size:.7rem;vertical-align:middle}.menu-tree-row--default .me-row-label{font-style:italic;opacity:.8}.menu-tree-grip{cursor:grab;color:var(--dm-text-muted)}.menu-tree-grip:hover{color:var(--dm-text)}.menu-tree{padding:8px 0}.menu-tree-row--separator{display:grid;grid-template-columns:26px minmax(80px,1fr) repeat(7,auto);gap:6px;align-items:center;padding:2px 0;opacity:.85}.menu-tree-row--separator:hover{opacity:1}.menu-tree-row--separator .me-sep-line{display:flex;align-items:center;gap:10px;width:100%}.menu-tree-row--separator .me-sep-line:before,.menu-tree-row--separator .me-sep-line:after{content:"";flex:1;border-top:1px dashed var(--dm-border, rgba(128, 128, 128, .55))}.menu-tree-row--separator .me-sep-label{font-size:.66rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--dm-text-muted, #8a8a8a);white-space:nowrap}.dm-admin-sidebar .sidebar-divider{border:0;border-top:1px solid var(--dm-border, rgba(128, 128, 128, .5));margin:.5rem .75rem;opacity:.8}.dm-admin-sidebar .sidebar-spacer--xs{height:var(--dm-space-1, .25rem)}.dm-admin-sidebar .sidebar-spacer--sm{height:var(--dm-space-2, .5rem)}.dm-admin-sidebar .sidebar-spacer--md{height:var(--dm-space-4, 1rem)}.dm-admin-sidebar .sidebar-spacer--lg{height:var(--dm-space-6, 1.5rem)}.dm-admin-sidebar .sidebar-spacer--xl{height:var(--dm-space-10, 2.5rem)}.dm-admin-sidebar .sidebar-spacer--flex{flex:1 1 auto;min-height:var(--dm-space-4, 1rem)}.dm-admin-sidebar--has-flex-spacer{display:flex;flex-direction:column;min-height:100%}.menu-tree-row--spacer{display:grid;grid-template-columns:26px minmax(80px,1fr) repeat(7,auto);gap:6px;align-items:center;padding:2px 0;opacity:.85}.menu-tree-row--spacer:hover{opacity:1}.menu-tree-row--spacer .me-spacer-line{display:flex;align-items:center;gap:8px;width:100%}.menu-tree-row--spacer .me-spacer-line:before,.menu-tree-row--spacer .me-spacer-line:after{content:"";flex:1;border-top:1px dotted var(--dm-border, rgba(128, 128, 128, .55))}.menu-tree-row--spacer .me-spacer-label{font-size:.66rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--dm-text-muted, #8a8a8a);white-space:nowrap}.menu-tree-row--spacer .me-spacer-size{width:auto;min-width:5.5rem;height:26px;padding:0 .35rem;font-size:.75rem}.menu-tree-row .me-icon-wrap{display:flex;gap:2px}.menu-tree-row .me-icon-wrap .me-icon{flex:1;min-width:0}.menu-tree-row .me-icon-wrap .me-icon-pick{flex-shrink:0;padding:.2rem .45rem;font-size:.85em}.dm-admin-sidebar{display:flex;flex-direction:column;gap:2px;padding:8px 0;font-size:.875rem}.dm-admin-sidebar details{margin:0}.dm-admin-sidebar details>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:.5rem;padding:.4rem .75rem;border-radius:4px;user-select:none;font-size:.78rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--dm-text-muted, #888)}.dm-admin-sidebar details details>summary{font-size:.875rem;font-weight:500;text-transform:none;letter-spacing:0;color:inherit}.dm-admin-sidebar .dm-menu-badge{font-size:.7rem;font-weight:600}.dm-admin-sidebar details>summary::-webkit-details-marker{display:none}.dm-admin-sidebar details>summary:after{content:"\25b8";margin-left:auto;transition:transform .15s ease;color:var(--dm-text-muted, #999);font-size:.85em}.dm-admin-sidebar details[open]>summary:after{transform:rotate(90deg)}.dm-admin-sidebar details>div{padding-left:1rem;border-left:1px solid var(--dm-border-light, rgba(0, 0, 0, .08));margin-left:.95rem}.dm-admin-sidebar .sidebar-link{display:flex;align-items:center;gap:.5rem;padding:.35rem .75rem;text-decoration:none;color:var(--dm-text, inherit);border-radius:4px}.dm-admin-sidebar .sidebar-link:hover,.dm-admin-sidebar details>summary:hover{background:var(--dm-hover-bg, rgba(0, 0, 0, .05))}.dm-admin-sidebar .sidebar-link.active{background:var(--dm-active-bg, rgba(0, 0, 0, .08));font-weight:600}.dm-admin-sidebar .sidebar-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dm-admin-sidebar [data-icon]{flex-shrink:0}.dm-admin-sidebar-header{position:sticky;top:0;z-index:2;background:var(--dm-surface);display:flex;align-items:center;gap:.5rem;padding:.65rem .85rem;margin:0 0 .5rem;font-weight:600;font-size:.95rem;letter-spacing:.01em;color:var(--dm-text, inherit);border-bottom:1px solid var(--dm-border-light, rgba(0, 0, 0, .08))}.dm-admin-sidebar--dark .dm-admin-sidebar-header{background:#1a1d24}.dm-admin-sidebar--light .dm-admin-sidebar-header{background:#fff}.dm-admin-sidebar-header [data-icon]{color:var(--dm-text-muted, #999)}.dm-admin-sidebar-header .dm-admin-sidebar-arrange{margin-left:auto;padding:.2rem .35rem;color:var(--dm-text-muted, #999);line-height:1}.dm-admin-sidebar-header .dm-admin-sidebar-arrange:hover,.dm-admin-sidebar-header .dm-admin-sidebar-arrange:focus-visible{color:var(--dm-text)}.dm-admin-sidebar.is-arranging>:not(.dm-admin-sidebar-header):not(.sb-arrange):not(style){display:none!important}.dm-admin-sidebar.is-arranging .dm-admin-sidebar-arrange{display:none}.sb-arrange{box-sizing:border-box;max-width:100vw;padding:0 .5rem 1rem;animation:sb-arrange-in .18s cubic-bezier(.2,.8,.2,1)}@keyframes sb-arrange-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}.sb-arrange-bar{position:sticky;top:2.6rem;z-index:2;display:flex;align-items:center;gap:.4rem;padding:.4rem .25rem;background:inherit}.sb-arrange-title{font-weight:600;margin-right:auto}.sb-arrange-hint{margin:0 .25rem .5rem;font-size:.78rem;line-height:1.35;color:var(--dm-text-muted)}.sb-arr-row{display:flex;align-items:center;gap:.45rem;padding:.35rem .4rem .35rem calc(.4rem + var(--sb-arr-depth, 0) * 1rem);border-radius:var(--dm-radius-sm, 4px);cursor:grab;user-select:none;font-size:.9rem}.sb-arr-row:hover{background:color-mix(in srgb,var(--dm-text) 6%,transparent)}.sb-arr-row:focus-visible{outline:2px solid var(--dm-primary);outline-offset:-2px}.sb-arr-row--folder .sb-arr-text{font-weight:600}.sb-arr-row--hidden .sb-arr-text,.sb-arr-row--hidden .sb-arr-icon{opacity:.45;text-decoration:line-through}.sb-arr-row--structural .sb-arr-text{font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;color:var(--dm-text-muted)}.sb-arr-grip{color:var(--dm-text-muted);flex:none}.sb-arr-icon{width:16px;flex:none}.sb-arr-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sb-arr-hide{flex:none;display:inline-flex;padding:.15rem;border:0;border-radius:var(--dm-radius-sm, 4px);background:transparent;color:var(--dm-text-muted);cursor:pointer}.sb-arr-hide:hover,.sb-arr-hide:focus-visible{color:var(--dm-text);background:color-mix(in srgb,var(--dm-text) 8%,transparent)}.sb-arr-lock{flex:none;color:var(--dm-text-muted);opacity:.6}.dm-admin-sidebar .sidebar-badge{margin-left:auto;padding:0 .4rem;min-width:1.25rem;height:1.1rem;line-height:1.1rem;text-align:center;font-size:.7rem;font-weight:600;border-radius:999px;background:var(--dm-active-bg, rgba(0, 0, 0, .12));color:var(--dm-text-muted, #888)}.dm-admin-sidebar .sidebar-link.active .sidebar-badge{background:var(--dm-primary, #4a86e8);color:var(--dm-primary-text, #fff)}.dm-admin-sidebar .sidebar-children{overflow:hidden;transition:max-height .22s ease,opacity .18s ease}.dm-admin-sidebar details:not([open])>.sidebar-children{opacity:0}.dm-admin-sidebar{position:relative}.dm-admin-sidebar-handle{position:absolute;top:0;right:0;width:6px;height:100%;cursor:col-resize;background:transparent;z-index:10;transition:background .15s}.dm-admin-sidebar-handle:hover,.dm-admin-sidebar-handle:active{background:var(--dm-primary, #4a86e8);opacity:.35}.dm-admin-sidebar--dark{background:#1a1d24;color:#e3e6eb}.dm-admin-sidebar--dark .sidebar-link,.dm-admin-sidebar--dark summary{color:#e3e6eb}.dm-admin-sidebar--dark .sidebar-link:hover,.dm-admin-sidebar--dark details>summary:hover{background:#ffffff0f}.dm-admin-sidebar--dark .sidebar-link.active{background:#4a86e840}.dm-admin-sidebar--dark .sidebar-badge{background:#ffffff1f;color:#cbd0d8}.dm-admin-sidebar--light{background:#fff;color:#1a1d24;border-right:1px solid rgba(0,0,0,.08)}.dm-admin-sidebar--light .sidebar-link,.dm-admin-sidebar--light summary{color:#1a1d24}.dm-admin-sidebar--light .sidebar-link:hover,.dm-admin-sidebar--light details>summary:hover{background:#0000000a}.dm-admin-sidebar--light .sidebar-link.active{background:#4a86e826}.dm-admin-sidebar--transparent{background:transparent}.page-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin:0 0 1.25rem;padding-bottom:.75rem;border-bottom:1px solid var(--dm-border-light, rgba(0, 0, 0, .08))}.page-header h2{margin:0;display:flex;align-items:center;gap:.5rem;font-size:1.4rem;line-height:1.2}.page-header h2 [data-icon]{color:var(--dm-text-muted, #888)}.header-actions{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}.card+.card,.card+p,p+.card,.card+.toolbar,.toolbar+.card,.card+.grid{margin-top:1rem}.toolbar{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;margin:0 0 1rem}.btn+.btn,.btn+a.btn,a.btn+.btn,a.btn+a.btn{margin-left:.35rem}[style*=inline-flex] .btn+.btn,[style*=inline-flex] .btn+a.btn,[style*=inline-flex] a.btn+.btn{margin-left:0}.card-body>[id$=-form],.card-body>form{margin:.25rem 0}.card-header{display:flex;align-items:center;gap:.5rem}.card-header h3{margin:0;font-size:1.05rem}.card-header [data-icon]{color:var(--dm-text-muted, #888)}.page-header+p.text-muted{margin:-.5rem 0 1rem}.dm-pe-grid{gap:.75rem 1rem}.dm-pe-grid .form-group{display:flex;flex-direction:column;gap:.25rem;margin:0}.dm-pe-grid .form-group.col-span-2{grid-column:1 / -1}.dm-pe-grid label{font-size:.85rem;font-weight:600;color:var(--dm-text, inherit)}.dm-pe-grid label .required{color:var(--dm-danger, #c33);margin-left:2px}.dm-pe-grid .form-hint{font-size:.75rem;color:var(--dm-text-muted, #888);margin-top:.1rem}.dm-pe-grid .form-input{width:100%;padding:.4rem .6rem}.dm-pe-grid textarea.form-input{resize:vertical;min-height:2.5rem}.dm-menu-badge{display:inline-block;margin-left:6px;padding:1px 7px;font-size:.7em;font-weight:700;line-height:1.4;border-radius:999px;background:var(--dm-text-muted);color:var(--dm-text-inverse, #fff);vertical-align:middle}.menu-tree-row--slim{display:grid;grid-template-columns:26px 1fr auto repeat(9,auto);gap:6px;align-items:center}.menu-tree-row--slim .me-row-label{font-weight:600}.menu-tree-row--slim .me-row-url{color:var(--dm-text-muted);font-size:.85em}.me-pages-picker{display:flex;gap:6px;align-items:center;margin-bottom:6px}.me-pages-picker .form-input{flex:1;min-width:0}.me-colour-control{display:flex;gap:6px;align-items:center}.me-colour-control .me-colour-hex{width:48px;height:32px;padding:2px;flex:none}.me-bind-summary{padding:.6rem .8rem;border:1px solid var(--dm-border, rgba(128, 128, 128, .35));border-radius:var(--dm-radius-md, 6px);background:color-mix(in srgb,var(--dm-text) 4%,transparent);font-size:.9em}.me-bind-summary code{font-size:.9em}.me-item-form{display:flex;flex-direction:column;gap:10px;padding:4px 2px}.me-item-form .form-field{display:flex;flex-direction:column;gap:4px}.me-item-form .form-label{font-size:.85em;color:var(--dm-text-muted)}.me-form-section{margin:12px 0 2px;padding-top:10px;border-top:1px solid var(--dm-border-light, rgba(0,0,0,.15));font-size:.78em;text-transform:uppercase;letter-spacing:.06em;color:var(--dm-text-muted)}.me-item-form .me-form-section:first-child{margin-top:0;padding-top:0;border-top:0}.me-item-form .me-colour-hex{width:48px;height:32px;padding:2px}.me-item-form .me-field-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}.me-item-form .me-field-grid .form-field{margin:0}.me-item-form .me-icon-field{display:flex;align-items:center;gap:8px}.me-item-form .me-icon-field .form-input{flex:1}.me-item-form .me-icon-preview{width:24px;height:24px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;color:var(--dm-text-muted)}#admin-sidebar.dm-menu-floating{border:1px solid var(--dm-border);border-radius:var(--dm-radius-md, 8px);box-shadow:var(--dm-shadow-lg);overflow:hidden}@media(max-width:768px){#admin-sidebar.dm-menu-floating{position:static!important;inset:auto!important;max-height:none!important;transform:none!important}.dashboard-wrapper{padding-left:0!important;padding-right:0!important}}[data-logic-section]{border:1px solid var(--dm-border);border-radius:var(--dm-radius-md, 6px);padding:.9rem 1rem 1rem;margin-bottom:1rem;background:color-mix(in srgb,var(--dm-text) 3%,transparent)}[data-logic-section] .fb-logic-cond-row,[data-logic-section] .fb-logic-val-rule{padding:.55rem .65rem;border-radius:var(--dm-radius-sm, 4px);border:1px solid var(--dm-border);background:var(--dm-surface, transparent)}[data-logic-section] .fb-logic-cond-row:last-of-type,[data-logic-section] .fb-logic-val-rule:last-of-type{margin-bottom:.75rem}[data-logic-section]>.btn{margin-top:.15rem}[data-logic-section] textarea{min-height:5rem}.project-filter-notice{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap;margin:0 0 1rem;padding:.6rem .85rem;border:1px solid var(--dm-border);border-left:3px solid var(--dm-info, var(--dm-primary));border-radius:var(--dm-radius-md, 6px);background:color-mix(in srgb,var(--dm-info, var(--dm-primary)) 6%,transparent);font-size:.85rem;color:var(--dm-text-muted)}.project-filter-notice a{color:var(--dm-primary);font-weight:600}.ctx-help{display:inline-flex;align-items:center;justify-content:center;width:1.05rem;height:1.05rem;margin-left:.35rem;padding:0;border:1px solid var(--dm-border-dark, var(--dm-border));border-radius:var(--dm-radius-full, 9999px);background:transparent;color:var(--dm-text-muted);font-size:.68rem;font-weight:700;line-height:1;cursor:pointer;vertical-align:middle;flex-shrink:0}.ctx-help:hover,.ctx-help:focus-visible{border-color:var(--dm-primary);color:var(--dm-primary);outline:none}.card-header h3 .ctx-help{align-self:center}.ctx-preview-card{position:sticky;top:1rem}@media(max-width:1100px){.ctx-workspace>.col-8,.ctx-workspace>.col-4{flex:0 0 auto;width:100%}.ctx-preview-card{position:static}}.dm-plugin-shell{border:1px solid var(--dm-border);border-radius:var(--dm-radius-lg, 12px);background:var(--dm-surface);overflow:hidden}.dm-plugin-banner{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;padding:.7rem 1rem;background:var(--dm-background-alt);border-bottom:1px solid var(--dm-border)}.dm-plugin-banner-identity{display:flex;align-items:center;gap:.55rem;min-width:0;margin-right:auto}.dm-plugin-banner-actions{display:flex;align-items:center;gap:.25rem;flex:0 0 auto;margin-right:.15rem;padding-right:.4rem;border-right:1px solid var(--dm-border)}.dm-plugin-banner-action{padding:.25rem .4rem;line-height:1;color:var(--dm-text-muted)}.dm-plugin-banner-action:hover{color:var(--dm-primary)}.dm-plugin-banner-icon{display:inline-flex;align-items:center;color:var(--dm-primary);flex:0 0 auto}.dm-plugin-banner-name{margin:0;font-size:1.05rem;font-weight:600;letter-spacing:.01em;color:var(--dm-text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dm-activity{display:inline-flex;align-items:center;flex:0 0 auto;margin-left:.35rem}.dm-activity domma-loader{display:inline-block;line-height:0}.dm-activity[hidden]{display:none!important}#admin-topbar>.dm-activity{margin:0 .75rem 0 0}.dm-plugin-banner-parent{font-weight:500;color:var(--dm-text-muted)}.dm-plugin-banner-sep{margin:0 .4rem;color:var(--dm-text-muted)}.dm-plugin-banner-facts{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap}.dm-plugin-fact{font-size:.72rem;line-height:1.6;padding:1px 8px;border-radius:999px;border:1px solid var(--dm-border);color:var(--dm-text-muted);background:var(--dm-surface);white-space:nowrap}.dm-plugin-fact--version{font-variant-numeric:tabular-nums;color:var(--dm-text)}.dm-plugin-fact--licence.is-included{color:var(--dm-info);border-color:var(--dm-info)}.dm-plugin-fact--licence.is-licensed{color:var(--dm-success);border-color:var(--dm-success)}.dm-plugin-fact--expiry{font-variant-numeric:tabular-nums}.dm-plugin-fact--expiry.is-warning{color:var(--dm-warning);border-color:var(--dm-warning)}.dm-plugin-fact--expiry.is-danger{color:var(--dm-danger);border-color:var(--dm-danger)}.dm-plugin-body{padding:1rem}.dm-plugin-body .card.dm-plugin-unwrap{border:0;background:none;box-shadow:none;margin:0}.dm-plugin-body .card.dm-plugin-unwrap>.card-body{padding:0}.dm-plugin-body>.p-4{padding:0}@media(max-width:640px){.dm-plugin-banner{align-items:flex-start;flex-direction:column;gap:.5rem}.dm-plugin-body{padding:.75rem}}.analytics-filter{max-width:240px}.dm-help-btn{display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;margin-left:.3rem;padding:0;border:0;background:none;line-height:1;color:var(--dm-text-muted);opacity:.75;cursor:pointer}.dm-help-btn:hover,.dm-help-btn:focus-visible{color:var(--dm-primary);opacity:1}.dm-help-pop{position:fixed;z-index:10050;max-width:300px;padding:.6rem .75rem;background:var(--dm-surface, var(--dm-background));color:var(--dm-text);border:1px solid var(--dm-border);border-radius:var(--dm-radius-md);box-shadow:0 8px 24px #00000040;font-size:.85rem;line-height:1.45;text-align:left;font-weight:400}.dm-help-pop strong{display:block;margin-bottom:.2rem;font-weight:600}.dm-help-pop p{margin:0}.dm-admin-sidebar .sidebar-badge[data-badge-label]{cursor:help}.dm-admin-sidebar .sidebar-badge--danger,.dm-admin-sidebar .sidebar-link.active .sidebar-badge--danger{background:var(--dm-danger, #dc2626);color:#fff}.dm-admin-sidebar .sidebar-badge--live{background:color-mix(in srgb,var(--dm-success, #16a34a) 20%,transparent);color:var(--dm-success, #16a34a)}#admin-sidebar .sidebar-badge--live{padding-left:1.05rem!important}#admin-sidebar summary>.sidebar-badge--sum{position:static!important;transform:none!important;margin-left:auto!important;margin-right:.45rem;text-transform:none;letter-spacing:0}#admin-sidebar summary:has(>.sidebar-badge--sum):after{margin-left:0}#admin-sidebar details[open]>summary>.sidebar-badge--sum{display:none}.dm-admin-sidebar .sidebar-badge--live:before{content:"";position:absolute;left:.4rem;top:50%;width:.4rem;height:.4rem;margin-top:-.2rem;border-radius:50%;background:currentColor;animation:dm-badge-pulse 2s ease-in-out infinite}@keyframes dm-badge-pulse{50%{opacity:.35}}@media(prefers-reduced-motion:reduce){.dm-admin-sidebar .sidebar-badge--live:before{animation:none}}.dm-badge-pop{width:290px;max-width:calc(100vw - 16px);font-size:.8rem;pointer-events:none}.dm-badge-pop-title{display:block;font-size:.85rem}.dm-badge-pop-sub{margin:.1rem 0 .5rem;color:var(--dm-text-muted)}.dm-badge-pop-rows{display:grid;grid-template-columns:1fr auto;gap:.2rem .75rem;margin:0 0 .5rem;padding:.45rem 0;border-top:1px solid var(--dm-border);border-bottom:1px solid var(--dm-border)}.dm-badge-pop-rows dt{color:var(--dm-text-muted)}.dm-badge-pop-rows dd{margin:0;text-align:right;font-weight:600;font-variant-numeric:tabular-nums}.dm-badge-pop-items{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.4rem}.dm-badge-pop-items li{display:flex;flex-direction:column;min-width:0}.dm-badge-pop-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dm-badge-pop-meta{font-size:.72rem;color:var(--dm-text-muted)}.dm-badge-pop .is-danger,.dm-badge-pop li.is-danger .dm-badge-pop-meta{color:var(--dm-danger, #dc2626)}.dm-badge-pop-empty{margin:0;color:var(--dm-text-muted)}.dm-plugin-body,.dm-slideover{font-family:var(--dm-font-sans, inherit)}.dm-plugin-body :is(button,input,select,textarea,.btn,.form-input,.form-select,.form-textarea),.dm-slideover :is(button,input,select,textarea,.btn,.form-input,.form-select,.form-textarea){font-family:inherit}.dm-plugin-body :is(input,select,textarea,.form-input,.form-select,.form-textarea):not(.form-input-lg),.dm-slideover :is(input,select,textarea,.form-input,.form-select,.form-textarea):not(.form-input-lg){font-size:var(--dm-text-sm)}.dm-plugin-body .form-input-lg{font-size:var(--dm-text-base)}.dm-plugin-body :is(.font-mono,code,pre,kbd),.dm-slideover :is(.font-mono,code,pre,kbd){font-family:var(--dm-font-mono, monospace)}.dm-plugin-body .form-label,.dm-slideover .form-label{font-size:var(--dm-text-sm)}.related-box{display:flex;flex-direction:column;gap:.6rem;border-top:1px solid var(--dm-border);padding-top:.75rem}.related-box[hidden]{display:none}.related-head{display:flex;align-items:center;gap:.4rem}.related-head strong{flex:1}.related-list{list-style:none;margin:.3rem 0 0;padding:0;display:flex;flex-direction:column;gap:.25rem}.related-list li{display:flex;flex-direction:column}.related-list li.is-past{opacity:.7}.related-meta,.related-note,.related-loading{color:var(--dm-text-muted);font-size:var(--dm-text-xs);margin:0}.login-challenge{display:flex;flex-direction:column;gap:.6rem;margin-bottom:.75rem}.login-challenge #challenge-code{font-size:1.25rem;letter-spacing:.2em;text-align:center}.login-trust{display:flex;align-items:center;gap:.45rem;font-size:.875rem}.login-enrol{display:flex;flex-direction:column;align-items:center;gap:.6rem;margin-bottom:1rem}.login-enrol img{background:#fff;padding:.5rem;border-radius:.5rem}.login-secret{display:flex;flex-direction:column;align-items:center;gap:.25rem;text-align:center}.login-secret code{font-size:.95rem;letter-spacing:.08em;word-break:break-all}.usx-secret{display:flex;flex-direction:column;gap:.75rem;padding:1rem}.usx-secret-link{display:block;padding:.6rem .75rem;border:1px solid var(--dm-border);border-radius:var(--dm-radius-sm);background:var(--dm-background-alt);word-break:break-all;font-size:.8rem;user-select:all}.usx-secret-actions{display:flex;align-items:center;justify-content:flex-end;gap:.5rem}.usx-secret-actions .btn{display:inline-flex;align-items:center;gap:.35rem}.usx-secret-note{margin-right:auto;color:var(--dm-success)}.usx-secret-foot{color:var(--dm-text-muted);font-size:.8rem;margin:0}.uex-reset{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem .5rem;margin-top:.5rem}.uex-reset>small:first-child{flex-basis:100%;color:var(--dm-text-muted)}.uex-reset .btn{display:inline-flex;align-items:center;gap:.35rem}.uex-reset-open{flex-basis:100%;color:var(--dm-info)}
@@ -1 +1 @@
1
- import{applyDrop as d,isWithin as l}from"./menu-tree.js";import{isStructural as c}from"./menu-editor-arrange.js";const p={before:"above",after:"below",into:"into"};export function dropRow(o,r,u,f){const i=f==="after"?o.find(t=>t.parentId===u):null,n=i?i.id!==r&&d(o,r,i.id,"above"):d(o,r,u,p[f]);if(n){const t=o.find(e=>e.id===r);t&&(t.touched=!0)}return n}export function sortableMenuRows(o,r,u,{items:f,handle:i=null}){return typeof E.sortable!="function"?null:E.sortable(o,{items:f,handle:i,nest:!0,accepts(n,t,e){const s=r();return!(l(s,t.dataset.id,n.dataset.id)||e==="into"&&c(s.find(a=>a.id===t.dataset.id)))},onDrop({key:n,targetKey:t,zone:e}){return dropRow(r(),n,t,e)?(u(),!0):!1}})}
1
+ import{applyDrop as s,isWithin as d}from"./menu-tree.js";import{isStructural as p}from"./menu-editor-arrange.js";const c={before:"above",after:"below",into:"into"};export function dropRow(t,r,u,a){const o=a==="after"?t.find(e=>e.parentId===u):null,n=o?o.id!==r&&s(t,r,o.id,"above"):s(t,r,u,c[a]);if(n){const e=t.find(i=>i.id===r);e&&(e.touched=!0)}return n}export function sortableMenuRows(t,r,u,{items:a,handle:o=null}){return typeof E.sortable!="function"?null:E.sortable(t,{items:a,handle:o,nest:!0,accepts(n,e,i){const f=r();return!(d(f,e.dataset.id,n.dataset.id)||i==="into"&&p(f.find(l=>l.id===e.dataset.id)))},onDrop({key:n,targetKey:e,zone:i}){return dropRow(r(),n,e,i)?(u(),!0):!1}})}export function rowPlaceKeeper(){let t=null;return{start({item:r}){t={parent:r.parentNode,next:r.nextSibling}},restore(r){t&&(t.parent.insertBefore(r,t.next?.parentNode===t.parent?t.next:null),t=null)}}}
@@ -196,9 +196,10 @@
196
196
  .cex-row:last-child { border-bottom: 0; }
197
197
  .cex-row:hover, .cex-row:focus-visible { background: var(--dm-table-hover-bg, color-mix(in srgb, var(--dm-text) 6%, transparent)); outline: none; }
198
198
  .cex-row.is-bad { box-shadow: inset 3px 0 0 var(--dm-danger); }
199
- .cex-row.is-drag-over { box-shadow: inset 0 2px 0 var(--dm-primary); }
200
- .cex-row.is-dragging { opacity: .45; }
201
- .cex-grip { cursor: grab; color: var(--dm-text-muted); user-select: none; padding: 0 .15rem; }
199
+ /* Six dots drawn in CSS: the row template is a data-each template, so an icon
200
+ span would need scanning on every redraw. The whole row drags (E.sortable). */
201
+ .cex-grip { flex: none; width: 8px; height: 14px; margin: 0 .2rem; color: var(--dm-text-muted); cursor: grab;
202
+ background: radial-gradient(circle, currentColor 1.4px, transparent 1.6px) 0 0 / 4px 4.67px repeat; opacity: .8; }
202
203
  .cex-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
203
204
  .cex-main strong, .cex-main small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
204
205
  .cex-main small { color: var(--dm-text-muted); font-size: var(--dm-text-xs); }
@@ -242,6 +242,9 @@ p.cmx-err { margin: 0; }
242
242
  .cmx-list { display: flex; flex-direction: column; }
243
243
  .cmx-row { display: flex; align-items: center; gap: .6rem; padding: .5rem .35rem; border-bottom: 1px solid var(--dm-border); cursor: pointer; }
244
244
  .cmx-row:last-child { border-bottom: 0; }
245
+ /* Six dots drawn in CSS (the row is a data-each template). The whole row drags (E.sortable). */
246
+ .cmx-grip { flex: none; width: 8px; height: 14px; margin: 0 .1rem; color: var(--dm-text-muted); cursor: grab;
247
+ background: radial-gradient(circle, currentColor 1.4px, transparent 1.6px) 0 0 / 4px 4.67px repeat; opacity: .8; }
245
248
  .cmx-row:hover, .cmx-row:focus-visible { background: var(--dm-table-hover-bg, color-mix(in srgb, var(--dm-text) 6%, transparent)); outline: none; }
246
249
  .cmx-row.is-divider .cmx-main strong { color: var(--dm-text-muted); letter-spacing: .1em; font-weight: 400; }
247
250
  .cmx-row.is-header .cmx-main strong { text-transform: uppercase; font-size: var(--dm-text-xs); letter-spacing: .05em; color: var(--dm-text-muted); }
@@ -1,11 +1,11 @@
1
- import{api as g}from"../api.js";import{addBannerAction as ue}from"../lib/plugin-chrome.js";import{helpPopovers as Fe}from"../lib/help-popover.js";import{onceClosed as st,openMenuAt as Le}from"../lib/tool-kit.js";import{FIELD_TYPES as it,OPERATIONS as rt,OPTION_TYPES as ct,accessOptions as dt,checkForm as ut,draftOf as pt,duplicateField as ft,errorCount as K,fieldFromPanel as De,fieldProblem as mt,fieldRow as vt,formFromCollection as Ne,formFromDraft as ht,moveField as Te,nameFromLabel as bt,newField as gt,panelForm as yt,payloadFromForm as wt,roleLadder as xt,slugify as Z,snapshot as U,storageChange as qe}from"../lib/collection-editor-arrange.js";import{fmtDateTime as kt}from"../lib/dates.js";const Et=/^\/collections\/(new|edit\/[^/?#]+)\/?(\?.*)?$/,St=s=>`collection-editor.draft.${s||"new"}`,Mt=`
2
- <div class="cex-row" data-key="{{key}}" tabindex="0" draggable="true" data-bind-class="rowCls">
3
- <span class="cex-grip" title="Drag to reorder" aria-hidden="true">\u283F</span>
1
+ import{api as g}from"../api.js";import{addBannerAction as de}from"../lib/plugin-chrome.js";import{helpPopovers as Ae}from"../lib/help-popover.js";import{onceClosed as lt,openMenuAt as Fe}from"../lib/tool-kit.js";import{FIELD_TYPES as st,OPERATIONS as it,OPTION_TYPES as rt,accessOptions as ct,checkForm as dt,draftOf as ut,duplicateField as pt,errorCount as B,fieldFromPanel as Ne,fieldProblem as ft,fieldRow as mt,formFromCollection as De,formFromDraft as vt,moveField as Le,nameFromLabel as ht,newField as bt,panelForm as gt,payloadFromForm as yt,roleLadder as wt,slugify as X,snapshot as _,storageChange as Te}from"../lib/collection-editor-arrange.js";import{fmtDateTime as xt}from"../lib/dates.js";import{rowPlaceKeeper as kt}from"../lib/menu-drag.js";const Et=/^\/collections\/(new|edit\/[^/?#]+)\/?(\?.*)?$/,St=s=>`collection-editor.draft.${s||"new"}`,Mt=`
2
+ <div class="cex-row" data-key="{{key}}" tabindex="0" data-bind-class="rowCls">
3
+ <span class="cex-grip" title="Drag to reorder" aria-hidden="true"></span>
4
4
  <span class="cex-main"><strong data-bind-text="label"></strong><small data-bind-text="meta"></small><small class="cex-problem" data-bind-hidden="!problem" data-bind-text="problem"></small></span>
5
5
  <span class="cex-chip is-ok" data-bind-hidden="!required">Required</span>
6
6
  <span class="cex-chip" data-bind-hidden="!hidden">Hidden</span>
7
7
  <button type="button" class="cex-kebab" aria-label="Actions for this field" title="Actions">\u22EE</button>
8
- </div>`,ee=s=>String(s??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");function $t(s){const c=document.createElement("template");return c.innerHTML=s.trim(),c.content.firstElementChild}function Pe(s,c){const i=s.querySelector(".dm-plugin-banner-name");if(!i)return;const C=document.createElement("span");C.className="dm-plugin-banner-parent",C.textContent="Collections";const w=document.createElement("span");w.className="dm-plugin-banner-sep",w.setAttribute("aria-hidden","true"),w.textContent="\u203A",i.replaceChildren(C,w,document.createTextNode(c))}let y=null,Ie=!1;const te=s=>String(s||"").split("?")[0];function Ct(){Ie||!window.R?.use||(Ie=!0,R.use((s,c,i)=>{if(!(y&&Et.test(c?.path||"")&&te(s?.path)!==te(c?.path))||!y.dirty())return i();const w=`#${c.path}`;return E.confirm("This collection has unsaved changes. Leave anyway? They are kept as a draft for your next visit.").then(r=>{r?i():history.replaceState(null,"",w)})}),M.subscribe("router:afterChange",({to:s}={})=>{if(y&&te(s?.path)!==y.path){const c=y;y=null,c.dispose()}}))}export const collectionEditorView={templateUrl:"/admin/js/templates/collection-editor.html",async onMount(s){if(Ct(),y){const e=y;y=null,e.dispose()}const c=s.get(0),i=c.querySelector(".cex")||c,C=te(location.hash.replace(/^#/,""))||"/collections/new",w=C.match(/^\/collections\/edit\/([^/?#]+)/),r=w?decodeURIComponent(w[1]):null,q=!r,pe=[],b=e=>(pe.push(e),e);let fe=!1;const ne=()=>!fe&&i.isConnected,me=E.loader(c,{type:"dots"});let O=null,oe=[],P=null,ve=[],u=0,B=[];try{[O,oe,P,ve,B]=await Promise.all([r?g.collections.get(r):Promise.resolve(null),g.projects.list().catch(()=>[]),g.collections.proStatus().catch(()=>null),q?g.collections.list().then(e=>(e||[]).map(t=>t.slug)).catch(()=>[]):Promise.resolve([]),g.collections.listEntries("roles",{limit:1e3}).then(xt).catch(()=>[])]),r&&(u=(await g.collections.listEntries(r,{limit:1}).catch(()=>null))?.total??0)}catch(e){me.destroy(),E.toast(e?.status===404?"Collection not found.":`Could not load the collection: ${e.message||e}`,{type:"error"}),R.navigate("/collections");return}if(me.destroy(),!i.isConnected)return;if(r&&!O){E.toast("Collection not found.",{type:"error"}),R.navigate("/collections");return}const he=new URLSearchParams(location.hash.split("?")[1]||"").get("project")||"",f=Ne(O,{project:he,defaultRole:B.at(-1)?.name||""}),x=Object.fromEntries(f.fields.map(e=>[e._key,e.name])),Be=O?.meta||{};let H=f.storageAdapter;const _e=new Set(["public","token",...B.map(e=>e.name)]),be=(e,t)=>{if(!B.length)return"";const o=[...new Set(e.filter(a=>a&&!_e.has(a)))];return o.length?`Not a role on this site: ${o.join(", ")}. Until you pick another, ${t}.`:""},n={};for(const[e,t]of Object.entries(f))n[e]=M.observable(t);const k=M.observable(q),W=M.observable(!1),Y=()=>Object.fromEntries(Object.keys(n).map(e=>[e,n[e].peek()])),ge=()=>Object.fromEntries(Object.keys(n).map(e=>[e,n[e].value])),L=M.observable(U(f)),_=M.computed(()=>U(ge())!==L.value);let z=!q;b(M.effect(()=>{const e=n.title.value;z||(n.slug.value=Z(e))}));const m=M.computed(()=>ut(ge(),{isNew:k.value,taken:ve,original:x})),ye=M.observable([]);b(M.effect(()=>{const e=m.value.fields||{},t=n.layout.value==="grid";ye.value=n.fields.value.map(o=>vt(o,e,{grid:t}))}));const Ke=M.computed(()=>new Set(n.fields.value.map(e=>e.name))),Ue={...n,isNew:k,saving:W,dirty:_,rows:ye,errTitle:M.computed(()=>m.value.title||""),errSlug:M.computed(()=>m.value.slug||""),errColumns:M.computed(()=>m.value.columns||""),errExport:M.computed(()=>m.value.export||""),problemCount:M.computed(()=>K(m.value)),problemText:M.computed(()=>{const e=K(m.value);return e?`${e} thing${e===1?"":"s"} to fix before it can be saved`:""}),settingsBad:M.computed(()=>!!(m.value.title||m.value.slug||m.value.columns)),fieldsBad:M.computed(()=>!!m.value.fields),exportBad:M.computed(()=>!!m.value.export),fieldCount:M.computed(()=>n.fields.value.length),slugHint:M.computed(()=>k.value?`Will be created as "${Z(n.slug.value||n.title.value)||"\u2026"}".`:"Cannot be changed once the collection exists."),apiPath:M.computed(()=>`/api/collections/${Z(n.slug.value||n.title.value)||"<slug>"}/public`),unknownReadFields:M.computed(()=>{const e=String(n.readFields.value||"").split(",").map(t=>t.trim()).filter(t=>t&&!Ke.value.has(t));return e.length?`Not a field of this collection: ${e.join(", ")}`:""}),missingApiRoles:M.computed(()=>be(rt.filter(e=>n[`${e}Enabled`].value).map(e=>n[`${e}Access`].value),"only the level-0 role passes")),missingExportRole:M.computed(()=>be(n.exportEnabled.value?[n.exportAccess.value]:[],"only the level-0 role is offered export")),showStorage:M.observable(!!P?.pro&&r!=="roles"),storageNote:M.computed(()=>{const e=qe(H,n.storageAdapter.value);return!e||k.value?"":u?`Switching ${e}: Save asks whether to move the ${u} existing ${u===1?"entry":"entries"} across. Export them first if they matter.`:`Switching ${e}. There are no entries to move.`})},we=i.querySelector("#collection-project");for(const e of oe){const t=document.createElement("option");t.value=e.slug,t.textContent=e.name||e.slug,we.appendChild(t)}if(f.project&&!oe.some(e=>e.slug===f.project)){const e=document.createElement("option");e.value=f.project,e.textContent=`${f.project} (not found)`,we.appendChild(e)}const He=[...i.querySelectorAll('.cex-op select[data-model$="Access.value"]')],xe=e=>{for(const t of He){const o=t.getAttribute("data-model").split(".")[0],a=e[o];t.replaceChildren(...dt(B,a,{token:t.id!=="export-access"}).map(d=>new Option(d.label,d.value))),t.value=a}};xe(f);const We=i.querySelector("#storage-connection"),Ye=Array.isArray(P?.connections)&&P.connections.length?P.connections:["default"];for(const e of new Set([...Ye,f.storageConnection])){const t=document.createElement("option");t.value=e,t.textContent=e,We.appendChild(t)}const D=e=>n.fields.peek().findIndex(t=>t._key===e),j=e=>{n.fields.value=e};function G(e,t){const o=D(e);o<0||(j(Te(n.fields.peek(),o,o+t)),requestAnimationFrame(()=>i.querySelector(`.cex-row[data-key="${e}"]`)?.focus()))}async function ae(e){const t=D(e);if(t<0)return;const o=n.fields.peek()[t];!k.peek()&&u&&x[e]&&!await E.confirm(`Remove the field "${ee(o.label||o.name)}"? The ${u} existing ${u===1?"entry keeps its":"entries keep their"} value for it, but it is no longer shown or edited. Nothing is lost until you Save - Discard puts it back.`)||j(n.fields.peek().filter(a=>a._key!==e))}function V(e,{isAdded:t=!1}={}){const o=D(e);if(o<0)return;const a=n.fields.peek()[o],d=yt(a),v={};for(const[l,$]of Object.entries(d))v[l]=M.observable($);const p=JSON.stringify(d),Q=()=>Object.fromEntries(Object.keys(v).map(l=>[l,v[l].peek()])),Ce=()=>JSON.stringify(Q())!==p;let Oe=!!a.name;const Ze=M.effect(()=>{const l=v.label.value;Oe||(v.name.value=bt(l))}),et=new Set(n.fields.peek().filter(l=>l._key!==e).map(l=>l.name)),je=M.computed(()=>{const l=De(a,Object.fromEntries(Object.keys(v).map($=>[$,v[$].value])));return l.name&&et.has(l.name)?`"${l.name}" is used by another field.`:mt(l,x[e])}),tt=M.computed(()=>!k.peek()&&u&&x[e]&&v.name.value.trim()!==x[e]?`Entries keep their value under "${x[e]}" - renaming the field does not move it.`:""),nt={...v,problem:je,renamed:tt,isOptions:M.computed(()=>ct.has(v.type.value)),isGrid:M.computed(()=>n.layout.value==="grid")},h=E.slideover({title:t?"New field":`Field: ${ee(a.label||a.name||"Untitled")}`,size:"md",position:"right"}),F=$t(`
8
+ </div>`,Z=s=>String(s??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");function $t(s){const d=document.createElement("template");return d.innerHTML=s.trim(),d.content.firstElementChild}function Pe(s,d){const i=s.querySelector(".dm-plugin-banner-name");if(!i)return;const C=document.createElement("span");C.className="dm-plugin-banner-parent",C.textContent="Collections";const w=document.createElement("span");w.className="dm-plugin-banner-sep",w.setAttribute("aria-hidden","true"),w.textContent="\u203A",i.replaceChildren(C,w,document.createTextNode(d))}let y=null,qe=!1;const ee=s=>String(s||"").split("?")[0];function Ct(){qe||!window.R?.use||(qe=!0,R.use((s,d,i)=>{if(!(y&&Et.test(d?.path||"")&&ee(s?.path)!==ee(d?.path))||!y.dirty())return i();const w=`#${d.path}`;return E.confirm("This collection has unsaved changes. Leave anyway? They are kept as a draft for your next visit.").then(c=>{c?i():history.replaceState(null,"",w)})}),M.subscribe("router:afterChange",({to:s}={})=>{if(y&&ee(s?.path)!==y.path){const d=y;y=null,d.dispose()}}))}export const collectionEditorView={templateUrl:"/admin/js/templates/collection-editor.html",async onMount(s){if(Ct(),y){const e=y;y=null,e.dispose()}const d=s.get(0),i=d.querySelector(".cex")||d,C=ee(location.hash.replace(/^#/,""))||"/collections/new",w=C.match(/^\/collections\/edit\/([^/?#]+)/),c=w?decodeURIComponent(w[1]):null,D=!c,ue=[],h=e=>(ue.push(e),e);let pe=!1;const te=()=>!pe&&i.isConnected,fe=E.loader(d,{type:"dots"});let O=null,ne=[],L=null,me=[],u=0,T=[];try{[O,ne,L,me,T]=await Promise.all([c?g.collections.get(c):Promise.resolve(null),g.projects.list().catch(()=>[]),g.collections.proStatus().catch(()=>null),D?g.collections.list().then(e=>(e||[]).map(t=>t.slug)).catch(()=>[]):Promise.resolve([]),g.collections.listEntries("roles",{limit:1e3}).then(wt).catch(()=>[])]),c&&(u=(await g.collections.listEntries(c,{limit:1}).catch(()=>null))?.total??0)}catch(e){fe.destroy(),E.toast(e?.status===404?"Collection not found.":`Could not load the collection: ${e.message||e}`,{type:"error"}),R.navigate("/collections");return}if(fe.destroy(),!i.isConnected)return;if(c&&!O){E.toast("Collection not found.",{type:"error"}),R.navigate("/collections");return}const ve=new URLSearchParams(location.hash.split("?")[1]||"").get("project")||"",f=De(O,{project:ve,defaultRole:T.at(-1)?.name||""}),x=Object.fromEntries(f.fields.map(e=>[e._key,e.name])),Ie=O?.meta||{};let K=f.storageAdapter;const Be=new Set(["public","token",...T.map(e=>e.name)]),he=(e,t)=>{if(!T.length)return"";const o=[...new Set(e.filter(a=>a&&!Be.has(a)))];return o.length?`Not a role on this site: ${o.join(", ")}. Until you pick another, ${t}.`:""},n={};for(const[e,t]of Object.entries(f))n[e]=M.observable(t);const k=M.observable(D),U=M.observable(!1),H=()=>Object.fromEntries(Object.keys(n).map(e=>[e,n[e].peek()])),be=()=>Object.fromEntries(Object.keys(n).map(e=>[e,n[e].value])),N=M.observable(_(f)),P=M.computed(()=>_(be())!==N.value);let W=!D;h(M.effect(()=>{const e=n.title.value;W||(n.slug.value=X(e))}));const m=M.computed(()=>dt(be(),{isNew:k.value,taken:me,original:x})),ge=M.observable([]);h(M.effect(()=>{const e=m.value.fields||{},t=n.layout.value==="grid";ge.value=n.fields.value.map(o=>mt(o,e,{grid:t}))}));const _e=M.computed(()=>new Set(n.fields.value.map(e=>e.name))),Ke={...n,isNew:k,saving:U,dirty:P,rows:ge,errTitle:M.computed(()=>m.value.title||""),errSlug:M.computed(()=>m.value.slug||""),errColumns:M.computed(()=>m.value.columns||""),errExport:M.computed(()=>m.value.export||""),problemCount:M.computed(()=>B(m.value)),problemText:M.computed(()=>{const e=B(m.value);return e?`${e} thing${e===1?"":"s"} to fix before it can be saved`:""}),settingsBad:M.computed(()=>!!(m.value.title||m.value.slug||m.value.columns)),fieldsBad:M.computed(()=>!!m.value.fields),exportBad:M.computed(()=>!!m.value.export),fieldCount:M.computed(()=>n.fields.value.length),slugHint:M.computed(()=>k.value?`Will be created as "${X(n.slug.value||n.title.value)||"\u2026"}".`:"Cannot be changed once the collection exists."),apiPath:M.computed(()=>`/api/collections/${X(n.slug.value||n.title.value)||"<slug>"}/public`),unknownReadFields:M.computed(()=>{const e=String(n.readFields.value||"").split(",").map(t=>t.trim()).filter(t=>t&&!_e.value.has(t));return e.length?`Not a field of this collection: ${e.join(", ")}`:""}),missingApiRoles:M.computed(()=>he(it.filter(e=>n[`${e}Enabled`].value).map(e=>n[`${e}Access`].value),"only the level-0 role passes")),missingExportRole:M.computed(()=>he(n.exportEnabled.value?[n.exportAccess.value]:[],"only the level-0 role is offered export")),showStorage:M.observable(!!L?.pro&&c!=="roles"),storageNote:M.computed(()=>{const e=Te(K,n.storageAdapter.value);return!e||k.value?"":u?`Switching ${e}: Save asks whether to move the ${u} existing ${u===1?"entry":"entries"} across. Export them first if they matter.`:`Switching ${e}. There are no entries to move.`})},ye=i.querySelector("#collection-project");for(const e of ne){const t=document.createElement("option");t.value=e.slug,t.textContent=e.name||e.slug,ye.appendChild(t)}if(f.project&&!ne.some(e=>e.slug===f.project)){const e=document.createElement("option");e.value=f.project,e.textContent=`${f.project} (not found)`,ye.appendChild(e)}const Ue=[...i.querySelectorAll('.cex-op select[data-model$="Access.value"]')],we=e=>{for(const t of Ue){const o=t.getAttribute("data-model").split(".")[0],a=e[o];t.replaceChildren(...ct(T,a,{token:t.id!=="export-access"}).map(r=>new Option(r.label,r.value))),t.value=a}};we(f);const He=i.querySelector("#storage-connection"),We=Array.isArray(L?.connections)&&L.connections.length?L.connections:["default"];for(const e of new Set([...We,f.storageConnection])){const t=document.createElement("option");t.value=e,t.textContent=e,He.appendChild(t)}const Y=e=>n.fields.peek().findIndex(t=>t._key===e),j=e=>{n.fields.value=e};function z(e,t){const o=Y(e);o<0||(j(Le(n.fields.peek(),o,o+t)),requestAnimationFrame(()=>i.querySelector(`.cex-row[data-key="${e}"]`)?.focus()))}async function oe(e){const t=Y(e);if(t<0)return;const o=n.fields.peek()[t];!k.peek()&&u&&x[e]&&!await E.confirm(`Remove the field "${Z(o.label||o.name)}"? The ${u} existing ${u===1?"entry keeps its":"entries keep their"} value for it, but it is no longer shown or edited. Nothing is lost until you Save - Discard puts it back.`)||j(n.fields.peek().filter(a=>a._key!==e))}function G(e,{isAdded:t=!1}={}){const o=Y(e);if(o<0)return;const a=n.fields.peek()[o],r=gt(a),v={};for(const[l,$]of Object.entries(r))v[l]=M.observable($);const p=JSON.stringify(r),J=()=>Object.fromEntries(Object.keys(v).map(l=>[l,v[l].peek()])),$e=()=>JSON.stringify(J())!==p;let Ce=!!a.name;const Xe=M.effect(()=>{const l=v.label.value;Ce||(v.name.value=ht(l))}),Ze=new Set(n.fields.peek().filter(l=>l._key!==e).map(l=>l.name)),Oe=M.computed(()=>{const l=Ne(a,Object.fromEntries(Object.keys(v).map($=>[$,v[$].value])));return l.name&&Ze.has(l.name)?`"${l.name}" is used by another field.`:ft(l,x[e])}),et=M.computed(()=>!k.peek()&&u&&x[e]&&v.name.value.trim()!==x[e]?`Entries keep their value under "${x[e]}" - renaming the field does not move it.`:""),tt={...v,problem:Oe,renamed:et,isOptions:M.computed(()=>rt.has(v.type.value)),isGrid:M.computed(()=>n.layout.value==="grid")},b=E.slideover({title:t?"New field":`Field: ${Z(a.label||a.name||"Untitled")}`,size:"md",position:"right"}),F=$t(`
9
9
  <div class="cex-panel">
10
10
  <div class="cex-grid">
11
11
  <div>
@@ -20,7 +20,7 @@ import{api as g}from"../api.js";import{addBannerAction as ue}from"../lib/plugin-
20
20
  <div>
21
21
  <label class="form-label" for="cex-f-type">Type</label>
22
22
  <select id="cex-f-type" class="form-input" data-model="type.value">
23
- ${it.map(l=>`<option value="${l.value}">${l.label}</option>`).join("")}
23
+ ${st.map(l=>`<option value="${l.value}">${l.label}</option>`).join("")}
24
24
  </select>
25
25
  </div>
26
26
  <div class="cex-setting">
@@ -61,4 +61,4 @@ import{api as g}from"../api.js";import{addBannerAction as ue}from"../lib/plugin-
61
61
  <button type="button" class="btn btn-sm btn-ghost" data-on-click="cancel">Cancel</button>
62
62
  <button type="button" class="btn btn-sm btn-primary" data-on-click="done" data-bind-disabled="problem.value"><span data-icon="check" data-icon-size="13"></span> Done</button>
63
63
  </div>
64
- </div>`);let X=!1,ce=!1;const ot=h.close.bind(h);function Ae(){if(je.peek())return;const l=De(a,Q());j(n.fields.peek().map($=>$._key===e?l:$)),X=!0,h.close()}h.element.appendChild(F);const at=Fe(F),lt=M.applyBindings(nt,F,{methods:{done:Ae,cancel:()=>h.close(),remove:async()=>{X=!0,h.close(),await ae(e)}}}),Re=F.querySelector("#cex-f-name");Re.addEventListener("input",()=>{Oe=!!Re.value}),F.addEventListener("keydown",l=>{(l.ctrlKey||l.metaKey)&&l.key==="Enter"&&(l.preventDefault(),Ae())}),st(h,()=>{Ze(),lt.dispose(),at(),ie.delete(h)}),h.close=async l=>{if(!X&&l!==!0&&Ce()){if(ce)return;ce=!0;const de=await E.confirm("Discard the changes to this field?");if(ce=!1,!de)return}X=!0;const $=ot();return t&&!Ce()&&!a.name&&j(n.fields.peek().filter(de=>de._key!==e)),$},ie.add(h),I.scan(F),h.open(),F.querySelector("#cex-f-label")?.focus()}function ze(){const e=gt();j([...n.fields.peek(),e]),Je.activate?.(1),V(e._key,{isAdded:!0})}function Ge(e){const t=D(e);if(t<0)return[];const o=n.fields.peek()[t],a=n.fields.peek().length;return[{header:o.label||o.name||"Field"},{label:"Edit\u2026",icon:"edit",action:()=>V(e)},{label:"Move up",icon:"arrow-up",disabled:t===0,action:()=>G(e,-1)},{label:"Move down",icon:"arrow-down",disabled:t===a-1,action:()=>G(e,1)},{label:"Duplicate",icon:"copy",action:()=>j(ft(n.fields.peek(),t))},{type:"divider"},{label:"Remove\u2026",icon:"trash",danger:!0,action:()=>ae(e)}]}async function le(){if(W.peek())return;const e=m.peek();if(K(e)){E.toast(`Not saved - ${K(e)} thing${K(e)===1?"":"s"} to fix first (marked on the tabs).`,{type:"warning"});return}const t=wt(Y(),{isNew:k.peek(),meta:Be});W.value=!0;try{if(k.peek()){const a=await g.collections.create(t);L.value=U(Y()),re(),E.toast(`Created "${t.title}".`,{type:"success"}),R.navigate(`/collections/edit/${encodeURIComponent(a.slug)}`);return}const o=qe(H,t.storage.adapter);if(o&&u){if(await E.confirm(`You changed the storage (${o}). Move the ${u} existing ${u===1?"entry":"entries"} to the new storage?`)){const d=await g.collections.migrateStorage(r,t.storage);E.toast(`Moved ${d.migrated} of ${d.total} entries.`,{type:"success"})}else if(!await E.confirm(`Switch without moving them? The ${u} ${u===1?"entry stays":"entries stay"} in ${ee(H)} storage and this collection will show none until they are moved.`))return}if(await g.collections.update(r,t),!ne())return;H=t.storage.adapter,o&&(u=(await g.collections.listEntries(r,{limit:1}).catch(()=>null))?.total??u);for(const a of n.fields.peek())x[a._key]=a.name;L.value=U(Y()),re(),Pe(c,t.title),E.toast("Collection saved.",{type:"success"})}catch(o){E.toast(`Not saved: ${o.message||o}`,{type:"error"})}finally{W.value=!1}}async function Ve(){if(!_.peek()||!await E.confirm("Discard the changes you have not saved?"))return;const e=Ne(O,{project:he});for(const t of e.fields)x[t._key]=t.name;for(const[t,o]of Object.entries(e))n[t].value=o;L.value=U(e),z=!k.peek()}const N=i.querySelector(".cex-list");N.innerHTML=Mt;const Je=E.tabs(i.querySelector(".cex-tabs"),{tabSelector:".tab-item",panelSelector:".tab-panel"}),Qe=M.applyBindings(Ue,i,{methods:{save:()=>le(),discard:()=>Ve(),addField:()=>ze()}});b(()=>Qe.dispose()),b(Fe(i,{position:"bottom"}));const se=i.querySelector("#field-slug"),ke=()=>{z=!!se.value};se.addEventListener("input",ke),b(()=>se.removeEventListener("input",ke));const ie=new Set;b(()=>[...ie].forEach(e=>{try{e.close(!0)}catch{}}));const Xe=E.contextMenu(N,{cursor:"glyph",match:".cex-row",inherit:!1,density:"compact",items:e=>Ge(e.dataset.key)});b(()=>Xe?.destroy?.());let T=null;const Ee={click:e=>{const t=e.target.closest(".cex-row");if(!t)return;const o=e.target.closest(".cex-kebab");if(o){Le(o);return}V(t.dataset.key)},keydown:e=>{const t=e.target.closest(".cex-row");!t||e.target!==t||(e.key==="F10"&&e.shiftKey?(e.preventDefault(),Le(t)):e.key==="Enter"?V(t.dataset.key):e.altKey&&e.key==="ArrowUp"?(e.preventDefault(),G(t.dataset.key,-1)):e.altKey&&e.key==="ArrowDown"?(e.preventDefault(),G(t.dataset.key,1)):e.key==="Delete"&&(e.preventDefault(),ae(t.dataset.key)))},dragstart:e=>{const t=e.target.closest(".cex-row");t&&(T=t.dataset.key,t.classList.add("is-dragging"),e.dataTransfer.effectAllowed="move")},dragover:e=>{const t=e.target.closest(".cex-row");!t||!T||(e.preventDefault(),N.querySelectorAll(".is-drag-over").forEach(o=>o.classList.remove("is-drag-over")),t.classList.add("is-drag-over"))},drop:e=>{const t=e.target.closest(".cex-row");if(!t||!T)return;e.preventDefault();const o=D(T),a=D(t.dataset.key);T=null,j(Te(n.fields.peek(),o,a))},dragend:()=>{T=null,N.querySelectorAll(".is-drag-over, .is-dragging").forEach(e=>e.classList.remove("is-drag-over","is-dragging"))}};for(const[e,t]of Object.entries(Ee))N.addEventListener(e,t);b(()=>{for(const[e,t]of Object.entries(Ee))N.removeEventListener(e,t)}),Pe(c,O?.title||"New collection"),ue(s,{id:"collection-editor-back",icon:"arrow-left",title:"All collections",onClick:()=>R.navigate("/collections")}),r&&ue(s,{id:"collection-editor-entries",icon:"list",title:"Open entries",onClick:()=>R.navigate(`/collections/${encodeURIComponent(r)}/entries`)}),ue(s,{id:"collection-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>le()});const Se=e=>{!(e.ctrlKey||e.metaKey)||e.key!=="s"||!ne()||(e.preventDefault(),e.stopImmediatePropagation(),le())};document.addEventListener("keydown",Se,!0),b(()=>document.removeEventListener("keydown",Se,!0));const J=St(r);function re(){try{S.remove?S.remove(J):S.set(J,null)}catch{}}const Me=()=>{if(_.peek())try{S.set(J,{form:pt(Y()),base:L.peek(),at:new Date().toISOString()})}catch{}},$e=e=>{_.peek()&&(Me(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",$e),b(()=>window.removeEventListener("beforeunload",$e)),y={path:C,dirty:()=>_.peek(),dispose(){fe=!0,Me(),pe.splice(0).reverse().forEach(e=>{try{e()}catch{}})}},I.scan(i);let A=null;try{A=S.get(J)}catch{}if(A?.form){re();const e=A.base&&A.base!==L.peek(),t=A.at?` (${kt(A.at)})`:"",o=r?`changes to "${ee(O?.title||r)}"`:"a new collection",a=e?`You left unsaved ${o}${t}, but the saved collection has changed since. Restore your version anyway?`:`You left unsaved ${o}${t}. Restore them?`;if(await E.confirm(a)&&ne()){const d=ht(A.form,f);q||(d.slug=f.slug);const v=Object.fromEntries(f.fields.filter(p=>p.id).map(p=>[p.id,p.name]));for(const p of d.fields)p.id&&v[p.id]!==void 0&&(x[p._key]=v[p.id]);xe(d);for(const[p,Q]of Object.entries(d))n[p]&&(n[p].value=Q);q&&(z=!!d.slug&&d.slug!==Z(d.title))}}}};
64
+ </div>`);let Q=!1,re=!1;const nt=b.close.bind(b);function je(){if(Oe.peek())return;const l=Ne(a,J());j(n.fields.peek().map($=>$._key===e?l:$)),Q=!0,b.close()}b.element.appendChild(F);const ot=Ae(F),at=M.applyBindings(tt,F,{methods:{done:je,cancel:()=>b.close(),remove:async()=>{Q=!0,b.close(),await oe(e)}}}),Re=F.querySelector("#cex-f-name");Re.addEventListener("input",()=>{Ce=!!Re.value}),F.addEventListener("keydown",l=>{(l.ctrlKey||l.metaKey)&&l.key==="Enter"&&(l.preventDefault(),je())}),lt(b,()=>{Xe(),at.dispose(),ot(),se.delete(b)}),b.close=async l=>{if(!Q&&l!==!0&&$e()){if(re)return;re=!0;const ce=await E.confirm("Discard the changes to this field?");if(re=!1,!ce)return}Q=!0;const $=nt();return t&&!$e()&&!a.name&&j(n.fields.peek().filter(ce=>ce._key!==e)),$},se.add(b),I.scan(F),b.open(),F.querySelector("#cex-f-label")?.focus()}function Ye(){const e=bt();j([...n.fields.peek(),e]),Ve.activate?.(1),G(e._key,{isAdded:!0})}function ze(e){const t=Y(e);if(t<0)return[];const o=n.fields.peek()[t],a=n.fields.peek().length;return[{header:o.label||o.name||"Field"},{label:"Edit\u2026",icon:"edit",action:()=>G(e)},{label:"Move up",icon:"arrow-up",disabled:t===0,action:()=>z(e,-1)},{label:"Move down",icon:"arrow-down",disabled:t===a-1,action:()=>z(e,1)},{label:"Duplicate",icon:"copy",action:()=>j(pt(n.fields.peek(),t))},{type:"divider"},{label:"Remove\u2026",icon:"trash",danger:!0,action:()=>oe(e)}]}async function ae(){if(U.peek())return;const e=m.peek();if(B(e)){E.toast(`Not saved - ${B(e)} thing${B(e)===1?"":"s"} to fix first (marked on the tabs).`,{type:"warning"});return}const t=yt(H(),{isNew:k.peek(),meta:Ie});U.value=!0;try{if(k.peek()){const a=await g.collections.create(t);N.value=_(H()),ie(),E.toast(`Created "${t.title}".`,{type:"success"}),R.navigate(`/collections/edit/${encodeURIComponent(a.slug)}`);return}const o=Te(K,t.storage.adapter);if(o&&u){if(await E.confirm(`You changed the storage (${o}). Move the ${u} existing ${u===1?"entry":"entries"} to the new storage?`)){const r=await g.collections.migrateStorage(c,t.storage);E.toast(`Moved ${r.migrated} of ${r.total} entries.`,{type:"success"})}else if(!await E.confirm(`Switch without moving them? The ${u} ${u===1?"entry stays":"entries stay"} in ${Z(K)} storage and this collection will show none until they are moved.`))return}if(await g.collections.update(c,t),!te())return;K=t.storage.adapter,o&&(u=(await g.collections.listEntries(c,{limit:1}).catch(()=>null))?.total??u);for(const a of n.fields.peek())x[a._key]=a.name;N.value=_(H()),ie(),Pe(d,t.title),E.toast("Collection saved.",{type:"success"})}catch(o){E.toast(`Not saved: ${o.message||o}`,{type:"error"})}finally{U.value=!1}}async function Ge(){if(!P.peek()||!await E.confirm("Discard the changes you have not saved?"))return;const e=De(O,{project:ve});for(const t of e.fields)x[t._key]=t.name;for(const[t,o]of Object.entries(e))n[t].value=o;N.value=_(e),W=!k.peek()}const q=i.querySelector(".cex-list");q.innerHTML=Mt;const Ve=E.tabs(i.querySelector(".cex-tabs"),{tabSelector:".tab-item",panelSelector:".tab-panel"}),Je=M.applyBindings(Ke,i,{methods:{save:()=>ae(),discard:()=>Ge(),addField:()=>Ye()}});h(()=>Je.dispose()),h(Ae(i,{position:"bottom"}));const le=i.querySelector("#field-slug"),xe=()=>{W=!!le.value};le.addEventListener("input",xe),h(()=>le.removeEventListener("input",xe));const se=new Set;h(()=>[...se].forEach(e=>{try{e.close(!0)}catch{}}));const Qe=E.contextMenu(q,{cursor:"glyph",match:".cex-row",inherit:!1,density:"compact",items:e=>ze(e.dataset.key)});h(()=>Qe?.destroy?.());const ke={click:e=>{const t=e.target.closest(".cex-row");if(!t)return;const o=e.target.closest(".cex-kebab");if(o){Fe(o);return}G(t.dataset.key)},keydown:e=>{const t=e.target.closest(".cex-row");!t||e.target!==t||(e.key==="F10"&&e.shiftKey?(e.preventDefault(),Fe(t)):e.key==="Enter"?G(t.dataset.key):e.altKey&&e.key==="ArrowUp"?(e.preventDefault(),z(t.dataset.key,-1)):e.altKey&&e.key==="ArrowDown"?(e.preventDefault(),z(t.dataset.key,1)):e.key==="Delete"&&(e.preventDefault(),oe(t.dataset.key)))}};for(const[e,t]of Object.entries(ke))q.addEventListener(e,t);if(h(()=>{for(const[e,t]of Object.entries(ke))q.removeEventListener(e,t)}),typeof E.sortable=="function"){const e=kt(),t=E.sortable(q,{items:".cex-row",key:"data-key",keyboard:!1,onStart:e.start,onEnd:({item:o})=>e.restore(o),onSort:({item:o,from:a,to:r})=>{e.restore(o),j(Le(n.fields.peek(),a,r))}});h(()=>t.destroy())}Pe(d,O?.title||"New collection"),de(s,{id:"collection-editor-back",icon:"arrow-left",title:"All collections",onClick:()=>R.navigate("/collections")}),c&&de(s,{id:"collection-editor-entries",icon:"list",title:"Open entries",onClick:()=>R.navigate(`/collections/${encodeURIComponent(c)}/entries`)}),de(s,{id:"collection-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>ae()});const Ee=e=>{!(e.ctrlKey||e.metaKey)||e.key!=="s"||!te()||(e.preventDefault(),e.stopImmediatePropagation(),ae())};document.addEventListener("keydown",Ee,!0),h(()=>document.removeEventListener("keydown",Ee,!0));const V=St(c);function ie(){try{S.remove?S.remove(V):S.set(V,null)}catch{}}const Se=()=>{if(P.peek())try{S.set(V,{form:ut(H()),base:N.peek(),at:new Date().toISOString()})}catch{}},Me=e=>{P.peek()&&(Se(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",Me),h(()=>window.removeEventListener("beforeunload",Me)),y={path:C,dirty:()=>P.peek(),dispose(){pe=!0,Se(),ue.splice(0).reverse().forEach(e=>{try{e()}catch{}})}},I.scan(i);let A=null;try{A=S.get(V)}catch{}if(A?.form){ie();const e=A.base&&A.base!==N.peek(),t=A.at?` (${xt(A.at)})`:"",o=c?`changes to "${Z(O?.title||c)}"`:"a new collection",a=e?`You left unsaved ${o}${t}, but the saved collection has changed since. Restore your version anyway?`:`You left unsaved ${o}${t}. Restore them?`;if(await E.confirm(a)&&te()){const r=vt(A.form,f);D||(r.slug=f.slug);const v=Object.fromEntries(f.fields.filter(p=>p.id).map(p=>[p.id,p.name]));for(const p of r.fields)p.id&&v[p.id]!==void 0&&(x[p._key]=v[p.id]);we(r);for(const[p,J]of Object.entries(r))n[p]&&(n[p].value=J);D&&(W=!!r.slug&&r.slug!==X(r.title))}}}};
@@ -1,5 +1,6 @@
1
- import{api as de}from"../api.js";import{addBannerAction as je}from"../lib/plugin-chrome.js";import{helpPopovers as qe}from"../lib/help-popover.js";import{onceClosed as st,openMenuAt as Ne}from"../lib/tool-kit.js";import{makeIconInput as it}from"/admin/js/lib/shortcode-modal.js";import{makePageInput as rt}from"/admin/js/lib/page-picker.js";import{ACCENTS as ct,ACTION_ARG as K,ACTION_GROUPS as lt,EDITABLE_TYPES as dt,NEEDS_TARGET as ut,SELF_DISABLING as mt,checkMenu as pt,duplicateItem as vt,formFromMenu as Re,insertItem as ft,itemForm as ht,itemFromForm as Fe,itemRow as bt,moveItem as yt,newItem as gt,previewItems as xt,previewable as Pe,recordFromForm as kt,removeItem as Y,slugify as wt,snapshot as ue,splitList as Q,themeFromForm as Et}from"../lib/context-menu-editor-arrange.js";import{fmtDateTime as Mt}from"../lib/dates.js";const St=/^\/context-menus\/(new|edit\/[^/?#]+)\/?(\?.*)?$/,N=c=>`context-menu-editor.draft.${c||"new"}`,At=`
1
+ import{api as de}from"../api.js";import{addBannerAction as je}from"../lib/plugin-chrome.js";import{helpPopovers as qe}from"../lib/help-popover.js";import{onceClosed as it,openMenuAt as Ne}from"../lib/tool-kit.js";import{makeIconInput as rt}from"/admin/js/lib/shortcode-modal.js";import{makePageInput as ct}from"/admin/js/lib/page-picker.js";import{ACCENTS as lt,ACTION_ARG as H,ACTION_GROUPS as dt,EDITABLE_TYPES as ut,NEEDS_TARGET as mt,SELF_DISABLING as pt,checkMenu as vt,duplicateItem as ft,formFromMenu as Re,insertItem as ht,itemForm as bt,itemFromForm as Fe,itemRow as yt,moveItem as Pe,newItem as gt,previewItems as xt,previewable as Ke,recordFromForm as kt,removeItem as Y,slugify as wt,snapshot as ue,splitList as Q,themeFromForm as Et}from"../lib/context-menu-editor-arrange.js";import{fmtDateTime as St}from"../lib/dates.js";import{rowPlaceKeeper as Mt}from"../lib/menu-drag.js";const At=/^\/context-menus\/(new|edit\/[^/?#]+)\/?(\?.*)?$/,F=l=>`context-menu-editor.draft.${l||"new"}`,Tt=`
2
2
  <div class="cmx-row" data-index="{{index}}" tabindex="0" data-bind-class="cls">
3
+ <span class="cmx-grip" title="Drag to reorder" aria-hidden="true"></span>
3
4
  <span class="cmx-icon" aria-hidden="true" data-name="{{icon}}"></span>
4
5
  <span class="cmx-type">{{typeLabel}}</span>
5
6
  <span class="cmx-main"><strong>{{text}}</strong><small data-bind-hidden="!does">{{does}}</small><small data-bind-hidden="!note">{{note}}</small><small class="cmx-bad" data-bind-hidden="!problem">{{problem}}</small></span>
@@ -9,7 +10,7 @@ import{api as de}from"../api.js";import{addBannerAction as je}from"../lib/plugin
9
10
  <button type="button" class="cmx-down" data-bind-disabled="last" aria-label="Move down" title="Move down (Alt+\u2193)">\u2193</button>
10
11
  </span>
11
12
  <button type="button" class="cmx-kebab" aria-label="Actions for {{text}}" title="Actions">\u22EE</button>
12
- </div>`,Tt='<span class="cmx-chip" data-bind-class="cls">{{text}}</span>',It="<small>{{text}}</small>";function C(c){return String(c??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function Lt(c){const u=document.createElement("template");return u.innerHTML=c.trim(),u.content.firstElementChild}let X=null;function me(){if(X){try{X.destroy()}catch{}X=null}const c=document.getElementById("ctx-preview");if(c&&E.contextMenu&&E.contextMenu.registry)for(const u of E.contextMenu.registry(c))try{u.destroy()}catch{}}function pe(c,u){const l=c.querySelector(".dm-plugin-banner-name");if(!l)return;const L=l.querySelector(".dm-plugin-banner-sep");if(L){for(;L.nextSibling;)L.nextSibling.remove();l.appendChild(document.createTextNode(u))}}let k=null,He=!1;const Z=c=>String(c||"").split("?")[0].replace(/\/$/,"");function Ct(){He||!window.R?.use||(He=!0,R.use((c,u,l)=>!(St.test(u?.path||"")&&Z(c?.path)!==Z(u?.path))||!k?.dirty()?l():E.confirm("This context menu has unsaved changes. Leave anyway? They are kept as a draft for your next visit.").then(w=>{w?l():history.replaceState(null,"",`#${u.path}`)})),M.subscribe("router:afterChange",({to:c}={})=>{if(k&&Z(c?.path)!==k.path){const u=k;k=null,u.dispose()}}))}export const contextMenuEditorView={templateUrl:"/admin/js/templates/context-menu-editor.html",async onMount(c){if(Ct(),k){const e=k;k=null,e.dispose()}me();const u=[],l=e=>(u.push(e),e);let L=!1;const w=c.get(0),m=w.querySelector(".cmx")||w,B=()=>!L&&m.isConnected,ve=location.hash.match(/^#\/context-menus\/edit\/([^?#]+)/),p=ve?decodeURIComponent(ve[1]):null,h=!p,Ke=Z(location.hash.replace(/^#/,""));let g=null;if(!h){const e=E.loader(w,{type:"dots"});try{g=await de.contextMenus.get(p)}catch(n){e.destroy(),E.toast(`Could not load "${p}": ${n.message||n}`,{type:"error"});return}if(e.destroy(),!m.isConnected)return}const O=Re(g),r={};for(const[e,n]of Object.entries(O))r[e]=M.observable(n);const _=()=>Object.fromEntries(Object.keys(r).map(e=>[e,r[e].peek()])),fe=()=>Object.fromEntries(Object.keys(r).map(e=>[e,r[e].value])),s=M.observable(Array.isArray(g?.items)?g.items:[]),U=M.observable(ue(O,s.peek())),z=M.computed(()=>ue(fe(),s.value)!==U.value),G=M.observable(!1),V=M.observable(!1),F=M.observable([]),$=M.computed(()=>pt(fe(),s.value,{isNew:h})),Be=M.computed(()=>{const e=$.value.errors;if(V.value)return e;const n={};for(const t of Object.keys(e))t!=="items"&&String(r[t]?.value??"").trim()&&(n[t]=e[t]);return n}),he=M.computed(()=>{const e=V.value?$.value.errors:{};return{binding:!!(e.name||e.slug||e.selector),items:!!e.items||$.value.itemErrors.some(Boolean),appearance:!!(e.opacity||e.accent)}});let ee=!h;l(M.effect(()=>{const e=r.name.value;ee||(r.slug.value=wt(e))}));const te=M.observable([]);l(M.effect(()=>{const e=s.value,n=$.value.itemErrors;te.value=e.map((t,i)=>({...bt(t,i,e.length,n[i]||""),key:`${i}:${JSON.stringify(t)}`}))}));const x=m.querySelector("#ctx-items");l(M.effect(()=>{te.value,requestAnimationFrame(()=>{x?.isConnected&&(x.querySelectorAll(".cmx-icon[data-name]").forEach(e=>{const n=e.dataset.name;if(!n||e.dataset.drawn===n)return;e.dataset.drawn=n;const t=document.createElement("span");t.setAttribute("data-icon",n),t.setAttribute("data-icon-size","14"),e.replaceChildren(t)}),I.scan(x))})}));const _e=M.computed(()=>{const e=[];e.push(r.enabled.value?{text:"On",cls:"is-ok"}:{text:"Off",cls:"is-warn"});const n=Q(r.pages.value).length,t=Q(r.projects.value).length;e.push({text:n||t?`${n+t} scope rule${n+t===1?"":"s"}`:"Site-wide",cls:""});const i=s.value.filter(o=>!["divider","header"].includes(o?.type||"item")).length;return e.push({text:`${i} item${i===1?"":"s"} to click`,cls:i?"":"is-danger"}),r.selector.value.trim()&&e.push({text:r.selector.value.trim(),cls:""}),e});let ne=null;function Ue(){if(!B())return;me();const e=s.peek();if(!Pe(e))return;const n=Et(_());X=E.contextMenu("#ctx-preview",{cursor:"glyph",items:xt(e),inherit:!1,accent:n.accent,transition:n.transition,density:n.density,radius:n.radius,shadow:n.shadow,opacity:n.opacity})}l(M.effect(()=>{s.value,r.accent.value,r.transition.value,r.density.value,r.radius.value,r.shadow.value,r.opacity.value,clearTimeout(ne),ne=setTimeout(Ue,120)})),l(()=>{clearTimeout(ne),me()});const ze=M.computed(()=>Pe(s.value)?"Right-click here to try the menu":"Add an item to try the menu here"),ae=e=>be(e),A=e=>{s.value=e};function P(e){requestAnimationFrame(()=>x?.querySelector(`.cmx-row[data-index="${e}"]`)?.focus())}function D(e,n){n<0||n>=s.peek().length||(A(yt(s.peek(),e,n)),P(n))}function j(e,n=s.peek().length){const t=gt(e);A(ft(s.peek(),n,t)),e!=="divider"&&be(n,{isAdd:!0})}function Ge(e){const n=s.peek(),t=n[e];if(!t)return[];const i=t.type||"item";return[{header:i==="divider"?"Divider":t.text||"(no text)"},{label:i==="divider"?"Change\u2026":"Edit\u2026",icon:"edit",action:()=>ae(e)},{type:"divider"},{label:"Move up",icon:"arrow-up",disabled:e===0,action:()=>D(e,e-1)},{label:"Move down",icon:"arrow-down",disabled:e===n.length-1,action:()=>D(e,e+1)},{label:"Duplicate",icon:"copy",action:()=>{A(vt(s.peek(),e)),P(e+1)}},{label:"Add below",icon:"plus",submenu:[{label:"Item",action:()=>j("item",e+1)},{label:"Heading",action:()=>j("header",e+1)},{label:"Divider",action:()=>j("divider",e+1)}]},{type:"divider"},{label:"Remove",icon:"trash",danger:!0,action:()=>{A(Y(s.peek(),e)),P(Math.max(0,e-1))}}]}let v=null;function be(e,{isAdd:n=!1}={}){const t=s.peek()[e];if(!t)return;if(v)try{v.so.close(!0)}catch{}const i=ht(t),o={};for(const[a,d]of Object.entries(i))o[a]=M.observable(d);const J=()=>Object.fromEntries(Object.keys(o).map(a=>[a,o[a].peek()])),Xe=JSON.stringify(i),se=()=>JSON.stringify(J())!==Xe,Ae=!dt.includes(i.type),ie=Array.isArray(t.submenu)&&t.submenu.length,Te={...o,locked:Ae,notLocked:!Ae,hasSub:ie,subText:ie?`Opens a submenu of ${t.submenu.length} - kept as it is (edit it in the file).`:"",isItem:M.computed(()=>o.type.value!=="divider"&&o.type.value!=="header"),hasText:M.computed(()=>o.type.value!=="divider"),showAction:M.computed(()=>o.type.value!=="divider"&&o.type.value!=="header"&&!ie),argLabel:M.computed(()=>K[o.action.value]?.label||""),note:M.computed(()=>mt[o.action.value]||ut[o.action.value]||""),problem:M.computed(()=>{const a=Fe(Object.fromEntries(Object.keys(o).map(d=>[d,o[d].value])),t);return a.type==="divider"?"":String(a.text||"").trim()?K[a.action?.type]?.required&&!String(a.action?.[K[a.action.type].key]||"").trim()?`Needs a ${K[a.action.type].label.toLowerCase()}.`:"":"Needs text."})},y=E.slideover({title:n?"New item":i.type==="divider"?"Divider":`Edit ${C(i.text||"item")}`,size:"sm",position:"right"}),Ze=lt.map(a=>`<optgroup label="${C(a.label)}">${Object.entries(a.actions).map(([d,W])=>`<option value="${C(d)}">${C(W)}</option>`).join("")}</optgroup>`).join(""),T=Lt(`
13
+ </div>`,It='<span class="cmx-chip" data-bind-class="cls">{{text}}</span>',Lt="<small>{{text}}</small>";function C(l){return String(l??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function Ct(l){const u=document.createElement("template");return u.innerHTML=l.trim(),u.content.firstElementChild}let X=null;function me(){if(X){try{X.destroy()}catch{}X=null}const l=document.getElementById("ctx-preview");if(l&&E.contextMenu&&E.contextMenu.registry)for(const u of E.contextMenu.registry(l))try{u.destroy()}catch{}}function pe(l,u){const c=l.querySelector(".dm-plugin-banner-name");if(!c)return;const L=c.querySelector(".dm-plugin-banner-sep");if(L){for(;L.nextSibling;)L.nextSibling.remove();c.appendChild(document.createTextNode(u))}}let w=null,He=!1;const Z=l=>String(l||"").split("?")[0].replace(/\/$/,"");function Dt(){He||!window.R?.use||(He=!0,R.use((l,u,c)=>!(At.test(u?.path||"")&&Z(l?.path)!==Z(u?.path))||!w?.dirty()?c():E.confirm("This context menu has unsaved changes. Leave anyway? They are kept as a draft for your next visit.").then(A=>{A?c():history.replaceState(null,"",`#${u.path}`)})),M.subscribe("router:afterChange",({to:l}={})=>{if(w&&Z(l?.path)!==w.path){const u=w;w=null,u.dispose()}}))}export const contextMenuEditorView={templateUrl:"/admin/js/templates/context-menu-editor.html",async onMount(l){if(Dt(),w){const e=w;w=null,e.dispose()}me();const u=[],c=e=>(u.push(e),e);let L=!1;const A=l.get(0),m=A.querySelector(".cmx")||A,B=()=>!L&&m.isConnected,ve=location.hash.match(/^#\/context-menus\/edit\/([^?#]+)/),p=ve?decodeURIComponent(ve[1]):null,h=!p,Be=Z(location.hash.replace(/^#/,""));let x=null;if(!h){const e=E.loader(A,{type:"dots"});try{x=await de.contextMenus.get(p)}catch(n){e.destroy(),E.toast(`Could not load "${p}": ${n.message||n}`,{type:"error"});return}if(e.destroy(),!m.isConnected)return}const D=Re(x),r={};for(const[e,n]of Object.entries(D))r[e]=M.observable(n);const _=()=>Object.fromEntries(Object.keys(r).map(e=>[e,r[e].peek()])),fe=()=>Object.fromEntries(Object.keys(r).map(e=>[e,r[e].value])),s=M.observable(Array.isArray(x?.items)?x.items:[]),U=M.observable(ue(D,s.peek())),z=M.computed(()=>ue(fe(),s.value)!==U.value),G=M.observable(!1),V=M.observable(!1),P=M.observable([]),O=M.computed(()=>vt(fe(),s.value,{isNew:h})),_e=M.computed(()=>{const e=O.value.errors;if(V.value)return e;const n={};for(const t of Object.keys(e))t!=="items"&&String(r[t]?.value??"").trim()&&(n[t]=e[t]);return n}),he=M.computed(()=>{const e=V.value?O.value.errors:{};return{binding:!!(e.name||e.slug||e.selector),items:!!e.items||O.value.itemErrors.some(Boolean),appearance:!!(e.opacity||e.accent)}});let ee=!h;c(M.effect(()=>{const e=r.name.value;ee||(r.slug.value=wt(e))}));const te=M.observable([]);c(M.effect(()=>{const e=s.value,n=O.value.itemErrors;te.value=e.map((t,i)=>({...yt(t,i,e.length,n[i]||""),key:`${i}:${JSON.stringify(t)}`}))}));const b=m.querySelector("#ctx-items");c(M.effect(()=>{te.value,requestAnimationFrame(()=>{b?.isConnected&&(b.querySelectorAll(".cmx-icon[data-name]").forEach(e=>{const n=e.dataset.name;if(!n||e.dataset.drawn===n)return;e.dataset.drawn=n;const t=document.createElement("span");t.setAttribute("data-icon",n),t.setAttribute("data-icon-size","14"),e.replaceChildren(t)}),I.scan(b))})}));const Ue=M.computed(()=>{const e=[];e.push(r.enabled.value?{text:"On",cls:"is-ok"}:{text:"Off",cls:"is-warn"});const n=Q(r.pages.value).length,t=Q(r.projects.value).length;e.push({text:n||t?`${n+t} scope rule${n+t===1?"":"s"}`:"Site-wide",cls:""});const i=s.value.filter(a=>!["divider","header"].includes(a?.type||"item")).length;return e.push({text:`${i} item${i===1?"":"s"} to click`,cls:i?"":"is-danger"}),r.selector.value.trim()&&e.push({text:r.selector.value.trim(),cls:""}),e});let ne=null;function ze(){if(!B())return;me();const e=s.peek();if(!Ke(e))return;const n=Et(_());X=E.contextMenu("#ctx-preview",{cursor:"glyph",items:xt(e),inherit:!1,accent:n.accent,transition:n.transition,density:n.density,radius:n.radius,shadow:n.shadow,opacity:n.opacity})}c(M.effect(()=>{s.value,r.accent.value,r.transition.value,r.density.value,r.radius.value,r.shadow.value,r.opacity.value,clearTimeout(ne),ne=setTimeout(ze,120)})),c(()=>{clearTimeout(ne),me()});const Ge=M.computed(()=>Ke(s.value)?"Right-click here to try the menu":"Add an item to try the menu here"),ae=e=>be(e),k=e=>{s.value=e};function $(e){requestAnimationFrame(()=>b?.querySelector(`.cmx-row[data-index="${e}"]`)?.focus())}function j(e,n){n<0||n>=s.peek().length||(k(Pe(s.peek(),e,n)),$(n))}function q(e,n=s.peek().length){const t=gt(e);k(ht(s.peek(),n,t)),e!=="divider"&&be(n,{isAdd:!0})}function Ve(e){const n=s.peek(),t=n[e];if(!t)return[];const i=t.type||"item";return[{header:i==="divider"?"Divider":t.text||"(no text)"},{label:i==="divider"?"Change\u2026":"Edit\u2026",icon:"edit",action:()=>ae(e)},{type:"divider"},{label:"Move up",icon:"arrow-up",shortcut:"Alt+\u2191",disabled:e===0,action:()=>j(e,e-1)},{label:"Move down",icon:"arrow-down",shortcut:"Alt+\u2193",disabled:e===n.length-1,action:()=>j(e,e+1)},{label:"Duplicate",icon:"copy",action:()=>{k(ft(s.peek(),e)),$(e+1)}},{label:"Add below",icon:"plus",submenu:[{label:"Item",action:()=>q("item",e+1)},{label:"Heading",action:()=>q("header",e+1)},{label:"Divider",action:()=>q("divider",e+1)}]},{type:"divider"},{label:"Remove",icon:"trash",danger:!0,action:()=>{k(Y(s.peek(),e)),$(Math.max(0,e-1))}}]}let v=null;function be(e,{isAdd:n=!1}={}){const t=s.peek()[e];if(!t)return;if(v)try{v.so.close(!0)}catch{}const i=bt(t),a={};for(const[o,d]of Object.entries(i))a[o]=M.observable(d);const J=()=>Object.fromEntries(Object.keys(a).map(o=>[o,a[o].peek()])),Ze=JSON.stringify(i),se=()=>JSON.stringify(J())!==Ze,Ae=!ut.includes(i.type),ie=Array.isArray(t.submenu)&&t.submenu.length,Te={...a,locked:Ae,notLocked:!Ae,hasSub:ie,subText:ie?`Opens a submenu of ${t.submenu.length} - kept as it is (edit it in the file).`:"",isItem:M.computed(()=>a.type.value!=="divider"&&a.type.value!=="header"),hasText:M.computed(()=>a.type.value!=="divider"),showAction:M.computed(()=>a.type.value!=="divider"&&a.type.value!=="header"&&!ie),argLabel:M.computed(()=>H[a.action.value]?.label||""),note:M.computed(()=>pt[a.action.value]||mt[a.action.value]||""),problem:M.computed(()=>{const o=Fe(Object.fromEntries(Object.keys(a).map(d=>[d,a[d].value])),t);return o.type==="divider"?"":String(o.text||"").trim()?H[o.action?.type]?.required&&!String(o.action?.[H[o.action.type].key]||"").trim()?`Needs a ${H[o.action.type].label.toLowerCase()}.`:"":"Needs text."})},g=E.slideover({title:n?"New item":i.type==="divider"?"Divider":`Edit ${C(i.text||"item")}`,size:"sm",position:"right"}),et=dt.map(o=>`<optgroup label="${C(o.label)}">${Object.entries(o.actions).map(([d,W])=>`<option value="${C(d)}">${C(W)}</option>`).join("")}</optgroup>`).join(""),T=Ct(`
13
14
  <div class="cmx-form">
14
15
  <div data-bind-hidden="locked">
15
16
  <label class="form-label" for="cmx-i-type">Type
@@ -31,7 +32,7 @@ import{api as de}from"../api.js";import{addBannerAction as je}from"../lib/plugin
31
32
  <div data-bind-hidden="!showAction.value">
32
33
  <label class="form-label" for="cmx-i-action">Does
33
34
  <span data-help-title="What it does" data-help="A fixed set of actions, on purpose: nothing typed here runs as script on your pages. Some grey themselves out when they do not apply to the click - the note under the choice says when."></span></label>
34
- <select id="cmx-i-action" class="form-select" data-model="action.value">${Ze}</select>
35
+ <select id="cmx-i-action" class="form-select" data-model="action.value">${et}</select>
35
36
  <small class="cmx-hint" data-bind-hidden="!note.value" data-bind-text="note.value"></small>
36
37
  </div>
37
38
  <div data-bind-hidden="!argLabel.value || !showAction.value">
@@ -51,4 +52,4 @@ import{api as de}from"../api.js";import{addBannerAction as je}from"../lib/plugin
51
52
  <button type="button" class="btn btn-sm btn-ghost" data-on-click="cancel">Cancel</button>
52
53
  <button type="button" class="btn btn-sm btn-primary" data-on-click="done"><span data-icon="check" data-icon-size="13"></span> Done</button>
53
54
  </div>
54
- </div>`),q=it("edit",i.icon);q.input.id="cmx-i-icon",q.input.classList.add("form-input");const Ie=()=>{o.icon.value=q.input.value};q.input.addEventListener("input",Ie),T.querySelector(".cmx-icon-mount").appendChild(q.el);const re=T.querySelector(".cmx-arg-mount");let f=null;const ce=()=>{o.arg.value=f.value};function Le(){f?.removeEventListener("input",ce),re.replaceChildren();const a=K[o.action.peek()];if(!a){f=null;return}if(a.key==="url"){const d=rt(a.placeholder,o.arg.peek());f=d.input,re.appendChild(d.el)}else f=document.createElement("input"),f.type="text",f.className="form-input",f.placeholder=a.placeholder,f.value=o.arg.peek(),re.appendChild(f);f.id="cmx-i-arg",f.addEventListener("input",ce)}let Ce=o.action.peek();const et=M.effect(()=>{const a=o.action.value;a!==Ce&&(Ce=a,o.arg.value="",Le())});Le();const Oe=()=>{const a=Fe(J(),t),d=[...s.peek()],W=d.indexOf(t);W!==-1&&(d[W]=a,A(d))};let H=!1,le=!1;const $e={done:()=>{Oe(),H=!0,y.close(),P(e)},cancel:()=>y.close(),remove:()=>{const a=s.peek().indexOf(t);a!==-1&&A(Y(s.peek(),a)),H=!0,y.close()}};y.element.appendChild(T);const tt=qe(T),nt=M.applyBindings(Te,T,{methods:$e}),at=a=>{(a.ctrlKey||a.metaKey)&&a.key==="Enter"&&(a.preventDefault(),$e.done())};T.addEventListener("keydown",at);const De={so:y,dirty:se,apply:Oe};v=De,st(y,()=>{et(),nt.dispose(),tt(),q.input.removeEventListener("input",Ie),f?.removeEventListener("input",ce),v===De&&(v=null)});const ot=y.close.bind(y);y.close=async a=>{if(!H&&a!==!0&&se()){if(le)return;le=!0;const d=await E.confirm("Discard the changes to this item?");if(le=!1,!d)return}if(!H&&n&&a!==!0&&!se()){const d=s.peek().indexOf(t);d!==-1&&A(Y(s.peek(),d))}return H=!0,ot()},I.scan(T),y.open(),requestAnimationFrame(()=>T.querySelector(i.type==="divider"?"#cmx-i-type":"#cmx-i-text")?.focus())}l(()=>{if(v){const e=v;e.dirty()&&e.apply();try{e.so.close(!0)}catch{}}});async function oe(){if(G.peek())return;V.value=!0,F.value=[];const e=$.peek();if(!e.ok){const t=Object.keys(e.errors).length;E.toast(`Not saved yet - ${t===1?"one thing needs":`${t} things need`} fixing (marked in red).`,{type:"warning"});const i=he.peek(),o=i.binding?0:i.items?1:i.appearance?2:-1;o>=0&&We?.activate?.(o);return}G.value=!0;const n=kt(_(),s.peek());try{if(h)await de.contextMenus.create(n);else{const t=await de.contextMenus.update(p,n);t?.items&&(s.value=t.items)}if(!B())return;U.value=ue(_(),s.peek());try{S.remove?S.remove(N(p)):S.set(N(p),null)}catch{}window.dispatchEvent(new CustomEvent("dm:sidebar-count",{detail:{url:"#/context-menus"}})),h?(E.toast("Context menu created.",{type:"success"}),location.hash="#/context-menus"):(E.toast("Context menu saved.",{type:"success"}),pe(w,r.name.peek()||p))}catch(t){F.value=String(t.message||t).split("; ").map((i,o)=>({key:String(o),text:i})),m.querySelector(".cmx-alert")?.scrollIntoView({behavior:"smooth",block:"nearest"})}finally{G.value=!1}}function Ve(){E.confirm("Throw away your unsaved changes to this menu?").then(e=>{if(!e||!B())return;const n=Re(g);for(const[t,i]of Object.entries(n))r[t].value=i;s.value=Array.isArray(g?.items)?g.items:[],F.value=[]})}m.querySelector("#ctx-items").innerHTML=At,m.querySelector(".cmx-chips").innerHTML=Tt,m.querySelector(".cmx-server-errors").innerHTML=It;const ye=m.querySelector("#ctx-accent");if(O.accent&&!ct.includes(O.accent)&&ye){const e=document.createElement("option");e.value=O.accent,e.textContent=`Custom (${O.accent})`,ye.appendChild(e)}const Je={...r,items:s,rows:te,chips:_e,dirty:z,saving:G,err:Be,tabBad:he,serverErrors:F,isNew:h,notNew:!h,previewText:ze,serverError:M.computed(()=>F.value.length>0),saveText:M.computed(()=>h?"Create menu":"Save"),problemText:M.computed(()=>V.value&&!$.value.ok?" - some need fixing before they can be saved":""),scopeText:M.computed(()=>{const e=Q(r.pages.value),n=Q(r.projects.value);return!e.length&&!n.length?"Site-wide: every page carries this menu.":`Only ${[e.length&&`pages matching ${e.join(", ")}`,n.length&&`pages in ${n.join(", ")}`].filter(Boolean).join(", or ")}.`})},We=E.tabs(m.querySelector("#ctx-tabs"),{tabSelector:".tab-item",panelSelector:".tab-panel"}),Ye=M.applyBindings(Je,m,{methods:{save:()=>oe(),discard:()=>Ve(),addItem:()=>j("item"),addHeader:()=>j("header"),addDivider:()=>j("divider")}});l(()=>Ye.dispose()),l(qe(m,{position:"bottom"}));const ge=m.querySelector("#ctx-slug"),xe=()=>{ee=!0};ge?.addEventListener("input",xe),l(()=>ge?.removeEventListener("input",xe));const Qe=E.contextMenu(x,{cursor:"glyph",match:".cmx-row",inherit:!1,density:"compact",items:e=>Ge(Number(e.dataset.index))});l(()=>Qe?.destroy?.());const ke=e=>{const n=e.target.closest(".cmx-row");if(!n)return;const t=Number(n.dataset.index);if(e.target.closest(".cmx-kebab")){Ne(e.target.closest(".cmx-kebab"));return}if(e.target.closest(".cmx-up")){D(t,t-1);return}if(e.target.closest(".cmx-down")){D(t,t+1);return}ae(t)},we=e=>{const n=e.target.closest(".cmx-row");if(!n||e.target!==n)return;const t=Number(n.dataset.index);e.key==="F10"&&e.shiftKey?(e.preventDefault(),Ne(n)):e.key==="Enter"?(e.preventDefault(),ae(t)):e.altKey&&e.key==="ArrowUp"?(e.preventDefault(),D(t,t-1)):e.altKey&&e.key==="ArrowDown"?(e.preventDefault(),D(t,t+1)):e.key==="Delete"&&(e.preventDefault(),A(Y(s.peek(),t)),P(Math.max(0,t-1)))};x.addEventListener("click",ke),x.addEventListener("keydown",we),l(()=>{x.removeEventListener("click",ke),x.removeEventListener("keydown",we)}),h?pe(w,"New menu"):pe(w,g?.name||p),je(c,{id:"ctx-editor-back",icon:"arrow-left",title:"All context menus",onClick:()=>{location.hash="#/context-menus"}}),je(c,{id:"ctx-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>oe()});const Ee=e=>{!(e.ctrlKey||e.metaKey)||e.key!=="s"||v||(e.preventDefault(),e.stopImmediatePropagation(),oe())};document.addEventListener("keydown",Ee,!0),l(()=>document.removeEventListener("keydown",Ee,!0));const Me=()=>{if(z.peek())try{S.set(N(p),{form:_(),items:s.peek(),base:U.peek(),at:new Date().toISOString()})}catch{}},Se=e=>{v?.dirty()&&v.apply(),z.peek()&&(Me(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",Se),l(()=>window.removeEventListener("beforeunload",Se)),k={path:Ke,dirty:()=>z.peek()||!!v?.dirty(),dispose(){if(L=!0,v){const e=v;e.dirty()&&e.apply();try{e.so.close(!0)}catch{}}Me(),u.splice(0).reverse().forEach(e=>{try{e()}catch{}})}},I.scan(m);let b=null;try{b=S.get(N(p))}catch{}if(b?.form){try{S.remove?S.remove(N(p)):S.set(N(p),null)}catch{}const e=b.base&&b.base!==U.peek(),n=b.at?` (${Mt(b.at)})`:"",t=h?"the new context menu you started":`"${C(g?.name||p)}"`,i=e?`You left unsaved changes to ${t}${n}, but it has been saved since. Restore your version anyway?`:`You left unsaved changes to ${t}${n}. Restore them?`;if(await E.confirm(i)&&B()){for(const[o,J]of Object.entries(b.form))r[o]&&o!==(h?"":"slug")&&(r[o].value=J);h&&b.form.slug&&(ee=!0),Array.isArray(b.items)&&(s.value=b.items)}}}};
55
+ </div>`),N=rt("edit",i.icon);N.input.id="cmx-i-icon",N.input.classList.add("form-input");const Ie=()=>{a.icon.value=N.input.value};N.input.addEventListener("input",Ie),T.querySelector(".cmx-icon-mount").appendChild(N.el);const re=T.querySelector(".cmx-arg-mount");let f=null;const ce=()=>{a.arg.value=f.value};function Le(){f?.removeEventListener("input",ce),re.replaceChildren();const o=H[a.action.peek()];if(!o){f=null;return}if(o.key==="url"){const d=ct(o.placeholder,a.arg.peek());f=d.input,re.appendChild(d.el)}else f=document.createElement("input"),f.type="text",f.className="form-input",f.placeholder=o.placeholder,f.value=a.arg.peek(),re.appendChild(f);f.id="cmx-i-arg",f.addEventListener("input",ce)}let Ce=a.action.peek();const tt=M.effect(()=>{const o=a.action.value;o!==Ce&&(Ce=o,a.arg.value="",Le())});Le();const De=()=>{const o=Fe(J(),t),d=[...s.peek()],W=d.indexOf(t);W!==-1&&(d[W]=o,k(d))};let K=!1,le=!1;const Oe={done:()=>{De(),K=!0,g.close(),$(e)},cancel:()=>g.close(),remove:()=>{const o=s.peek().indexOf(t);o!==-1&&k(Y(s.peek(),o)),K=!0,g.close()}};g.element.appendChild(T);const nt=qe(T),at=M.applyBindings(Te,T,{methods:Oe}),ot=o=>{(o.ctrlKey||o.metaKey)&&o.key==="Enter"&&(o.preventDefault(),Oe.done())};T.addEventListener("keydown",ot);const $e={so:g,dirty:se,apply:De};v=$e,it(g,()=>{tt(),at.dispose(),nt(),N.input.removeEventListener("input",Ie),f?.removeEventListener("input",ce),v===$e&&(v=null)});const st=g.close.bind(g);g.close=async o=>{if(!K&&o!==!0&&se()){if(le)return;le=!0;const d=await E.confirm("Discard the changes to this item?");if(le=!1,!d)return}if(!K&&n&&o!==!0&&!se()){const d=s.peek().indexOf(t);d!==-1&&k(Y(s.peek(),d))}return K=!0,st()},I.scan(T),g.open(),requestAnimationFrame(()=>T.querySelector(i.type==="divider"?"#cmx-i-type":"#cmx-i-text")?.focus())}c(()=>{if(v){const e=v;e.dirty()&&e.apply();try{e.so.close(!0)}catch{}}});async function oe(){if(G.peek())return;V.value=!0,P.value=[];const e=O.peek();if(!e.ok){const t=Object.keys(e.errors).length;E.toast(`Not saved yet - ${t===1?"one thing needs":`${t} things need`} fixing (marked in red).`,{type:"warning"});const i=he.peek(),a=i.binding?0:i.items?1:i.appearance?2:-1;a>=0&&Ye?.activate?.(a);return}G.value=!0;const n=kt(_(),s.peek());try{if(h)await de.contextMenus.create(n);else{const t=await de.contextMenus.update(p,n);t?.items&&(s.value=t.items)}if(!B())return;U.value=ue(_(),s.peek());try{S.remove?S.remove(F(p)):S.set(F(p),null)}catch{}window.dispatchEvent(new CustomEvent("dm:sidebar-count",{detail:{url:"#/context-menus"}})),h?(E.toast("Context menu created.",{type:"success"}),location.hash="#/context-menus"):(E.toast("Context menu saved.",{type:"success"}),pe(A,r.name.peek()||p))}catch(t){P.value=String(t.message||t).split("; ").map((i,a)=>({key:String(a),text:i})),m.querySelector(".cmx-alert")?.scrollIntoView({behavior:"smooth",block:"nearest"})}finally{G.value=!1}}function Je(){E.confirm("Throw away your unsaved changes to this menu?").then(e=>{if(!e||!B())return;const n=Re(x);for(const[t,i]of Object.entries(n))r[t].value=i;s.value=Array.isArray(x?.items)?x.items:[],P.value=[]})}m.querySelector("#ctx-items").innerHTML=Tt,m.querySelector(".cmx-chips").innerHTML=It,m.querySelector(".cmx-server-errors").innerHTML=Lt;const ye=m.querySelector("#ctx-accent");if(D.accent&&!lt.includes(D.accent)&&ye){const e=document.createElement("option");e.value=D.accent,e.textContent=`Custom (${D.accent})`,ye.appendChild(e)}const We={...r,items:s,rows:te,chips:Ue,dirty:z,saving:G,err:_e,tabBad:he,serverErrors:P,isNew:h,notNew:!h,previewText:Ge,serverError:M.computed(()=>P.value.length>0),saveText:M.computed(()=>h?"Create menu":"Save"),problemText:M.computed(()=>V.value&&!O.value.ok?" - some need fixing before they can be saved":""),scopeText:M.computed(()=>{const e=Q(r.pages.value),n=Q(r.projects.value);return!e.length&&!n.length?"Site-wide: every page carries this menu.":`Only ${[e.length&&`pages matching ${e.join(", ")}`,n.length&&`pages in ${n.join(", ")}`].filter(Boolean).join(", or ")}.`})},Ye=E.tabs(m.querySelector("#ctx-tabs"),{tabSelector:".tab-item",panelSelector:".tab-panel"}),Qe=M.applyBindings(We,m,{methods:{save:()=>oe(),discard:()=>Je(),addItem:()=>q("item"),addHeader:()=>q("header"),addDivider:()=>q("divider")}});c(()=>Qe.dispose()),c(qe(m,{position:"bottom"}));const ge=m.querySelector("#ctx-slug"),xe=()=>{ee=!0};ge?.addEventListener("input",xe),c(()=>ge?.removeEventListener("input",xe));const Xe=E.contextMenu(b,{cursor:"glyph",match:".cmx-row",inherit:!1,density:"compact",items:e=>Ve(Number(e.dataset.index))});c(()=>Xe?.destroy?.());const ke=e=>{const n=e.target.closest(".cmx-row");if(!n)return;const t=Number(n.dataset.index);if(e.target.closest(".cmx-kebab")){Ne(e.target.closest(".cmx-kebab"));return}if(e.target.closest(".cmx-up")){j(t,t-1);return}if(e.target.closest(".cmx-down")){j(t,t+1);return}ae(t)},we=e=>{const n=e.target.closest(".cmx-row");if(!n||e.target!==n)return;const t=Number(n.dataset.index);e.key==="F10"&&e.shiftKey?(e.preventDefault(),Ne(n)):e.key==="Enter"?(e.preventDefault(),ae(t)):e.altKey&&e.key==="ArrowUp"?(e.preventDefault(),j(t,t-1)):e.altKey&&e.key==="ArrowDown"?(e.preventDefault(),j(t,t+1)):e.key==="Delete"&&(e.preventDefault(),k(Y(s.peek(),t)),$(Math.max(0,t-1)))};if(b.addEventListener("click",ke),b.addEventListener("keydown",we),c(()=>{b.removeEventListener("click",ke),b.removeEventListener("keydown",we)}),typeof E.sortable=="function"){const e=Mt(),n=E.sortable(b,{items:".cmx-row",key:null,keyboard:!1,onStart:e.start,onEnd:({item:t})=>e.restore(t),onSort:({item:t,from:i,to:a})=>{e.restore(t),k(Pe(s.peek(),i,a)),$(a)}});c(()=>n.destroy())}h?pe(A,"New menu"):pe(A,x?.name||p),je(l,{id:"ctx-editor-back",icon:"arrow-left",title:"All context menus",onClick:()=>{location.hash="#/context-menus"}}),je(l,{id:"ctx-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>oe()});const Ee=e=>{!(e.ctrlKey||e.metaKey)||e.key!=="s"||v||(e.preventDefault(),e.stopImmediatePropagation(),oe())};document.addEventListener("keydown",Ee,!0),c(()=>document.removeEventListener("keydown",Ee,!0));const Se=()=>{if(z.peek())try{S.set(F(p),{form:_(),items:s.peek(),base:U.peek(),at:new Date().toISOString()})}catch{}},Me=e=>{v?.dirty()&&v.apply(),z.peek()&&(Se(),e.preventDefault(),e.returnValue="")};window.addEventListener("beforeunload",Me),c(()=>window.removeEventListener("beforeunload",Me)),w={path:Be,dirty:()=>z.peek()||!!v?.dirty(),dispose(){if(L=!0,v){const e=v;e.dirty()&&e.apply();try{e.so.close(!0)}catch{}}Se(),u.splice(0).reverse().forEach(e=>{try{e()}catch{}})}},I.scan(m);let y=null;try{y=S.get(F(p))}catch{}if(y?.form){try{S.remove?S.remove(F(p)):S.set(F(p),null)}catch{}const e=y.base&&y.base!==U.peek(),n=y.at?` (${St(y.at)})`:"",t=h?"the new context menu you started":`"${C(x?.name||p)}"`,i=e?`You left unsaved changes to ${t}${n}, but it has been saved since. Restore your version anyway?`:`You left unsaved changes to ${t}${n}. Restore them?`;if(await E.confirm(i)&&B()){for(const[a,J]of Object.entries(y.form))r[a]&&a!==(h?"":"slug")&&(r[a].value=J);h&&y.form.slug&&(ee=!0),Array.isArray(y.items)&&(s.value=y.items)}}}};
@@ -1,8 +1,8 @@
1
- import{apiRequest as ie}from"/admin/js/api.js";import{makeIconInput as Mt}from"/admin/js/lib/shortcode-modal.js";import{enhancePickerFields as tt}from"/public/js/forms.js";import{buildWizardSteps as zt}from"/public/js/form-steps.mjs";import{addBannerAction as $e}from"../lib/plugin-chrome.js";import{helpPopovers as Pt}from"../lib/help-popover.js";import{openMenuAt as nt,sidebarCount as _t}from"../lib/tool-kit.js";import{draftKey as se,draftOf as jt,duplicateField as Vt,fieldTitle as Ae,fingerprint as lt,leavingEditor as at,moveField as ot,restoreDraft as Gt,snapshotOf as Fe}from"../lib/form-editor-arrange.js";import{fmtDateTime as Wt}from"../lib/dates.js";const it=[{value:"string",label:"Text (single line)"},{value:"email",label:"Email"},{value:"tel",label:"Phone"},{value:"number",label:"Number"},{value:"textarea",label:"Textarea (multi-line)"},{value:"select",label:"Dropdown (select)"},{value:"radio",label:"Radio buttons"},{value:"checkbox",label:"Single checkbox"},{value:"checkbox-group",label:"Checkbox group"},{value:"chooser",label:"Chooser (visual options)"},{value:"icon",label:"Icon (icon picker)"},{value:"image",label:"Image (media library)"},{value:"date",label:"Date"},{value:"time",label:"Time"},{value:"url",label:"URL"},{value:"password",label:"Password"},{value:"file",label:"File upload"},{value:"hidden",label:"Hidden field"}],Ie=new Set(["select","radio","checkbox-group","chooser"]);let C=[],he=[],N=null,be=null,ne=null,ge={};function q(e,t,o=14){e.textContent="";const n=document.createElement("span");return n.setAttribute("data-icon",t),n.setAttribute("data-icon-size",String(o)),n.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(n),window.I?.scan?.(e),e}function re(e,t,o,n=14){return q(e,t,n),e.appendChild(document.createTextNode(" "+o)),e}function Be(e){const t=document.createElement("span");return t.setAttribute("data-icon","help-circle"),t.setAttribute("data-icon-size","12"),t.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;margin-left:.3rem;opacity:.55;cursor:help;",t.title=e,window.I?.scan?.(t),requestAnimationFrame(()=>{try{t.parentNode&&typeof E<"u"&&E.tooltip&&(t.removeAttribute("title"),E.tooltip(t,{content:e,position:"top"}))}catch{}}),t}let ye=null,st=null,Oe=null,ce=null;function Re(){Oe?.(),clearTimeout(st),st=setTimeout(()=>{ye&&ye()},350)}function rt(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")}function ct(e){return it.find(t=>t.value===e)?.label||e}function dt(e){return(e||[]).some(t=>t.logic||Array.isArray(t.triggers)&&t.triggers.length)}function pt(e){return e?!!(e.visibility?.conditions?.length||e.requirement?.conditions?.length||e.validation?.length||e.cascade?.sourceField):!1}function Ht(e){const t={...C[e]};if(t.type==="spacer")return t;if(t.type==="page-break"){const f=document.getElementById(`fb-pb-label-${e}`),x=document.getElementById(`fb-pb-desc-${e}`);return f&&(t.label=f.value.trim()||t.label),x&&(t.description=x.value.trim()),t}const o=document.getElementById(`fb-label-${e}`),n=document.getElementById(`fb-name-${e}`),l=document.getElementById(`fb-type-${e}`),a=document.getElementById(`fb-required-${e}`),i=document.getElementById(`fb-placeholder-${e}`),r=document.getElementById(`fb-helper-${e}`),c=document.getElementById(`fb-tooltip-${e}`);if(o&&(t.label=o.value.trim()||t.label),n&&(t.name=n.value.trim()||t.name),l&&(t.type=l.value||t.type),a&&(t.required=a.checked),i&&(t.placeholder=i.value.trim()),r&&(t.helper=r.value.trim()),c&&(t.tooltip=c.value.trim()),t.type==="chooser"){const f=document.getElementById(`fb-chooser-variant-${e}`)?.value;f&&(t.variant=f);const x=document.getElementById(`fb-chooser-multiple-${e}`);x&&(t.multiple=x.checked);const $=document.getElementById(`fb-chooser-density-${e}`)?.value;$&&(t.density=$);const A=document.getElementById(`fb-chooser-columns-${e}`)?.value;A!==""&&A!==void 0&&(t.columns=parseInt(A,10)||3);const G=document.getElementById(`fb-chooser-accent-${e}`)?.value.trim();G?t.accent=G:delete t.accent;const P=document.getElementById(`fb-chooser-accent-style-${e}`)?.value;P?t.accentStyle=P:delete t.accentStyle;const _=document.getElementById(`fb-chooser-glow-${e}`);_&&(t.glow=_.checked);const I=document.getElementById(`fb-chooser-glow-colour-${e}`)?.value.trim();I?t.glowColour=I:delete t.glowColour;const Q=document.getElementById(`fb-chooser-shadow-${e}`)?.value;Q&&Q!=="none"?t.shadow=Q:delete t.shadow;const H=document.getElementById(`fb-chooser-shadow-colour-${e}`)?.value.trim();H?t.shadowColour=H:delete t.shadowColour,ke(e),C[e]&&Array.isArray(C[e].options)&&(t.options=C[e].options)}else if(Ie.has(t.type)){["variant","density","columns","accent","accentStyle","glow","glowColour","shadow","shadowColour"].forEach(x=>delete t[x]),t.type!=="checkbox-group"&&t.type!=="multiselect"&&delete t.multiple;const f=document.getElementById(`fb-options-${e}`);f&&(t.options=f.value.split(`
2
- `).filter(x=>x.trim()).map(x=>{const[$,...A]=x.split(":");return{value:$.trim(),label:A.join(":").trim()||$.trim()}}))}if(t.type==="textarea"){const f=parseInt(document.getElementById(`fb-rows-${e}`)?.value,10);f>0&&(t.formConfig={...t.formConfig||{},rows:f})}const s=document.getElementById(`fb-span-${e}`),d=document.getElementById(`fb-fullwidth-${e}`);if(s||d){const f={...t.formConfig||{}};if(d?.checked)f.span="full";else{const x=parseInt(s?.value,10);x>1?f.span=x:delete f.span}t.formConfig=Object.keys(f).length?f:void 0}const u=document.getElementById(`fb-minlength-${e}`)?.value;u&&(t.minLength=parseInt(u,10));const b=document.getElementById(`fb-maxlength-${e}`)?.value;b&&(t.maxLength=parseInt(b,10));const g=document.getElementById(`fb-min-${e}`)?.value;g!==""&&g!==void 0&&(t.min=parseFloat(g));const m=document.getElementById(`fb-max-${e}`)?.value;m!==""&&m!==void 0&&(t.max=parseFloat(m));const h=Ut(e);h?t.logic=h:delete t.logic;const w=dn(e);return w?t.triggers=w:delete t.triggers,t}function Ut(e){const t=document.querySelector(`.fb-field-card[data-index="${e}"]`);if(!t)return;const o=t.querySelector(".fb-field-logic");if(!o)return;const n={};let l=!1;const a=o.querySelector('[data-logic-section="visibility"]');if(a){const s=a.querySelector(".fb-logic-vis-default"),d=a.querySelector(".fb-logic-vis-transition"),u=Array.from(a.querySelectorAll(".fb-logic-cond-row")).map(h=>{const w=h.querySelector(".fb-logic-cond-field"),f=h.querySelector(".fb-logic-cond-op"),x=h.querySelector(".fb-logic-cond-val"),$=h.querySelector(".fb-logic-vis-then");return w?.value?{when:{all:[{field:w.value,operator:f.value,value:x.value}]},then:$.value}:null}).filter(Boolean),b=s?.value||"visible",g=d?.value||"none",m=parseInt(a.querySelector(".fb-logic-vis-duration")?.value||"",10);(b!=="visible"||u.length>0||g!=="none")&&(n.visibility={default:b,conditions:u},g!=="none"&&(n.visibility.transition=g),g!=="none"&&Number.isFinite(m)&&(n.visibility.duration=m),l=!0)}const i=o.querySelector('[data-logic-section="requirement"]');if(i){const s=i.querySelector(".fb-logic-req-default"),d=Array.from(i.querySelectorAll(".fb-logic-cond-row")).map(u=>{const b=u.querySelector(".fb-logic-cond-field"),g=u.querySelector(".fb-logic-cond-op"),m=u.querySelector(".fb-logic-cond-val"),h=u.querySelector(".fb-logic-req-then");return b?.value?{when:{all:[{field:b.value,operator:g.value,value:m.value}]},then:h.value==="true"}:null}).filter(Boolean);d.length>0&&(n.requirement={default:s?.checked===!0,conditions:d},l=!0)}const r=o.querySelector('[data-logic-section="validation"]');if(r){const s=Array.from(r.querySelectorAll(".fb-logic-val-rule")).map(d=>{const u=d.querySelector(".fb-logic-val-type"),b=d.querySelector(".fb-logic-val-pattern"),g=d.querySelector(".fb-logic-val-flags"),m=d.querySelector(".fb-logic-val-message");if(!b?.value.trim())return null;const h=u?.value||"regex",w={type:h,message:m?.value.trim()||"Invalid value."};return h==="regex"?(w.pattern=b.value.trim(),g?.value.trim()&&(w.flags=g.value.trim())):w.field=b.value.trim(),w}).filter(Boolean);s.length>0&&(n.validation=s,l=!0)}const c=o.querySelector('[data-logic-section="cascade"]');if(c){const s=c.querySelector(".fb-logic-cascade-source"),d=c.querySelector(".fb-logic-cascade-mapping"),u=c.querySelector(".fb-logic-cascade-defaults"),b=s?.value?.trim();if(b){let g={};try{g=JSON.parse(d?.value||"{}")}catch{}const m=(u?.value||"").split(`
3
- `).filter(h=>h.trim()).map(h=>{const[w,...f]=h.split(":");return{value:w.trim(),label:f.join(":").trim()||w.trim()}});n.cascade={sourceField:b,mapping:g,defaultOptions:m},l=!0}}return l?n:void 0}function O(){C=C.map((e,t)=>Ht(t))}let le=null;function Jt(e,t,o){const n=e.firstElementChild;if(!n)return;const l=document.createElement("span");l.setAttribute("data-icon","menu"),l.setAttribute("data-icon-size","13"),l.title="Drag to reorder",l.style.cssText="cursor:grab;opacity:.35;flex-shrink:0;display:inline-flex;align-items:center;",n.insertBefore(l,n.firstChild),window.I?.scan?.(n),n.draggable=!0,n.addEventListener("dragstart",a=>{le=t,a.dataTransfer.effectAllowed="move",e.style.opacity="0.4"}),n.addEventListener("dragend",()=>{e.style.opacity="",document.querySelectorAll("#fields-list .fb-field-card").forEach(a=>a.classList.remove("fb-drag-over"))}),e.addEventListener("dragover",a=>{le!=null&&(a.preventDefault(),a.dataTransfer.dropEffect="move",document.querySelectorAll("#fields-list .fb-field-card").forEach(i=>i.classList.remove("fb-drag-over")),e.classList.add("fb-drag-over"))}),e.addEventListener("dragleave",()=>e.classList.remove("fb-drag-over")),e.addEventListener("drop",a=>{if(a.preventDefault(),e.classList.remove("fb-drag-over"),le==null||le===t){le=null;return}O();const[i]=C.splice(le,1);C.splice(t,0,i),le=null,J(o)})}function J(e){const t=e.find("#fields-list").get(0),o=e.find("#fields-empty-msg").get(0);if(t){if(Array.from(t.querySelectorAll(".fb-field-card")).forEach(n=>n.remove()),C.length===0){o&&(o.style.display=""),ce?.(t),Re();return}o&&(o.style.display="none"),C.forEach((n,l)=>{const a=n.type==="page-break"?Yt(n,l,e):n.type==="spacer"?Kt(n,l,e):Qt(n,l,e);Jt(a,l,e),t.appendChild(a)}),ce?.(t),Re()}}function Yt(e,t,o){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:2px dashed var(--dm-border);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.6rem .8rem;cursor:pointer;user-select:none;";const a=document.createElement("span");a.textContent="- Page Break -",a.style.cssText="font-size:.7rem;padding:.15rem .5rem;border-radius:999px;background:color-mix(in srgb, var(--dm-text-muted) 20%, transparent);color:var(--dm-text-muted);white-space:nowrap;flex-shrink:0;font-style:italic;";const i=document.createElement("span");i.textContent=e.label||"Untitled Step",i.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text-muted);";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit step",q(c,"more-horizontal"),c.addEventListener("click",g=>{g.stopPropagation(),d.style.display=d.style.display==="none"?"":"none"}),r.appendChild(c);const s=document.createElement("button");s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove page break",q(s,"x"),s.addEventListener("click",async g=>{g.stopPropagation(),await E.confirm("Remove this page break?")&&(O(),C.splice(t,1),J(o))}),r.appendChild(s),l.appendChild(a),l.appendChild(i),l.appendChild(r),l.addEventListener("click",()=>{d.style.display=d.style.display==="none"?"":"none"});const d=document.createElement("div");d.className="fb-field-body",d.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border);display:none;";const u=D([z("Step Title",`fb-pb-label-${t}`,"text",e.label||"","Shown as the wizard step heading"),z("Step Description",`fb-pb-desc-${t}`,"text",e.description||"","Optional sub-heading")]),b=u.querySelector(`#fb-pb-label-${t}`);return b&&b.addEventListener("input",()=>{i.textContent=b.value||"Untitled Step"}),d.appendChild(u),n.appendChild(l),n.appendChild(d),n}function Kt(e,t,o){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px dashed var(--dm-border);border-radius:6px;margin-bottom:.5rem;background:transparent;";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.4rem .8rem;";const a=document.createElement("div");a.style.cssText="flex:1;height:1px;background:var(--dm-border);";const i=document.createElement("span");i.textContent="Spacer",i.style.cssText="font-size:.7rem;color:var(--dm-text-muted);white-space:nowrap;padding:0 .4rem;font-style:italic;";const r=document.createElement("div");r.style.cssText="flex:1;height:1px;background:var(--dm-border);";const c=document.createElement("div");c.style.cssText="display:flex;gap:.25rem;flex-shrink:0;";const s=document.createElement("button");return s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove spacer",q(s,"x"),s.addEventListener("click",async d=>{d.stopPropagation(),O(),C.splice(t,1),J(o)}),c.appendChild(s),l.appendChild(a),l.appendChild(i),l.appendChild(r),l.appendChild(c),n.appendChild(l),n}function Qt(e,t,o){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px solid var(--dm-border);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);box-shadow:var(--dm-shadow-sm);";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.65rem .85rem;background:var(--dm-card-header-bg);cursor:pointer;user-select:none;";const a=document.createElement("span");a.textContent=ct(e.type),a.style.cssText="font-size:.7rem;padding:.15rem .45rem;border-radius:999px;background:color-mix(in srgb, var(--dm-primary) 14%, transparent);color:var(--dm-primary);white-space:nowrap;flex-shrink:0;";const i=document.createElement("span");i.textContent=e.label||"(unlabelled)",i.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit field",q(c,"more-horizontal"),c.addEventListener("click",u=>{u.stopPropagation(),d.style.display=d.style.display==="none"?"":"none"}),r.appendChild(c);const s=document.createElement("button");if(s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove field",q(s,"x"),s.addEventListener("click",async u=>{u.stopPropagation(),await E.confirm("Remove this field?")&&(O(),C.splice(t,1),J(o))}),r.appendChild(s),l.appendChild(a),l.appendChild(i),e.required){const u=document.createElement("span");u.textContent="required",u.style.cssText="font-size:.7rem;color:var(--dm-danger);flex-shrink:0;",l.appendChild(u)}if(pt(e.logic)){const u=document.createElement("span");q(u,"zap"),u.title="Has conditional logic",u.style.cssText="font-size:.75rem;color:var(--dm-primary);flex-shrink:0;",l.appendChild(u)}l.appendChild(r),l.addEventListener("click",()=>{d.style.display=d.style.display==="none"?"":"none"});const d=Xt(e,t,i);return d.style.display="none",n.appendChild(l),n.appendChild(d),n}function Xt(e,t,o){const n=document.createElement("div");n.className="fb-field-body",n.style.cssText="padding:1rem .9rem;border-top:1px solid var(--dm-border);";const l=D([z("Label",`fb-label-${t}`,"text",e.label||"","Shown above the field"),z("Field Name",`fb-name-${t}`,"text",e.name||"","Used as data key")]),a=D([gn("Type",`fb-type-${t}`,it,e.type||"string"),Lt("Required",`fb-required-${t}`,e.required||!1)]),i=D([z("Placeholder",`fb-placeholder-${t}`,"text",e.placeholder||"","Hint text inside the field")]),r=D([z("Helper Text",`fb-helper-${t}`,"text",e.helper||"","Shown below the field"),z("Tooltip",`fb-tooltip-${t}`,"text",e.tooltip||"","Shown on hover via a help icon next to the label")]),c=e.formConfig?.span,s=D([z("Column Span",`fb-span-${t}`,"number",c&&c!=="full"?String(c):"1","Columns to span (grid only)"),Lt("Full Width",`fb-fullwidth-${t}`,c==="full")]);s.classList.add("fb-grid-row"),s.style.display=document.getElementById("setting-layout")?.value==="grid"?"flex":"none",n.appendChild(l),n.appendChild(a),n.appendChild(i),n.appendChild(r),n.appendChild(s);const d=n.querySelector(`#fb-label-${t}`),u=n.querySelector(`#fb-name-${t}`);d&&d.addEventListener("input",()=>{o&&(o.textContent=d.value||"(unlabelled)"),u&&!u.dataset.manuallyEdited&&(u.value=rt(d.value))}),u&&u.addEventListener("input",()=>{u.dataset.manuallyEdited="1"});const b=n.querySelector(`#fb-type-${t}`);b&&b.addEventListener("change",()=>{const m=n.closest(".fb-field-card");if(m){const f=m.querySelector("span");f&&(f.textContent=ct(b.value))}const h=n.querySelector(".fb-field-extras");h&&h.remove();const w=kt(b.value,e,t);w&&n.appendChild(w)});const g=kt(e.type,e,t);return g&&n.appendChild(g),n.appendChild(ln(e,t)),n.appendChild(rn(e,t)),n}const ve=[{value:"equals",label:"equals"},{value:"not_equals",label:"does not equal"},{value:"contains",label:"contains"},{value:"not_contains",label:"does not contain"},{value:"starts_with",label:"starts with"},{value:"ends_with",label:"ends with"},{value:"greater_than",label:"is greater than"},{value:"less_than",label:"is less than"},{value:"is_empty",label:"is empty"},{value:"is_not_empty",label:"is not empty"},{value:"in",label:"is one of (comma sep)"},{value:"not_in",label:"is not one of (comma sep)"},{value:"matches_regex",label:"matches regex"}],De=new Set(["is_empty","is_not_empty"]),ut={equals:"includes",not_equals:"does not include",contains:"any value contains",not_contains:"no value contains",starts_with:"any value starts with",ends_with:"any value ends with",greater_than:"any value is greater than",less_than:"any value is less than",is_empty:"nothing selected",is_not_empty:"something selected",in:"includes one of (comma sep)",not_in:"includes none of (comma sep)",matches_regex:"any value matches regex"};function Me(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function xe(e){const t=document.createElement("p");return t.textContent=e,t.style.cssText="font-size:.75rem;font-weight:700;color:var(--dm-text-muted);margin:0 0 .7rem;text-transform:uppercase;letter-spacing:.06em;",t}function Ce(e,t,o,n,l){const a=document.createElement("div");a.className="fb-logic-cond-row",a.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const i=document.createElement("span");i.textContent="When",i.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const r=document.createElement("select");r.className="form-select fb-logic-cond-field",r.style.cssText="flex:1 1 140px;min-width:140px;",t.forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,e&&m.value===e.field&&(h.selected=!0),r.appendChild(h)});const c=document.createElement("select");c.className="form-select fb-logic-cond-op",c.style.cssText="flex:1 1 160px;min-width:140px;",ve.forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,e&&m.value===e.operator&&(h.selected=!0),c.appendChild(h)});const s=()=>{const m=t.find(h=>h.value===r.value);Array.from(c.options).forEach(h=>{const w=ve.find(f=>f.value===h.value);h.textContent=m?.multi&&ut[h.value]||w?.label||h.value})};s(),r.addEventListener("change",s);const d=document.createElement("input");d.type="text",d.className="form-input fb-logic-cond-val",d.placeholder="value",d.style.cssText="flex:1 1 120px;min-width:100px;",d.value=e?.value||"",e&&De.has(e.operator)&&(d.style.display="none"),c.addEventListener("change",()=>{d.style.display=De.has(c.value)?"none":""});const u=document.createElement("span");q(u,"arrow-right"),u.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const b=document.createElement("select");b.className=`form-select ${n}`,b.style.cssText="flex:1 1 140px;min-width:120px;",o.forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,m.value===l&&(h.selected=!0),b.appendChild(h)});const g=document.createElement("button");return g.type="button",g.className="btn btn-xs btn-ghost",g.style.cssText="line-height:1;opacity:.6;",q(g,"x"),g.style.flexShrink="0",g.addEventListener("click",()=>a.remove()),a.appendChild(i),a.appendChild(r),a.appendChild(c),a.appendChild(d),a.appendChild(u),a.appendChild(b),a.appendChild(g),a}function Zt(e,t,o){const n=document.createElement("div");n.dataset.logicSection="visibility",n.appendChild(xe("Visibility"));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const a=document.createElement("span");a.textContent="Default:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-vis-default",i.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(f=>{const x=document.createElement("option");x.value=f.value,x.textContent=f.label,f.value===(e.default||"visible")&&(x.selected=!0),i.appendChild(x)}),l.appendChild(a),l.appendChild(i),n.appendChild(l);const r=document.createElement("div");r.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const c=document.createElement("span");c.textContent="Transition:",c.style.cssText="font-size:.8rem;flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-vis-transition",s.style.cssText="max-width:240px;",[{value:"none",label:"None (instant)"},{value:"fade",label:"Fade"},{value:"slide",label:"Slide"},{value:"scale",label:"Scale"}].forEach(f=>{const x=document.createElement("option");x.value=f.value,x.textContent=f.label,f.value===(e.transition||"none")&&(x.selected=!0),s.appendChild(x)}),r.appendChild(c),r.appendChild(s),n.appendChild(r);const d=document.createElement("div");d.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const u=document.createElement("span");u.textContent="Speed:",u.style.cssText="font-size:.8rem;flex-shrink:0;";const b=document.createElement("select");b.className="form-select fb-logic-vis-duration",b.style.cssText="max-width:240px;",[{value:"",label:"Default"},{value:"120",label:"Very fast (120ms)"},{value:"200",label:"Fast (200ms)"},{value:"350",label:"Medium (350ms)"},{value:"600",label:"Slow (600ms)"},{value:"1000",label:"Very slow (1s)"}].forEach(f=>{const x=document.createElement("option");x.value=f.value,x.textContent=f.label,f.value===String(e.duration??"")&&(x.selected=!0),b.appendChild(x)}),d.appendChild(u),d.appendChild(b),n.appendChild(d);const g=()=>{d.style.display=s.value==="none"?"none":""};g(),s.addEventListener("change",g);const m=document.createElement("div");m.className="fb-logic-vis-rules";const h=o.map(f=>({value:f.name,label:f.label||f.name,multi:Me(f)})),w=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(f=>{const x=(f.when?.all||f.when?.any||[])[0],$=f.then==="hidden"?"hidden":"visible";h.length>0&&m.appendChild(Ce(x,h,w,"fb-logic-vis-then",$))}),n.appendChild(m),h.length>0){const f=document.createElement("button");f.type="button",f.className="btn btn-xs btn-ghost",f.style.cssText="font-size:.73rem;margin-top:.35rem;",re(f,"plus","Add visibility rule"),f.addEventListener("click",()=>m.appendChild(Ce(null,h,w,"fb-logic-vis-then","visible"))),n.appendChild(f)}return n}function en(e,t,o){const n=document.createElement("div");n.dataset.logicSection="requirement",n.appendChild(xe("Conditional Requirement"));const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.8rem;cursor:pointer;margin-bottom:.65rem;";const a=document.createElement("input");a.type="checkbox",a.className="fb-logic-req-default",a.checked=e.default===!0,l.appendChild(a),l.appendChild(document.createTextNode("Required by default")),n.appendChild(l);const i=document.createElement("div");i.className="fb-logic-req-rules";const r=o.map(s=>({value:s.name,label:s.label||s.name,multi:Me(s)})),c=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(s=>{const d=(s.when?.all||s.when?.any||[])[0],u=s.then===!0?"true":"false";r.length>0&&i.appendChild(Ce(d,r,c,"fb-logic-req-then",u))}),n.appendChild(i),r.length>0){const s=document.createElement("button");s.type="button",s.className="btn btn-xs btn-ghost",s.style.cssText="font-size:.73rem;margin-top:.35rem;",re(s,"plus","Add requirement rule"),s.addEventListener("click",()=>i.appendChild(Ce(null,r,c,"fb-logic-req-then","true"))),n.appendChild(s)}return n}function mt(e){const t=document.createElement("div");t.className="fb-logic-val-rule",t.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const o=document.createElement("select");o.className="form-select fb-logic-val-type",o.style.cssText="flex:0 0 140px;",[{value:"regex",label:"Regex"},{value:"match",label:"Match field"}].forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===(e?.type||"regex")&&(c.selected=!0),o.appendChild(c)});const n=document.createElement("input");n.type="text",n.className="form-input fb-logic-val-pattern",n.placeholder=e?.type==="match"?"field name":"pattern",n.value=e?.pattern||e?.field||"",n.style.cssText="flex:3;";const l=document.createElement("input");l.type="text",l.className="form-input fb-logic-val-flags",l.placeholder="flags",l.value=e?.flags||"",l.style.cssText="flex:0 0 55px;",e?.type==="match"&&(l.style.display="none"),o.addEventListener("change",()=>{l.style.display=o.value==="match"?"none":"",n.placeholder=o.value==="match"?"field name":"pattern"});const a=document.createElement("input");a.type="text",a.className="form-input fb-logic-val-message",a.placeholder="Error message",a.value=e?.message||"",a.style.cssText="flex:4;";const i=document.createElement("button");return i.type="button",i.className="btn btn-xs btn-ghost",i.style.cssText="line-height:1;opacity:.6;",q(i,"x"),i.style.flexShrink="0",i.addEventListener("click",()=>t.remove()),t.appendChild(o),t.appendChild(n),t.appendChild(l),t.appendChild(a),t.appendChild(i),t}function tn(e,t,o){const n=document.createElement("div");n.dataset.logicSection="validation",n.appendChild(xe("Custom Validation"));const l=document.createElement("div");l.className="fb-logic-val-rules",(e||[]).forEach(i=>l.appendChild(mt(i))),n.appendChild(l);const a=document.createElement("button");return a.type="button",a.className="btn btn-xs btn-ghost",a.style.cssText="font-size:.73rem;margin-top:.35rem;",re(a,"plus","Add validation rule"),a.addEventListener("click",()=>l.appendChild(mt(null))),n.appendChild(a),n}function nn(e,t,o){const n=document.createElement("div");n.dataset.logicSection="cascade",n.appendChild(xe("Cascade Options")),n.lastChild.appendChild(Be("Make this field's options depend on another field. When the source field changes, the options here are replaced by the mapping entry for its value; if nothing matches, the default options below are shown."));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const a=document.createElement("span");a.textContent="Source field:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-cascade-source",i.style.cssText="flex:1;";const r=document.createElement("option");r.value="",r.textContent="- none -",i.appendChild(r),o.forEach(b=>{const g=document.createElement("option");g.value=b.name,g.textContent=b.label||b.name,b.name===e.sourceField&&(g.selected=!0),i.appendChild(g)}),l.appendChild(a),l.appendChild(i),n.appendChild(l);const c=document.createElement("p");c.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',c.appendChild(Be(`Each key is a value of the source field; its list becomes this field's options when that value is picked. Example: {"uk":[{"value":"london","label":"London"}]} shows London when the source is "uk".`)),c.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const s=document.createElement("textarea");s.className="form-input fb-logic-cascade-mapping",s.rows=4,s.style.cssText="font-family:monospace;",s.placeholder='{"uk": [{"value": "london", "label": "London"}]}',s.value=e.mapping?JSON.stringify(e.mapping,null,2):"",n.appendChild(c),n.appendChild(s);const d=document.createElement("p");d.textContent="Default options (one per line: value:Label)",d.appendChild(Be("Shown before the source field has a value, or when its value has no mapping entry.")),d.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const u=document.createElement("textarea");return u.className="form-input fb-logic-cascade-defaults",u.rows=3,u.style.cssText="font-family:monospace;",u.placeholder=`option1:Option 1
4
- option2:Option 2`,u.value=(e.defaultOptions||[]).map(b=>{const g=typeof b=="string"?b:b.value??"",m=typeof b=="string"?b:b.label??g;return g===m?g:`${g}:${m}`}).join(`
5
- `),n.appendChild(d),n.appendChild(u),n}function ln(e,t){const o=e.logic||{},n=C.filter((u,b)=>b!==t&&u.type!=="page-break"&&u.type!=="spacer"),l=document.createElement("div");l.className="fb-field-logic",l.style.cssText="margin-top:.75rem;border-top:1px solid var(--dm-border);padding-top:.5rem;";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const i=document.createElement("span");i.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted);",i.textContent="\u26A1 Conditional Logic";const r=pt(o),c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",q(c,r?"chevron-down":"chevron-right",12);const s=document.createElement("div");s.className="fb-logic-body",s.style.cssText="padding:.25rem 0 .25rem;"+(r?"":"display:none;"),a.addEventListener("click",()=>{const u=s.style.display==="none";s.style.display=u?"":"none",q(c,u?"chevron-down":"chevron-right",12)}),a.appendChild(i),a.appendChild(c),l.appendChild(a),s.appendChild(Zt(o.visibility||{},t,n)),s.appendChild(en(o.requirement||{},t,n)),s.appendChild(tn(o.validation||[],t,n));const d=document.getElementById(`fb-type-${t}`)?.value||e.type;return Ie.has(d)&&s.appendChild(nn(o.cascade||{},t,n)),l.appendChild(s),l}const de=[{value:"banner",label:"Show a banner",kind:"state",params:["message","level","position","dismissible"],placeholder:"e.g. You must be 18 or over to continue."},{value:"toast",label:"Show a toast",kind:"event",params:["message","level"],placeholder:"e.g. Thanks - carry on."},{value:"hide-fields",label:"Hide fields",kind:"state",params:["target"]},{value:"disable-fields",label:"Disable fields",kind:"state",params:["target"]},{value:"require-fields",label:"Make fields required",kind:"state",params:["target"]},{value:"block-submit",label:"Block submission",kind:"state",params:["message"],messageLabel:"Reason, shown under the button",placeholder:'Blank: "This form cannot be submitted yet."'},{value:"end-form",label:"End the form here",kind:"state",params:["message","finish","finishLabel","doneMessage","record"],messageLabel:"Message shown in place of the rest",placeholder:"e.g. Sorry - you must be 18 or over to apply."},{value:"goto-step",label:"Jump to a wizard step",kind:"event",params:["step"]},{value:"redirect",label:"Redirect after submit",kind:"event",params:["url"]},{value:"celebrate",label:"Celebrate",kind:"event",params:["theme","intensity"]},{value:"run-action",label:"Run a CMS action",kind:"event",params:["slug"]},{value:"notify",label:"Notify the admins",kind:"event",params:["message","level"],messageLabel:"Notification title",placeholder:"Blank: titled after the form",noOnce:!0,kindText:"when the form is submitted"}],Ee=[{value:"info",label:"Info"},{value:"success",label:"Success"},{value:"warning",label:"Warning"},{value:"error",label:"Error"}],ft=[{value:"field-below",label:"Below this field"},{value:"field-above",label:"Above this field"},{value:"form-top",label:"Top of the form"}],ht=[{value:"rest",label:"The rest of the form"},{value:"all",label:"Every other field"},{value:"listed",label:"Chosen fields"}],bt=[{value:"auto",label:"Whatever is in season"},{value:"christmas",label:"Christmas"},{value:"halloween",label:"Halloween"},{value:"valentines",label:"Valentine's Day"},{value:"guy-fawkes",label:"Guy Fawkes Night"},{value:"st-patricks",label:"St Patrick's Day"},{value:"st-andrews",label:"St Andrew's Day"},{value:"st-davids",label:"St David's Day"},{value:"st-georges",label:"St George's Day"}];function gt(e,t=!1){const o=(i,r)=>({value:i.name,label:`${i.label||i.name}${r?" (this field)":""}`,multi:Me(i)}),n=i=>i&&i.type!=="page-break"&&i.type!=="spacer"&&i.name,l=C.filter((i,r)=>r!==e&&n(i)).map(i=>o(i,!1)),a=C[e];return t&&n(a)?[o(a,!0),...l]:l}function Y(e,t,o){const n=document.createElement("select");return n.className=`form-select ${e}`,t.forEach(l=>{const a=document.createElement("option");a.value=l.value,a.textContent=l.label,l.value===o&&(a.selected=!0),n.appendChild(a)}),n}function ae(e,t,o){const n=document.createElement("input");return n.type="text",n.className=`form-input ${e}`,n.value=t==null?"":String(t),o&&(n.placeholder=o),n}function ze(e,t){const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost fb-trig-remove",t&&(o.title=t,o.setAttribute("aria-label",t)),q(o,"x"),o.addEventListener("click",n=>{n.stopPropagation(),e()}),o}function V(e,t,{full:o=!1,hint:n=""}={}){const l=document.createElement("label");l.className=`fb-trig-f${o?" fb-trig-f--full":""}`;const a=document.createElement("span");if(a.className="fb-trig-f-label",a.textContent=e,l.appendChild(a),l.appendChild(t),n){const i=document.createElement("span");i.className="fb-trig-f-hint",i.textContent=n,l.appendChild(i)}return l}function pe(e,t,o,n){const l=document.createElement("label");l.className="fb-trig-check",n&&(l.title=n);const a=document.createElement("input");return a.type="checkbox",a.className=`form-check ${e}`,a.checked=!!t,l.appendChild(a),l.appendChild(document.createTextNode(o)),l}function yt(e,t){const o=document.createElement("div");o.className="fb-trig-cond-row";const n=Y("fb-trig-cond-field",t,e?.field),l=Y("fb-trig-cond-op",ve,e?.operator),a=ae("fb-trig-cond-val",e?.value,"value"),i=()=>{const c=t.find(s=>s.value===n.value);Array.from(l.options).forEach(s=>{const d=ve.find(u=>u.value===s.value);s.textContent=c?.multi&&ut[s.value]||d?.label||s.value})},r=()=>{a.hidden=De.has(l.value)};return i(),r(),n.addEventListener("change",i),l.addEventListener("change",r),o.appendChild(n),o.appendChild(l),o.appendChild(a),o.appendChild(ze(()=>o.remove(),"Remove condition")),o}function vt(e,t){const o=document.createElement("div");o.className="fb-trig-params";const n=de.find(c=>c.value===(e.type||"banner"));if(!n)return o;const l=document.createElement("div");l.className="fb-trig-grid";const a=document.createElement("div");a.className="fb-trig-opts";const i=[];for(const c of n.params)switch(c){case"message":l.appendChild(V(n.messageLabel||"Message",ae("fb-trig-p-message",e.message,n.placeholder||""),{full:!0}));break;case"finish":a.appendChild(pe("fb-trig-p-finish-on",e.finish!==!1,"Let the visitor finish (send the answers given so far)",'Untick to stop the form dead: the submit button is disabled and nothing is sent, so nothing is saved and "Notify the admins" cannot fire.'));break;case"finishLabel":{const s=V("Button text",ae("fb-trig-p-finish",e.finishLabel,"Finish"));i.push(s),l.appendChild(s);break}case"doneMessage":{const s=V("Closing message",ae("fb-trig-p-done",e.doneMessage,"Blank: the form's own success message"));i.push(s),l.appendChild(s);break}case"record":{const s=pe("fb-trig-p-record",e.record!==!1,"Save the answers given so far",`Untick to keep nothing: no submission is stored and the form's email, webhook and actions do not run. A "Notify the admins" action still fires.`);i.push(s),a.appendChild(s);break}case"level":l.appendChild(V(n.value==="notify"?"Severity":"Level",Y("fb-trig-p-level",Ee,e.level||"info")));break;case"position":l.appendChild(V("Where",Y("fb-trig-p-position",ft,e.position||"field-below")));break;case"dismissible":a.appendChild(pe("fb-trig-p-dismissible",e.dismissible!==!1,"The visitor can dismiss it"));break;case"target":{const s=Y("fb-trig-p-target",ht,e.target||(e.fields?.length?"listed":"rest")),d=document.createElement("select");d.className="form-select fb-trig-p-fields",d.multiple=!0,d.size=4;const u=new Set(e.fields||[]);gt(t).forEach(m=>{const h=document.createElement("option");h.value=m.value,h.textContent=m.label,u.has(m.value)&&(h.selected=!0),d.appendChild(h)});const b=V("Fields",d,{hint:"Ctrl/Cmd-click to pick several"}),g=()=>{b.hidden=s.value!=="listed"};g(),s.addEventListener("change",g),l.appendChild(V("Which fields",s)),l.appendChild(b);break}case"step":{const s=ae("fb-trig-p-step",e.step,"0");s.type="number",s.min="0",l.appendChild(V("Step",s,{hint:"Counting from 0"}));break}case"url":l.appendChild(V("Send them to",ae("fb-trig-p-url",e.url,"/thank-you"),{full:!0}));break;case"theme":l.appendChild(V("Theme",Y("fb-trig-p-theme",bt,e.theme||"auto")));break;case"intensity":l.appendChild(V("Intensity",Y("fb-trig-p-intensity",[{value:"low",label:"Low"},{value:"medium",label:"Medium"},{value:"high",label:"High"}],e.intensity||"medium")));break;case"slug":{const s=[{value:"",label:he.length?"Choose an action":"No actions available"}].concat(he.map(d=>({value:d.slug,label:d.title||d.slug})));l.appendChild(V("Action",Y("fb-trig-p-slug",s,e.slug||""),{full:!0}));break}default:break}n.kind==="event"&&!n.noOnce&&a.appendChild(pe("fb-trig-p-once",!!e.once,"Only once","Fire the first time only, rather than every time the answer swings back."));const r=a.querySelector(".fb-trig-p-finish-on");if(r){const c=()=>i.forEach(s=>{s.hidden=!r.checked});c(),r.addEventListener("change",c)}return l.children.length&&o.appendChild(l),a.children.length&&o.appendChild(a),o}function an(e){return e?.kindText?e.kindText:e?.kind==="event"?"once, when it becomes true":"while it is true"}const on=(e,t=48)=>e.length>t?`${e.slice(0,t-1)}\u2026`:e,oe=(e,t)=>e.find(o=>o.value===t)?.label||t;function sn(e){if(!e)return"";const t=[],o=l=>l?`"${on(l)}"`:"",n=()=>e.target==="listed"?e.fields?.length?e.fields.join(", "):"no fields chosen":oe(ht,e.target||"rest").toLowerCase();switch(e.type){case"banner":t.push(o(e.message)||"No message yet",oe(Ee,e.level||"info"),oe(ft,e.position||"field-below").toLowerCase());break;case"toast":t.push(o(e.message)||"No message yet",oe(Ee,e.level||"info"));break;case"hide-fields":case"disable-fields":case"require-fields":t.push(n());break;case"block-submit":t.push(o(e.message)||"the standard reason");break;case"end-form":t.push(o(e.message)||"no message"),e.finish===!1?t.push("submit disabled"):t.push(`button "${e.finishLabel||"Finish"}"`,e.record===!1?"saves nothing":"saves the answers");break;case"goto-step":t.push(Number.isFinite(e.step)?`step ${e.step}`:"no step yet");break;case"redirect":t.push(e.url||"no address yet");break;case"celebrate":t.push(oe(bt,e.theme||"auto"),`${e.intensity||"medium"} intensity`);break;case"run-action":t.push(e.slug?he.find(l=>l.slug===e.slug)?.title||e.slug:"no action chosen");break;case"notify":t.push(o(e.message)||"titled after the form",oe(Ee,e.level||"info"));break;default:break}return e.once&&t.push("only once"),t.filter(Boolean).join(" \xB7 ")}function Pe(e,t,{open:o=!1}={}){const n=document.createElement("div");n.className="fb-trig-action-row";const l=document.createElement("div");l.className="fb-trig-action-head",l.tabIndex=0,l.setAttribute("role","button");const a=document.createElement("span");a.className="fb-trig-chevron";const i=document.createElement("span");i.className="fb-trig-action-main";const r=document.createElement("strong"),c=document.createElement("small");c.className="fb-trig-action-summary",i.append(r,c);const s=document.createElement("span");s.className="fb-trig-kind",l.append(a,i,s,ze(()=>n.remove(),"Remove action"));const d=document.createElement("div");d.className="fb-trig-action-body";const u=Y("fb-trig-action-type",de,e.type||"banner");d.appendChild(V("Action",u,{full:!0})),d.appendChild(vt(e,t));const b=()=>{const m=de.find(h=>h.value===u.value);r.textContent=m?.label||u.value,s.textContent=an(m),s.classList.toggle("fb-trig-kind--event",m?.kind==="event"),c.textContent=sn(wt(n))},g=m=>{d.hidden=!m,n.classList.toggle("is-open",m),l.setAttribute("aria-expanded",String(m)),q(a,m?"chevron-down":"chevron-right",12)};return l.addEventListener("click",()=>g(d.hidden)),l.addEventListener("keydown",m=>{m.target!==l||m.key!=="Enter"&&m.key!==" "||(m.preventDefault(),g(d.hidden))}),u.addEventListener("change",()=>{const m=vt({type:u.value},t);d.replaceChild(m,d.querySelector(".fb-trig-params")),b(),window.I?.scan?.()}),d.addEventListener("input",b),d.addEventListener("change",b),n.append(l,d),g(o),b(),n}function xt(e,t,o){const n=document.createElement("section");n.className=`fb-trig-sec fb-trig-sec--${e}`;const l=document.createElement("div");l.className="fb-trig-sec-head";const a=document.createElement("span");if(a.className="fb-trig-sec-title",a.textContent=t,l.appendChild(a),o){const i=document.createElement("span");i.className="fb-trig-sec-hint",i.textContent=o,l.appendChild(i)}return n.appendChild(l),n}function _e(e,t){const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost fb-trig-add",re(o,"plus",e,12),o.addEventListener("click",t),o}function Ct(e,t,o,n){const a=xt(e,t,e==="then"?"What happens while the answers match.":"What happens while they do not. Leave empty for nothing.");a.classList.add("fb-trig-branch"),a.dataset.branch=e;const i=document.createElement("div");return i.className="fb-trig-action-list",(o||[]).forEach(r=>i.appendChild(Pe(r,n))),a.appendChild(i),a.appendChild(_e("Add action",()=>{i.appendChild(Pe({type:"banner"},n,{open:!0})),window.I?.scan?.()})),a}function Et(e,t,o){const n=gt(t,!0),l=document.createElement("div");l.className="fb-trig-card",l.dataset.triggerId=e.id||`trg-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;const a=document.createElement("div");a.className="fb-trig-card-head";const i=document.createElement("span");i.className="fb-trig-card-title",i.textContent=`Trigger ${o+1}`,a.appendChild(i);const r=pe("fb-trig-enabled",e.enabled!==!1,"Enabled","Untick to keep the trigger but switch it off.");if(a.appendChild(r),a.appendChild(ze(()=>l.remove(),"Remove trigger")),l.appendChild(a),!n.length){const u=document.createElement("p");return u.className="fb-trig-empty",u.textContent="Give this field a name first - a trigger tests an answer, and it needs something to test.",l.appendChild(u),l}const c=xt("when","When");c.querySelector(".fb-trig-sec-head").appendChild(Y("fb-trig-match",[{value:"all",label:"all of these are true"},{value:"any",label:"any of these is true"}],Array.isArray(e.when?.any)?"any":"all"));const s=document.createElement("div");s.className="fb-trig-cond-list";const d=e.when?.all||e.when?.any||[];return(d.length?d:[{}]).forEach(u=>s.appendChild(yt(u,n))),c.appendChild(s),c.appendChild(_e("Add condition",()=>{s.appendChild(yt({},n)),window.I?.scan?.()})),l.appendChild(c),l.appendChild(Ct("then","Then",e.then,t)),l.appendChild(Ct("otherwise","Otherwise",e.otherwise,t)),l}function rn(e,t){const o=Array.isArray(e.triggers)?e.triggers:[],n=document.createElement("div");n.className="fb-field-triggers";const l=document.createElement("div");l.className="fb-trig-panel-head";const a=document.createElement("span");a.className="fb-trig-panel-title",a.textContent=`\u{1F3AF} Triggers${o.length?` (${o.length})`:""}`;const i=document.createElement("button");i.type="button",i.className="btn btn-xs btn-ghost",q(i,o.length?"chevron-down":"chevron-right",12);const r=document.createElement("div");r.className="fb-triggers-body",r.hidden=!o.length,l.addEventListener("click",()=>{r.hidden=!r.hidden,q(i,r.hidden?"chevron-right":"chevron-down",12)});const c=document.createElement("p");c.className="fb-trig-blurb",c.textContent="Do something to the form when the answers meet a condition - show a banner or toast, hide, disable or require other fields, refuse the submit, end the form early, notify the admins, jump to a step, or celebrate.",r.appendChild(c);const s=document.createElement("div");return s.className="fb-trig-list",o.forEach((d,u)=>s.appendChild(Et(d,t,u))),r.appendChild(s),r.appendChild(_e("Add trigger",()=>{const d=Et({enabled:!0,then:[]},t,s.children.length);s.appendChild(d),d.querySelector('.fb-trig-branch[data-branch="then"] .fb-trig-action-list')?.appendChild(Pe({type:"banner"},t,{open:!0})),window.I?.scan?.()})),l.appendChild(a),l.appendChild(i),n.appendChild(l),n.appendChild(r),n}function wt(e){const t=e.querySelector(".fb-trig-action-type")?.value,o=de.find(a=>a.value===t);if(!o)return null;const n={type:t},l=a=>e.querySelector(a)?.value?.trim()||"";for(const a of o.params)switch(a){case"message":n.message=l(".fb-trig-p-message");break;case"finishLabel":{const i=l(".fb-trig-p-finish");i&&(n.finishLabel=i);break}case"doneMessage":{const i=l(".fb-trig-p-done");i&&(n.doneMessage=i);break}case"finish":e.querySelector(".fb-trig-p-finish-on")?.checked||(n.finish=!1);break;case"record":e.querySelector(".fb-trig-p-record")?.checked||(n.record=!1);break;case"level":n.level=l(".fb-trig-p-level")||"info";break;case"position":n.position=l(".fb-trig-p-position")||"field-below";break;case"dismissible":n.dismissible=!!e.querySelector(".fb-trig-p-dismissible")?.checked;break;case"target":{const i=l(".fb-trig-p-target")||"rest";n.target=i,i==="listed"&&(n.fields=Array.from(e.querySelectorAll(".fb-trig-p-fields option")).filter(r=>r.selected).map(r=>r.value));break}case"step":{const i=parseInt(l(".fb-trig-p-step"),10);Number.isFinite(i)&&(n.step=i);break}case"url":n.url=l(".fb-trig-p-url");break;case"theme":n.theme=l(".fb-trig-p-theme")||"auto";break;case"intensity":n.intensity=l(".fb-trig-p-intensity")||"medium";break;case"slug":n.slug=l(".fb-trig-p-slug");break;default:break}return o.kind==="event"&&!o.noOnce&&e.querySelector(".fb-trig-p-once")?.checked&&(n.once=!0),n}function cn(e){const t=wt(e);if(!t)return null;const o=de.find(a=>a.value===t.type),n=t.type,l=["block-submit","end-form","notify"].includes(o.value);return o.params.includes("message")&&!t.message&&!l?(delete t.message,null):(l&&!t.message&&delete t.message,n==="redirect"&&!t.url||n==="run-action"&&!t.slug?null:t)}function dn(e){const o=document.querySelector(`.fb-field-card[data-index="${e}"]`)?.querySelector(".fb-field-triggers");if(!o)return;const n=[];return o.querySelectorAll(".fb-trig-card").forEach(l=>{const a=Array.from(l.querySelectorAll(".fb-trig-cond-row")).map(u=>{const b=u.querySelector(".fb-trig-cond-field")?.value,g=u.querySelector(".fb-trig-cond-op")?.value;if(!b||!g)return null;const m=u.querySelector(".fb-trig-cond-val")?.value??"";return{field:b,operator:g,value:m}}).filter(Boolean);if(!a.length)return;const i=u=>Array.from(l.querySelectorAll(`.fb-trig-branch[data-branch="${u}"] .fb-trig-action-row`)).map(cn).filter(Boolean),r=i("then"),c=i("otherwise");if(!r.length&&!c.length)return;const s=l.querySelector(".fb-trig-match")?.value==="any"?"any":"all",d={id:l.dataset.triggerId,enabled:!!l.querySelector(".fb-trig-enabled")?.checked,when:{[s]:a}};r.length&&(d.then=r),c.length&&(d.otherwise=c),n.push(d)}),n.length?n:void 0}function kt(e,t,o){const n=document.createElement("div");return n.className="fb-field-extras",e==="chooser"?(n.appendChild(pn(t,o)),n.appendChild(mn(t.options||[],o))):(Ie.has(e)&&n.appendChild(yn(t.options||[],o)),e==="textarea"&&n.appendChild(D([z("Rows",`fb-rows-${o}`,"number",t.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&n.appendChild(D([z("Min Length",`fb-minlength-${o}`,"number",t.minLength||"",""),z("Max Length",`fb-maxlength-${o}`,"number",t.maxLength||"","")])),e==="number"&&n.appendChild(D([z("Min",`fb-min-${o}`,"number",t.min??"",""),z("Max",`fb-max-${o}`,"number",t.max??"","")]))),n.children.length?n:null}function St(e){const t=document.createElement("div");t.className="fb-chooser-section",t.style.cssText="border:1px solid var(--dm-border); border-radius:6px; margin-top:.5rem; overflow:hidden;";const o=document.createElement("div");o.style.cssText="padding:.4rem .6rem; background:color-mix(in srgb, var(--dm-background) 60%, transparent); font-weight:600; font-size:.82rem; border-bottom:1px solid var(--dm-border);",o.textContent=e,t.appendChild(o);const n=document.createElement("div");return n.className="fb-chooser-section-body",n.style.cssText="padding:.55rem .6rem; display:flex; flex-direction:column; gap:.45rem;",t.appendChild(n),{wrap:t,body:n}}function we(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=t,i.style.fontSize=".8rem";const r=document.createElement("select");if(r.id=e,r.className="form-input",n.forEach(([c,s])=>{const d=document.createElement("option");d.value=c,d.textContent=s,String(c)===String(o)&&(d.selected=!0),r.appendChild(d)}),a.appendChild(i),a.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(c)}return a}function Tt(e,t,o,n){const l=document.createElement("div");l.style.flex="1";const a=document.createElement("label");a.style.cssText="display:inline-flex;align-items:center;gap:.4rem;font-size:.82rem;";const i=document.createElement("input");if(i.id=e,i.type="checkbox",i.checked=!!o,a.appendChild(i),a.appendChild(document.createTextNode(" "+t)),l.appendChild(a),n){const r=document.createElement("p");r.className="form-hint text-muted",r.textContent=n,r.style.cssText="font-size:.72rem;margin-top:.2rem;",l.appendChild(r)}return l}function je(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=t,i.style.fontSize=".8rem",a.appendChild(i);const r=document.createElement("div");r.style.cssText="display:flex;gap:.4rem;align-items:stretch;";const c=document.createElement("input");c.id=e,c.type="text",c.className="form-input",c.value=o||"",n&&(c.placeholder=n),c.style.flex="1";const s=document.createElement("input");s.type="color",s.title="Pick a colour",s.style.cssText="width:36px;height:auto;padding:0;border:1px solid var(--dm-border);border-radius:4px;cursor:pointer;";const d=String(c.value).match(/^#[0-9a-fA-F]{3,8}$/);if(s.value=d?c.value:"#000000",s.addEventListener("input",()=>{c.value=s.value,c.dispatchEvent(new Event("input",{bubbles:!0}))}),r.appendChild(c),r.appendChild(s),a.appendChild(r),l){const u=document.createElement("p");u.className="form-hint text-muted",u.textContent=l,u.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(u)}return a}function pn(e,t){const o=document.createElement("div");o.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const n=St("Layout");n.body.appendChild(D([we(`fb-chooser-variant-${t}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),Tt(`fb-chooser-multiple-${t}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),n.body.appendChild(D([we(`fb-chooser-density-${t}`,"Density",e.density||"comfortable",[["comfortable","Comfortable"],["compact","Compact"]],"Compact strips description (card variant only)."),z("Columns",`fb-chooser-columns-${t}`,"number",e.columns||3,"Card grid (1-6). Ignored for chips.")])),o.appendChild(n.wrap);const l=St("Visual");return l.body.appendChild(D([je(`fb-chooser-accent-${t}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),we(`fb-chooser-accent-style-${t}`,"Accent style",e.accentStyle||"border",[["border","Border (default)"],["solid","Solid"],["glow","Glow"],["overlay","Overlay"],["underline","Underline"]],"Visual treatment of the selected state.")])),l.body.appendChild(D([Tt(`fb-chooser-glow-${t}`,"Glow on selected",!!e.glow,"Soft outer glow."),je(`fb-chooser-glow-colour-${t}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),l.body.appendChild(D([we(`fb-chooser-shadow-${t}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),je(`fb-chooser-shadow-colour-${t}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),o.appendChild(l.wrap),o}function un(e,t,o,n){const l=document.createElement("div");l.className="fb-chooser-option-row",l.dataset.optIdx=String(o),l.style.cssText="border:1px solid var(--dm-border); border-radius:4px; padding:.5rem; background:var(--dm-background-alt); display:flex; flex-direction:column; gap:.35rem;";const a=document.createElement("div");a.style.cssText="display:flex; gap:.4rem; align-items:center;";const i=document.createElement("div");i.style.cssText="display:flex; flex-direction:column; gap:1px;";const r=document.createElement("button");r.type="button",r.className="btn btn-xs btn-ghost",r.title="Move up",q(r,"arrow-up"),r.addEventListener("click",I=>{I.preventDefault(),Nt(t,o,-1,n)});const c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",c.title="Move down",q(c,"arrow-down"),c.addEventListener("click",I=>{I.preventDefault(),Nt(t,o,1,n)}),i.appendChild(r),i.appendChild(c),a.appendChild(i);const s=document.createElement("input");s.type="text",s.className="form-input fb-chooser-opt-value",s.placeholder="value",s.value=e.value||"",s.style.flex="1",a.appendChild(s);const d=document.createElement("input");d.type="text",d.className="form-input fb-chooser-opt-label",d.placeholder="label (visible to users)",d.value=e.label||"",d.style.flex="2",a.appendChild(d);const u=document.createElement("button");u.type="button",u.className="btn btn-xs btn-ghost",u.style.cssText="line-height:1;opacity:.6;",u.title="Remove option",q(u,"x"),u.addEventListener("click",I=>{I.preventDefault(),bn(t,o,n)}),a.appendChild(u),l.appendChild(a);const b=document.createElement("div");b.style.cssText="display:flex; gap:.4rem;";const g=Mt("icon name (optional)",e.icon||"");g.input.classList.add("fb-chooser-opt-icon"),g.el.style.flex="1",b.appendChild(g.el);const m=document.createElement("input");m.type="text",m.className="form-input fb-chooser-opt-description",m.placeholder="description (card + comfortable only)",m.value=e.description||"",m.style.flex="2",b.appendChild(m),l.appendChild(b);const h=document.createElement("div");h.style.cssText="display:flex; gap:.4rem;";const w=document.createElement("input");w.type="text",w.className="form-input fb-chooser-opt-tooltip",w.placeholder="tooltip (hover hint)",w.value=e.tooltip||"",w.style.flex="2",h.appendChild(w);const f=document.createElement("input");f.type="text",f.className="form-input fb-chooser-opt-badge-text",f.placeholder="badge text",f.value=e.badge?.text||"",f.style.flex="1",h.appendChild(f);const x=document.createElement("select");x.className="form-input fb-chooser-opt-badge-type",x.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([I,Q])=>{const H=document.createElement("option");H.value=I,H.textContent=Q,(e.badge?.type||"")===I&&(H.selected=!0),x.appendChild(H)}),h.appendChild(x),l.appendChild(h);const $=document.createElement("div");$.style.cssText="display:flex; gap:1rem; font-size:.8rem;";const A=document.createElement("label");A.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const G=document.createElement("input");G.type="checkbox",G.className="fb-chooser-opt-recommended",G.checked=!!e.recommended,A.appendChild(G),A.appendChild(document.createTextNode(" Recommended")),$.appendChild(A);const P=document.createElement("label");P.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const _=document.createElement("input");return _.type="checkbox",_.className="fb-chooser-opt-disabled",_.checked=!!e.disabled,P.appendChild(_),P.appendChild(document.createTextNode(" Disabled")),$.appendChild(P),l.appendChild($),l}function mn(e,t){const o=document.createElement("div");o.style.cssText="margin-top:.5rem;";const n=document.createElement("div");n.style.cssText="display:flex; align-items:center; justify-content:space-between; margin-bottom:.4rem;";const l=document.createElement("p");l.textContent="Options",l.style.cssText="font-size:.85rem;font-weight:600;margin:0;",n.appendChild(l);const a=document.createElement("button");a.type="button",a.className="btn btn-xs btn-ghost",re(a,"plus","Add option"),n.appendChild(a),o.appendChild(n);const i=document.createElement("div");i.className="fb-chooser-options-list",i.id=`fb-chooser-options-${t}`,i.style.cssText="display:flex; flex-direction:column; gap:.4rem;",o.appendChild(i);const r=()=>{i.replaceChildren();const c=fn(t);(c.length?c:e||[]).forEach((d,u)=>{i.appendChild(un(d,t,u,r))})};return a.addEventListener("click",c=>{c.preventDefault(),hn(t,r)}),r(),o}function fn(e){const t=C[e];return!t||!Array.isArray(t.options)?[]:t.options}function Ve(e){return C[e]?(Array.isArray(C[e].options)||(C[e].options=[]),C[e].options):[]}function hn(e,t){ke(e),Ve(e).push({value:"new",label:"New option"}),t()}function bn(e,t,o){ke(e),Ve(e).splice(t,1),o()}function Nt(e,t,o,n){ke(e);const l=Ve(e),a=t+o;if(a<0||a>=l.length)return;const[i]=l.splice(t,1);l.splice(a,0,i),n()}function ke(e){const t=document.getElementById(`fb-chooser-options-${e}`);if(!t)return;const o=t.querySelectorAll(".fb-chooser-option-row"),n=[];o.forEach(l=>{const a={value:l.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:l.querySelector(".fb-chooser-opt-label")?.value.trim()||""},i=l.querySelector(".fb-chooser-opt-icon")?.value.trim();i&&(a.icon=i);const r=l.querySelector(".fb-chooser-opt-description")?.value.trim();r&&(a.description=r);const c=l.querySelector(".fb-chooser-opt-tooltip")?.value.trim();c&&(a.tooltip=c);const s=l.querySelector(".fb-chooser-opt-badge-text")?.value.trim(),d=l.querySelector(".fb-chooser-opt-badge-type")?.value;(s||d)&&(a.badge={},s&&(a.badge.text=s),d&&(a.badge.type=d)),l.querySelector(".fb-chooser-opt-recommended")?.checked&&(a.recommended=!0),l.querySelector(".fb-chooser-opt-disabled")?.checked&&(a.disabled=!0),n.push(a)}),C[e]&&(C[e].options=n)}function D(e){const t=document.createElement("div");return t.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(o=>{o&&t.appendChild(o)}),t}function z(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=t,i.className="form-label",i.textContent=e,i.style.fontSize=".8rem";const r=document.createElement("input");if(r.id=t,r.type=o||"text",r.className="form-input",r.value=n??"",a.appendChild(i),a.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.73rem;margin-top:.35rem;",a.appendChild(c)}return a}function gn(e,t,o,n){const l=document.createElement("div");l.style.flex="1";const a=document.createElement("label");a.htmlFor=t,a.className="form-label",a.textContent=e,a.style.fontSize=".8rem";const i=document.createElement("select");return i.id=t,i.className="form-select",o.forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===n&&(c.selected=!0),i.appendChild(c)}),l.appendChild(a),l.appendChild(i),l}function Lt(e,t,o){const n=document.createElement("div");n.style.cssText="flex:0;min-width:80px;display:flex;flex-direction:column;justify-content:flex-end;";const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;font-size:.8rem;white-space:nowrap;";const a=document.createElement("input");return a.id=t,a.type="checkbox",a.checked=o,l.appendChild(a),l.appendChild(document.createTextNode(e)),n.appendChild(l),n}function yn(e,t){const o=document.createElement("div");o.style.cssText="margin-top:.4rem;";const n=document.createElement("p");n.textContent="Options (one per line: value or value:Label)",n.style.cssText="font-size:.8rem;font-weight:600;margin-bottom:.3rem;";const l=document.createElement("textarea");return l.id=`fb-options-${t}`,l.className="form-input",l.rows=4,l.placeholder=`yes:Yes
1
+ import{apiRequest as ie}from"/admin/js/api.js";import{makeIconInput as Mt}from"/admin/js/lib/shortcode-modal.js";import{enhancePickerFields as et}from"/public/js/forms.js";import{buildWizardSteps as zt}from"/public/js/form-steps.mjs";import{addBannerAction as qe}from"../lib/plugin-chrome.js";import{helpPopovers as Dt}from"../lib/help-popover.js";import{openMenuAt as tt,sidebarCount as Pt}from"../lib/tool-kit.js";import{draftKey as se,draftOf as _t,duplicateField as jt,fieldTitle as $e,fingerprint as nt,leavingEditor as lt,moveField as at,restoreDraft as Vt,snapshotOf as Ae}from"../lib/form-editor-arrange.js";import{fmtDateTime as Gt}from"../lib/dates.js";const ot=[{value:"string",label:"Text (single line)"},{value:"email",label:"Email"},{value:"tel",label:"Phone"},{value:"number",label:"Number"},{value:"textarea",label:"Textarea (multi-line)"},{value:"select",label:"Dropdown (select)"},{value:"radio",label:"Radio buttons"},{value:"checkbox",label:"Single checkbox"},{value:"checkbox-group",label:"Checkbox group"},{value:"chooser",label:"Chooser (visual options)"},{value:"icon",label:"Icon (icon picker)"},{value:"image",label:"Image (media library)"},{value:"date",label:"Date"},{value:"time",label:"Time"},{value:"url",label:"URL"},{value:"password",label:"Password"},{value:"file",label:"File upload"},{value:"hidden",label:"Hidden field"}],Fe=new Set(["select","radio","checkbox-group","chooser"]);let C=[],fe=[],N=null,he=null,ne=null,be={};function q(e,t,o=14){e.textContent="";const n=document.createElement("span");return n.setAttribute("data-icon",t),n.setAttribute("data-icon-size",String(o)),n.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(n),window.I?.scan?.(e),e}function re(e,t,o,n=14){return q(e,t,n),e.appendChild(document.createTextNode(" "+o)),e}function Ie(e){const t=document.createElement("span");return t.setAttribute("data-icon","help-circle"),t.setAttribute("data-icon-size","12"),t.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;margin-left:.3rem;opacity:.55;cursor:help;",t.title=e,window.I?.scan?.(t),requestAnimationFrame(()=>{try{t.parentNode&&typeof E<"u"&&E.tooltip&&(t.removeAttribute("title"),E.tooltip(t,{content:e,position:"top"}))}catch{}}),t}let ge=null,it=null,Be=null,ce=null;function Oe(){Be?.(),clearTimeout(it),it=setTimeout(()=>{ge&&ge()},350)}function st(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_|_$/g,"")}function rt(e){return ot.find(t=>t.value===e)?.label||e}function ct(e){return(e||[]).some(t=>t.logic||Array.isArray(t.triggers)&&t.triggers.length)}function dt(e){return e?!!(e.visibility?.conditions?.length||e.requirement?.conditions?.length||e.validation?.length||e.cascade?.sourceField):!1}function Wt(e){const t={...C[e]};if(t.type==="spacer")return t;if(t.type==="page-break"){const h=document.getElementById(`fb-pb-label-${e}`),x=document.getElementById(`fb-pb-desc-${e}`);return h&&(t.label=h.value.trim()||t.label),x&&(t.description=x.value.trim()),t}const o=document.getElementById(`fb-label-${e}`),n=document.getElementById(`fb-name-${e}`),l=document.getElementById(`fb-type-${e}`),a=document.getElementById(`fb-required-${e}`),i=document.getElementById(`fb-placeholder-${e}`),r=document.getElementById(`fb-helper-${e}`),c=document.getElementById(`fb-tooltip-${e}`);if(o&&(t.label=o.value.trim()||t.label),n&&(t.name=n.value.trim()||t.name),l&&(t.type=l.value||t.type),a&&(t.required=a.checked),i&&(t.placeholder=i.value.trim()),r&&(t.helper=r.value.trim()),c&&(t.tooltip=c.value.trim()),t.type==="chooser"){const h=document.getElementById(`fb-chooser-variant-${e}`)?.value;h&&(t.variant=h);const x=document.getElementById(`fb-chooser-multiple-${e}`);x&&(t.multiple=x.checked);const $=document.getElementById(`fb-chooser-density-${e}`)?.value;$&&(t.density=$);const A=document.getElementById(`fb-chooser-columns-${e}`)?.value;A!==""&&A!==void 0&&(t.columns=parseInt(A,10)||3);const G=document.getElementById(`fb-chooser-accent-${e}`)?.value.trim();G?t.accent=G:delete t.accent;const _=document.getElementById(`fb-chooser-accent-style-${e}`)?.value;_?t.accentStyle=_:delete t.accentStyle;const j=document.getElementById(`fb-chooser-glow-${e}`);j&&(t.glow=j.checked);const I=document.getElementById(`fb-chooser-glow-colour-${e}`)?.value.trim();I?t.glowColour=I:delete t.glowColour;const X=document.getElementById(`fb-chooser-shadow-${e}`)?.value;X&&X!=="none"?t.shadow=X:delete t.shadow;const H=document.getElementById(`fb-chooser-shadow-colour-${e}`)?.value.trim();H?t.shadowColour=H:delete t.shadowColour,we(e),C[e]&&Array.isArray(C[e].options)&&(t.options=C[e].options)}else if(Fe.has(t.type)){["variant","density","columns","accent","accentStyle","glow","glowColour","shadow","shadowColour"].forEach(x=>delete t[x]),t.type!=="checkbox-group"&&t.type!=="multiselect"&&delete t.multiple;const h=document.getElementById(`fb-options-${e}`);h&&(t.options=h.value.split(`
2
+ `).filter(x=>x.trim()).map(x=>{const[$,...A]=x.split(":");return{value:$.trim(),label:A.join(":").trim()||$.trim()}}))}if(t.type==="textarea"){const h=parseInt(document.getElementById(`fb-rows-${e}`)?.value,10);h>0&&(t.formConfig={...t.formConfig||{},rows:h})}const s=document.getElementById(`fb-span-${e}`),d=document.getElementById(`fb-fullwidth-${e}`);if(s||d){const h={...t.formConfig||{}};if(d?.checked)h.span="full";else{const x=parseInt(s?.value,10);x>1?h.span=x:delete h.span}t.formConfig=Object.keys(h).length?h:void 0}const u=document.getElementById(`fb-minlength-${e}`)?.value;u&&(t.minLength=parseInt(u,10));const b=document.getElementById(`fb-maxlength-${e}`)?.value;b&&(t.maxLength=parseInt(b,10));const y=document.getElementById(`fb-min-${e}`)?.value;y!==""&&y!==void 0&&(t.min=parseFloat(y));const m=document.getElementById(`fb-max-${e}`)?.value;m!==""&&m!==void 0&&(t.max=parseFloat(m));const f=Ht(e);f?t.logic=f:delete t.logic;const k=cn(e);return k?t.triggers=k:delete t.triggers,t}function Ht(e){const t=document.querySelector(`.fb-field-card[data-index="${e}"]`);if(!t)return;const o=t.querySelector(".fb-field-logic");if(!o)return;const n={};let l=!1;const a=o.querySelector('[data-logic-section="visibility"]');if(a){const s=a.querySelector(".fb-logic-vis-default"),d=a.querySelector(".fb-logic-vis-transition"),u=Array.from(a.querySelectorAll(".fb-logic-cond-row")).map(f=>{const k=f.querySelector(".fb-logic-cond-field"),h=f.querySelector(".fb-logic-cond-op"),x=f.querySelector(".fb-logic-cond-val"),$=f.querySelector(".fb-logic-vis-then");return k?.value?{when:{all:[{field:k.value,operator:h.value,value:x.value}]},then:$.value}:null}).filter(Boolean),b=s?.value||"visible",y=d?.value||"none",m=parseInt(a.querySelector(".fb-logic-vis-duration")?.value||"",10);(b!=="visible"||u.length>0||y!=="none")&&(n.visibility={default:b,conditions:u},y!=="none"&&(n.visibility.transition=y),y!=="none"&&Number.isFinite(m)&&(n.visibility.duration=m),l=!0)}const i=o.querySelector('[data-logic-section="requirement"]');if(i){const s=i.querySelector(".fb-logic-req-default"),d=Array.from(i.querySelectorAll(".fb-logic-cond-row")).map(u=>{const b=u.querySelector(".fb-logic-cond-field"),y=u.querySelector(".fb-logic-cond-op"),m=u.querySelector(".fb-logic-cond-val"),f=u.querySelector(".fb-logic-req-then");return b?.value?{when:{all:[{field:b.value,operator:y.value,value:m.value}]},then:f.value==="true"}:null}).filter(Boolean);d.length>0&&(n.requirement={default:s?.checked===!0,conditions:d},l=!0)}const r=o.querySelector('[data-logic-section="validation"]');if(r){const s=Array.from(r.querySelectorAll(".fb-logic-val-rule")).map(d=>{const u=d.querySelector(".fb-logic-val-type"),b=d.querySelector(".fb-logic-val-pattern"),y=d.querySelector(".fb-logic-val-flags"),m=d.querySelector(".fb-logic-val-message");if(!b?.value.trim())return null;const f=u?.value||"regex",k={type:f,message:m?.value.trim()||"Invalid value."};return f==="regex"?(k.pattern=b.value.trim(),y?.value.trim()&&(k.flags=y.value.trim())):k.field=b.value.trim(),k}).filter(Boolean);s.length>0&&(n.validation=s,l=!0)}const c=o.querySelector('[data-logic-section="cascade"]');if(c){const s=c.querySelector(".fb-logic-cascade-source"),d=c.querySelector(".fb-logic-cascade-mapping"),u=c.querySelector(".fb-logic-cascade-defaults"),b=s?.value?.trim();if(b){let y={};try{y=JSON.parse(d?.value||"{}")}catch{}const m=(u?.value||"").split(`
3
+ `).filter(f=>f.trim()).map(f=>{const[k,...h]=f.split(":");return{value:k.trim(),label:h.join(":").trim()||k.trim()}});n.cascade={sourceField:b,mapping:y,defaultOptions:m},l=!0}}return l?n:void 0}function z(){C=C.map((e,t)=>Wt(t))}function Ut(e){const t=e.firstElementChild;if(!t||t.querySelector(".fb-drag-grip"))return;const o=document.createElement("span");o.className="fb-drag-grip",o.setAttribute("data-icon","grip-vertical"),o.setAttribute("data-icon-size","16"),o.title="Drag to reorder",t.insertBefore(o,t.firstChild),window.I?.scan?.(t)}function Q(e){const t=e.find("#fields-list").get(0),o=e.find("#fields-empty-msg").get(0);if(t){if(Array.from(t.querySelectorAll(".fb-field-card")).forEach(n=>n.remove()),C.length===0){o&&(o.style.display=""),ce?.(t),Oe();return}o&&(o.style.display="none"),C.forEach((n,l)=>{const a=n.type==="page-break"?Jt(n,l,e):n.type==="spacer"?Yt(n,l,e):Kt(n,l,e);Ut(a),t.appendChild(a)}),ce?.(t),Oe()}}function Jt(e,t,o){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:2px dashed var(--dm-border);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.6rem .8rem;cursor:pointer;user-select:none;";const a=document.createElement("span");a.textContent="- Page Break -",a.style.cssText="font-size:.7rem;padding:.15rem .5rem;border-radius:999px;background:color-mix(in srgb, var(--dm-text-muted) 20%, transparent);color:var(--dm-text-muted);white-space:nowrap;flex-shrink:0;font-style:italic;";const i=document.createElement("span");i.textContent=e.label||"Untitled Step",i.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dm-text-muted);";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit step",q(c,"more-horizontal"),c.addEventListener("click",y=>{y.stopPropagation(),d.style.display=d.style.display==="none"?"":"none"}),r.appendChild(c);const s=document.createElement("button");s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove page break",q(s,"x"),s.addEventListener("click",async y=>{y.stopPropagation(),await E.confirm("Remove this page break?")&&(z(),C.splice(t,1),Q(o))}),r.appendChild(s),l.appendChild(a),l.appendChild(i),l.appendChild(r),l.addEventListener("click",()=>{d.style.display=d.style.display==="none"?"":"none"});const d=document.createElement("div");d.className="fb-field-body",d.style.cssText="padding:.8rem;border-top:1px dashed var(--dm-border);display:none;";const u=D([P("Step Title",`fb-pb-label-${t}`,"text",e.label||"","Shown as the wizard step heading"),P("Step Description",`fb-pb-desc-${t}`,"text",e.description||"","Optional sub-heading")]),b=u.querySelector(`#fb-pb-label-${t}`);return b&&b.addEventListener("input",()=>{i.textContent=b.value||"Untitled Step"}),d.appendChild(u),n.appendChild(l),n.appendChild(d),n}function Yt(e,t,o){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px dashed var(--dm-border);border-radius:6px;margin-bottom:.5rem;background:transparent;";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.4rem .8rem;";const a=document.createElement("div");a.style.cssText="flex:1;height:1px;background:var(--dm-border);";const i=document.createElement("span");i.textContent="Spacer",i.style.cssText="font-size:.7rem;color:var(--dm-text-muted);white-space:nowrap;padding:0 .4rem;font-style:italic;";const r=document.createElement("div");r.style.cssText="flex:1;height:1px;background:var(--dm-border);";const c=document.createElement("div");c.style.cssText="display:flex;gap:.25rem;flex-shrink:0;";const s=document.createElement("button");return s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove spacer",q(s,"x"),s.addEventListener("click",async d=>{d.stopPropagation(),z(),C.splice(t,1),Q(o)}),c.appendChild(s),l.appendChild(a),l.appendChild(i),l.appendChild(r),l.appendChild(c),n.appendChild(l),n}function Kt(e,t,o){const n=document.createElement("div");n.className="fb-field-card",n.dataset.index=t,n.style.cssText="border:1px solid var(--dm-border);border-radius:8px;overflow:hidden;margin-bottom:.75rem;background:var(--dm-card-bg);box-shadow:var(--dm-shadow-sm);";const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;padding:.65rem .85rem;background:var(--dm-card-header-bg);cursor:pointer;user-select:none;";const a=document.createElement("span");a.textContent=rt(e.type),a.style.cssText="font-size:.7rem;padding:.15rem .45rem;border-radius:999px;background:color-mix(in srgb, var(--dm-primary) 14%, transparent);color:var(--dm-primary);white-space:nowrap;flex-shrink:0;";const i=document.createElement("span");i.textContent=e.label||"(unlabelled)",i.style.cssText="flex:1;font-weight:600;font-size:.9rem;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;";const r=document.createElement("div");r.style.cssText="display:flex;gap:.25rem;flex-shrink:0;margin-left:.5rem;";const c=document.createElement("button");c.className="btn btn-xs btn-ghost",c.title="Edit field",q(c,"more-horizontal"),c.addEventListener("click",u=>{u.stopPropagation(),d.style.display=d.style.display==="none"?"":"none"}),r.appendChild(c);const s=document.createElement("button");if(s.className="btn btn-xs btn-ghost",s.style.cssText="line-height:1;opacity:.6;",s.title="Remove field",q(s,"x"),s.addEventListener("click",async u=>{u.stopPropagation(),await E.confirm("Remove this field?")&&(z(),C.splice(t,1),Q(o))}),r.appendChild(s),l.appendChild(a),l.appendChild(i),e.required){const u=document.createElement("span");u.textContent="required",u.style.cssText="font-size:.7rem;color:var(--dm-danger);flex-shrink:0;",l.appendChild(u)}if(dt(e.logic)){const u=document.createElement("span");q(u,"zap"),u.title="Has conditional logic",u.style.cssText="font-size:.75rem;color:var(--dm-primary);flex-shrink:0;",l.appendChild(u)}l.appendChild(r),l.addEventListener("click",()=>{d.style.display=d.style.display==="none"?"":"none"});const d=Qt(e,t,i);return d.style.display="none",n.appendChild(l),n.appendChild(d),n}function Qt(e,t,o){const n=document.createElement("div");n.className="fb-field-body",n.style.cssText="padding:1rem .9rem;border-top:1px solid var(--dm-border);";const l=D([P("Label",`fb-label-${t}`,"text",e.label||"","Shown above the field"),P("Field Name",`fb-name-${t}`,"text",e.name||"","Used as data key")]),a=D([bn("Type",`fb-type-${t}`,ot,e.type||"string"),Nt("Required",`fb-required-${t}`,e.required||!1)]),i=D([P("Placeholder",`fb-placeholder-${t}`,"text",e.placeholder||"","Hint text inside the field")]),r=D([P("Helper Text",`fb-helper-${t}`,"text",e.helper||"","Shown below the field"),P("Tooltip",`fb-tooltip-${t}`,"text",e.tooltip||"","Shown on hover via a help icon next to the label")]),c=e.formConfig?.span,s=D([P("Column Span",`fb-span-${t}`,"number",c&&c!=="full"?String(c):"1","Columns to span (grid only)"),Nt("Full Width",`fb-fullwidth-${t}`,c==="full")]);s.classList.add("fb-grid-row"),s.style.display=document.getElementById("setting-layout")?.value==="grid"?"flex":"none",n.appendChild(l),n.appendChild(a),n.appendChild(i),n.appendChild(r),n.appendChild(s);const d=n.querySelector(`#fb-label-${t}`),u=n.querySelector(`#fb-name-${t}`);d&&d.addEventListener("input",()=>{o&&(o.textContent=d.value||"(unlabelled)"),u&&!u.dataset.manuallyEdited&&(u.value=st(d.value))}),u&&u.addEventListener("input",()=>{u.dataset.manuallyEdited="1"});const b=n.querySelector(`#fb-type-${t}`);b&&b.addEventListener("change",()=>{const m=n.closest(".fb-field-card");if(m){const h=m.querySelector("span");h&&(h.textContent=rt(b.value))}const f=n.querySelector(".fb-field-extras");f&&f.remove();const k=wt(b.value,e,t);k&&n.appendChild(k)});const y=wt(e.type,e,t);return y&&n.appendChild(y),n.appendChild(nn(e,t)),n.appendChild(sn(e,t)),n}const ye=[{value:"equals",label:"equals"},{value:"not_equals",label:"does not equal"},{value:"contains",label:"contains"},{value:"not_contains",label:"does not contain"},{value:"starts_with",label:"starts with"},{value:"ends_with",label:"ends with"},{value:"greater_than",label:"is greater than"},{value:"less_than",label:"is less than"},{value:"is_empty",label:"is empty"},{value:"is_not_empty",label:"is not empty"},{value:"in",label:"is one of (comma sep)"},{value:"not_in",label:"is not one of (comma sep)"},{value:"matches_regex",label:"matches regex"}],Re=new Set(["is_empty","is_not_empty"]),pt={equals:"includes",not_equals:"does not include",contains:"any value contains",not_contains:"no value contains",starts_with:"any value starts with",ends_with:"any value ends with",greater_than:"any value is greater than",less_than:"any value is less than",is_empty:"nothing selected",is_not_empty:"something selected",in:"includes one of (comma sep)",not_in:"includes none of (comma sep)",matches_regex:"any value matches regex"};function Me(e){return!!e&&(e.type==="checkbox-group"||!!e.multiple)}function ve(e){const t=document.createElement("p");return t.textContent=e,t.style.cssText="font-size:.75rem;font-weight:700;color:var(--dm-text-muted);margin:0 0 .7rem;text-transform:uppercase;letter-spacing:.06em;",t}function xe(e,t,o,n,l){const a=document.createElement("div");a.className="fb-logic-cond-row",a.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const i=document.createElement("span");i.textContent="When",i.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const r=document.createElement("select");r.className="form-select fb-logic-cond-field",r.style.cssText="flex:1 1 140px;min-width:140px;",t.forEach(m=>{const f=document.createElement("option");f.value=m.value,f.textContent=m.label,e&&m.value===e.field&&(f.selected=!0),r.appendChild(f)});const c=document.createElement("select");c.className="form-select fb-logic-cond-op",c.style.cssText="flex:1 1 160px;min-width:140px;",ye.forEach(m=>{const f=document.createElement("option");f.value=m.value,f.textContent=m.label,e&&m.value===e.operator&&(f.selected=!0),c.appendChild(f)});const s=()=>{const m=t.find(f=>f.value===r.value);Array.from(c.options).forEach(f=>{const k=ye.find(h=>h.value===f.value);f.textContent=m?.multi&&pt[f.value]||k?.label||f.value})};s(),r.addEventListener("change",s);const d=document.createElement("input");d.type="text",d.className="form-input fb-logic-cond-val",d.placeholder="value",d.style.cssText="flex:1 1 120px;min-width:100px;",d.value=e?.value||"",e&&Re.has(e.operator)&&(d.style.display="none"),c.addEventListener("change",()=>{d.style.display=Re.has(c.value)?"none":""});const u=document.createElement("span");q(u,"arrow-right"),u.style.cssText="font-size:.73rem;color:var(--dm-text-muted);flex-shrink:0;";const b=document.createElement("select");b.className=`form-select ${n}`,b.style.cssText="flex:1 1 140px;min-width:120px;",o.forEach(m=>{const f=document.createElement("option");f.value=m.value,f.textContent=m.label,m.value===l&&(f.selected=!0),b.appendChild(f)});const y=document.createElement("button");return y.type="button",y.className="btn btn-xs btn-ghost",y.style.cssText="line-height:1;opacity:.6;",q(y,"x"),y.style.flexShrink="0",y.addEventListener("click",()=>a.remove()),a.appendChild(i),a.appendChild(r),a.appendChild(c),a.appendChild(d),a.appendChild(u),a.appendChild(b),a.appendChild(y),a}function Xt(e,t,o){const n=document.createElement("div");n.dataset.logicSection="visibility",n.appendChild(ve("Visibility"));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const a=document.createElement("span");a.textContent="Default:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-vis-default",i.style.cssText="max-width:240px;",[{value:"visible",label:"Visible"},{value:"hidden",label:"Hidden"}].forEach(h=>{const x=document.createElement("option");x.value=h.value,x.textContent=h.label,h.value===(e.default||"visible")&&(x.selected=!0),i.appendChild(x)}),l.appendChild(a),l.appendChild(i),n.appendChild(l);const r=document.createElement("div");r.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const c=document.createElement("span");c.textContent="Transition:",c.style.cssText="font-size:.8rem;flex-shrink:0;";const s=document.createElement("select");s.className="form-select fb-logic-vis-transition",s.style.cssText="max-width:240px;",[{value:"none",label:"None (instant)"},{value:"fade",label:"Fade"},{value:"slide",label:"Slide"},{value:"scale",label:"Scale"}].forEach(h=>{const x=document.createElement("option");x.value=h.value,x.textContent=h.label,h.value===(e.transition||"none")&&(x.selected=!0),s.appendChild(x)}),r.appendChild(c),r.appendChild(s),n.appendChild(r);const d=document.createElement("div");d.style.cssText="display:flex;align-items:center;gap:.6rem;margin-bottom:.65rem;flex-wrap:wrap;";const u=document.createElement("span");u.textContent="Speed:",u.style.cssText="font-size:.8rem;flex-shrink:0;";const b=document.createElement("select");b.className="form-select fb-logic-vis-duration",b.style.cssText="max-width:240px;",[{value:"",label:"Default"},{value:"120",label:"Very fast (120ms)"},{value:"200",label:"Fast (200ms)"},{value:"350",label:"Medium (350ms)"},{value:"600",label:"Slow (600ms)"},{value:"1000",label:"Very slow (1s)"}].forEach(h=>{const x=document.createElement("option");x.value=h.value,x.textContent=h.label,h.value===String(e.duration??"")&&(x.selected=!0),b.appendChild(x)}),d.appendChild(u),d.appendChild(b),n.appendChild(d);const y=()=>{d.style.display=s.value==="none"?"none":""};y(),s.addEventListener("change",y);const m=document.createElement("div");m.className="fb-logic-vis-rules";const f=o.map(h=>({value:h.name,label:h.label||h.name,multi:Me(h)})),k=[{value:"visible",label:"Show"},{value:"hidden",label:"Hide"}];if((e.conditions||[]).forEach(h=>{const x=(h.when?.all||h.when?.any||[])[0],$=h.then==="hidden"?"hidden":"visible";f.length>0&&m.appendChild(xe(x,f,k,"fb-logic-vis-then",$))}),n.appendChild(m),f.length>0){const h=document.createElement("button");h.type="button",h.className="btn btn-xs btn-ghost",h.style.cssText="font-size:.73rem;margin-top:.35rem;",re(h,"plus","Add visibility rule"),h.addEventListener("click",()=>m.appendChild(xe(null,f,k,"fb-logic-vis-then","visible"))),n.appendChild(h)}return n}function Zt(e,t,o){const n=document.createElement("div");n.dataset.logicSection="requirement",n.appendChild(ve("Conditional Requirement"));const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.5rem;font-size:.8rem;cursor:pointer;margin-bottom:.65rem;";const a=document.createElement("input");a.type="checkbox",a.className="fb-logic-req-default",a.checked=e.default===!0,l.appendChild(a),l.appendChild(document.createTextNode("Required by default")),n.appendChild(l);const i=document.createElement("div");i.className="fb-logic-req-rules";const r=o.map(s=>({value:s.name,label:s.label||s.name,multi:Me(s)})),c=[{value:"true",label:"Make required"},{value:"false",label:"Make optional"}];if((e.conditions||[]).forEach(s=>{const d=(s.when?.all||s.when?.any||[])[0],u=s.then===!0?"true":"false";r.length>0&&i.appendChild(xe(d,r,c,"fb-logic-req-then",u))}),n.appendChild(i),r.length>0){const s=document.createElement("button");s.type="button",s.className="btn btn-xs btn-ghost",s.style.cssText="font-size:.73rem;margin-top:.35rem;",re(s,"plus","Add requirement rule"),s.addEventListener("click",()=>i.appendChild(xe(null,r,c,"fb-logic-req-then","true"))),n.appendChild(s)}return n}function ut(e){const t=document.createElement("div");t.className="fb-logic-val-rule",t.style.cssText="display:flex;gap:.55rem;align-items:center;margin-bottom:.6rem;flex-wrap:wrap;";const o=document.createElement("select");o.className="form-select fb-logic-val-type",o.style.cssText="flex:0 0 140px;",[{value:"regex",label:"Regex"},{value:"match",label:"Match field"}].forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===(e?.type||"regex")&&(c.selected=!0),o.appendChild(c)});const n=document.createElement("input");n.type="text",n.className="form-input fb-logic-val-pattern",n.placeholder=e?.type==="match"?"field name":"pattern",n.value=e?.pattern||e?.field||"",n.style.cssText="flex:3;";const l=document.createElement("input");l.type="text",l.className="form-input fb-logic-val-flags",l.placeholder="flags",l.value=e?.flags||"",l.style.cssText="flex:0 0 55px;",e?.type==="match"&&(l.style.display="none"),o.addEventListener("change",()=>{l.style.display=o.value==="match"?"none":"",n.placeholder=o.value==="match"?"field name":"pattern"});const a=document.createElement("input");a.type="text",a.className="form-input fb-logic-val-message",a.placeholder="Error message",a.value=e?.message||"",a.style.cssText="flex:4;";const i=document.createElement("button");return i.type="button",i.className="btn btn-xs btn-ghost",i.style.cssText="line-height:1;opacity:.6;",q(i,"x"),i.style.flexShrink="0",i.addEventListener("click",()=>t.remove()),t.appendChild(o),t.appendChild(n),t.appendChild(l),t.appendChild(a),t.appendChild(i),t}function en(e,t,o){const n=document.createElement("div");n.dataset.logicSection="validation",n.appendChild(ve("Custom Validation"));const l=document.createElement("div");l.className="fb-logic-val-rules",(e||[]).forEach(i=>l.appendChild(ut(i))),n.appendChild(l);const a=document.createElement("button");return a.type="button",a.className="btn btn-xs btn-ghost",a.style.cssText="font-size:.73rem;margin-top:.35rem;",re(a,"plus","Add validation rule"),a.addEventListener("click",()=>l.appendChild(ut(null))),n.appendChild(a),n}function tn(e,t,o){const n=document.createElement("div");n.dataset.logicSection="cascade",n.appendChild(ve("Cascade Options")),n.lastChild.appendChild(Ie("Make this field's options depend on another field. When the source field changes, the options here are replaced by the mapping entry for its value; if nothing matches, the default options below are shown."));const l=document.createElement("div");l.style.cssText="display:flex;align-items:center;gap:.5rem;margin-bottom:.5rem;";const a=document.createElement("span");a.textContent="Source field:",a.style.cssText="font-size:.8rem;flex-shrink:0;";const i=document.createElement("select");i.className="form-select fb-logic-cascade-source",i.style.cssText="flex:1;";const r=document.createElement("option");r.value="",r.textContent="- none -",i.appendChild(r),o.forEach(b=>{const y=document.createElement("option");y.value=b.name,y.textContent=b.label||b.name,b.name===e.sourceField&&(y.selected=!0),i.appendChild(y)}),l.appendChild(a),l.appendChild(i),n.appendChild(l);const c=document.createElement("p");c.textContent='Mapping JSON - {"value":[{"value":"...","label":"..."}]}',c.appendChild(Ie(`Each key is a value of the source field; its list becomes this field's options when that value is picked. Example: {"uk":[{"value":"london","label":"London"}]} shows London when the source is "uk".`)),c.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const s=document.createElement("textarea");s.className="form-input fb-logic-cascade-mapping",s.rows=4,s.style.cssText="font-family:monospace;",s.placeholder='{"uk": [{"value": "london", "label": "London"}]}',s.value=e.mapping?JSON.stringify(e.mapping,null,2):"",n.appendChild(c),n.appendChild(s);const d=document.createElement("p");d.textContent="Default options (one per line: value:Label)",d.appendChild(Ie("Shown before the source field has a value, or when its value has no mapping entry.")),d.style.cssText="font-size:.73rem;color:var(--dm-text-muted);margin:.3rem 0 .2rem;";const u=document.createElement("textarea");return u.className="form-input fb-logic-cascade-defaults",u.rows=3,u.style.cssText="font-family:monospace;",u.placeholder=`option1:Option 1
4
+ option2:Option 2`,u.value=(e.defaultOptions||[]).map(b=>{const y=typeof b=="string"?b:b.value??"",m=typeof b=="string"?b:b.label??y;return y===m?y:`${y}:${m}`}).join(`
5
+ `),n.appendChild(d),n.appendChild(u),n}function nn(e,t){const o=e.logic||{},n=C.filter((u,b)=>b!==t&&u.type!=="page-break"&&u.type!=="spacer"),l=document.createElement("div");l.className="fb-field-logic",l.style.cssText="margin-top:.75rem;border-top:1px solid var(--dm-border);padding-top:.5rem;";const a=document.createElement("div");a.style.cssText="display:flex;align-items:center;justify-content:space-between;cursor:pointer;padding:.15rem 0;";const i=document.createElement("span");i.style.cssText="font-size:.8rem;font-weight:600;color:var(--dm-text-muted);",i.textContent="\u26A1 Conditional Logic";const r=dt(o),c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",q(c,r?"chevron-down":"chevron-right",12);const s=document.createElement("div");s.className="fb-logic-body",s.style.cssText="padding:.25rem 0 .25rem;"+(r?"":"display:none;"),a.addEventListener("click",()=>{const u=s.style.display==="none";s.style.display=u?"":"none",q(c,u?"chevron-down":"chevron-right",12)}),a.appendChild(i),a.appendChild(c),l.appendChild(a),s.appendChild(Xt(o.visibility||{},t,n)),s.appendChild(Zt(o.requirement||{},t,n)),s.appendChild(en(o.validation||[],t,n));const d=document.getElementById(`fb-type-${t}`)?.value||e.type;return Fe.has(d)&&s.appendChild(tn(o.cascade||{},t,n)),l.appendChild(s),l}const de=[{value:"banner",label:"Show a banner",kind:"state",params:["message","level","position","dismissible"],placeholder:"e.g. You must be 18 or over to continue."},{value:"toast",label:"Show a toast",kind:"event",params:["message","level"],placeholder:"e.g. Thanks - carry on."},{value:"hide-fields",label:"Hide fields",kind:"state",params:["target"]},{value:"disable-fields",label:"Disable fields",kind:"state",params:["target"]},{value:"require-fields",label:"Make fields required",kind:"state",params:["target"]},{value:"block-submit",label:"Block submission",kind:"state",params:["message"],messageLabel:"Reason, shown under the button",placeholder:'Blank: "This form cannot be submitted yet."'},{value:"end-form",label:"End the form here",kind:"state",params:["message","finish","finishLabel","doneMessage","record"],messageLabel:"Message shown in place of the rest",placeholder:"e.g. Sorry - you must be 18 or over to apply."},{value:"goto-step",label:"Jump to a wizard step",kind:"event",params:["step"]},{value:"redirect",label:"Redirect after submit",kind:"event",params:["url"]},{value:"celebrate",label:"Celebrate",kind:"event",params:["theme","intensity"]},{value:"run-action",label:"Run a CMS action",kind:"event",params:["slug"]},{value:"notify",label:"Notify the admins",kind:"event",params:["message","level"],messageLabel:"Notification title",placeholder:"Blank: titled after the form",noOnce:!0,kindText:"when the form is submitted"}],Ce=[{value:"info",label:"Info"},{value:"success",label:"Success"},{value:"warning",label:"Warning"},{value:"error",label:"Error"}],mt=[{value:"field-below",label:"Below this field"},{value:"field-above",label:"Above this field"},{value:"form-top",label:"Top of the form"}],ft=[{value:"rest",label:"The rest of the form"},{value:"all",label:"Every other field"},{value:"listed",label:"Chosen fields"}],ht=[{value:"auto",label:"Whatever is in season"},{value:"christmas",label:"Christmas"},{value:"halloween",label:"Halloween"},{value:"valentines",label:"Valentine's Day"},{value:"guy-fawkes",label:"Guy Fawkes Night"},{value:"st-patricks",label:"St Patrick's Day"},{value:"st-andrews",label:"St Andrew's Day"},{value:"st-davids",label:"St David's Day"},{value:"st-georges",label:"St George's Day"}];function bt(e,t=!1){const o=(i,r)=>({value:i.name,label:`${i.label||i.name}${r?" (this field)":""}`,multi:Me(i)}),n=i=>i&&i.type!=="page-break"&&i.type!=="spacer"&&i.name,l=C.filter((i,r)=>r!==e&&n(i)).map(i=>o(i,!1)),a=C[e];return t&&n(a)?[o(a,!0),...l]:l}function J(e,t,o){const n=document.createElement("select");return n.className=`form-select ${e}`,t.forEach(l=>{const a=document.createElement("option");a.value=l.value,a.textContent=l.label,l.value===o&&(a.selected=!0),n.appendChild(a)}),n}function le(e,t,o){const n=document.createElement("input");return n.type="text",n.className=`form-input ${e}`,n.value=t==null?"":String(t),o&&(n.placeholder=o),n}function ze(e,t){const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost fb-trig-remove",t&&(o.title=t,o.setAttribute("aria-label",t)),q(o,"x"),o.addEventListener("click",n=>{n.stopPropagation(),e()}),o}function V(e,t,{full:o=!1,hint:n=""}={}){const l=document.createElement("label");l.className=`fb-trig-f${o?" fb-trig-f--full":""}`;const a=document.createElement("span");if(a.className="fb-trig-f-label",a.textContent=e,l.appendChild(a),l.appendChild(t),n){const i=document.createElement("span");i.className="fb-trig-f-hint",i.textContent=n,l.appendChild(i)}return l}function pe(e,t,o,n){const l=document.createElement("label");l.className="fb-trig-check",n&&(l.title=n);const a=document.createElement("input");return a.type="checkbox",a.className=`form-check ${e}`,a.checked=!!t,l.appendChild(a),l.appendChild(document.createTextNode(o)),l}function gt(e,t){const o=document.createElement("div");o.className="fb-trig-cond-row";const n=J("fb-trig-cond-field",t,e?.field),l=J("fb-trig-cond-op",ye,e?.operator),a=le("fb-trig-cond-val",e?.value,"value"),i=()=>{const c=t.find(s=>s.value===n.value);Array.from(l.options).forEach(s=>{const d=ye.find(u=>u.value===s.value);s.textContent=c?.multi&&pt[s.value]||d?.label||s.value})},r=()=>{a.hidden=Re.has(l.value)};return i(),r(),n.addEventListener("change",i),l.addEventListener("change",r),o.appendChild(n),o.appendChild(l),o.appendChild(a),o.appendChild(ze(()=>o.remove(),"Remove condition")),o}function yt(e,t){const o=document.createElement("div");o.className="fb-trig-params";const n=de.find(c=>c.value===(e.type||"banner"));if(!n)return o;const l=document.createElement("div");l.className="fb-trig-grid";const a=document.createElement("div");a.className="fb-trig-opts";const i=[];for(const c of n.params)switch(c){case"message":l.appendChild(V(n.messageLabel||"Message",le("fb-trig-p-message",e.message,n.placeholder||""),{full:!0}));break;case"finish":a.appendChild(pe("fb-trig-p-finish-on",e.finish!==!1,"Let the visitor finish (send the answers given so far)",'Untick to stop the form dead: the submit button is disabled and nothing is sent, so nothing is saved and "Notify the admins" cannot fire.'));break;case"finishLabel":{const s=V("Button text",le("fb-trig-p-finish",e.finishLabel,"Finish"));i.push(s),l.appendChild(s);break}case"doneMessage":{const s=V("Closing message",le("fb-trig-p-done",e.doneMessage,"Blank: the form's own success message"));i.push(s),l.appendChild(s);break}case"record":{const s=pe("fb-trig-p-record",e.record!==!1,"Save the answers given so far",`Untick to keep nothing: no submission is stored and the form's email, webhook and actions do not run. A "Notify the admins" action still fires.`);i.push(s),a.appendChild(s);break}case"level":l.appendChild(V(n.value==="notify"?"Severity":"Level",J("fb-trig-p-level",Ce,e.level||"info")));break;case"position":l.appendChild(V("Where",J("fb-trig-p-position",mt,e.position||"field-below")));break;case"dismissible":a.appendChild(pe("fb-trig-p-dismissible",e.dismissible!==!1,"The visitor can dismiss it"));break;case"target":{const s=J("fb-trig-p-target",ft,e.target||(e.fields?.length?"listed":"rest")),d=document.createElement("select");d.className="form-select fb-trig-p-fields",d.multiple=!0,d.size=4;const u=new Set(e.fields||[]);bt(t).forEach(m=>{const f=document.createElement("option");f.value=m.value,f.textContent=m.label,u.has(m.value)&&(f.selected=!0),d.appendChild(f)});const b=V("Fields",d,{hint:"Ctrl/Cmd-click to pick several"}),y=()=>{b.hidden=s.value!=="listed"};y(),s.addEventListener("change",y),l.appendChild(V("Which fields",s)),l.appendChild(b);break}case"step":{const s=le("fb-trig-p-step",e.step,"0");s.type="number",s.min="0",l.appendChild(V("Step",s,{hint:"Counting from 0"}));break}case"url":l.appendChild(V("Send them to",le("fb-trig-p-url",e.url,"/thank-you"),{full:!0}));break;case"theme":l.appendChild(V("Theme",J("fb-trig-p-theme",ht,e.theme||"auto")));break;case"intensity":l.appendChild(V("Intensity",J("fb-trig-p-intensity",[{value:"low",label:"Low"},{value:"medium",label:"Medium"},{value:"high",label:"High"}],e.intensity||"medium")));break;case"slug":{const s=[{value:"",label:fe.length?"Choose an action":"No actions available"}].concat(fe.map(d=>({value:d.slug,label:d.title||d.slug})));l.appendChild(V("Action",J("fb-trig-p-slug",s,e.slug||""),{full:!0}));break}default:break}n.kind==="event"&&!n.noOnce&&a.appendChild(pe("fb-trig-p-once",!!e.once,"Only once","Fire the first time only, rather than every time the answer swings back."));const r=a.querySelector(".fb-trig-p-finish-on");if(r){const c=()=>i.forEach(s=>{s.hidden=!r.checked});c(),r.addEventListener("change",c)}return l.children.length&&o.appendChild(l),a.children.length&&o.appendChild(a),o}function ln(e){return e?.kindText?e.kindText:e?.kind==="event"?"once, when it becomes true":"while it is true"}const an=(e,t=48)=>e.length>t?`${e.slice(0,t-1)}\u2026`:e,ae=(e,t)=>e.find(o=>o.value===t)?.label||t;function on(e){if(!e)return"";const t=[],o=l=>l?`"${an(l)}"`:"",n=()=>e.target==="listed"?e.fields?.length?e.fields.join(", "):"no fields chosen":ae(ft,e.target||"rest").toLowerCase();switch(e.type){case"banner":t.push(o(e.message)||"No message yet",ae(Ce,e.level||"info"),ae(mt,e.position||"field-below").toLowerCase());break;case"toast":t.push(o(e.message)||"No message yet",ae(Ce,e.level||"info"));break;case"hide-fields":case"disable-fields":case"require-fields":t.push(n());break;case"block-submit":t.push(o(e.message)||"the standard reason");break;case"end-form":t.push(o(e.message)||"no message"),e.finish===!1?t.push("submit disabled"):t.push(`button "${e.finishLabel||"Finish"}"`,e.record===!1?"saves nothing":"saves the answers");break;case"goto-step":t.push(Number.isFinite(e.step)?`step ${e.step}`:"no step yet");break;case"redirect":t.push(e.url||"no address yet");break;case"celebrate":t.push(ae(ht,e.theme||"auto"),`${e.intensity||"medium"} intensity`);break;case"run-action":t.push(e.slug?fe.find(l=>l.slug===e.slug)?.title||e.slug:"no action chosen");break;case"notify":t.push(o(e.message)||"titled after the form",ae(Ce,e.level||"info"));break;default:break}return e.once&&t.push("only once"),t.filter(Boolean).join(" \xB7 ")}function De(e,t,{open:o=!1}={}){const n=document.createElement("div");n.className="fb-trig-action-row";const l=document.createElement("div");l.className="fb-trig-action-head",l.tabIndex=0,l.setAttribute("role","button");const a=document.createElement("span");a.className="fb-trig-chevron";const i=document.createElement("span");i.className="fb-trig-action-main";const r=document.createElement("strong"),c=document.createElement("small");c.className="fb-trig-action-summary",i.append(r,c);const s=document.createElement("span");s.className="fb-trig-kind",l.append(a,i,s,ze(()=>n.remove(),"Remove action"));const d=document.createElement("div");d.className="fb-trig-action-body";const u=J("fb-trig-action-type",de,e.type||"banner");d.appendChild(V("Action",u,{full:!0})),d.appendChild(yt(e,t));const b=()=>{const m=de.find(f=>f.value===u.value);r.textContent=m?.label||u.value,s.textContent=ln(m),s.classList.toggle("fb-trig-kind--event",m?.kind==="event"),c.textContent=on(Et(n))},y=m=>{d.hidden=!m,n.classList.toggle("is-open",m),l.setAttribute("aria-expanded",String(m)),q(a,m?"chevron-down":"chevron-right",12)};return l.addEventListener("click",()=>y(d.hidden)),l.addEventListener("keydown",m=>{m.target!==l||m.key!=="Enter"&&m.key!==" "||(m.preventDefault(),y(d.hidden))}),u.addEventListener("change",()=>{const m=yt({type:u.value},t);d.replaceChild(m,d.querySelector(".fb-trig-params")),b(),window.I?.scan?.()}),d.addEventListener("input",b),d.addEventListener("change",b),n.append(l,d),y(o),b(),n}function vt(e,t,o){const n=document.createElement("section");n.className=`fb-trig-sec fb-trig-sec--${e}`;const l=document.createElement("div");l.className="fb-trig-sec-head";const a=document.createElement("span");if(a.className="fb-trig-sec-title",a.textContent=t,l.appendChild(a),o){const i=document.createElement("span");i.className="fb-trig-sec-hint",i.textContent=o,l.appendChild(i)}return n.appendChild(l),n}function Pe(e,t){const o=document.createElement("button");return o.type="button",o.className="btn btn-xs btn-ghost fb-trig-add",re(o,"plus",e,12),o.addEventListener("click",t),o}function xt(e,t,o,n){const a=vt(e,t,e==="then"?"What happens while the answers match.":"What happens while they do not. Leave empty for nothing.");a.classList.add("fb-trig-branch"),a.dataset.branch=e;const i=document.createElement("div");return i.className="fb-trig-action-list",(o||[]).forEach(r=>i.appendChild(De(r,n))),a.appendChild(i),a.appendChild(Pe("Add action",()=>{i.appendChild(De({type:"banner"},n,{open:!0})),window.I?.scan?.()})),a}function Ct(e,t,o){const n=bt(t,!0),l=document.createElement("div");l.className="fb-trig-card",l.dataset.triggerId=e.id||`trg-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;const a=document.createElement("div");a.className="fb-trig-card-head";const i=document.createElement("span");i.className="fb-trig-card-title",i.textContent=`Trigger ${o+1}`,a.appendChild(i);const r=pe("fb-trig-enabled",e.enabled!==!1,"Enabled","Untick to keep the trigger but switch it off.");if(a.appendChild(r),a.appendChild(ze(()=>l.remove(),"Remove trigger")),l.appendChild(a),!n.length){const u=document.createElement("p");return u.className="fb-trig-empty",u.textContent="Give this field a name first - a trigger tests an answer, and it needs something to test.",l.appendChild(u),l}const c=vt("when","When");c.querySelector(".fb-trig-sec-head").appendChild(J("fb-trig-match",[{value:"all",label:"all of these are true"},{value:"any",label:"any of these is true"}],Array.isArray(e.when?.any)?"any":"all"));const s=document.createElement("div");s.className="fb-trig-cond-list";const d=e.when?.all||e.when?.any||[];return(d.length?d:[{}]).forEach(u=>s.appendChild(gt(u,n))),c.appendChild(s),c.appendChild(Pe("Add condition",()=>{s.appendChild(gt({},n)),window.I?.scan?.()})),l.appendChild(c),l.appendChild(xt("then","Then",e.then,t)),l.appendChild(xt("otherwise","Otherwise",e.otherwise,t)),l}function sn(e,t){const o=Array.isArray(e.triggers)?e.triggers:[],n=document.createElement("div");n.className="fb-field-triggers";const l=document.createElement("div");l.className="fb-trig-panel-head";const a=document.createElement("span");a.className="fb-trig-panel-title",a.textContent=`\u{1F3AF} Triggers${o.length?` (${o.length})`:""}`;const i=document.createElement("button");i.type="button",i.className="btn btn-xs btn-ghost",q(i,o.length?"chevron-down":"chevron-right",12);const r=document.createElement("div");r.className="fb-triggers-body",r.hidden=!o.length,l.addEventListener("click",()=>{r.hidden=!r.hidden,q(i,r.hidden?"chevron-right":"chevron-down",12)});const c=document.createElement("p");c.className="fb-trig-blurb",c.textContent="Do something to the form when the answers meet a condition - show a banner or toast, hide, disable or require other fields, refuse the submit, end the form early, notify the admins, jump to a step, or celebrate.",r.appendChild(c);const s=document.createElement("div");return s.className="fb-trig-list",o.forEach((d,u)=>s.appendChild(Ct(d,t,u))),r.appendChild(s),r.appendChild(Pe("Add trigger",()=>{const d=Ct({enabled:!0,then:[]},t,s.children.length);s.appendChild(d),d.querySelector('.fb-trig-branch[data-branch="then"] .fb-trig-action-list')?.appendChild(De({type:"banner"},t,{open:!0})),window.I?.scan?.()})),l.appendChild(a),l.appendChild(i),n.appendChild(l),n.appendChild(r),n}function Et(e){const t=e.querySelector(".fb-trig-action-type")?.value,o=de.find(a=>a.value===t);if(!o)return null;const n={type:t},l=a=>e.querySelector(a)?.value?.trim()||"";for(const a of o.params)switch(a){case"message":n.message=l(".fb-trig-p-message");break;case"finishLabel":{const i=l(".fb-trig-p-finish");i&&(n.finishLabel=i);break}case"doneMessage":{const i=l(".fb-trig-p-done");i&&(n.doneMessage=i);break}case"finish":e.querySelector(".fb-trig-p-finish-on")?.checked||(n.finish=!1);break;case"record":e.querySelector(".fb-trig-p-record")?.checked||(n.record=!1);break;case"level":n.level=l(".fb-trig-p-level")||"info";break;case"position":n.position=l(".fb-trig-p-position")||"field-below";break;case"dismissible":n.dismissible=!!e.querySelector(".fb-trig-p-dismissible")?.checked;break;case"target":{const i=l(".fb-trig-p-target")||"rest";n.target=i,i==="listed"&&(n.fields=Array.from(e.querySelectorAll(".fb-trig-p-fields option")).filter(r=>r.selected).map(r=>r.value));break}case"step":{const i=parseInt(l(".fb-trig-p-step"),10);Number.isFinite(i)&&(n.step=i);break}case"url":n.url=l(".fb-trig-p-url");break;case"theme":n.theme=l(".fb-trig-p-theme")||"auto";break;case"intensity":n.intensity=l(".fb-trig-p-intensity")||"medium";break;case"slug":n.slug=l(".fb-trig-p-slug");break;default:break}return o.kind==="event"&&!o.noOnce&&e.querySelector(".fb-trig-p-once")?.checked&&(n.once=!0),n}function rn(e){const t=Et(e);if(!t)return null;const o=de.find(a=>a.value===t.type),n=t.type,l=["block-submit","end-form","notify"].includes(o.value);return o.params.includes("message")&&!t.message&&!l?(delete t.message,null):(l&&!t.message&&delete t.message,n==="redirect"&&!t.url||n==="run-action"&&!t.slug?null:t)}function cn(e){const o=document.querySelector(`.fb-field-card[data-index="${e}"]`)?.querySelector(".fb-field-triggers");if(!o)return;const n=[];return o.querySelectorAll(".fb-trig-card").forEach(l=>{const a=Array.from(l.querySelectorAll(".fb-trig-cond-row")).map(u=>{const b=u.querySelector(".fb-trig-cond-field")?.value,y=u.querySelector(".fb-trig-cond-op")?.value;if(!b||!y)return null;const m=u.querySelector(".fb-trig-cond-val")?.value??"";return{field:b,operator:y,value:m}}).filter(Boolean);if(!a.length)return;const i=u=>Array.from(l.querySelectorAll(`.fb-trig-branch[data-branch="${u}"] .fb-trig-action-row`)).map(rn).filter(Boolean),r=i("then"),c=i("otherwise");if(!r.length&&!c.length)return;const s=l.querySelector(".fb-trig-match")?.value==="any"?"any":"all",d={id:l.dataset.triggerId,enabled:!!l.querySelector(".fb-trig-enabled")?.checked,when:{[s]:a}};r.length&&(d.then=r),c.length&&(d.otherwise=c),n.push(d)}),n.length?n:void 0}function wt(e,t,o){const n=document.createElement("div");return n.className="fb-field-extras",e==="chooser"?(n.appendChild(dn(t,o)),n.appendChild(un(t.options||[],o))):(Fe.has(e)&&n.appendChild(gn(t.options||[],o)),e==="textarea"&&n.appendChild(D([P("Rows",`fb-rows-${o}`,"number",t.formConfig?.rows||4,"Height of textarea")])),(e==="string"||e==="textarea")&&n.appendChild(D([P("Min Length",`fb-minlength-${o}`,"number",t.minLength||"",""),P("Max Length",`fb-maxlength-${o}`,"number",t.maxLength||"","")])),e==="number"&&n.appendChild(D([P("Min",`fb-min-${o}`,"number",t.min??"",""),P("Max",`fb-max-${o}`,"number",t.max??"","")]))),n.children.length?n:null}function kt(e){const t=document.createElement("div");t.className="fb-chooser-section",t.style.cssText="border:1px solid var(--dm-border); border-radius:6px; margin-top:.5rem; overflow:hidden;";const o=document.createElement("div");o.style.cssText="padding:.4rem .6rem; background:color-mix(in srgb, var(--dm-background) 60%, transparent); font-weight:600; font-size:.82rem; border-bottom:1px solid var(--dm-border);",o.textContent=e,t.appendChild(o);const n=document.createElement("div");return n.className="fb-chooser-section-body",n.style.cssText="padding:.55rem .6rem; display:flex; flex-direction:column; gap:.45rem;",t.appendChild(n),{wrap:t,body:n}}function Ee(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=t,i.style.fontSize=".8rem";const r=document.createElement("select");if(r.id=e,r.className="form-input",n.forEach(([c,s])=>{const d=document.createElement("option");d.value=c,d.textContent=s,String(c)===String(o)&&(d.selected=!0),r.appendChild(d)}),a.appendChild(i),a.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(c)}return a}function St(e,t,o,n){const l=document.createElement("div");l.style.flex="1";const a=document.createElement("label");a.style.cssText="display:inline-flex;align-items:center;gap:.4rem;font-size:.82rem;";const i=document.createElement("input");if(i.id=e,i.type="checkbox",i.checked=!!o,a.appendChild(i),a.appendChild(document.createTextNode(" "+t)),l.appendChild(a),n){const r=document.createElement("p");r.className="form-hint text-muted",r.textContent=n,r.style.cssText="font-size:.72rem;margin-top:.2rem;",l.appendChild(r)}return l}function _e(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=e,i.className="form-label",i.textContent=t,i.style.fontSize=".8rem",a.appendChild(i);const r=document.createElement("div");r.style.cssText="display:flex;gap:.4rem;align-items:stretch;";const c=document.createElement("input");c.id=e,c.type="text",c.className="form-input",c.value=o||"",n&&(c.placeholder=n),c.style.flex="1";const s=document.createElement("input");s.type="color",s.title="Pick a colour",s.style.cssText="width:36px;height:auto;padding:0;border:1px solid var(--dm-border);border-radius:4px;cursor:pointer;";const d=String(c.value).match(/^#[0-9a-fA-F]{3,8}$/);if(s.value=d?c.value:"#000000",s.addEventListener("input",()=>{c.value=s.value,c.dispatchEvent(new Event("input",{bubbles:!0}))}),r.appendChild(c),r.appendChild(s),a.appendChild(r),l){const u=document.createElement("p");u.className="form-hint text-muted",u.textContent=l,u.style.cssText="font-size:.72rem;margin-top:.2rem;",a.appendChild(u)}return a}function dn(e,t){const o=document.createElement("div");o.style.cssText="margin-top:.5rem; display:flex; flex-direction:column; gap:.4rem;";const n=kt("Layout");n.body.appendChild(D([Ee(`fb-chooser-variant-${t}`,"Variant",e.variant||"card",[["card","Card - rich tiles"],["chip","Chip - compact pills"]],"Card supports description and grid columns; chips wrap."),St(`fb-chooser-multiple-${t}`,"Multi-select",!!e.multiple,"Off = single (radio); on = multi (checkbox).")])),n.body.appendChild(D([Ee(`fb-chooser-density-${t}`,"Density",e.density||"comfortable",[["comfortable","Comfortable"],["compact","Compact"]],"Compact strips description (card variant only)."),P("Columns",`fb-chooser-columns-${t}`,"number",e.columns||3,"Card grid (1-6). Ignored for chips.")])),o.appendChild(n.wrap);const l=kt("Visual");return l.body.appendChild(D([_e(`fb-chooser-accent-${t}`,"Accent",e.accent||"","primary / success / #ec4899","Selected highlight colour - semantic name or any CSS colour."),Ee(`fb-chooser-accent-style-${t}`,"Accent style",e.accentStyle||"border",[["border","Border (default)"],["solid","Solid"],["glow","Glow"],["overlay","Overlay"],["underline","Underline"]],"Visual treatment of the selected state.")])),l.body.appendChild(D([St(`fb-chooser-glow-${t}`,"Glow on selected",!!e.glow,"Soft outer glow."),_e(`fb-chooser-glow-colour-${t}`,"Glow colour",e.glowColour||"","defaults to accent","Optional; semantic name or CSS colour.")])),l.body.appendChild(D([Ee(`fb-chooser-shadow-${t}`,"Shadow",e.shadow||"none",[["none","None"],["sm","Small"],["md","Medium"],["lg","Large"],["xl","Extra Large"]],"Drop shadow on every option."),_e(`fb-chooser-shadow-colour-${t}`,"Shadow colour",e.shadowColour||"","rgba(0,0,0,0.1)","Optional shadow tint.")])),o.appendChild(l.wrap),o}function pn(e,t,o,n){const l=document.createElement("div");l.className="fb-chooser-option-row",l.dataset.optIdx=String(o),l.style.cssText="border:1px solid var(--dm-border); border-radius:4px; padding:.5rem; background:var(--dm-background-alt); display:flex; flex-direction:column; gap:.35rem;";const a=document.createElement("div");a.style.cssText="display:flex; gap:.4rem; align-items:center;";const i=document.createElement("div");i.style.cssText="display:flex; flex-direction:column; gap:1px;";const r=document.createElement("button");r.type="button",r.className="btn btn-xs btn-ghost",r.title="Move up",q(r,"arrow-up"),r.addEventListener("click",I=>{I.preventDefault(),Tt(t,o,-1,n)});const c=document.createElement("button");c.type="button",c.className="btn btn-xs btn-ghost",c.title="Move down",q(c,"arrow-down"),c.addEventListener("click",I=>{I.preventDefault(),Tt(t,o,1,n)}),i.appendChild(r),i.appendChild(c),a.appendChild(i);const s=document.createElement("input");s.type="text",s.className="form-input fb-chooser-opt-value",s.placeholder="value",s.value=e.value||"",s.style.flex="1",a.appendChild(s);const d=document.createElement("input");d.type="text",d.className="form-input fb-chooser-opt-label",d.placeholder="label (visible to users)",d.value=e.label||"",d.style.flex="2",a.appendChild(d);const u=document.createElement("button");u.type="button",u.className="btn btn-xs btn-ghost",u.style.cssText="line-height:1;opacity:.6;",u.title="Remove option",q(u,"x"),u.addEventListener("click",I=>{I.preventDefault(),hn(t,o,n)}),a.appendChild(u),l.appendChild(a);const b=document.createElement("div");b.style.cssText="display:flex; gap:.4rem;";const y=Mt("icon name (optional)",e.icon||"");y.input.classList.add("fb-chooser-opt-icon"),y.el.style.flex="1",b.appendChild(y.el);const m=document.createElement("input");m.type="text",m.className="form-input fb-chooser-opt-description",m.placeholder="description (card + comfortable only)",m.value=e.description||"",m.style.flex="2",b.appendChild(m),l.appendChild(b);const f=document.createElement("div");f.style.cssText="display:flex; gap:.4rem;";const k=document.createElement("input");k.type="text",k.className="form-input fb-chooser-opt-tooltip",k.placeholder="tooltip (hover hint)",k.value=e.tooltip||"",k.style.flex="2",f.appendChild(k);const h=document.createElement("input");h.type="text",h.className="form-input fb-chooser-opt-badge-text",h.placeholder="badge text",h.value=e.badge?.text||"",h.style.flex="1",f.appendChild(h);const x=document.createElement("select");x.className="form-input fb-chooser-opt-badge-type",x.style.flex="1",[["","no badge"],["primary","primary"],["success","success"],["info","info"],["warning","warning"],["danger","danger"]].forEach(([I,X])=>{const H=document.createElement("option");H.value=I,H.textContent=X,(e.badge?.type||"")===I&&(H.selected=!0),x.appendChild(H)}),f.appendChild(x),l.appendChild(f);const $=document.createElement("div");$.style.cssText="display:flex; gap:1rem; font-size:.8rem;";const A=document.createElement("label");A.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const G=document.createElement("input");G.type="checkbox",G.className="fb-chooser-opt-recommended",G.checked=!!e.recommended,A.appendChild(G),A.appendChild(document.createTextNode(" Recommended")),$.appendChild(A);const _=document.createElement("label");_.style.cssText="display:inline-flex;align-items:center;gap:.3rem;";const j=document.createElement("input");return j.type="checkbox",j.className="fb-chooser-opt-disabled",j.checked=!!e.disabled,_.appendChild(j),_.appendChild(document.createTextNode(" Disabled")),$.appendChild(_),l.appendChild($),l}function un(e,t){const o=document.createElement("div");o.style.cssText="margin-top:.5rem;";const n=document.createElement("div");n.style.cssText="display:flex; align-items:center; justify-content:space-between; margin-bottom:.4rem;";const l=document.createElement("p");l.textContent="Options",l.style.cssText="font-size:.85rem;font-weight:600;margin:0;",n.appendChild(l);const a=document.createElement("button");a.type="button",a.className="btn btn-xs btn-ghost",re(a,"plus","Add option"),n.appendChild(a),o.appendChild(n);const i=document.createElement("div");i.className="fb-chooser-options-list",i.id=`fb-chooser-options-${t}`,i.style.cssText="display:flex; flex-direction:column; gap:.4rem;",o.appendChild(i);const r=()=>{i.replaceChildren();const c=mn(t);(c.length?c:e||[]).forEach((d,u)=>{i.appendChild(pn(d,t,u,r))})};return a.addEventListener("click",c=>{c.preventDefault(),fn(t,r)}),r(),o}function mn(e){const t=C[e];return!t||!Array.isArray(t.options)?[]:t.options}function je(e){return C[e]?(Array.isArray(C[e].options)||(C[e].options=[]),C[e].options):[]}function fn(e,t){we(e),je(e).push({value:"new",label:"New option"}),t()}function hn(e,t,o){we(e),je(e).splice(t,1),o()}function Tt(e,t,o,n){we(e);const l=je(e),a=t+o;if(a<0||a>=l.length)return;const[i]=l.splice(t,1);l.splice(a,0,i),n()}function we(e){const t=document.getElementById(`fb-chooser-options-${e}`);if(!t)return;const o=t.querySelectorAll(".fb-chooser-option-row"),n=[];o.forEach(l=>{const a={value:l.querySelector(".fb-chooser-opt-value")?.value.trim()||"",label:l.querySelector(".fb-chooser-opt-label")?.value.trim()||""},i=l.querySelector(".fb-chooser-opt-icon")?.value.trim();i&&(a.icon=i);const r=l.querySelector(".fb-chooser-opt-description")?.value.trim();r&&(a.description=r);const c=l.querySelector(".fb-chooser-opt-tooltip")?.value.trim();c&&(a.tooltip=c);const s=l.querySelector(".fb-chooser-opt-badge-text")?.value.trim(),d=l.querySelector(".fb-chooser-opt-badge-type")?.value;(s||d)&&(a.badge={},s&&(a.badge.text=s),d&&(a.badge.type=d)),l.querySelector(".fb-chooser-opt-recommended")?.checked&&(a.recommended=!0),l.querySelector(".fb-chooser-opt-disabled")?.checked&&(a.disabled=!0),n.push(a)}),C[e]&&(C[e].options=n)}function D(e){const t=document.createElement("div");return t.style.cssText="display:flex;gap:.85rem;margin-bottom:.75rem;",e.forEach(o=>{o&&t.appendChild(o)}),t}function P(e,t,o,n,l){const a=document.createElement("div");a.style.flex="1";const i=document.createElement("label");i.htmlFor=t,i.className="form-label",i.textContent=e,i.style.fontSize=".8rem";const r=document.createElement("input");if(r.id=t,r.type=o||"text",r.className="form-input",r.value=n??"",a.appendChild(i),a.appendChild(r),l){const c=document.createElement("p");c.className="form-hint text-muted",c.textContent=l,c.style.cssText="font-size:.73rem;margin-top:.35rem;",a.appendChild(c)}return a}function bn(e,t,o,n){const l=document.createElement("div");l.style.flex="1";const a=document.createElement("label");a.htmlFor=t,a.className="form-label",a.textContent=e,a.style.fontSize=".8rem";const i=document.createElement("select");return i.id=t,i.className="form-select",o.forEach(r=>{const c=document.createElement("option");c.value=r.value,c.textContent=r.label,r.value===n&&(c.selected=!0),i.appendChild(c)}),l.appendChild(a),l.appendChild(i),l}function Nt(e,t,o){const n=document.createElement("div");n.style.cssText="flex:0;min-width:80px;display:flex;flex-direction:column;justify-content:flex-end;";const l=document.createElement("label");l.style.cssText="display:flex;align-items:center;gap:.4rem;cursor:pointer;font-size:.8rem;white-space:nowrap;";const a=document.createElement("input");return a.id=t,a.type="checkbox",a.checked=o,l.appendChild(a),l.appendChild(document.createTextNode(e)),n.appendChild(l),n}function gn(e,t){const o=document.createElement("div");o.style.cssText="margin-top:.4rem;";const n=document.createElement("p");n.textContent="Options (one per line: value or value:Label)",n.style.cssText="font-size:.8rem;font-weight:600;margin-bottom:.3rem;";const l=document.createElement("textarea");return l.id=`fb-options-${t}`,l.className="form-input",l.rows=4,l.placeholder=`yes:Yes
6
6
  no:No
7
7
  maybe:Maybe`,l.value=(e||[]).map(a=>{const i=typeof a=="string"?a:a.value??"",r=typeof a=="string"?a:a.label??i;return i===r?i:`${i}:${r}`}).join(`
8
- `),l.style.fontFamily="monospace",o.appendChild(n),o.appendChild(l),o}function Se(e){return parseInt(e,10)===3?3:2}function Te(e){const t=e.find("#field-project").val()||"";return O(),{title:e.find("#field-title").val().trim(),slug:e.find("#field-slug").val().trim(),description:e.find("#field-description").val().trim(),...e.find("#field-bundled").is(":checked")?{bundled:!0}:{},meta:{...ge||{},project:t||null},fields:C,settings:{submitText:e.find("#setting-submit-text").val().trim()||"Submit",successMessage:e.find("#setting-success-message").val().trim()||"Thank you.",layout:e.find("#setting-layout").val()||"grid",columns:Se(e.find("#setting-columns").val()),submitSpan:e.find("#setting-submit-span").val()||"",honeypot:e.find("#setting-honeypot").prop("checked"),rateLimitPerMinute:parseInt(e.find("#setting-rate-limit").val(),10)||3,successRedirect:e.find("#setting-success-redirect").val().trim()||null,actionSlug:e.find("#action-cms-slug").val()||null},actions:{email:{enabled:e.find("#action-email-enabled").prop("checked"),recipients:e.find("#action-email-recipients").val().trim(),subjectPrefix:e.find("#action-email-subject-prefix").val().trim()},webhook:{enabled:e.find("#action-webhook-enabled").prop("checked"),url:e.find("#action-webhook-url").val().trim(),method:e.find("#action-webhook-method").val()},...be!==null&&{collection:be}}}}function qt(e,t){const o={};return e.forEach(n=>{if(n.type==="page-break"||n.type==="spacer")return;const l={...n.formConfig||{}};l.span==="full"&&t&&(l.span=t);const a=n.type==="chooser"||!!(n.variant&&["select","radio","checkbox-group"].includes(n.type)),r={type:n.type==="checkbox"?"boolean":n.type==="date"||n.type==="icon"||n.type==="image"?"string":a?"chooser":n.type,label:n.label,required:n.required,options:n.options,formConfig:{...n.placeholder&&{placeholder:n.placeholder},...n.helper&&{helperText:n.helper},...n.tooltip&&{tooltip:n.tooltip},...l}};a&&(n.variant&&(r.variant=n.variant),(n.multiple||n.type==="checkbox-group")&&(r.multiple=!0),n.density&&(r.density=n.density),n.columns&&(r.columns=n.columns),n.accent&&(r.accent=n.accent),n.accentStyle&&(r.accentStyle=n.accentStyle),n.glow&&(r.glow=!0),n.glowColour&&(r.glowColour=n.glowColour),n.shadow&&(r.shadow=n.shadow),n.shadowColour&&(r.shadowColour=n.shadowColour)),o[n.name]=r}),o}function $t(e,t){const o=typeof e=="string"?document.querySelector(e):e;o&&(t||[]).forEach(n=>{if(n.type!=="date"||!n.name)return;const l=o.querySelector(`[name="${n.name}"]`);l&&l.type!=="date"&&(l.type="date")})}function At(e,t){const o=e?.querySelector?.(".dm-plugin-banner-name .dm-plugin-banner-sep");if(o){for(;o.nextSibling;)o.nextSibling.remove();o.after(document.createTextNode(String(t||"")))}}const vn=e=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");let W=null,Ft=0,It=!1;const Ne=e=>String(e||"").split("?")[0].replace(/\/$/,"");function xn(){It||!window.R?.use||(It=!0,R.use((e,t,o)=>!W||!at(t?.path,e?.path)||W.path!==Ne(t?.path)||(W.flush(),!W.dirty())?o():E.confirm("You have unsaved changes to this form. Leave anyway? They are kept as a draft for your next visit to it.").then(n=>{n?o():history.replaceState(null,"",`#${t.path}`)})),M.subscribe("router:afterChange",({to:e,from:t}={})=>{if(W&&W.path===Ne(t?.path)&&at(t?.path,e?.path)){const o=W;W=null,o.dispose()}}))}export const formEditorView={templateUrl:"/admin/js/templates/form-editor.html",async onMount(e){if(xn(),W){const p=W;W=null,p.dispose()}const t=Ne(location.hash.replace(/^#/,"")),o=++Ft,n=()=>o!==Ft||!e.get(0)?.isConnected||Ne(location.hash.replace(/^#/,""))!==t;C=[],N=null,be=null;const l=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);N=l?l[1]:null;let a=null;const i=E.loader(e.get(0),{type:"dots"});if(N)try{if(a=await ie(`/forms/${N}`),n()){i.destroy();return}C=a.fields||[],be=a.actions?.collection??null}catch{if(n()){i.destroy();return}E.toast("Could not load form.",{type:"error"})}ge={};try{const p=await ie("/projects").catch(()=>[]);if(n()){i.destroy();return}const v=e.find("#field-project").get(0);v&&(Array.isArray(p)?p:[]).forEach(y=>{const k=document.createElement("option");k.value=y.slug,k.textContent=y.name||y.slug,v.appendChild(k)})}catch{}if(i.destroy(),At(e.get(0),a?a.title||a.slug:"New form"),N||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(rt(this.value))}),E.tabs(e.find("#editor-tabs").get(0)),a){e.find("#field-title").val(a.title),e.find("#field-slug").val(a.slug),e.find("#field-description").val(a.description||""),e.find("#field-bundled").prop("checked",!!a.bundled),ge=a.meta||{},e.find("#field-project").val(a.meta?.project||"");const p=a.settings||{};e.find("#setting-submit-text").val(p.submitText||"Submit"),e.find("#setting-success-message").val(p.successMessage||""),e.find("#setting-layout").val(p.layout||"grid"),e.find("#setting-columns").val(Se(p.columns)),e.find("#setting-submit-span").val(p.submitSpan||""),e.find("#columns-group").get(0).style.display=(p.layout||"grid")==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",p.honeypot!==!1),e.find("#setting-rate-limit").val(p.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(p.successRedirect||"");const v=a.actions?.email||{};e.find("#action-email-enabled").prop("checked",v.enabled||!1),e.find("#action-email-recipients").val(v.recipients||""),e.find("#action-email-subject-prefix").val(v.subjectPrefix||"");const y=a.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",y.enabled||!1),e.find("#action-webhook-url").val(y.url||""),e.find("#action-webhook-method").val(y.method||"POST")}const r=a?.settings?.actionSlug||"";try{const p=await ie("/actions").catch(()=>[]);if(n())return;const v=e.find("#action-cms-slug").get(0);if(he=Array.isArray(p)?p:[],(Array.isArray(p)?p:[]).forEach(y=>{const k=document.createElement("option");k.value=y.slug,k.textContent=y.title||y.slug,y.slug===r&&(k.selected=!0),v.appendChild(k)}),!p.length){const y=document.createElement("option");y.value="",y.textContent="No actions available",y.disabled=!0,v.appendChild(y)}}catch{}const c=p=>{e.find("#columns-group").get(0).style.display=p?"":"none",document.querySelectorAll(".fb-grid-row").forEach(v=>{v.style.display=p?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){c(this.value==="grid")}),c(e.find("#setting-layout").val()==="grid"),J(e);const s=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",p=>{p.stopPropagation(),s.style.display=s.style.display==="none"?"":"none"}),ne&&document.removeEventListener("click",ne),ne=()=>{s&&(s.style.display="none")},document.addEventListener("click",ne),e.find("#add-field-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),O();const p=C.length;C.push({name:`field_${p+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),J(e);const v=e.find("#fields-list").get(0)?.lastElementChild;if(v){const y=v.querySelector(".fb-field-body");y&&(y.style.display="")}}),e.find("#add-spacer-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),O(),C.push({type:"spacer"}),J(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),O();const p=C.filter(v=>v.type==="page-break").length+2;C.push({type:"page-break",label:`Step ${p}`,description:""}),J(e)}),ye=()=>{const p=Te(e),v=e.find("#preview-container").get(0);if(!v)return;const y=e.find("#preview-test-result").get(0),k=e.find("#preview-test-badge").get(0);y&&(y.style.display="none",y.textContent=""),k&&(k.style.display=N?"":"none"),e.find("#preview-card").get(0).style.display="",v.textContent="";const j=document.createElement("div");j.id="fb-preview-form",v.appendChild(j);const U=N?async L=>{y&&(y.style.display="none",y.textContent="");try{const T=await fetch(`/api/forms/submit/${N}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(L)}),K=await T.json();if(!T.ok)throw new Error(K.error||"Submission failed.");y&&(y.textContent=K.message||p.settings?.successMessage||"Submitted successfully.",y.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-success) 12%, transparent);color:var(--dm-success);"),E.toast("Test submission stored.",{type:"success"})}catch(T){y&&(y.textContent=T.message,y.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-danger) 12%, transparent);color:var(--dm-danger);"),E.toast(T.message,{type:"error"})}return!1}:()=>!1,me=p.fields.some(L=>L.type==="page-break");if(j.addEventListener("dm-form-end",L=>{const T=L.detail?.validation;if(T&&!T.valid){E.toast(`Still to answer: ${T.missing.map(K=>K.label).concat(T.errors).join(", ")}`,{type:"warning"});return}U(L.detail?.values||{})}),typeof F<"u"){const L=Se(p.settings?.columns),T=p.settings?.layout||"grid";if(me&&F.wizard){const K=zt(p.fields,p.title),fe=K.map(te=>({title:te.title,description:te.description,fields:qt(te.fields,L)}));let B=0,X=null,qe=null;const Ze=te=>{const et=(K[B]||{}).fields||[];$t("#fb-preview-form",et),tt(j,et),te&&window.FormLogicEngine&&dt(p.fields)&&(X?.destroy?.(),X=new window.FormLogicEngine.FormLogicRuntime({fields:p.fields},j,{baseValues:qe?.getStepData?qe.getStepData():{}}),X.init())};qe=F.wizard("#fb-preview-form",{schema:{steps:fe},layout:T,columns:L,finishText:p.settings?.submitText||"Finish",onStepChange:te=>{B=te,queueMicrotask(()=>Ze(!0))},onSubmit:U}),Ze(!1)}else if(F.render){const K=qt(p.fields,L),fe={};if(p.fields.forEach(B=>{if(!(!B.name||B.type==="page-break"||B.type==="spacer")&&(B.type==="select"||B.type==="multiselect")&&B.required){const X=(B.options||[])[0];X&&(fe[B.name]=typeof X=="object"?X.value:X)}}),F.render("#fb-preview-form",K,fe,{submitText:p.settings?.submitText||"Submit",layout:T,columns:L,onSubmit:U}),T==="grid"&&p.settings?.submitSpan==="full"){const B=document.querySelector("#fb-preview-form .form-buttons");B&&B.classList.add("col-span-full")}$t("#fb-preview-form",p.fields),tt(j,p.fields)}window.FormLogicEngine&&dt(p.fields)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:p.fields},j).init()})}else{const L=document.createElement("p");L.textContent=`${p.fields.filter(T=>T.type!=="page-break").length} field(s): ${p.fields.filter(T=>T.type!=="page-break").map(T=>T.label).join(", ")}`,L.style.cssText="color:var(--dm-text-muted);font-style:italic;",j.appendChild(L)}},ye();const d=e.find("#editor-tabs").get(0),u=e.find("#preview-card").get(0),b=p=>{u&&u.contains(p.target)||Re()};d&&(d.addEventListener("input",b),d.addEventListener("change",b));const g=e.get(0),m=[],h=p=>(m.push(p),p);let w=!1;const f=M.observable(!1),x=M.observable(!1);let $=N,A=Te(e),G=Fe(A),P=A;const _=()=>{w||!g.isConnected||(P=Te(e),f.value=Fe(P)!==G)};let I=null;Oe=()=>{clearTimeout(I),I=setTimeout(_,150)},h(()=>{clearTimeout(I),Oe=null,ce=null});const Q=p=>{const v=p.settings||{};e.find("#field-title").val(p.title||""),e.find("#field-slug").val(p.slug||""),e.find("#field-description").val(p.description||""),e.find("#field-bundled").prop("checked",!!p.bundled),ge={...p.meta||{}},e.find("#field-project").val(p.meta?.project||""),e.find("#setting-submit-text").val(v.submitText||"Submit"),e.find("#setting-success-message").val(v.successMessage||""),e.find("#setting-layout").val(v.layout||"grid"),e.find("#setting-columns").val(Se(v.columns)),e.find("#setting-submit-span").val(v.submitSpan||""),e.find("#setting-honeypot").prop("checked",v.honeypot!==!1),e.find("#setting-rate-limit").val(v.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(v.successRedirect||""),e.find("#action-cms-slug").val(v.actionSlug||"");const y=p.actions?.email||{};e.find("#action-email-enabled").prop("checked",!!y.enabled),e.find("#action-email-recipients").val(y.recipients||""),e.find("#action-email-subject-prefix").val(y.subjectPrefix||"");const k=p.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",!!k.enabled),e.find("#action-webhook-url").val(k.url||""),e.find("#action-webhook-method").val(k.method||"POST"),C=JSON.parse(JSON.stringify(p.fields||[])),c((v.layout||"grid")==="grid"),J(e)};async function H(){if(x.peek()||w)return;const p=Te(e);if(!p.title){E.toast("Please enter a form title (Form Details).",{type:"error"});return}x.value=!0;const v=N;try{N?(await ie(`/forms/${N}`,{method:"PUT",body:JSON.stringify(p)}),E.toast("Form saved.",{type:"success"})):(N=(await ie("/forms",{method:"POST",body:JSON.stringify(p)})).slug,E.toast("Form created.",{type:"success"})),$=N,A=p,G=Fe(p),P=p,f.value=!1;for(const y of new Set([se(v),se(N)]))try{S.remove?S.remove(y):S.set(y,null)}catch{}At(g,p.title),_t("#/forms"),v||R.navigate(`/forms/edit/${N}`)}catch(y){v||(N=null),E.toast(y.message||"Failed to save form.",{type:"error"})}finally{x.value=!1}}async function Bt(){f.peek()&&(!await E.confirm("Discard the changes you have not saved?")||w||(Q(A),_(),Ke()))}const Ge=g.querySelector(".fex-bar");if(Ge){const p=M.applyBindings({dirty:f,saving:x},Ge,{methods:{save:H,discard:Bt}});h(()=>p.dispose())}h(Pt(g,{position:"bottom"})),$e(e,{id:"form-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>H()}),$e(e,{id:"form-editor-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),N&&$e(e,{id:"form-editor-subs",icon:"list",title:"Submissions",onClick:()=>{location.hash=`#/forms/${encodeURIComponent(N)}/submissions`}});const We=p=>{n()||!(p.ctrlKey||p.metaKey)||String(p.key).toLowerCase()!=="s"||(p.preventDefault(),p.stopImmediatePropagation(),H())};document.addEventListener("keydown",We,!0),h(()=>document.removeEventListener("keydown",We,!0));const Z=e.find("#fields-list").get(0),Ot=p=>p?.closest?.(".fb-field-card"),He=p=>Number(p?.dataset.index),Ue=p=>p?.querySelector(":scope > .fb-field-body"),Je=p=>{const v=Ue(p);v&&(v.style.display=v.style.display==="none"?"":"none")},ue=(p,v)=>{C=p,J(e),v!=null&&Z?.querySelectorAll(".fb-field-card")[v]?.focus()},Rt=async p=>{try{await navigator.clipboard.writeText(p),E.toast(`Copied "${p}".`,{type:"success"})}catch{E.toast(`Copy failed - the name is ${p}.`,{type:"info"})}},Dt=p=>{const v=Ot(p),y=He(v);O();const k=C[y];if(!k)return[];const j=k.type!=="spacer"&&k.type!=="page-break",U=Ue(v),me=U&&U.style.display!=="none";return[{header:Ae(k)},...U?[{label:me?"Close":"Edit",icon:me?"chevron-up":"edit",action:()=>Je(v)}]:[],...j?[{label:"Logic & triggers",icon:"zap",action:()=>{U&&(U.style.display=""),(U?.querySelector(".fb-field-logic")||U)?.scrollIntoView({block:"center",behavior:"smooth"})}}]:[],{label:"Duplicate",icon:"copy",action:()=>{O(),ue(Vt(C,y),y+1)}},{type:"divider"},{label:"Move up",icon:"arrow-up",disabled:y===0,action:()=>{O(),ue(ot(C,y,-1),y-1)}},{label:"Move down",icon:"arrow-down",disabled:y>=C.length-1,action:()=>{O(),ue(ot(C,y,1),y+1)}},...j&&k.name?[{label:"Copy field name",icon:"clipboard",action:()=>Rt(k.name)}]:[],{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:async()=>{if(k.type!=="spacer"&&!await E.confirm(`Remove "${vn(Ae(k))}"?`))return;O();const L=[...C];L.splice(y,1),ue(L,Math.min(y,L.length-1))}}]};let Ye=null;if(Z&&E.contextMenu&&(Ye=E.contextMenu(Z,{cursor:"glyph",match:".fb-field-card > :first-child",inherit:!1,density:"compact",items:p=>Dt(p)}),h(()=>Ye?.destroy?.())),ce=p=>{for(const v of p.querySelectorAll(".fb-field-card")){v.tabIndex=0;const y=v.firstElementChild;if(!y||y.querySelector(".fex-kebab"))continue;const k=document.createElement("button");k.type="button",k.className="fex-kebab",k.textContent="\u22EE",k.title="Actions",O(),k.setAttribute("aria-label",`Actions for ${Ae(C[He(v)])}`),k.addEventListener("click",j=>{j.stopPropagation(),nt(k)}),y.appendChild(k)}},Z){ce(Z);const p=v=>{const y=v.target?.classList?.contains("fb-field-card")?v.target:null;y&&(v.key==="F10"&&v.shiftKey?(v.preventDefault(),nt(y.firstElementChild)):v.key==="Enter"&&(v.preventDefault(),Je(y)))};Z.addEventListener("keydown",p),h(()=>Z.removeEventListener("keydown",p))}const Ke=()=>{try{const p=se($);S.remove?S.remove(p):S.set(p,null)}catch{}},Qe=p=>{if(!f.peek()||!p){Ke();return}try{S.set(se($),{data:jt(p),base:lt(G),at:new Date().toISOString()})}catch{}},Xe=p=>{_(),f.peek()&&(Qe(P),p.preventDefault(),p.returnValue="")};window.addEventListener("beforeunload",Xe),h(()=>window.removeEventListener("beforeunload",Xe)),h(()=>{ne&&(document.removeEventListener("click",ne),ne=null)}),W={path:t,dirty:()=>f.peek(),flush:()=>{clearTimeout(I),_()},dispose(){w||(Qe(P),w=!0,m.splice(0).reverse().forEach(p=>{try{p?.()}catch{}}))}};const Le=se(N);let ee=null;try{ee=S.get(Le)}catch{}if(ee?.data){try{S.remove?S.remove(Le):S.set(Le,null)}catch{}const p=ee.base&&ee.base!==lt(G),v=ee.at?` (${Wt(ee.at)})`:"";await E.confirm(`You left unsaved changes to this form${v}.${p?" The saved form has changed since then.":""} Pick up where you left off?`)&&!w&&(Q(Gt(ee.data,A)),_())}}};
8
+ `),l.style.fontFamily="monospace",o.appendChild(n),o.appendChild(l),o}function ke(e){return parseInt(e,10)===3?3:2}function Se(e){const t=e.find("#field-project").val()||"";return z(),{title:e.find("#field-title").val().trim(),slug:e.find("#field-slug").val().trim(),description:e.find("#field-description").val().trim(),...e.find("#field-bundled").is(":checked")?{bundled:!0}:{},meta:{...be||{},project:t||null},fields:C,settings:{submitText:e.find("#setting-submit-text").val().trim()||"Submit",successMessage:e.find("#setting-success-message").val().trim()||"Thank you.",layout:e.find("#setting-layout").val()||"grid",columns:ke(e.find("#setting-columns").val()),submitSpan:e.find("#setting-submit-span").val()||"",honeypot:e.find("#setting-honeypot").prop("checked"),rateLimitPerMinute:parseInt(e.find("#setting-rate-limit").val(),10)||3,successRedirect:e.find("#setting-success-redirect").val().trim()||null,actionSlug:e.find("#action-cms-slug").val()||null},actions:{email:{enabled:e.find("#action-email-enabled").prop("checked"),recipients:e.find("#action-email-recipients").val().trim(),subjectPrefix:e.find("#action-email-subject-prefix").val().trim()},webhook:{enabled:e.find("#action-webhook-enabled").prop("checked"),url:e.find("#action-webhook-url").val().trim(),method:e.find("#action-webhook-method").val()},...he!==null&&{collection:he}}}}function Lt(e,t){const o={};return e.forEach(n=>{if(n.type==="page-break"||n.type==="spacer")return;const l={...n.formConfig||{}};l.span==="full"&&t&&(l.span=t);const a=n.type==="chooser"||!!(n.variant&&["select","radio","checkbox-group"].includes(n.type)),r={type:n.type==="checkbox"?"boolean":n.type==="date"||n.type==="icon"||n.type==="image"?"string":a?"chooser":n.type,label:n.label,required:n.required,options:n.options,formConfig:{...n.placeholder&&{placeholder:n.placeholder},...n.helper&&{helperText:n.helper},...n.tooltip&&{tooltip:n.tooltip},...l}};a&&(n.variant&&(r.variant=n.variant),(n.multiple||n.type==="checkbox-group")&&(r.multiple=!0),n.density&&(r.density=n.density),n.columns&&(r.columns=n.columns),n.accent&&(r.accent=n.accent),n.accentStyle&&(r.accentStyle=n.accentStyle),n.glow&&(r.glow=!0),n.glowColour&&(r.glowColour=n.glowColour),n.shadow&&(r.shadow=n.shadow),n.shadowColour&&(r.shadowColour=n.shadowColour)),o[n.name]=r}),o}function qt(e,t){const o=typeof e=="string"?document.querySelector(e):e;o&&(t||[]).forEach(n=>{if(n.type!=="date"||!n.name)return;const l=o.querySelector(`[name="${n.name}"]`);l&&l.type!=="date"&&(l.type="date")})}function $t(e,t){const o=e?.querySelector?.(".dm-plugin-banner-name .dm-plugin-banner-sep");if(o){for(;o.nextSibling;)o.nextSibling.remove();o.after(document.createTextNode(String(t||"")))}}const yn=e=>String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;");let W=null,At=0,Ft=!1;const Te=e=>String(e||"").split("?")[0].replace(/\/$/,"");function vn(){Ft||!window.R?.use||(Ft=!0,R.use((e,t,o)=>!W||!lt(t?.path,e?.path)||W.path!==Te(t?.path)||(W.flush(),!W.dirty())?o():E.confirm("You have unsaved changes to this form. Leave anyway? They are kept as a draft for your next visit to it.").then(n=>{n?o():history.replaceState(null,"",`#${t.path}`)})),M.subscribe("router:afterChange",({to:e,from:t}={})=>{if(W&&W.path===Te(t?.path)&&lt(t?.path,e?.path)){const o=W;W=null,o.dispose()}}))}export const formEditorView={templateUrl:"/admin/js/templates/form-editor.html",async onMount(e){if(vn(),W){const p=W;W=null,p.dispose()}const t=Te(location.hash.replace(/^#/,"")),o=++At,n=()=>o!==At||!e.get(0)?.isConnected||Te(location.hash.replace(/^#/,""))!==t;C=[],N=null,he=null;const l=window.location.hash.match(/\/forms\/edit\/([^/?#]+)/);N=l?l[1]:null;let a=null;const i=E.loader(e.get(0),{type:"dots"});if(N)try{if(a=await ie(`/forms/${N}`),n()){i.destroy();return}C=a.fields||[],he=a.actions?.collection??null}catch{if(n()){i.destroy();return}E.toast("Could not load form.",{type:"error"})}be={};try{const p=await ie("/projects").catch(()=>[]);if(n()){i.destroy();return}const v=e.find("#field-project").get(0);v&&(Array.isArray(p)?p:[]).forEach(g=>{const w=document.createElement("option");w.value=g.slug,w.textContent=g.name||g.slug,v.appendChild(w)})}catch{}if(i.destroy(),$t(e.get(0),a?a.title||a.slug:"New form"),N||e.find("#field-title").get(0).addEventListener("input",function(){e.find("#field-slug").val(st(this.value))}),E.tabs(e.find("#editor-tabs").get(0)),a){e.find("#field-title").val(a.title),e.find("#field-slug").val(a.slug),e.find("#field-description").val(a.description||""),e.find("#field-bundled").prop("checked",!!a.bundled),be=a.meta||{},e.find("#field-project").val(a.meta?.project||"");const p=a.settings||{};e.find("#setting-submit-text").val(p.submitText||"Submit"),e.find("#setting-success-message").val(p.successMessage||""),e.find("#setting-layout").val(p.layout||"grid"),e.find("#setting-columns").val(ke(p.columns)),e.find("#setting-submit-span").val(p.submitSpan||""),e.find("#columns-group").get(0).style.display=(p.layout||"grid")==="grid"?"":"none",e.find("#setting-honeypot").prop("checked",p.honeypot!==!1),e.find("#setting-rate-limit").val(p.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(p.successRedirect||"");const v=a.actions?.email||{};e.find("#action-email-enabled").prop("checked",v.enabled||!1),e.find("#action-email-recipients").val(v.recipients||""),e.find("#action-email-subject-prefix").val(v.subjectPrefix||"");const g=a.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",g.enabled||!1),e.find("#action-webhook-url").val(g.url||""),e.find("#action-webhook-method").val(g.method||"POST")}const r=a?.settings?.actionSlug||"";try{const p=await ie("/actions").catch(()=>[]);if(n())return;const v=e.find("#action-cms-slug").get(0);if(fe=Array.isArray(p)?p:[],(Array.isArray(p)?p:[]).forEach(g=>{const w=document.createElement("option");w.value=g.slug,w.textContent=g.title||g.slug,g.slug===r&&(w.selected=!0),v.appendChild(w)}),!p.length){const g=document.createElement("option");g.value="",g.textContent="No actions available",g.disabled=!0,v.appendChild(g)}}catch{}const c=p=>{e.find("#columns-group").get(0).style.display=p?"":"none",document.querySelectorAll(".fb-grid-row").forEach(v=>{v.style.display=p?"flex":"none"})};e.find("#setting-layout").get(0)?.addEventListener("change",function(){c(this.value==="grid")}),c(e.find("#setting-layout").val()==="grid"),Q(e);const s=e.find("#add-element-menu").get(0);e.find("#add-element-btn").get(0).addEventListener("click",p=>{p.stopPropagation(),s.style.display=s.style.display==="none"?"":"none"}),ne&&document.removeEventListener("click",ne),ne=()=>{s&&(s.style.display="none")},document.addEventListener("click",ne),e.find("#add-field-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),z();const p=C.length;C.push({name:`field_${p+1}`,type:"string",label:"New Field",required:!1,placeholder:""}),Q(e);const v=e.find("#fields-list").get(0)?.lastElementChild;if(v){const g=v.querySelector(".fb-field-body");g&&(g.style.display="")}}),e.find("#add-spacer-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),z(),C.push({type:"spacer"}),Q(e)}),e.find("#add-page-break-btn").get(0).addEventListener("click",()=>{s&&(s.style.display="none"),z();const p=C.filter(v=>v.type==="page-break").length+2;C.push({type:"page-break",label:`Step ${p}`,description:""}),Q(e)}),ge=()=>{const p=Se(e),v=e.find("#preview-container").get(0);if(!v)return;const g=e.find("#preview-test-result").get(0),w=e.find("#preview-test-badge").get(0);g&&(g.style.display="none",g.textContent=""),w&&(w.style.display=N?"":"none"),e.find("#preview-card").get(0).style.display="",v.textContent="";const B=document.createElement("div");B.id="fb-preview-form",v.appendChild(B);const U=N?async L=>{g&&(g.style.display="none",g.textContent="");try{const T=await fetch(`/api/forms/submit/${N}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(L)}),K=await T.json();if(!T.ok)throw new Error(K.error||"Submission failed.");g&&(g.textContent=K.message||p.settings?.successMessage||"Submitted successfully.",g.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-success) 12%, transparent);color:var(--dm-success);"),E.toast("Test submission stored.",{type:"success"})}catch(T){g&&(g.textContent=T.message,g.style.cssText="display:block;margin-top:.75rem;padding:.6rem .9rem;border-radius:6px;font-size:.9rem;background:color-mix(in srgb, var(--dm-danger) 12%, transparent);color:var(--dm-danger);"),E.toast(T.message,{type:"error"})}return!1}:()=>!1,ue=p.fields.some(L=>L.type==="page-break");if(B.addEventListener("dm-form-end",L=>{const T=L.detail?.validation;if(T&&!T.valid){E.toast(`Still to answer: ${T.missing.map(K=>K.label).concat(T.errors).join(", ")}`,{type:"warning"});return}U(L.detail?.values||{})}),typeof F<"u"){const L=ke(p.settings?.columns),T=p.settings?.layout||"grid";if(ue&&F.wizard){const K=zt(p.fields,p.title),me=K.map(te=>({title:te.title,description:te.description,fields:Lt(te.fields,L)}));let O=0,Z=null,Le=null;const Xe=te=>{const Ze=(K[O]||{}).fields||[];qt("#fb-preview-form",Ze),et(B,Ze),te&&window.FormLogicEngine&&ct(p.fields)&&(Z?.destroy?.(),Z=new window.FormLogicEngine.FormLogicRuntime({fields:p.fields},B,{baseValues:Le?.getStepData?Le.getStepData():{}}),Z.init())};Le=F.wizard("#fb-preview-form",{schema:{steps:me},layout:T,columns:L,finishText:p.settings?.submitText||"Finish",onStepChange:te=>{O=te,queueMicrotask(()=>Xe(!0))},onSubmit:U}),Xe(!1)}else if(F.render){const K=Lt(p.fields,L),me={};if(p.fields.forEach(O=>{if(!(!O.name||O.type==="page-break"||O.type==="spacer")&&(O.type==="select"||O.type==="multiselect")&&O.required){const Z=(O.options||[])[0];Z&&(me[O.name]=typeof Z=="object"?Z.value:Z)}}),F.render("#fb-preview-form",K,me,{submitText:p.settings?.submitText||"Submit",layout:T,columns:L,onSubmit:U}),T==="grid"&&p.settings?.submitSpan==="full"){const O=document.querySelector("#fb-preview-form .form-buttons");O&&O.classList.add("col-span-full")}qt("#fb-preview-form",p.fields),et(B,p.fields)}window.FormLogicEngine&&ct(p.fields)&&requestAnimationFrame(()=>{new window.FormLogicEngine.FormLogicRuntime({fields:p.fields},B).init()})}else{const L=document.createElement("p");L.textContent=`${p.fields.filter(T=>T.type!=="page-break").length} field(s): ${p.fields.filter(T=>T.type!=="page-break").map(T=>T.label).join(", ")}`,L.style.cssText="color:var(--dm-text-muted);font-style:italic;",B.appendChild(L)}},ge();const d=e.find("#editor-tabs").get(0),u=e.find("#preview-card").get(0),b=p=>{u&&u.contains(p.target)||Oe()};d&&(d.addEventListener("input",b),d.addEventListener("change",b));const y=e.get(0),m=[],f=p=>(m.push(p),p);let k=!1;const h=M.observable(!1),x=M.observable(!1);let $=N,A=Se(e),G=Ae(A),_=A;const j=()=>{k||!y.isConnected||(_=Se(e),h.value=Ae(_)!==G)};let I=null;Be=()=>{clearTimeout(I),I=setTimeout(j,150)},f(()=>{clearTimeout(I),Be=null,ce=null});const X=p=>{const v=p.settings||{};e.find("#field-title").val(p.title||""),e.find("#field-slug").val(p.slug||""),e.find("#field-description").val(p.description||""),e.find("#field-bundled").prop("checked",!!p.bundled),be={...p.meta||{}},e.find("#field-project").val(p.meta?.project||""),e.find("#setting-submit-text").val(v.submitText||"Submit"),e.find("#setting-success-message").val(v.successMessage||""),e.find("#setting-layout").val(v.layout||"grid"),e.find("#setting-columns").val(ke(v.columns)),e.find("#setting-submit-span").val(v.submitSpan||""),e.find("#setting-honeypot").prop("checked",v.honeypot!==!1),e.find("#setting-rate-limit").val(v.rateLimitPerMinute||3),e.find("#setting-success-redirect").val(v.successRedirect||""),e.find("#action-cms-slug").val(v.actionSlug||"");const g=p.actions?.email||{};e.find("#action-email-enabled").prop("checked",!!g.enabled),e.find("#action-email-recipients").val(g.recipients||""),e.find("#action-email-subject-prefix").val(g.subjectPrefix||"");const w=p.actions?.webhook||{};e.find("#action-webhook-enabled").prop("checked",!!w.enabled),e.find("#action-webhook-url").val(w.url||""),e.find("#action-webhook-method").val(w.method||"POST"),C=JSON.parse(JSON.stringify(p.fields||[])),c((v.layout||"grid")==="grid"),Q(e)};async function H(){if(x.peek()||k)return;const p=Se(e);if(!p.title){E.toast("Please enter a form title (Form Details).",{type:"error"});return}x.value=!0;const v=N;try{N?(await ie(`/forms/${N}`,{method:"PUT",body:JSON.stringify(p)}),E.toast("Form saved.",{type:"success"})):(N=(await ie("/forms",{method:"POST",body:JSON.stringify(p)})).slug,E.toast("Form created.",{type:"success"})),$=N,A=p,G=Ae(p),_=p,h.value=!1;for(const g of new Set([se(v),se(N)]))try{S.remove?S.remove(g):S.set(g,null)}catch{}$t(y,p.title),Pt("#/forms"),v||R.navigate(`/forms/edit/${N}`)}catch(g){v||(N=null),E.toast(g.message||"Failed to save form.",{type:"error"})}finally{x.value=!1}}async function It(){h.peek()&&(!await E.confirm("Discard the changes you have not saved?")||k||(X(A),j(),Ye()))}const Ve=y.querySelector(".fex-bar");if(Ve){const p=M.applyBindings({dirty:h,saving:x},Ve,{methods:{save:H,discard:It}});f(()=>p.dispose())}f(Dt(y,{position:"bottom"})),qe(e,{id:"form-editor-save",icon:"save",title:"Save (Ctrl+S)",onClick:()=>H()}),qe(e,{id:"form-editor-back",icon:"arrow-left",title:"All forms",onClick:()=>{location.hash="#/forms"}}),N&&qe(e,{id:"form-editor-subs",icon:"list",title:"Submissions",onClick:()=>{location.hash=`#/forms/${encodeURIComponent(N)}/submissions`}});const Ge=p=>{n()||!(p.ctrlKey||p.metaKey)||String(p.key).toLowerCase()!=="s"||(p.preventDefault(),p.stopImmediatePropagation(),H())};document.addEventListener("keydown",Ge,!0),f(()=>document.removeEventListener("keydown",Ge,!0));const Y=e.find("#fields-list").get(0),Bt=p=>p?.closest?.(".fb-field-card"),We=p=>Number(p?.dataset.index),He=p=>p?.querySelector(":scope > .fb-field-body"),Ue=p=>{const v=He(p);v&&(v.style.display=v.style.display==="none"?"":"none")},oe=(p,v)=>{C=p,Q(e),v!=null&&Y?.querySelectorAll(".fb-field-card")[v]?.focus()},Ot=async p=>{try{await navigator.clipboard.writeText(p),E.toast(`Copied "${p}".`,{type:"success"})}catch{E.toast(`Copy failed - the name is ${p}.`,{type:"info"})}},Rt=p=>{const v=Bt(p),g=We(v);z();const w=C[g];if(!w)return[];const B=w.type!=="spacer"&&w.type!=="page-break",U=He(v),ue=U&&U.style.display!=="none";return[{header:$e(w)},...U?[{label:ue?"Close":"Edit",icon:ue?"chevron-up":"edit",action:()=>Ue(v)}]:[],...B?[{label:"Logic & triggers",icon:"zap",action:()=>{U&&(U.style.display=""),(U?.querySelector(".fb-field-logic")||U)?.scrollIntoView({block:"center",behavior:"smooth"})}}]:[],{label:"Duplicate",icon:"copy",action:()=>{z(),oe(jt(C,g),g+1)}},{type:"divider"},{label:"Move up",icon:"arrow-up",shortcut:"Alt+\u2191",disabled:g===0,action:()=>{z(),oe(at(C,g,-1),g-1)}},{label:"Move down",icon:"arrow-down",shortcut:"Alt+\u2193",disabled:g>=C.length-1,action:()=>{z(),oe(at(C,g,1),g+1)}},...B&&w.name?[{label:"Copy field name",icon:"clipboard",action:()=>Ot(w.name)}]:[],{type:"divider"},{label:"Delete\u2026",icon:"trash",danger:!0,action:async()=>{if(w.type!=="spacer"&&!await E.confirm(`Remove "${yn($e(w))}"?`))return;z();const L=[...C];L.splice(g,1),oe(L,Math.min(g,L.length-1))}}]};if(Y&&typeof E.sortable=="function"){const p=E.sortable(Y,{items:".fb-field-card",handle:".fb-drag-grip",key:null,onSort:({from:v,to:g})=>{z();const w=[...C],[B]=w.splice(v,1);w.splice(g,0,B),oe(w,g)}});f(()=>p.destroy())}let Je=null;if(Y&&E.contextMenu&&(Je=E.contextMenu(Y,{cursor:"glyph",match:".fb-field-card > :first-child",inherit:!1,density:"compact",items:p=>Rt(p)}),f(()=>Je?.destroy?.())),ce=p=>{for(const v of p.querySelectorAll(".fb-field-card")){v.tabIndex=0;const g=v.firstElementChild;if(!g||g.querySelector(".fex-kebab"))continue;const w=document.createElement("button");w.type="button",w.className="fex-kebab",w.textContent="\u22EE",w.title="Actions",z(),w.setAttribute("aria-label",`Actions for ${$e(C[We(v)])}`),w.addEventListener("click",B=>{B.stopPropagation(),tt(w)}),g.appendChild(w)}},Y){ce(Y);const p=v=>{const g=v.target?.classList?.contains("fb-field-card")?v.target:null;g&&(v.key==="F10"&&v.shiftKey?(v.preventDefault(),tt(g.firstElementChild)):v.key==="Enter"&&(v.preventDefault(),Ue(g)))};Y.addEventListener("keydown",p),f(()=>Y.removeEventListener("keydown",p))}const Ye=()=>{try{const p=se($);S.remove?S.remove(p):S.set(p,null)}catch{}},Ke=p=>{if(!h.peek()||!p){Ye();return}try{S.set(se($),{data:_t(p),base:nt(G),at:new Date().toISOString()})}catch{}},Qe=p=>{j(),h.peek()&&(Ke(_),p.preventDefault(),p.returnValue="")};window.addEventListener("beforeunload",Qe),f(()=>window.removeEventListener("beforeunload",Qe)),f(()=>{ne&&(document.removeEventListener("click",ne),ne=null)}),W={path:t,dirty:()=>h.peek(),flush:()=>{clearTimeout(I),j()},dispose(){k||(Ke(_),k=!0,m.splice(0).reverse().forEach(p=>{try{p?.()}catch{}}))}};const Ne=se(N);let ee=null;try{ee=S.get(Ne)}catch{}if(ee?.data){try{S.remove?S.remove(Ne):S.set(Ne,null)}catch{}const p=ee.base&&ee.base!==nt(G),v=ee.at?` (${Gt(ee.at)})`:"";await E.confirm(`You left unsaved changes to this form${v}.${p?" The saved form has changed since then.":""} Pick up where you left off?`)&&!k&&(X(Vt(ee.data,A)),j())}}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "0.97.0",
3
+ "version": "0.98.0",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",