@agent-cms/agentcms 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/changelog.json +11 -0
- package/dist/admin/admin-files.json +4 -4
- package/dist/admin/assets/{CodeEditor-DcFzGUt8.js → CodeEditor-Wx1WlF3h.js} +1 -1
- package/dist/admin/assets/{index-CLZ1gQZl.js → index-DFVZw8E0.js} +23 -23
- package/dist/admin/assets/{sql-wasm-CYl3LXH_.js → sql-wasm-Bfkbn6Oa.js} +1 -1
- package/dist/admin/index.html +2 -2
- package/dist/admin/plugins/core-seo/bundle.js +2 -2
- package/dist/admin/plugins/flexweg-search/bundle.js +15 -15
- package/dist/admin/themes/marketplace-core/bundle.js +1 -1
- package/dist/agent/agentcms.mjs +7 -7
- package/dist/agent/chunks/{hosting-D_uj-Mt1.mjs → hosting-BftlDdsL.mjs} +3 -3
- package/dist/agent/chunks/{index-CrvEoyi0.mjs → index-BG05qslv.mjs} +29 -29
- package/dist/agent/chunks/{install-DkCCcKAO.mjs → install-DnmgOT3F.mjs} +4 -4
- package/dist/agent/chunks/{plan-EYKegfhp.mjs → plan-BrM8ztEp.mjs} +2 -2
- package/dist/agent/chunks/{registry-lkfb_E9O.mjs → registry-C9TSnZ77.mjs} +6 -6
- package/dist/agent/chunks/{siteAdd-BqcYt8nu.mjs → siteAdd-BcXhN9fk.mjs} +4 -4
- package/dist/version.json +1 -1
- package/package.json +2 -2
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/skills/agentcms-install/SKILL.md +15 -15
- package/plugin/skills/agentcms-install/references/flexweg.md +1 -1
- package/plugin/skills/agentcms-install/references/github.md +2 -2
- package/plugin/skills/agentcms-install/references/gitlab.md +1 -1
- package/plugin/skills/agentcms-install/references/s3.md +2 -2
- package/plugin/skills/agentcms-manage/SKILL.md +11 -11
|
@@ -594,7 +594,7 @@ Error generating stack: `+F.message+`
|
|
|
594
594
|
*
|
|
595
595
|
* This source code is licensed under the ISC license.
|
|
596
596
|
* See the LICENSE file in the root directory of this source tree.
|
|
597
|
-
*/const QW=We("Zap",[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]]);var AS,o4;function XW(){return o4||(o4=1,AS={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0}),AS}var ZW=XW();const YW=qd(ZW);var eG=/\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?(".*?"|'.*?')/g;function l4(t){var e={type:"tag",name:"",voidElement:!1,attrs:{},children:[]},n=t.match(/<\/?([^\s]+?)[/\s>]/);if(n&&(e.name=n[1],(YW[n[1]]||t.charAt(t.length-2)==="/")&&(e.voidElement=!0),e.name.startsWith("!--"))){var r=t.indexOf("-->");return{type:"comment",comment:r!==-1?t.slice(4,r):""}}for(var s=new RegExp(eG),i=null;(i=s.exec(t))!==null;)if(i[0].trim())if(i[1]){var a=i[1].trim(),o=[a,""];a.indexOf("=")>-1&&(o=a.split("=")),e.attrs[o[0]]=o[1],s.lastIndex--}else i[2]&&(e.attrs[i[2]]=i[3].trim().substring(1,i[3].length-1));return e}var tG=/<[a-zA-Z0-9\-\!\/](?:"[^"]*"|'[^']*'|[^'">])*>/g,nG=/^\s*$/,rG=Object.create(null);function B6(t,e){switch(e.type){case"text":return t+e.content;case"tag":return t+="<"+e.name+(e.attrs?(function(n){var r=[];for(var s in n)r.push(s+'="'+n[s]+'"');return r.length?" "+r.join(" "):""})(e.attrs):"")+(e.voidElement?"/>":">"),e.voidElement?t:t+e.children.reduce(B6,"")+"</"+e.name+">";case"comment":return t+"<!--"+e.comment+"-->"}}var sG={parse:function(t,e){e||(e={}),e.components||(e.components=rG);var n,r=[],s=[],i=-1,a=!1;if(t.indexOf("<")!==0){var o=t.indexOf("<");r.push({type:"text",content:o===-1?t:t.substring(0,o)})}return t.replace(tG,function(l,c){if(a){if(l!=="</"+n.name+">")return;a=!1}var h,p=l.charAt(1)!=="/",m=l.startsWith("<!--"),g=c+l.length,y=t.charAt(g);if(m){var x=l4(l);return i<0?(r.push(x),r):((h=s[i]).children.push(x),r)}if(p&&(i++,(n=l4(l)).type==="tag"&&e.components[n.name]&&(n.type="component",a=!0),n.voidElement||a||!y||y==="<"||n.children.push({type:"text",content:t.slice(g,t.indexOf("<",g))}),i===0&&r.push(n),(h=s[i-1])&&h.children.push(n),s[i]=n),(!p||n.voidElement)&&(i>-1&&(n.voidElement||n.name===l.slice(2,-1))&&(i--,n=i===-1?r:s[i]),!a&&y!=="<"&&y)){h=i===-1?r:s[i].children;var v=t.indexOf("<",g),k=t.slice(g,v===-1?void 0:v);nG.test(k)&&(k=" "),(v>-1&&i+h.length>=0||k!==" ")&&h.push({type:"text",content:k})}}),r},stringify:function(t){return t.reduce(function(e,n){return e+B6("",n)},"")}};const Dy=(t,e,n,r)=>{var i,a,o,l;const s=[n,{code:e,...r||{}}];if((a=(i=t==null?void 0:t.services)==null?void 0:i.logger)!=null&&a.forward)return t.services.logger.forward(s,"warn","react-i18next::",!0);Yi(s[0])&&(s[0]=`react-i18next:: ${s[0]}`),(l=(o=t==null?void 0:t.services)==null?void 0:o.logger)!=null&&l.warn?t.services.logger.warn(...s):console!=null&&console.warn&&console.warn(...s)},c4={},hg=(t,e,n,r)=>{Yi(n)&&c4[n]||(Yi(n)&&(c4[n]=new Date),Dy(t,e,n,r))},$6=(t,e)=>()=>{if(t.isInitialized)e();else{const n=()=>{setTimeout(()=>{t.off("initialized",n)},0),e()};t.on("initialized",n)}},EE=(t,e,n)=>{t.loadNamespaces(e,$6(t,n))},u4=(t,e,n,r)=>{if(Yi(n)&&(n=[n]),t.options.preload&&t.options.preload.indexOf(e)>-1)return EE(t,n,r);n.forEach(s=>{t.options.ns.indexOf(s)<0&&t.options.ns.push(s)}),t.loadLanguages(e,$6(t,r))},iG=(t,e,n={})=>!e.languages||!e.languages.length?(hg(e,"NO_LANGUAGES","i18n.languages were undefined or empty",{languages:e.languages}),!0):e.hasLoadedNamespace(t,{lng:n.lng,precheck:(r,s)=>{if(n.bindI18n&&n.bindI18n.indexOf("languageChanging")>-1&&r.services.backendConnector.backend&&r.isLanguageChangingTo&&!s(r.isLanguageChangingTo,t))return!1}}),H6=t=>t.displayName||t.name||(Yi(t)&&t.length>0?t:"Unknown"),Yi=t=>typeof t=="string",Bc=t=>typeof t=="object"&&t!==null,aG=/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g,oG={"&":"&","&":"&","<":"<","<":"<",">":">",">":">","'":"'","'":"'",""":'"',""":'"'," ":" "," ":" ","©":"©","©":"©","®":"®","®":"®","…":"…","…":"…","/":"/","/":"/"},lG=t=>oG[t],cG=t=>t.replace(aG,lG);let _E={bindI18n:"languageChanged",bindI18nStore:"",transEmptyNodeValue:"",transSupportBasicHtmlNodes:!0,transWrapTextNodes:"",transKeepBasicHtmlNodesFor:["br","strong","i","p"],useSuspense:!0,unescape:cG};const V6=(t={})=>{_E={..._E,...t}},$C=()=>_E;let q6;const W6=t=>{q6=t},Kf=()=>q6,TS=(t,e)=>{var r;if(!t)return!1;const n=((r=t.props)==null?void 0:r.children)??t.children;return e?n.length>0:!!n},IS=t=>{var n,r;if(!t)return[];const e=((n=t.props)==null?void 0:n.children)??t.children;return(r=t.props)!=null&&r.i18nIsDynamicList?Kh(e):e},uG=t=>Array.isArray(t)&&t.every(U.isValidElement),Kh=t=>Array.isArray(t)?t:[t],dG=(t,e)=>{const n={...e};return n.props=Object.assign(t.props,e.props),n},G6=(t,e,n,r)=>{if(!t)return"";let s="";const i=Kh(t),a=e!=null&&e.transSupportBasicHtmlNodes?e.transKeepBasicHtmlNodesFor??[]:[];return i.forEach((o,l)=>{if(Yi(o)){s+=`${o}`;return}if(U.isValidElement(o)){const{props:c,type:h}=o,p=Object.keys(c).length,m=a.indexOf(h)>-1,g=c.children;if(!g&&m&&!p){s+=`<${h}/>`;return}if(!g&&(!m||p)||c.i18nIsDynamicList){s+=`<${l}></${l}>`;return}if(m&&p===1&&Yi(g)){s+=`<${h}>${g}</${h}>`;return}const y=G6(g,e,n,r);s+=`<${l}>${y}</${l}>`;return}if(o===null){Dy(n,"TRANS_NULL_VALUE","Passed in a null value as child",{i18nKey:r});return}if(Bc(o)){const{format:c,...h}=o,p=Object.keys(h);if(p.length===1){const m=c?`${p[0]}, ${c}`:p[0];s+=`{{${m}}}`;return}Dy(n,"TRANS_INVALID_OBJ","Invalid child - Object should only have keys {{ value, format }} (format is optional).",{i18nKey:r,child:o});return}Dy(n,"TRANS_INVALID_VAR","Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.",{i18nKey:r,child:o})}),s},hG=(t,e,n,r,s,i,a)=>{if(n==="")return[];const o=s.transKeepBasicHtmlNodesFor||[],l=n&&new RegExp(o.map(k=>`<${k}`).join("|")).test(n);if(!t&&!e&&!l&&!a)return[n];const c=e??{},h=k=>{Kh(k).forEach(N=>{Yi(N)||(TS(N)?h(IS(N)):Bc(N)&&!U.isValidElement(N)&&Object.assign(c,N))})};h(t);const p=sG.parse(`<0>${n}</0>`),m={...c,...i},g=(k,C,N)=>{var D;const _=IS(k),P=x(_,C.children,N);return uG(_)&&P.length===0||(D=k.props)!=null&&D.i18nIsDynamicList?_:P},y=(k,C,N,_,P)=>{k.dummy?(k.children=C,N.push(U.cloneElement(k,{key:_},P?void 0:C))):N.push(...U.Children.map([k],D=>{const I={...D.props};return delete I.i18nIsDynamicList,U.createElement(D.type,{...I,key:_,ref:D.props.ref??D.ref},P?null:C)}))},x=(k,C,N)=>{const _=Kh(k);return Kh(C).reduce((D,I,L)=>{var q,V;const j=((V=(q=I.children)==null?void 0:q[0])==null?void 0:V.content)&&r.services.interpolator.interpolate(I.children[0].content,m,r.language);if(I.type==="tag"){let O=_[parseInt(I.name,10)];!O&&e&&(O=e[I.name]),N.length===1&&!O&&(O=N[0][I.name]),O||(O={});const $=Object.keys(I.attrs).length!==0?dG({props:I.attrs},O):O,B=U.isValidElement($),X=B&&TS(I,!0)&&!I.voidElement,fe=l&&Bc($)&&$.dummy&&!B,ie=Bc(e)&&Object.hasOwnProperty.call(e,I.name);if(Yi($)){const ae=r.services.interpolator.interpolate($,m,r.language);D.push(ae)}else if(TS($)||X){const ae=g($,I,N);y($,ae,D,L)}else if(fe){const ae=x(_,I.children,N);y($,ae,D,L)}else if(Number.isNaN(parseFloat(I.name)))if(ie){const ae=g($,I,N);y($,ae,D,L,I.voidElement)}else if(s.transSupportBasicHtmlNodes&&o.indexOf(I.name)>-1)if(I.voidElement)D.push(U.createElement(I.name,{key:`${I.name}-${L}`}));else{const ae=x(_,I.children,N);D.push(U.createElement(I.name,{key:`${I.name}-${L}`},ae))}else if(I.voidElement)D.push(`<${I.name} />`);else{const ae=x(_,I.children,N);D.push(`<${I.name}>${ae}</${I.name}>`)}else if(Bc($)&&!B){const ae=I.children[0]?j:null;ae&&D.push(ae)}else y($,j,D,L,I.children.length!==1||!j)}else if(I.type==="text"){const O=s.transWrapTextNodes,$=a?s.unescape(r.services.interpolator.interpolate(I.content,m,r.language)):r.services.interpolator.interpolate(I.content,m,r.language);O?D.push(U.createElement(O,{key:`${I.name}-${L}`},$)):D.push($)}return D},[])},v=x([{dummy:!0,children:t||[]}],p,Kh(t||[]));return IS(v[0])},K6=(t,e,n)=>{const r=t.key||e,s=U.cloneElement(t,{key:r});if(!s.props||!s.props.children||n.indexOf(`${e}/>`)<0&&n.indexOf(`${e} />`)<0)return s;function i(){return U.createElement(U.Fragment,null,s)}return U.createElement(i,{key:r})},fG=(t,e)=>t.map((n,r)=>K6(n,r,e)),pG=(t,e)=>{const n={};return Object.keys(t).forEach(r=>{Object.assign(n,{[r]:K6(t[r],r,e)})}),n},mG=(t,e,n,r)=>t?Array.isArray(t)?fG(t,e):Bc(t)?pG(t,e):(hg(n,"TRANS_INVALID_COMPONENTS",'<Trans /> "components" prop expects an object or array',{i18nKey:r}),null):null,gG=t=>!Bc(t)||Array.isArray(t)?!1:Object.keys(t).reduce((e,n)=>e&&Number.isNaN(Number.parseFloat(n)),!0);function J6({children:t,count:e,parent:n,i18nKey:r,context:s,tOptions:i={},values:a,defaults:o,components:l,ns:c,i18n:h,t:p,shouldUnescape:m,...g}){var B,X,fe,ie,ae,ue;const y=h||Kf();if(!y)return hg(y,"NO_I18NEXT_INSTANCE","Trans: You need to pass in an i18next instance using i18nextReactModule",{i18nKey:r}),t;const x=p||y.t.bind(y)||(ve=>ve),v={...$C(),...(B=y.options)==null?void 0:B.react};let k=c||x.ns||((X=y.options)==null?void 0:X.defaultNS);k=Yi(k)?[k]:k||["translation"];const C=G6(t,v,y,r),N=o||C||v.transEmptyNodeValue||r,{hashTransKey:_}=v,P=r||(_?_(C||N):C||N);(ie=(fe=y.options)==null?void 0:fe.interpolation)!=null&&ie.defaultVariables&&(a=a&&Object.keys(a).length>0?{...a,...y.options.interpolation.defaultVariables}:{...y.options.interpolation.defaultVariables});const D=a||e!==void 0&&!((ue=(ae=y.options)==null?void 0:ae.interpolation)!=null&&ue.alwaysFormat)||!t?i.interpolation:{interpolation:{...i.interpolation,prefix:"#$?",suffix:"?$#"}},I={...i,context:s||i.context,count:e,...a,...D,defaultValue:N,ns:k},L=P?x(P,I):N,j=mG(l,L,y,r);let q=j||t,V=null;gG(j)&&(V=j,q=t);const O=hG(q,V,L,y,v,I,m),$=n??v.defaultTransParent;return $?U.createElement($,g,O):O}const Q6={type:"3rdParty",init(t){V6(t.options.react),W6(t)}},c0=U.createContext();class bG{constructor(){this.usedNamespaces={}}addUsedNamespaces(e){e.forEach(n=>{this.usedNamespaces[n]||(this.usedNamespaces[n]=!0)})}getUsedNamespaces(){return Object.keys(this.usedNamespaces)}}const X6=t=>async e=>{var s;const n=await((s=t.getInitialProps)==null?void 0:s.call(t,e))??{},r=Z6();return{...n,...r}},Z6=()=>{var s;const t=Kf(),e=((s=t.reportNamespaces)==null?void 0:s.getUsedNamespaces())??[],n={},r={};return t.languages.forEach(i=>{r[i]={},e.forEach(a=>{r[i][a]=t.getResourceBundle(i,a)||{}})}),n.initialI18nStore=r,n.initialLanguage=t.language,n};function yG({children:t,count:e,parent:n,i18nKey:r,context:s,tOptions:i={},values:a,defaults:o,components:l,ns:c,i18n:h,t:p,shouldUnescape:m,...g}){var C;const{i18n:y,defaultNS:x}=U.useContext(c0)||{},v=h||y||Kf(),k=p||(v==null?void 0:v.t.bind(v));return J6({children:t,count:e,parent:n,i18nKey:r,context:s,tOptions:i,values:a,defaults:o,components:l,ns:c||(k==null?void 0:k.ns)||x||((C=v==null?void 0:v.options)==null?void 0:C.defaultNS),i18n:v,t:p,shouldUnescape:m,...g})}const vG=(t,e)=>{const n=U.useRef();return U.useEffect(()=>{n.current=t},[t,e]),n.current},Y6=(t,e,n,r)=>t.getFixedT(e,n,r),xG=(t,e,n,r)=>U.useCallback(Y6(t,e,n,r),[t,e,n,r]),Fe=(t,e={})=>{var _,P,D,I;const{i18n:n}=e,{i18n:r,defaultNS:s}=U.useContext(c0)||{},i=n||r||Kf();if(i&&!i.reportNamespaces&&(i.reportNamespaces=new bG),!i){hg(i,"NO_I18NEXT_INSTANCE","useTranslation: You will need to pass in an i18next instance by using initReactI18next");const L=(q,V)=>Yi(V)?V:Bc(V)&&Yi(V.defaultValue)?V.defaultValue:Array.isArray(q)?q[q.length-1]:q,j=[L,{},!1];return j.t=L,j.i18n={},j.ready=!1,j}(_=i.options.react)!=null&&_.wait&&hg(i,"DEPRECATED_OPTION","useTranslation: It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.");const a={...$C(),...i.options.react,...e},{useSuspense:o,keyPrefix:l}=a;let c=t||s||((P=i.options)==null?void 0:P.defaultNS);c=Yi(c)?[c]:c||["translation"],(I=(D=i.reportNamespaces).addUsedNamespaces)==null||I.call(D,c);const h=(i.isInitialized||i.initializedStoreOnce)&&c.every(L=>iG(L,i,a)),p=xG(i,e.lng||null,a.nsMode==="fallback"?c:c[0],l),m=()=>p,g=()=>Y6(i,e.lng||null,a.nsMode==="fallback"?c:c[0],l),[y,x]=U.useState(m);let v=c.join();e.lng&&(v=`${e.lng}${v}`);const k=vG(v),C=U.useRef(!0);U.useEffect(()=>{const{bindI18n:L,bindI18nStore:j}=a;C.current=!0,!h&&!o&&(e.lng?u4(i,e.lng,c,()=>{C.current&&x(g)}):EE(i,c,()=>{C.current&&x(g)})),h&&k&&k!==v&&C.current&&x(g);const q=()=>{C.current&&x(g)};return L&&(i==null||i.on(L,q)),j&&(i==null||i.store.on(j,q)),()=>{C.current=!1,i&&L&&(L==null||L.split(" ").forEach(V=>i.off(V,q))),j&&i&&j.split(" ").forEach(V=>i.store.off(V,q))}},[i,v]),U.useEffect(()=>{C.current&&h&&x(m)},[i,l,h]);const N=[y,i,h];if(N.t=y,N.i18n=i,N.ready=h,h||!h&&!o)return N;throw new Promise(L=>{e.lng?u4(i,e.lng,c,()=>L()):EE(i,c,()=>L())})},wG=(t,e={})=>function(r){function s({forwardedRef:a,...o}){const[l,c,h]=Fe(t,{...o,keyPrefix:e.keyPrefix}),p={...o,t:l,i18n:c,tReady:h};return e.withRef&&a?p.ref=a:!e.withRef&&a&&(p.forwardedRef=a),U.createElement(r,p)}s.displayName=`withI18nextTranslation(${H6(r)})`,s.WrappedComponent=r;const i=(a,o)=>U.createElement(s,Object.assign({},a,{forwardedRef:o}));return e.withRef?U.forwardRef(i):s},kG=({ns:t,children:e,...n})=>{const[r,s,i]=Fe(t,n);return e(r,{i18n:s,lng:s.language},i)};function SG({i18n:t,defaultNS:e,children:n}){const r=U.useMemo(()=>({i18n:t,defaultNS:e}),[t,e]);return U.createElement(c0.Provider,{value:r},n)}const e5=(t,e,n={})=>{var a;const{i18n:r}=n,{i18n:s}=U.useContext(c0)||{},i=r||s||Kf();(a=i.options)!=null&&a.isClone||(t&&!i.initializedStoreOnce&&(i.services.resourceStore.data=t,i.options.ns=Object.values(t).reduce((o,l)=>(Object.keys(l).forEach(c=>{o.indexOf(c)<0&&o.push(c)}),o),i.options.ns),i.initializedStoreOnce=!0,i.isInitialized=!0),e&&!i.initializedLanguageOnce&&(i.changeLanguage(e),i.initializedLanguageOnce=!0))},EG=()=>function(e){function n({initialI18nStore:r,initialLanguage:s,...i}){return e5(r,s),U.createElement(e,{...i})}return n.getInitialProps=X6(e),n.displayName=`withI18nextSSR(${H6(e)})`,n.WrappedComponent=e,n},_G=()=>"",CG=()=>"",AG=()=>"",TG=()=>"",IG=()=>"",NG=()=>"",PG=Object.freeze(Object.defineProperty({__proto__:null,I18nContext:c0,I18nextProvider:SG,Trans:yG,TransWithoutContext:J6,Translation:kG,composeInitialProps:X6,date:_G,getDefaults:$C,getI18n:Kf,getInitialProps:Z6,initReactI18next:Q6,number:AG,plural:IG,select:TG,selectOrdinal:NG,setDefaults:V6,setI18n:W6,time:CG,useSSR:e5,useTranslation:Fe,withSSR:EG,withTranslation:wG},Symbol.toStringTag,{value:"Module"})),RG={BASE_URL:"./",DEV:!1,MODE:"production",PROD:!0,SSR:!1};function ao(t){return t==="sqlite-file"||t==="markdown-git"||t==="local"}const t5=["apiKey","authDomain","projectId","storageBucket","messagingSenderId","appId"],jG={apiKey:"VITE_FIREBASE_API_KEY",authDomain:"VITE_FIREBASE_AUTH_DOMAIN",projectId:"VITE_FIREBASE_PROJECT_ID",storageBucket:"VITE_FIREBASE_STORAGE_BUCKET",messagingSenderId:"VITE_FIREBASE_MESSAGING_SENDER_ID",appId:"VITE_FIREBASE_APP_ID"};function Xi(t){return typeof t=="string"&&t.trim().length>0}function MG(t){if(!t||typeof t!="object")return!1;const e=t;if(e.backend!=="flexweg-sqlite")return!1;const n=e.flexweg;return!!n&&typeof n=="object"&&Xi(n.siteUrl)&&Xi(n.apiBaseUrl)&&Xi(n.sqliteToken)&&Xi(n.sqlitePath)}function LG(t){if(!t||typeof t!="object")return!1;const e=t;if(e.backend!==void 0&&e.backend!=="firebase")return!1;const n=e.firebase;if(!n)return!1;for(const r of t5)if(!Xi(n[r]))return!1;return!0}function DG(t){if(!t||typeof t!="object")return!1;const e=t;if(e.backend!=="markdown-git"||!e.git||typeof e.git!="object")return!1;const n=e.git;return!Xi(n.branch)&&n.provider!=="local"?!1:n.provider==="github"?Xi(n.owner)&&Xi(n.repo):n.provider==="gitlab"?Xi(n.project):n.provider==="local"}function FG(t){if(!t||typeof t!="object")return!1;const e=t;return e.backend==="sqlite-file"&&!!e.sqlite&&Xi(e.sqlite.connectorId)&&Xi(e.sqlite.path)&&!!e.sqlite.settings&&typeof e.sqlite.settings=="object"}const fv="flexweg.runtimeConfig";function OG(){try{const t=window.localStorage.getItem(fv);return t?JSON.parse(t):null}catch{return null}}function _w(t){try{t?window.localStorage.setItem(fv,JSON.stringify(t)):window.localStorage.removeItem(fv)}catch{}Jh=void 0}function zG(){if(typeof window>"u")return null;const t=window.__FLEXWEG_CONFIG__,e=t&&typeof t=="object"?t:OG();return!e||typeof e!="object"?null:DG(e)||FG(e)?e:e.backend==="local"?{backend:"local"}:MG(e)?e:LG(e)?{backend:"firebase",firebase:e.firebase,adminEmail:e.adminEmail}:null}function UG(){const t=RG,e={};for(const r of t5){const s=t[jG[r]];if(!Xi(s))return null;e[r]=s}const n=t.VITE_ADMIN_EMAIL;return{backend:"firebase",firebase:e,...Xi(n)?{adminEmail:n}:{}}}let Jh;function ra(){return Jh!==void 0||(Jh=zG()??UG()),Jh}function u0(){Jh=void 0}function $r(){var t;return((t=ra())==null?void 0:t.backend)??null}function HC(t){const e=`// Generated by Flexweg CMS first-run setup. Do not edit by hand —
|
|
597
|
+
*/const QW=We("Zap",[["path",{d:"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z",key:"1xq2db"}]]);var AS,o4;function XW(){return o4||(o4=1,AS={area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0}),AS}var ZW=XW();const YW=qd(ZW);var eG=/\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?(".*?"|'.*?')/g;function l4(t){var e={type:"tag",name:"",voidElement:!1,attrs:{},children:[]},n=t.match(/<\/?([^\s]+?)[/\s>]/);if(n&&(e.name=n[1],(YW[n[1]]||t.charAt(t.length-2)==="/")&&(e.voidElement=!0),e.name.startsWith("!--"))){var r=t.indexOf("-->");return{type:"comment",comment:r!==-1?t.slice(4,r):""}}for(var s=new RegExp(eG),i=null;(i=s.exec(t))!==null;)if(i[0].trim())if(i[1]){var a=i[1].trim(),o=[a,""];a.indexOf("=")>-1&&(o=a.split("=")),e.attrs[o[0]]=o[1],s.lastIndex--}else i[2]&&(e.attrs[i[2]]=i[3].trim().substring(1,i[3].length-1));return e}var tG=/<[a-zA-Z0-9\-\!\/](?:"[^"]*"|'[^']*'|[^'">])*>/g,nG=/^\s*$/,rG=Object.create(null);function B6(t,e){switch(e.type){case"text":return t+e.content;case"tag":return t+="<"+e.name+(e.attrs?(function(n){var r=[];for(var s in n)r.push(s+'="'+n[s]+'"');return r.length?" "+r.join(" "):""})(e.attrs):"")+(e.voidElement?"/>":">"),e.voidElement?t:t+e.children.reduce(B6,"")+"</"+e.name+">";case"comment":return t+"<!--"+e.comment+"-->"}}var sG={parse:function(t,e){e||(e={}),e.components||(e.components=rG);var n,r=[],s=[],i=-1,a=!1;if(t.indexOf("<")!==0){var o=t.indexOf("<");r.push({type:"text",content:o===-1?t:t.substring(0,o)})}return t.replace(tG,function(l,c){if(a){if(l!=="</"+n.name+">")return;a=!1}var h,p=l.charAt(1)!=="/",m=l.startsWith("<!--"),g=c+l.length,y=t.charAt(g);if(m){var x=l4(l);return i<0?(r.push(x),r):((h=s[i]).children.push(x),r)}if(p&&(i++,(n=l4(l)).type==="tag"&&e.components[n.name]&&(n.type="component",a=!0),n.voidElement||a||!y||y==="<"||n.children.push({type:"text",content:t.slice(g,t.indexOf("<",g))}),i===0&&r.push(n),(h=s[i-1])&&h.children.push(n),s[i]=n),(!p||n.voidElement)&&(i>-1&&(n.voidElement||n.name===l.slice(2,-1))&&(i--,n=i===-1?r:s[i]),!a&&y!=="<"&&y)){h=i===-1?r:s[i].children;var v=t.indexOf("<",g),k=t.slice(g,v===-1?void 0:v);nG.test(k)&&(k=" "),(v>-1&&i+h.length>=0||k!==" ")&&h.push({type:"text",content:k})}}),r},stringify:function(t){return t.reduce(function(e,n){return e+B6("",n)},"")}};const Dy=(t,e,n,r)=>{var i,a,o,l;const s=[n,{code:e,...r||{}}];if((a=(i=t==null?void 0:t.services)==null?void 0:i.logger)!=null&&a.forward)return t.services.logger.forward(s,"warn","react-i18next::",!0);Yi(s[0])&&(s[0]=`react-i18next:: ${s[0]}`),(l=(o=t==null?void 0:t.services)==null?void 0:o.logger)!=null&&l.warn?t.services.logger.warn(...s):console!=null&&console.warn&&console.warn(...s)},c4={},hg=(t,e,n,r)=>{Yi(n)&&c4[n]||(Yi(n)&&(c4[n]=new Date),Dy(t,e,n,r))},$6=(t,e)=>()=>{if(t.isInitialized)e();else{const n=()=>{setTimeout(()=>{t.off("initialized",n)},0),e()};t.on("initialized",n)}},EE=(t,e,n)=>{t.loadNamespaces(e,$6(t,n))},u4=(t,e,n,r)=>{if(Yi(n)&&(n=[n]),t.options.preload&&t.options.preload.indexOf(e)>-1)return EE(t,n,r);n.forEach(s=>{t.options.ns.indexOf(s)<0&&t.options.ns.push(s)}),t.loadLanguages(e,$6(t,r))},iG=(t,e,n={})=>!e.languages||!e.languages.length?(hg(e,"NO_LANGUAGES","i18n.languages were undefined or empty",{languages:e.languages}),!0):e.hasLoadedNamespace(t,{lng:n.lng,precheck:(r,s)=>{if(n.bindI18n&&n.bindI18n.indexOf("languageChanging")>-1&&r.services.backendConnector.backend&&r.isLanguageChangingTo&&!s(r.isLanguageChangingTo,t))return!1}}),H6=t=>t.displayName||t.name||(Yi(t)&&t.length>0?t:"Unknown"),Yi=t=>typeof t=="string",Bc=t=>typeof t=="object"&&t!==null,aG=/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g,oG={"&":"&","&":"&","<":"<","<":"<",">":">",">":">","'":"'","'":"'",""":'"',""":'"'," ":" "," ":" ","©":"©","©":"©","®":"®","®":"®","…":"…","…":"…","/":"/","/":"/"},lG=t=>oG[t],cG=t=>t.replace(aG,lG);let _E={bindI18n:"languageChanged",bindI18nStore:"",transEmptyNodeValue:"",transSupportBasicHtmlNodes:!0,transWrapTextNodes:"",transKeepBasicHtmlNodesFor:["br","strong","i","p"],useSuspense:!0,unescape:cG};const V6=(t={})=>{_E={..._E,...t}},$C=()=>_E;let q6;const W6=t=>{q6=t},Kf=()=>q6,TS=(t,e)=>{var r;if(!t)return!1;const n=((r=t.props)==null?void 0:r.children)??t.children;return e?n.length>0:!!n},IS=t=>{var n,r;if(!t)return[];const e=((n=t.props)==null?void 0:n.children)??t.children;return(r=t.props)!=null&&r.i18nIsDynamicList?Kh(e):e},uG=t=>Array.isArray(t)&&t.every(U.isValidElement),Kh=t=>Array.isArray(t)?t:[t],dG=(t,e)=>{const n={...e};return n.props=Object.assign(t.props,e.props),n},G6=(t,e,n,r)=>{if(!t)return"";let s="";const i=Kh(t),a=e!=null&&e.transSupportBasicHtmlNodes?e.transKeepBasicHtmlNodesFor??[]:[];return i.forEach((o,l)=>{if(Yi(o)){s+=`${o}`;return}if(U.isValidElement(o)){const{props:c,type:h}=o,p=Object.keys(c).length,m=a.indexOf(h)>-1,g=c.children;if(!g&&m&&!p){s+=`<${h}/>`;return}if(!g&&(!m||p)||c.i18nIsDynamicList){s+=`<${l}></${l}>`;return}if(m&&p===1&&Yi(g)){s+=`<${h}>${g}</${h}>`;return}const y=G6(g,e,n,r);s+=`<${l}>${y}</${l}>`;return}if(o===null){Dy(n,"TRANS_NULL_VALUE","Passed in a null value as child",{i18nKey:r});return}if(Bc(o)){const{format:c,...h}=o,p=Object.keys(h);if(p.length===1){const m=c?`${p[0]}, ${c}`:p[0];s+=`{{${m}}}`;return}Dy(n,"TRANS_INVALID_OBJ","Invalid child - Object should only have keys {{ value, format }} (format is optional).",{i18nKey:r,child:o});return}Dy(n,"TRANS_INVALID_VAR","Passed in a variable like {number} - pass variables for interpolation as full objects like {{number}}.",{i18nKey:r,child:o})}),s},hG=(t,e,n,r,s,i,a)=>{if(n==="")return[];const o=s.transKeepBasicHtmlNodesFor||[],l=n&&new RegExp(o.map(k=>`<${k}`).join("|")).test(n);if(!t&&!e&&!l&&!a)return[n];const c=e??{},h=k=>{Kh(k).forEach(N=>{Yi(N)||(TS(N)?h(IS(N)):Bc(N)&&!U.isValidElement(N)&&Object.assign(c,N))})};h(t);const p=sG.parse(`<0>${n}</0>`),m={...c,...i},g=(k,C,N)=>{var D;const _=IS(k),P=x(_,C.children,N);return uG(_)&&P.length===0||(D=k.props)!=null&&D.i18nIsDynamicList?_:P},y=(k,C,N,_,P)=>{k.dummy?(k.children=C,N.push(U.cloneElement(k,{key:_},P?void 0:C))):N.push(...U.Children.map([k],D=>{const I={...D.props};return delete I.i18nIsDynamicList,U.createElement(D.type,{...I,key:_,ref:D.props.ref??D.ref},P?null:C)}))},x=(k,C,N)=>{const _=Kh(k);return Kh(C).reduce((D,I,L)=>{var q,V;const j=((V=(q=I.children)==null?void 0:q[0])==null?void 0:V.content)&&r.services.interpolator.interpolate(I.children[0].content,m,r.language);if(I.type==="tag"){let O=_[parseInt(I.name,10)];!O&&e&&(O=e[I.name]),N.length===1&&!O&&(O=N[0][I.name]),O||(O={});const $=Object.keys(I.attrs).length!==0?dG({props:I.attrs},O):O,B=U.isValidElement($),X=B&&TS(I,!0)&&!I.voidElement,fe=l&&Bc($)&&$.dummy&&!B,ie=Bc(e)&&Object.hasOwnProperty.call(e,I.name);if(Yi($)){const ae=r.services.interpolator.interpolate($,m,r.language);D.push(ae)}else if(TS($)||X){const ae=g($,I,N);y($,ae,D,L)}else if(fe){const ae=x(_,I.children,N);y($,ae,D,L)}else if(Number.isNaN(parseFloat(I.name)))if(ie){const ae=g($,I,N);y($,ae,D,L,I.voidElement)}else if(s.transSupportBasicHtmlNodes&&o.indexOf(I.name)>-1)if(I.voidElement)D.push(U.createElement(I.name,{key:`${I.name}-${L}`}));else{const ae=x(_,I.children,N);D.push(U.createElement(I.name,{key:`${I.name}-${L}`},ae))}else if(I.voidElement)D.push(`<${I.name} />`);else{const ae=x(_,I.children,N);D.push(`<${I.name}>${ae}</${I.name}>`)}else if(Bc($)&&!B){const ae=I.children[0]?j:null;ae&&D.push(ae)}else y($,j,D,L,I.children.length!==1||!j)}else if(I.type==="text"){const O=s.transWrapTextNodes,$=a?s.unescape(r.services.interpolator.interpolate(I.content,m,r.language)):r.services.interpolator.interpolate(I.content,m,r.language);O?D.push(U.createElement(O,{key:`${I.name}-${L}`},$)):D.push($)}return D},[])},v=x([{dummy:!0,children:t||[]}],p,Kh(t||[]));return IS(v[0])},K6=(t,e,n)=>{const r=t.key||e,s=U.cloneElement(t,{key:r});if(!s.props||!s.props.children||n.indexOf(`${e}/>`)<0&&n.indexOf(`${e} />`)<0)return s;function i(){return U.createElement(U.Fragment,null,s)}return U.createElement(i,{key:r})},fG=(t,e)=>t.map((n,r)=>K6(n,r,e)),pG=(t,e)=>{const n={};return Object.keys(t).forEach(r=>{Object.assign(n,{[r]:K6(t[r],r,e)})}),n},mG=(t,e,n,r)=>t?Array.isArray(t)?fG(t,e):Bc(t)?pG(t,e):(hg(n,"TRANS_INVALID_COMPONENTS",'<Trans /> "components" prop expects an object or array',{i18nKey:r}),null):null,gG=t=>!Bc(t)||Array.isArray(t)?!1:Object.keys(t).reduce((e,n)=>e&&Number.isNaN(Number.parseFloat(n)),!0);function J6({children:t,count:e,parent:n,i18nKey:r,context:s,tOptions:i={},values:a,defaults:o,components:l,ns:c,i18n:h,t:p,shouldUnescape:m,...g}){var B,X,fe,ie,ae,ue;const y=h||Kf();if(!y)return hg(y,"NO_I18NEXT_INSTANCE","Trans: You need to pass in an i18next instance using i18nextReactModule",{i18nKey:r}),t;const x=p||y.t.bind(y)||(ve=>ve),v={...$C(),...(B=y.options)==null?void 0:B.react};let k=c||x.ns||((X=y.options)==null?void 0:X.defaultNS);k=Yi(k)?[k]:k||["translation"];const C=G6(t,v,y,r),N=o||C||v.transEmptyNodeValue||r,{hashTransKey:_}=v,P=r||(_?_(C||N):C||N);(ie=(fe=y.options)==null?void 0:fe.interpolation)!=null&&ie.defaultVariables&&(a=a&&Object.keys(a).length>0?{...a,...y.options.interpolation.defaultVariables}:{...y.options.interpolation.defaultVariables});const D=a||e!==void 0&&!((ue=(ae=y.options)==null?void 0:ae.interpolation)!=null&&ue.alwaysFormat)||!t?i.interpolation:{interpolation:{...i.interpolation,prefix:"#$?",suffix:"?$#"}},I={...i,context:s||i.context,count:e,...a,...D,defaultValue:N,ns:k},L=P?x(P,I):N,j=mG(l,L,y,r);let q=j||t,V=null;gG(j)&&(V=j,q=t);const O=hG(q,V,L,y,v,I,m),$=n??v.defaultTransParent;return $?U.createElement($,g,O):O}const Q6={type:"3rdParty",init(t){V6(t.options.react),W6(t)}},c0=U.createContext();class bG{constructor(){this.usedNamespaces={}}addUsedNamespaces(e){e.forEach(n=>{this.usedNamespaces[n]||(this.usedNamespaces[n]=!0)})}getUsedNamespaces(){return Object.keys(this.usedNamespaces)}}const X6=t=>async e=>{var s;const n=await((s=t.getInitialProps)==null?void 0:s.call(t,e))??{},r=Z6();return{...n,...r}},Z6=()=>{var s;const t=Kf(),e=((s=t.reportNamespaces)==null?void 0:s.getUsedNamespaces())??[],n={},r={};return t.languages.forEach(i=>{r[i]={},e.forEach(a=>{r[i][a]=t.getResourceBundle(i,a)||{}})}),n.initialI18nStore=r,n.initialLanguage=t.language,n};function yG({children:t,count:e,parent:n,i18nKey:r,context:s,tOptions:i={},values:a,defaults:o,components:l,ns:c,i18n:h,t:p,shouldUnescape:m,...g}){var C;const{i18n:y,defaultNS:x}=U.useContext(c0)||{},v=h||y||Kf(),k=p||(v==null?void 0:v.t.bind(v));return J6({children:t,count:e,parent:n,i18nKey:r,context:s,tOptions:i,values:a,defaults:o,components:l,ns:c||(k==null?void 0:k.ns)||x||((C=v==null?void 0:v.options)==null?void 0:C.defaultNS),i18n:v,t:p,shouldUnescape:m,...g})}const vG=(t,e)=>{const n=U.useRef();return U.useEffect(()=>{n.current=t},[t,e]),n.current},Y6=(t,e,n,r)=>t.getFixedT(e,n,r),xG=(t,e,n,r)=>U.useCallback(Y6(t,e,n,r),[t,e,n,r]),Fe=(t,e={})=>{var _,P,D,I;const{i18n:n}=e,{i18n:r,defaultNS:s}=U.useContext(c0)||{},i=n||r||Kf();if(i&&!i.reportNamespaces&&(i.reportNamespaces=new bG),!i){hg(i,"NO_I18NEXT_INSTANCE","useTranslation: You will need to pass in an i18next instance by using initReactI18next");const L=(q,V)=>Yi(V)?V:Bc(V)&&Yi(V.defaultValue)?V.defaultValue:Array.isArray(q)?q[q.length-1]:q,j=[L,{},!1];return j.t=L,j.i18n={},j.ready=!1,j}(_=i.options.react)!=null&&_.wait&&hg(i,"DEPRECATED_OPTION","useTranslation: It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.");const a={...$C(),...i.options.react,...e},{useSuspense:o,keyPrefix:l}=a;let c=t||s||((P=i.options)==null?void 0:P.defaultNS);c=Yi(c)?[c]:c||["translation"],(I=(D=i.reportNamespaces).addUsedNamespaces)==null||I.call(D,c);const h=(i.isInitialized||i.initializedStoreOnce)&&c.every(L=>iG(L,i,a)),p=xG(i,e.lng||null,a.nsMode==="fallback"?c:c[0],l),m=()=>p,g=()=>Y6(i,e.lng||null,a.nsMode==="fallback"?c:c[0],l),[y,x]=U.useState(m);let v=c.join();e.lng&&(v=`${e.lng}${v}`);const k=vG(v),C=U.useRef(!0);U.useEffect(()=>{const{bindI18n:L,bindI18nStore:j}=a;C.current=!0,!h&&!o&&(e.lng?u4(i,e.lng,c,()=>{C.current&&x(g)}):EE(i,c,()=>{C.current&&x(g)})),h&&k&&k!==v&&C.current&&x(g);const q=()=>{C.current&&x(g)};return L&&(i==null||i.on(L,q)),j&&(i==null||i.store.on(j,q)),()=>{C.current=!1,i&&L&&(L==null||L.split(" ").forEach(V=>i.off(V,q))),j&&i&&j.split(" ").forEach(V=>i.store.off(V,q))}},[i,v]),U.useEffect(()=>{C.current&&h&&x(m)},[i,l,h]);const N=[y,i,h];if(N.t=y,N.i18n=i,N.ready=h,h||!h&&!o)return N;throw new Promise(L=>{e.lng?u4(i,e.lng,c,()=>L()):EE(i,c,()=>L())})},wG=(t,e={})=>function(r){function s({forwardedRef:a,...o}){const[l,c,h]=Fe(t,{...o,keyPrefix:e.keyPrefix}),p={...o,t:l,i18n:c,tReady:h};return e.withRef&&a?p.ref=a:!e.withRef&&a&&(p.forwardedRef=a),U.createElement(r,p)}s.displayName=`withI18nextTranslation(${H6(r)})`,s.WrappedComponent=r;const i=(a,o)=>U.createElement(s,Object.assign({},a,{forwardedRef:o}));return e.withRef?U.forwardRef(i):s},kG=({ns:t,children:e,...n})=>{const[r,s,i]=Fe(t,n);return e(r,{i18n:s,lng:s.language},i)};function SG({i18n:t,defaultNS:e,children:n}){const r=U.useMemo(()=>({i18n:t,defaultNS:e}),[t,e]);return U.createElement(c0.Provider,{value:r},n)}const e5=(t,e,n={})=>{var a;const{i18n:r}=n,{i18n:s}=U.useContext(c0)||{},i=r||s||Kf();(a=i.options)!=null&&a.isClone||(t&&!i.initializedStoreOnce&&(i.services.resourceStore.data=t,i.options.ns=Object.values(t).reduce((o,l)=>(Object.keys(l).forEach(c=>{o.indexOf(c)<0&&o.push(c)}),o),i.options.ns),i.initializedStoreOnce=!0,i.isInitialized=!0),e&&!i.initializedLanguageOnce&&(i.changeLanguage(e),i.initializedLanguageOnce=!0))},EG=()=>function(e){function n({initialI18nStore:r,initialLanguage:s,...i}){return e5(r,s),U.createElement(e,{...i})}return n.getInitialProps=X6(e),n.displayName=`withI18nextSSR(${H6(e)})`,n.WrappedComponent=e,n},_G=()=>"",CG=()=>"",AG=()=>"",TG=()=>"",IG=()=>"",NG=()=>"",PG=Object.freeze(Object.defineProperty({__proto__:null,I18nContext:c0,I18nextProvider:SG,Trans:yG,TransWithoutContext:J6,Translation:kG,composeInitialProps:X6,date:_G,getDefaults:$C,getI18n:Kf,getInitialProps:Z6,initReactI18next:Q6,number:AG,plural:IG,select:TG,selectOrdinal:NG,setDefaults:V6,setI18n:W6,time:CG,useSSR:e5,useTranslation:Fe,withSSR:EG,withTranslation:wG},Symbol.toStringTag,{value:"Module"})),RG={BASE_URL:"./",DEV:!1,MODE:"production",PROD:!0,SSR:!1};function ao(t){return t==="sqlite-file"||t==="markdown-git"||t==="local"}const t5=["apiKey","authDomain","projectId","storageBucket","messagingSenderId","appId"],jG={apiKey:"VITE_FIREBASE_API_KEY",authDomain:"VITE_FIREBASE_AUTH_DOMAIN",projectId:"VITE_FIREBASE_PROJECT_ID",storageBucket:"VITE_FIREBASE_STORAGE_BUCKET",messagingSenderId:"VITE_FIREBASE_MESSAGING_SENDER_ID",appId:"VITE_FIREBASE_APP_ID"};function Xi(t){return typeof t=="string"&&t.trim().length>0}function MG(t){if(!t||typeof t!="object")return!1;const e=t;if(e.backend!=="flexweg-sqlite")return!1;const n=e.flexweg;return!!n&&typeof n=="object"&&Xi(n.siteUrl)&&Xi(n.apiBaseUrl)&&Xi(n.sqliteToken)&&Xi(n.sqlitePath)}function LG(t){if(!t||typeof t!="object")return!1;const e=t;if(e.backend!==void 0&&e.backend!=="firebase")return!1;const n=e.firebase;if(!n)return!1;for(const r of t5)if(!Xi(n[r]))return!1;return!0}function DG(t){if(!t||typeof t!="object")return!1;const e=t;if(e.backend!=="markdown-git"||!e.git||typeof e.git!="object")return!1;const n=e.git;return!Xi(n.branch)&&n.provider!=="local"?!1:n.provider==="github"?Xi(n.owner)&&Xi(n.repo):n.provider==="gitlab"?Xi(n.project):n.provider==="local"}function FG(t){if(!t||typeof t!="object")return!1;const e=t;return e.backend==="sqlite-file"&&!!e.sqlite&&Xi(e.sqlite.connectorId)&&Xi(e.sqlite.path)&&!!e.sqlite.settings&&typeof e.sqlite.settings=="object"}const fv="flexweg.runtimeConfig";function OG(){try{const t=window.localStorage.getItem(fv);return t?JSON.parse(t):null}catch{return null}}function _w(t){try{t?window.localStorage.setItem(fv,JSON.stringify(t)):window.localStorage.removeItem(fv)}catch{}Jh=void 0}function zG(){if(typeof window>"u")return null;const t=window.__FLEXWEG_CONFIG__,e=t&&typeof t=="object"?t:OG();return!e||typeof e!="object"?null:DG(e)||FG(e)?e:e.backend==="local"?{backend:"local"}:MG(e)?e:LG(e)?{backend:"firebase",firebase:e.firebase,adminEmail:e.adminEmail}:null}function UG(){const t=RG,e={};for(const r of t5){const s=t[jG[r]];if(!Xi(s))return null;e[r]=s}const n=t.VITE_ADMIN_EMAIL;return{backend:"firebase",firebase:e,...Xi(n)?{adminEmail:n}:{}}}let Jh;function ra(){return Jh!==void 0||(Jh=zG()??UG()),Jh}function u0(){Jh=void 0}function $r(){var t;return((t=ra())==null?void 0:t.backend)??null}function HC(t){const e=`// Generated by AgentCMS first-run setup. Do not edit by hand —
|
|
598
598
|
// re-run the admin setup form to update.
|
|
599
599
|
`;let n;return t.backend==="firebase"?n={backend:t.backend,firebase:t.firebase}:t.backend==="flexweg-sqlite"?n={backend:t.backend,flexweg:t.flexweg}:t.backend==="markdown-git"?n={backend:t.backend,git:t.git}:t.backend==="sqlite-file"?n={backend:t.backend,sqlite:t.sqlite}:n={backend:t.backend},`${e}window.__FLEXWEG_CONFIG__ = ${JSON.stringify(n,null,2)};
|
|
600
600
|
`}const BG=()=>{};var d4={};/**
|
|
@@ -3844,33 +3844,33 @@ This typically indicates that your device does not have a healthy Internet conne
|
|
|
3844
3844
|
*/const rte=300,ste=o5("authIdTokenMaxAge")||rte;let UR=null;const ite=t=>async e=>{const n=e&&await e.getIdTokenResult(),r=n&&(new Date().getTime()-Date.parse(n.issuedAtTime))/1e3;if(r&&r>ste)return;const s=n==null?void 0:n.token;UR!==s&&(UR=s,await fetch(t,{method:s?"POST":"DELETE",headers:s?{Authorization:`Bearer ${s}`}:{}}))};function ate(t=h5()){const e=WC(t,"auth");if(e.isInitialized())return e.getImmediate();const n=AY(t,{popupRedirectResolver:Yee,persistence:[uee,ZY,gO]}),r=o5("authTokenSyncURL");if(r&&typeof isSecureContext=="boolean"&&isSecureContext){const i=new URL(r,location.origin);if(location.origin===i.origin){const a=ite(i.toString());GY(n,a,()=>a(n.currentUser)),WY(n,o=>a(o))}}const s=i5("auth");return s&&IY(n,`http://${s}`),n}function ote(){var t,e;return(e=(t=document.getElementsByTagName("head"))===null||t===void 0?void 0:t[0])!==null&&e!==void 0?e:document}vY({loadJS(t){return new Promise((e,n)=>{const r=document.createElement("script");r.setAttribute("src",t),r.onload=e,r.onerror=s=>{const i=Bo("internal-error");i.customData=s,n(i)},r.type="text/javascript",r.charset="UTF-8",ote().appendChild(r)})},gapiScript:"https://apis.google.com/js/api.js",recaptchaV2Script:"https://www.google.com/recaptcha/api.js",recaptchaEnterpriseScript:"https://www.google.com/recaptcha/enterprise.js?render="});nte("Browser");function lte(){const t=ra();if(!t||t.backend!=="firebase")return"";const e=t.adminEmail;return typeof e=="string"?e.trim().toLowerCase():""}let Zb=null,Yb=null,Xh=null;function SO(){if(Xh)return Xh;const t=ra();if(!t)throw new Error("Firebase config not available. The runtime resolver returned null — either fill .env or complete the in-admin setup form.");if(t.backend!=="firebase")throw new Error(`Firebase service called while active backend is "${t.backend}". Dispatcher bug — fix the calling code to read through services/<name>.ts, not services/firebase/<name>.ts directly.`);return Xh=pJ()[0]??GC(t.firebase),Xh}function Xs(){return Zb||(Zb=_Z(SO()),Zb)}function _f(){return Yb||(Yb=ate(SO()),Yb)}function cte(t){if(t.backend!=="firebase")throw new Error(`initFirebaseFromSetup called with non-Firebase config (backend="${t.backend}"). Use the SQLite install helper for that backend.`);typeof window<"u"&&(window.__FLEXWEG_CONFIG__=t),u0(),!Xh&&(Xh=GC(t.firebase))}const ls={posts:"posts",terms:"terms",media:"media",config:"config",users:"users",settings:"settings"},e1={flexweg:"flexweg",storage:"storage",admin:"admin"},ute={site:"site"},EO=()=>tp(Xs(),ls.terms),VA=t=>rl(Xs(),ls.terms,t);function dte(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function hte(t,e){const n=no(EO(),Gl("name","asc"));return Yd(n,r=>t(r.docs.map(s=>({id:s.id,...s.data()}))),e)}async function fte(){const t=no(EO(),Gl("name","asc"));return(await Sg(t)).docs.map(n=>({id:n.id,...n.data()}))}async function pte(t){const e=dte(),n={type:t.type,name:t.name,slug:t.slug,createdAt:Jo(),updatedAt:Jo()};return t.description&&(n.description=t.description),t.parentId&&(n.parentId=t.parentId),await ro(VA(e),n),e}async function mte(t,e){const n={updatedAt:Jo()};for(const[r,s]of Object.entries(e))s!==void 0&&(n[r]=s);await ec(VA(t),n)}async function gte(t){await Jw(VA(t))}const bte=Object.freeze(Object.defineProperty({__proto__:null,createTerm:pte,deleteTerm:gte,fetchAllTerms:fte,subscribeToTerms:hte,updateTerm:mte},Symbol.toStringTag,{value:"Module"})),qA="flexweg-cms-user-token";function _O(){if(typeof window>"u")return null;try{const t=window.localStorage.getItem(qA);return t&&t.trim()?t:null}catch{return null}}function yte(t){typeof window>"u"||window.localStorage.setItem(qA,t)}function WA(){typeof window>"u"||window.localStorage.removeItem(qA)}function vte(){const t=ra();if(!t||t.backend!=="flexweg-sqlite")throw new Error("Flexweg SQLite client called outside flexweg-sqlite backend mode. This is a dispatcher bug.");return{apiBaseUrl:t.flexweg.apiBaseUrl,sqliteToken:t.flexweg.sqliteToken}}class t1 extends Error{constructor(e,n,r){super(e),this.status=n,this.body=r,this.name="SqliteApiError"}}let CO=()=>{};function xte(t){CO=t}async function oo(t,e,n,r={}){const s=vte(),i=`${s.apiBaseUrl}/sqlite${t}`,a=new Headers(e.headers);if(a.set("X-Sqlite-Token",s.sqliteToken),r.masterApiKey&&a.set("X-API-Key",r.masterApiKey),!r.skipUserToken){const l=r.userToken??_O();l&&a.set("X-Sqlite-User-Token",l)}e.body!==void 0&&!a.has("Content-Type")&&a.set("Content-Type","application/json");const o=await fetch(i,{...e,headers:a});if(!o.ok){const l=await o.text().catch(()=>"");if(o.status===401&&!t.startsWith("/auth/login")&&!t.startsWith("/auth/register"))try{CO()}catch{}throw new t1(`Flexweg SQLite ${t} failed (${o.status})${l?`: ${l.slice(0,240)}`:""}`,o.status,l)}return o.status===204?{}:await o.json()}function hs(t,e=[],n){return oo("/query",{method:"POST",body:JSON.stringify({sql:t,params:e})})}function Kn(t,e=[],n){return oo("/exec",{method:"POST",body:JSON.stringify({sql:t,params:e})})}function wte(t,e){return oo("/batch",{method:"POST",body:JSON.stringify({statements:t})})}function kte(t){return oo("/version",{method:"GET"})}async function Ste(t){const e=`${t.apiBaseUrl}/sqlite/auth/install`,n=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json","X-API-Key":t.masterApiKey},body:JSON.stringify({path:t.path,name:t.name,requireUserAuth:t.requireUserAuth??!0,allowedOrigins:t.allowedOrigins})});if(!n.ok){const r=await n.text().catch(()=>"");throw new t1(`Flexweg SQLite install failed (${n.status})${r?`: ${r.slice(0,240)}`:""}`,n.status,r)}return await n.json()}const Ete=4e3,Dm=new Set;let xm=null,Fm=null,BS=!1;async function YE(){if(!BS){BS=!0;try{const t=await kte();if(xm===null){xm=t.version;return}if(t.version!==xm){xm=t.version;const e=Array.from(Dm);for(const n of e)try{const r=await n.fetch();n.onChange(r)}catch(r){n.onError&&n.onError(r)}}}catch(t){if(t instanceof t1&&(t.status===401||t.status===403)){const e=Array.from(Dm);for(const n of e)n.onError&&n.onError(t)}}finally{BS=!1}}}function _te(){Fm===null&&(YE(),Fm=setInterval(YE,Ete))}function Cte(){Fm!==null&&(clearInterval(Fm),Fm=null,xm=null)}function th(t,e,n){const r={fetch:t,onChange:e,onError:n};return Dm.add(r),_te(),t().then(e).catch(s=>{n?n(s):console.error("subscribeWithPolling initial fetch failed",s)}),()=>{Dm.delete(r),Dm.size===0&&Cte()}}function Ir(){setTimeout(()=>{YE()},50)}function BR(t){if(t)try{return JSON.parse(t)}catch{return}}function AO(t){const e={id:t.id,type:t.type,name:t.name,slug:t.slug,createdAt:en.fromMillis(t.created_at),updatedAt:en.fromMillis(t.updated_at)};t.description&&(e.description=t.description),t.parent_id&&(e.parentId=t.parent_id),t.last_published_path&&(e.lastPublishedPath=t.last_published_path);const n=BR(t.translations);n&&Object.keys(n).length>0&&(e.translations=n);const r=BR(t.seo);return r&&(r.title||r.description||r.ogImage)&&(e.seo=r),e}function Ate(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function Tte(t,e){return th(async()=>{const{rows:n}=await hs("SELECT * FROM terms ORDER BY name ASC",[]);return n.map(AO)},t,e)}async function Ite(){const{rows:t}=await hs("SELECT * FROM terms ORDER BY name ASC",[]);return t.map(AO)}async function Nte(t){const e=Ate(),n=Date.now();return await Kn(`INSERT INTO terms (
|
|
3845
3845
|
id, type, name, slug, description, parent_id,
|
|
3846
3846
|
created_at, updated_at, last_published_path, translations, seo
|
|
3847
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[e,t.type,t.name,t.slug,t.description??null,t.parentId??null,n,n,null,null,null]),Ir(),e}async function Pte(t,e){const n=[],r=[];if(e.name!==void 0&&(n.push("name = ?"),r.push(e.name)),e.slug!==void 0&&(n.push("slug = ?"),r.push(e.slug)),e.description!==void 0&&(n.push("description = ?"),r.push(e.description??null)),e.parentId!==void 0&&(n.push("parent_id = ?"),r.push(e.parentId??null)),e.translations!==void 0&&(n.push("translations = ?"),r.push(e.translations&&Object.keys(e.translations).length>0?JSON.stringify(e.translations):null)),e.seo!==void 0){n.push("seo = ?");const s=e.seo,i=s&&(s.title||s.description||s.ogImage);r.push(i?JSON.stringify(s):null)}n.push("updated_at = ?"),r.push(Date.now()),r.push(t),await Kn(`UPDATE terms SET ${n.join(", ")} WHERE id = ?`,r),Ir()}async function Rte(t){await Kn("DELETE FROM terms WHERE id = ?",[t]),Ir()}const jte=Object.freeze(Object.defineProperty({__proto__:null,createTerm:Nte,deleteTerm:Rte,fetchAllTerms:Ite,subscribeToTerms:Tte,updateTerm:Pte},Symbol.toStringTag,{value:"Module"})),Tu=["posts","terms","media","users","settings","config"];class e_ extends Error{constructor(e,n,r){super(e),this.collection=n,this.id=r,this.name="DocConflictError"}}function E0(){return Object.fromEntries(Tu.map(t=>[t,new Map]))}function TO(t){return Object.fromEntries(Tu.map(e=>[e,new Map(t[e])]))}function t_(t){if(Array.isArray(t))return Object.freeze(t.map(t_));if(t&&typeof t=="object"&&Object.getPrototypeOf(t)===Object.prototype){const e={};for(const[n,r]of Object.entries(t))r!==void 0&&(e[n]=t_(r));return Object.freeze(e)}return t}function Mte(t,e){const n=TO(t),r=new Set;for(const s of e)s.op==="set"?n[s.collection].set(s.doc.id,t_(s.doc)):n[s.collection].delete(s.id),r.add(s.collection);return{next:n,changed:r}}function Lte(t,e){const n=new Set;for(const r of Tu){if(t[r].size!==e[r].size){n.add(r);continue}for(const[s,i]of t[r]){const a=e[r].get(s);if(!a||JSON.stringify(a)!==JSON.stringify(i)){n.add(r);break}}}return n}function GA(t){let e=E0(),n=null,r=Promise.resolve(),s=0;const i=new Set;let a=null;function o(m){if(m.size!==0)for(const g of[...i])try{g(m)}catch(y){console.error("[docstore] listener failed:",y)}}function l(){return n||(n=t.load().then(m=>{e=m,o(new Set(Tu))},m=>{throw n=null,m})),n}async function c(){if(await l(),!t.poll||s>0)return;const m=await t.poll();if(!m||s>0)return;const g=Lte(e,m);e=m,o(g)}function h(){a||!t.poll||(a=setInterval(()=>{c().catch(m=>console.warn("[docstore] poll failed:",m))},t.pollIntervalMs??3e4))}function p(){a&&clearInterval(a),a=null}return{kind:t.kind,ready:l,refresh:c,identity:()=>t.identity(),list(m){return[...e[m].values()]},get(m,g){return e[m].get(g)},async write(m,g){if(await l(),m.length===0)return;const y=e,{next:x,changed:v}=Mte(y,m);e=x,o(v),s++;const k=r.then(()=>t.persist(m,y,x,(g==null?void 0:g.message)??"Update content"));r=k.catch(()=>{});try{await k}catch(C){const N=TO(e);for(const _ of m){const P=_.op==="set"?_.doc.id:_.id,D=y[_.collection].get(P);D?N[_.collection].set(P,D):N[_.collection].delete(P)}throw e=N,o(v),C}finally{s--}},subscribe(m){return i.add(m),h(),()=>{i.delete(m),i.size===0&&p()}}}}const Vt=t=>typeof t=="string",Jp=()=>{let t,e;const n=new Promise((r,s)=>{t=r,e=s});return n.resolve=t,n.reject=e,n},$R=t=>t==null?"":""+t,Dte=(t,e,n)=>{t.forEach(r=>{e[r]&&(n[r]=e[r])})},Fte=/###/g,HR=t=>t&&t.indexOf("###")>-1?t.replace(Fte,"."):t,VR=t=>!t||Vt(t),Om=(t,e,n)=>{const r=Vt(e)?e.split("."):e;let s=0;for(;s<r.length-1;){if(VR(t))return{};const i=HR(r[s]);!t[i]&&n&&(t[i]=new n),Object.prototype.hasOwnProperty.call(t,i)?t=t[i]:t={},++s}return VR(t)?{}:{obj:t,k:HR(r[s])}},qR=(t,e,n)=>{const{obj:r,k:s}=Om(t,e,Object);if(r!==void 0||e.length===1){r[s]=n;return}let i=e[e.length-1],a=e.slice(0,e.length-1),o=Om(t,a,Object);for(;o.obj===void 0&&a.length;)i=`${a[a.length-1]}.${i}`,a=a.slice(0,a.length-1),o=Om(t,a,Object),o&&o.obj&&typeof o.obj[`${o.k}.${i}`]<"u"&&(o.obj=void 0);o.obj[`${o.k}.${i}`]=n},Ote=(t,e,n,r)=>{const{obj:s,k:i}=Om(t,e,Object);s[i]=s[i]||[],s[i].push(n)},jv=(t,e)=>{const{obj:n,k:r}=Om(t,e);if(n)return n[r]},zte=(t,e,n)=>{const r=jv(t,n);return r!==void 0?r:jv(e,n)},IO=(t,e,n)=>{for(const r in e)r!=="__proto__"&&r!=="constructor"&&(r in t?Vt(t[r])||t[r]instanceof String||Vt(e[r])||e[r]instanceof String?n&&(t[r]=e[r]):IO(t[r],e[r],n):t[r]=e[r]);return t},Ah=t=>t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&");var Ute={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};const Bte=t=>Vt(t)?t.replace(/[&<>"'\/]/g,e=>Ute[e]):t;class $te{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){const n=this.regExpMap.get(e);if(n!==void 0)return n;const r=new RegExp(e);return this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,r),this.regExpQueue.push(e),r}}const Hte=[" ",",","?","!",";"],Vte=new $te(20),qte=(t,e,n)=>{e=e||"",n=n||"";const r=Hte.filter(a=>e.indexOf(a)<0&&n.indexOf(a)<0);if(r.length===0)return!0;const s=Vte.getRegExp(`(${r.map(a=>a==="?"?"\\?":a).join("|")})`);let i=!s.test(t);if(!i){const a=t.indexOf(n);a>0&&!s.test(t.substring(0,a))&&(i=!0)}return i},n_=function(t,e){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:".";if(!t)return;if(t[e])return t[e];const r=e.split(n);let s=t;for(let i=0;i<r.length;){if(!s||typeof s!="object")return;let a,o="";for(let l=i;l<r.length;++l)if(l!==i&&(o+=n),o+=r[l],a=s[o],a!==void 0){if(["string","number","boolean"].indexOf(typeof a)>-1&&l<r.length-1)continue;i+=l-i+1;break}s=a}return s},Mv=t=>t&&t.replace("_","-"),Wte={type:"logger",log(t){this.output("log",t)},warn(t){this.output("warn",t)},error(t){this.output("error",t)},output(t,e){console&&console[t]&&console[t].apply(console,e)}};class Lv{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.init(e,n)}init(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.prefix=n.prefix||"i18next:",this.logger=e||Wte,this.options=n,this.debug=n.debug}log(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return this.forward(n,"log","",!0)}warn(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return this.forward(n,"warn","",!0)}error(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return this.forward(n,"error","")}deprecate(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return this.forward(n,"warn","WARNING DEPRECATED: ",!0)}forward(e,n,r,s){return s&&!this.debug?null:(Vt(e[0])&&(e[0]=`${r}${this.prefix} ${e[0]}`),this.logger[n](e))}create(e){return new Lv(this.logger,{prefix:`${this.prefix}:${e}:`,...this.options})}clone(e){return e=e||this.options,e.prefix=e.prefix||this.prefix,new Lv(this.logger,e)}}var Po=new Lv;let n1=class{constructor(){this.observers={}}on(e,n){return e.split(" ").forEach(r=>{this.observers[r]||(this.observers[r]=new Map);const s=this.observers[r].get(n)||0;this.observers[r].set(n,s+1)}),this}off(e,n){if(this.observers[e]){if(!n){delete this.observers[e];return}this.observers[e].delete(n)}}emit(e){for(var n=arguments.length,r=new Array(n>1?n-1:0),s=1;s<n;s++)r[s-1]=arguments[s];this.observers[e]&&Array.from(this.observers[e].entries()).forEach(a=>{let[o,l]=a;for(let c=0;c<l;c++)o(...r)}),this.observers["*"]&&Array.from(this.observers["*"].entries()).forEach(a=>{let[o,l]=a;for(let c=0;c<l;c++)o.apply(o,[e,...r])})}};class WR extends n1{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{ns:["translation"],defaultNS:"translation"};super(),this.data=e||{},this.options=n,this.options.keySeparator===void 0&&(this.options.keySeparator="."),this.options.ignoreJSONStructure===void 0&&(this.options.ignoreJSONStructure=!0)}addNamespaces(e){this.options.ns.indexOf(e)<0&&this.options.ns.push(e)}removeNamespaces(e){const n=this.options.ns.indexOf(e);n>-1&&this.options.ns.splice(n,1)}getResource(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};const i=s.keySeparator!==void 0?s.keySeparator:this.options.keySeparator,a=s.ignoreJSONStructure!==void 0?s.ignoreJSONStructure:this.options.ignoreJSONStructure;let o;e.indexOf(".")>-1?o=e.split("."):(o=[e,n],r&&(Array.isArray(r)?o.push(...r):Vt(r)&&i?o.push(...r.split(i)):o.push(r)));const l=jv(this.data,o);return!l&&!n&&!r&&e.indexOf(".")>-1&&(e=o[0],n=o[1],r=o.slice(2).join(".")),l||!a||!Vt(r)?l:n_(this.data&&this.data[e]&&this.data[e][n],r,i)}addResource(e,n,r,s){let i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:{silent:!1};const a=i.keySeparator!==void 0?i.keySeparator:this.options.keySeparator;let o=[e,n];r&&(o=o.concat(a?r.split(a):r)),e.indexOf(".")>-1&&(o=e.split("."),s=n,n=o[1]),this.addNamespaces(n),qR(this.data,o,s),i.silent||this.emit("added",e,n,r,s)}addResources(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{silent:!1};for(const i in r)(Vt(r[i])||Array.isArray(r[i]))&&this.addResource(e,n,i,r[i],{silent:!0});s.silent||this.emit("added",e,n,r)}addResourceBundle(e,n,r,s,i){let a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:{silent:!1,skipCopy:!1},o=[e,n];e.indexOf(".")>-1&&(o=e.split("."),s=r,r=n,n=o[1]),this.addNamespaces(n);let l=jv(this.data,o)||{};a.skipCopy||(r=JSON.parse(JSON.stringify(r))),s?IO(l,r,i):l={...l,...r},qR(this.data,o,l),a.silent||this.emit("added",e,n,r)}removeResourceBundle(e,n){this.hasResourceBundle(e,n)&&delete this.data[e][n],this.removeNamespaces(n),this.emit("removed",e,n)}hasResourceBundle(e,n){return this.getResource(e,n)!==void 0}getResourceBundle(e,n){return n||(n=this.options.defaultNS),this.options.compatibilityAPI==="v1"?{...this.getResource(e,n)}:this.getResource(e,n)}getDataByLanguage(e){return this.data[e]}hasLanguageSomeTranslations(e){const n=this.getDataByLanguage(e);return!!(n&&Object.keys(n)||[]).find(s=>n[s]&&Object.keys(n[s]).length>0)}toJSON(){return this.data}}var NO={processors:{},addPostProcessor(t){this.processors[t.name]=t},handle(t,e,n,r,s){return t.forEach(i=>{this.processors[i]&&(e=this.processors[i].process(e,n,r,s))}),e}};const GR={};class Dv extends n1{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};super(),Dte(["resourceStore","languageUtils","pluralResolver","interpolator","backendConnector","i18nFormat","utils"],e,this),this.options=n,this.options.keySeparator===void 0&&(this.options.keySeparator="."),this.logger=Po.create("translator")}changeLanguage(e){e&&(this.language=e)}exists(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{interpolation:{}};if(e==null)return!1;const r=this.resolve(e,n);return r&&r.res!==void 0}extractFromKey(e,n){let r=n.nsSeparator!==void 0?n.nsSeparator:this.options.nsSeparator;r===void 0&&(r=":");const s=n.keySeparator!==void 0?n.keySeparator:this.options.keySeparator;let i=n.ns||this.options.defaultNS||[];const a=r&&e.indexOf(r)>-1,o=!this.options.userDefinedKeySeparator&&!n.keySeparator&&!this.options.userDefinedNsSeparator&&!n.nsSeparator&&!qte(e,r,s);if(a&&!o){const l=e.match(this.interpolator.nestingRegexp);if(l&&l.length>0)return{key:e,namespaces:Vt(i)?[i]:i};const c=e.split(r);(r!==s||r===s&&this.options.ns.indexOf(c[0])>-1)&&(i=c.shift()),e=c.join(s)}return{key:e,namespaces:Vt(i)?[i]:i}}translate(e,n,r){if(typeof n!="object"&&this.options.overloadTranslationOptionHandler&&(n=this.options.overloadTranslationOptionHandler(arguments)),typeof n=="object"&&(n={...n}),n||(n={}),e==null)return"";Array.isArray(e)||(e=[String(e)]);const s=n.returnDetails!==void 0?n.returnDetails:this.options.returnDetails,i=n.keySeparator!==void 0?n.keySeparator:this.options.keySeparator,{key:a,namespaces:o}=this.extractFromKey(e[e.length-1],n),l=o[o.length-1],c=n.lng||this.language,h=n.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(c&&c.toLowerCase()==="cimode"){if(h){const _=n.nsSeparator||this.options.nsSeparator;return s?{res:`${l}${_}${a}`,usedKey:a,exactUsedKey:a,usedLng:c,usedNS:l,usedParams:this.getUsedParamsDetails(n)}:`${l}${_}${a}`}return s?{res:a,usedKey:a,exactUsedKey:a,usedLng:c,usedNS:l,usedParams:this.getUsedParamsDetails(n)}:a}const p=this.resolve(e,n);let m=p&&p.res;const g=p&&p.usedKey||a,y=p&&p.exactUsedKey||a,x=Object.prototype.toString.apply(m),v=["[object Number]","[object Function]","[object RegExp]"],k=n.joinArrays!==void 0?n.joinArrays:this.options.joinArrays,C=!this.i18nFormat||this.i18nFormat.handleAsObject,N=!Vt(m)&&typeof m!="boolean"&&typeof m!="number";if(C&&m&&N&&v.indexOf(x)<0&&!(Vt(k)&&Array.isArray(m))){if(!n.returnObjects&&!this.options.returnObjects){this.options.returnedObjectHandler||this.logger.warn("accessing an object - but returnObjects options is not enabled!");const _=this.options.returnedObjectHandler?this.options.returnedObjectHandler(g,m,{...n,ns:o}):`key '${a} (${this.language})' returned an object instead of string.`;return s?(p.res=_,p.usedParams=this.getUsedParamsDetails(n),p):_}if(i){const _=Array.isArray(m),P=_?[]:{},D=_?y:g;for(const I in m)if(Object.prototype.hasOwnProperty.call(m,I)){const L=`${D}${i}${I}`;P[I]=this.translate(L,{...n,joinArrays:!1,ns:o}),P[I]===L&&(P[I]=m[I])}m=P}}else if(C&&Vt(k)&&Array.isArray(m))m=m.join(k),m&&(m=this.extendTranslation(m,e,n,r));else{let _=!1,P=!1;const D=n.count!==void 0&&!Vt(n.count),I=Dv.hasDefaultValue(n),L=D?this.pluralResolver.getSuffix(c,n.count,n):"",j=n.ordinal&&D?this.pluralResolver.getSuffix(c,n.count,{ordinal:!1}):"",q=D&&!n.ordinal&&n.count===0&&this.pluralResolver.shouldUseIntlApi(),V=q&&n[`defaultValue${this.options.pluralSeparator}zero`]||n[`defaultValue${L}`]||n[`defaultValue${j}`]||n.defaultValue;!this.isValidLookup(m)&&I&&(_=!0,m=V),this.isValidLookup(m)||(P=!0,m=a);const $=(n.missingKeyNoValueFallbackToKey||this.options.missingKeyNoValueFallbackToKey)&&P?void 0:m,B=I&&V!==m&&this.options.updateMissing;if(P||_||B){if(this.logger.log(B?"updateKey":"missingKey",c,l,a,B?V:m),i){const ae=this.resolve(a,{...n,keySeparator:!1});ae&&ae.res&&this.logger.warn("Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.")}let X=[];const fe=this.languageUtils.getFallbackCodes(this.options.fallbackLng,n.lng||this.language);if(this.options.saveMissingTo==="fallback"&&fe&&fe[0])for(let ae=0;ae<fe.length;ae++)X.push(fe[ae]);else this.options.saveMissingTo==="all"?X=this.languageUtils.toResolveHierarchy(n.lng||this.language):X.push(n.lng||this.language);const ie=(ae,ue,ve)=>{const K=I&&ve!==m?ve:$;this.options.missingKeyHandler?this.options.missingKeyHandler(ae,l,ue,K,B,n):this.backendConnector&&this.backendConnector.saveMissing&&this.backendConnector.saveMissing(ae,l,ue,K,B,n),this.emit("missingKey",ae,l,ue,m)};this.options.saveMissing&&(this.options.saveMissingPlurals&&D?X.forEach(ae=>{const ue=this.pluralResolver.getSuffixes(ae,n);q&&n[`defaultValue${this.options.pluralSeparator}zero`]&&ue.indexOf(`${this.options.pluralSeparator}zero`)<0&&ue.push(`${this.options.pluralSeparator}zero`),ue.forEach(ve=>{ie([ae],a+ve,n[`defaultValue${ve}`]||V)})}):ie(X,a,V))}m=this.extendTranslation(m,e,n,p,r),P&&m===a&&this.options.appendNamespaceToMissingKey&&(m=`${l}:${a}`),(P||_)&&this.options.parseMissingKeyHandler&&(this.options.compatibilityAPI!=="v1"?m=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${l}:${a}`:a,_?m:void 0):m=this.options.parseMissingKeyHandler(m))}return s?(p.res=m,p.usedParams=this.getUsedParamsDetails(n),p):m}extendTranslation(e,n,r,s,i){var a=this;if(this.i18nFormat&&this.i18nFormat.parse)e=this.i18nFormat.parse(e,{...this.options.interpolation.defaultVariables,...r},r.lng||this.language||s.usedLng,s.usedNS,s.usedKey,{resolved:s});else if(!r.skipInterpolation){r.interpolation&&this.interpolator.init({...r,interpolation:{...this.options.interpolation,...r.interpolation}});const c=Vt(e)&&(r&&r.interpolation&&r.interpolation.skipOnVariables!==void 0?r.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables);let h;if(c){const m=e.match(this.interpolator.nestingRegexp);h=m&&m.length}let p=r.replace&&!Vt(r.replace)?r.replace:r;if(this.options.interpolation.defaultVariables&&(p={...this.options.interpolation.defaultVariables,...p}),e=this.interpolator.interpolate(e,p,r.lng||this.language||s.usedLng,r),c){const m=e.match(this.interpolator.nestingRegexp),g=m&&m.length;h<g&&(r.nest=!1)}!r.lng&&this.options.compatibilityAPI!=="v1"&&s&&s.res&&(r.lng=this.language||s.usedLng),r.nest!==!1&&(e=this.interpolator.nest(e,function(){for(var m=arguments.length,g=new Array(m),y=0;y<m;y++)g[y]=arguments[y];return i&&i[0]===g[0]&&!r.context?(a.logger.warn(`It seems you are nesting recursively key: ${g[0]} in key: ${n[0]}`),null):a.translate(...g,n)},r)),r.interpolation&&this.interpolator.reset()}const o=r.postProcess||this.options.postProcess,l=Vt(o)?[o]:o;return e!=null&&l&&l.length&&r.applyPostProcessor!==!1&&(e=NO.handle(l,e,n,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...s,usedParams:this.getUsedParamsDetails(r)},...r}:r,this)),e}resolve(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r,s,i,a,o;return Vt(e)&&(e=[e]),e.forEach(l=>{if(this.isValidLookup(r))return;const c=this.extractFromKey(l,n),h=c.key;s=h;let p=c.namespaces;this.options.fallbackNS&&(p=p.concat(this.options.fallbackNS));const m=n.count!==void 0&&!Vt(n.count),g=m&&!n.ordinal&&n.count===0&&this.pluralResolver.shouldUseIntlApi(),y=n.context!==void 0&&(Vt(n.context)||typeof n.context=="number")&&n.context!=="",x=n.lngs?n.lngs:this.languageUtils.toResolveHierarchy(n.lng||this.language,n.fallbackLng);p.forEach(v=>{this.isValidLookup(r)||(o=v,!GR[`${x[0]}-${v}`]&&this.utils&&this.utils.hasLoadedNamespace&&!this.utils.hasLoadedNamespace(o)&&(GR[`${x[0]}-${v}`]=!0,this.logger.warn(`key "${s}" for languages "${x.join(", ")}" won't get resolved as namespace "${o}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!")),x.forEach(k=>{if(this.isValidLookup(r))return;a=k;const C=[h];if(this.i18nFormat&&this.i18nFormat.addLookupKeys)this.i18nFormat.addLookupKeys(C,h,k,v,n);else{let _;m&&(_=this.pluralResolver.getSuffix(k,n.count,n));const P=`${this.options.pluralSeparator}zero`,D=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(m&&(C.push(h+_),n.ordinal&&_.indexOf(D)===0&&C.push(h+_.replace(D,this.options.pluralSeparator)),g&&C.push(h+P)),y){const I=`${h}${this.options.contextSeparator}${n.context}`;C.push(I),m&&(C.push(I+_),n.ordinal&&_.indexOf(D)===0&&C.push(I+_.replace(D,this.options.pluralSeparator)),g&&C.push(I+P))}}let N;for(;N=C.pop();)this.isValidLookup(r)||(i=N,r=this.getResource(k,v,N,n))}))})}),{res:r,usedKey:s,exactUsedKey:i,usedLng:a,usedNS:o}}isValidLookup(e){return e!==void 0&&!(!this.options.returnNull&&e===null)&&!(!this.options.returnEmptyString&&e==="")}getResource(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};return this.i18nFormat&&this.i18nFormat.getResource?this.i18nFormat.getResource(e,n,r,s):this.resourceStore.getResource(e,n,r,s)}getUsedParamsDetails(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};const n=["defaultValue","ordinal","context","replace","lng","lngs","fallbackLng","ns","keySeparator","nsSeparator","returnObjects","returnDetails","joinArrays","postProcess","interpolation"],r=e.replace&&!Vt(e.replace);let s=r?e.replace:e;if(r&&typeof e.count<"u"&&(s.count=e.count),this.options.interpolation.defaultVariables&&(s={...this.options.interpolation.defaultVariables,...s}),!r){s={...s};for(const i of n)delete s[i]}return s}static hasDefaultValue(e){const n="defaultValue";for(const r in e)if(Object.prototype.hasOwnProperty.call(e,r)&&n===r.substring(0,n.length)&&e[r]!==void 0)return!0;return!1}}const $S=t=>t.charAt(0).toUpperCase()+t.slice(1);class KR{constructor(e){this.options=e,this.supportedLngs=this.options.supportedLngs||!1,this.logger=Po.create("languageUtils")}getScriptPartFromCode(e){if(e=Mv(e),!e||e.indexOf("-")<0)return null;const n=e.split("-");return n.length===2||(n.pop(),n[n.length-1].toLowerCase()==="x")?null:this.formatLanguageCode(n.join("-"))}getLanguagePartFromCode(e){if(e=Mv(e),!e||e.indexOf("-")<0)return e;const n=e.split("-");return this.formatLanguageCode(n[0])}formatLanguageCode(e){if(Vt(e)&&e.indexOf("-")>-1){if(typeof Intl<"u"&&typeof Intl.getCanonicalLocales<"u")try{let s=Intl.getCanonicalLocales(e)[0];if(s&&this.options.lowerCaseLng&&(s=s.toLowerCase()),s)return s}catch{}const n=["hans","hant","latn","cyrl","cans","mong","arab"];let r=e.split("-");return this.options.lowerCaseLng?r=r.map(s=>s.toLowerCase()):r.length===2?(r[0]=r[0].toLowerCase(),r[1]=r[1].toUpperCase(),n.indexOf(r[1].toLowerCase())>-1&&(r[1]=$S(r[1].toLowerCase()))):r.length===3&&(r[0]=r[0].toLowerCase(),r[1].length===2&&(r[1]=r[1].toUpperCase()),r[0]!=="sgn"&&r[2].length===2&&(r[2]=r[2].toUpperCase()),n.indexOf(r[1].toLowerCase())>-1&&(r[1]=$S(r[1].toLowerCase())),n.indexOf(r[2].toLowerCase())>-1&&(r[2]=$S(r[2].toLowerCase()))),r.join("-")}return this.options.cleanCode||this.options.lowerCaseLng?e.toLowerCase():e}isSupportedCode(e){return(this.options.load==="languageOnly"||this.options.nonExplicitSupportedLngs)&&(e=this.getLanguagePartFromCode(e)),!this.supportedLngs||!this.supportedLngs.length||this.supportedLngs.indexOf(e)>-1}getBestMatchFromCodes(e){if(!e)return null;let n;return e.forEach(r=>{if(n)return;const s=this.formatLanguageCode(r);(!this.options.supportedLngs||this.isSupportedCode(s))&&(n=s)}),!n&&this.options.supportedLngs&&e.forEach(r=>{if(n)return;const s=this.getLanguagePartFromCode(r);if(this.isSupportedCode(s))return n=s;n=this.options.supportedLngs.find(i=>{if(i===s)return i;if(!(i.indexOf("-")<0&&s.indexOf("-")<0)&&(i.indexOf("-")>0&&s.indexOf("-")<0&&i.substring(0,i.indexOf("-"))===s||i.indexOf(s)===0&&s.length>1))return i})}),n||(n=this.getFallbackCodes(this.options.fallbackLng)[0]),n}getFallbackCodes(e,n){if(!e)return[];if(typeof e=="function"&&(e=e(n)),Vt(e)&&(e=[e]),Array.isArray(e))return e;if(!n)return e.default||[];let r=e[n];return r||(r=e[this.getScriptPartFromCode(n)]),r||(r=e[this.formatLanguageCode(n)]),r||(r=e[this.getLanguagePartFromCode(n)]),r||(r=e.default),r||[]}toResolveHierarchy(e,n){const r=this.getFallbackCodes(n||this.options.fallbackLng||[],e),s=[],i=a=>{a&&(this.isSupportedCode(a)?s.push(a):this.logger.warn(`rejecting language code not found in supportedLngs: ${a}`))};return Vt(e)&&(e.indexOf("-")>-1||e.indexOf("_")>-1)?(this.options.load!=="languageOnly"&&i(this.formatLanguageCode(e)),this.options.load!=="languageOnly"&&this.options.load!=="currentOnly"&&i(this.getScriptPartFromCode(e)),this.options.load!=="currentOnly"&&i(this.getLanguagePartFromCode(e))):Vt(e)&&i(this.formatLanguageCode(e)),r.forEach(a=>{s.indexOf(a)<0&&i(this.formatLanguageCode(a))}),s}}let Gte=[{lngs:["ach","ak","am","arn","br","fil","gun","ln","mfe","mg","mi","oc","pt","pt-BR","tg","tl","ti","tr","uz","wa"],nr:[1,2],fc:1},{lngs:["af","an","ast","az","bg","bn","ca","da","de","dev","el","en","eo","es","et","eu","fi","fo","fur","fy","gl","gu","ha","hi","hu","hy","ia","it","kk","kn","ku","lb","mai","ml","mn","mr","nah","nap","nb","ne","nl","nn","no","nso","pa","pap","pms","ps","pt-PT","rm","sco","se","si","so","son","sq","sv","sw","ta","te","tk","ur","yo"],nr:[1,2],fc:2},{lngs:["ay","bo","cgg","fa","ht","id","ja","jbo","ka","km","ko","ky","lo","ms","sah","su","th","tt","ug","vi","wo","zh"],nr:[1],fc:3},{lngs:["be","bs","cnr","dz","hr","ru","sr","uk"],nr:[1,2,5],fc:4},{lngs:["ar"],nr:[0,1,2,3,11,100],fc:5},{lngs:["cs","sk"],nr:[1,2,5],fc:6},{lngs:["csb","pl"],nr:[1,2,5],fc:7},{lngs:["cy"],nr:[1,2,3,8],fc:8},{lngs:["fr"],nr:[1,2],fc:9},{lngs:["ga"],nr:[1,2,3,7,11],fc:10},{lngs:["gd"],nr:[1,2,3,20],fc:11},{lngs:["is"],nr:[1,2],fc:12},{lngs:["jv"],nr:[0,1],fc:13},{lngs:["kw"],nr:[1,2,3,4],fc:14},{lngs:["lt"],nr:[1,2,10],fc:15},{lngs:["lv"],nr:[1,2,0],fc:16},{lngs:["mk"],nr:[1,2],fc:17},{lngs:["mnk"],nr:[0,1,2],fc:18},{lngs:["mt"],nr:[1,2,11,20],fc:19},{lngs:["or"],nr:[2,1],fc:2},{lngs:["ro"],nr:[1,2,20],fc:20},{lngs:["sl"],nr:[5,1,2,3],fc:21},{lngs:["he","iw"],nr:[1,2,20,21],fc:22}],Kte={1:t=>+(t>1),2:t=>+(t!=1),3:t=>0,4:t=>t%10==1&&t%100!=11?0:t%10>=2&&t%10<=4&&(t%100<10||t%100>=20)?1:2,5:t=>t==0?0:t==1?1:t==2?2:t%100>=3&&t%100<=10?3:t%100>=11?4:5,6:t=>t==1?0:t>=2&&t<=4?1:2,7:t=>t==1?0:t%10>=2&&t%10<=4&&(t%100<10||t%100>=20)?1:2,8:t=>t==1?0:t==2?1:t!=8&&t!=11?2:3,9:t=>+(t>=2),10:t=>t==1?0:t==2?1:t<7?2:t<11?3:4,11:t=>t==1||t==11?0:t==2||t==12?1:t>2&&t<20?2:3,12:t=>+(t%10!=1||t%100==11),13:t=>+(t!==0),14:t=>t==1?0:t==2?1:t==3?2:3,15:t=>t%10==1&&t%100!=11?0:t%10>=2&&(t%100<10||t%100>=20)?1:2,16:t=>t%10==1&&t%100!=11?0:t!==0?1:2,17:t=>t==1||t%10==1&&t%100!=11?0:1,18:t=>t==0?0:t==1?1:2,19:t=>t==1?0:t==0||t%100>1&&t%100<11?1:t%100>10&&t%100<20?2:3,20:t=>t==1?0:t==0||t%100>0&&t%100<20?1:2,21:t=>t%100==1?1:t%100==2?2:t%100==3||t%100==4?3:0,22:t=>t==1?0:t==2?1:(t<0||t>10)&&t%10==0?2:3};const Jte=["v1","v2","v3"],Qte=["v4"],JR={zero:0,one:1,two:2,few:3,many:4,other:5},Xte=()=>{const t={};return Gte.forEach(e=>{e.lngs.forEach(n=>{t[n]={numbers:e.nr,plurals:Kte[e.fc]}})}),t};class Zte{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.languageUtils=e,this.options=n,this.logger=Po.create("pluralResolver"),(!this.options.compatibilityJSON||Qte.includes(this.options.compatibilityJSON))&&(typeof Intl>"u"||!Intl.PluralRules)&&(this.options.compatibilityJSON="v3",this.logger.error("Your environment seems not to be Intl API compatible, use an Intl.PluralRules polyfill. Will fallback to the compatibilityJSON v3 format handling.")),this.rules=Xte(),this.pluralRulesCache={}}addRule(e,n){this.rules[e]=n}clearCache(){this.pluralRulesCache={}}getRule(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(this.shouldUseIntlApi()){const r=Mv(e==="dev"?"en":e),s=n.ordinal?"ordinal":"cardinal",i=JSON.stringify({cleanedCode:r,type:s});if(i in this.pluralRulesCache)return this.pluralRulesCache[i];let a;try{a=new Intl.PluralRules(r,{type:s})}catch{if(!e.match(/-|_/))return;const l=this.languageUtils.getLanguagePartFromCode(e);a=this.getRule(l,n)}return this.pluralRulesCache[i]=a,a}return this.rules[e]||this.rules[this.languageUtils.getLanguagePartFromCode(e)]}needsPlural(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};const r=this.getRule(e,n);return this.shouldUseIntlApi()?r&&r.resolvedOptions().pluralCategories.length>1:r&&r.numbers.length>1}getPluralFormsOfKey(e,n){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return this.getSuffixes(e,r).map(s=>`${n}${s}`)}getSuffixes(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};const r=this.getRule(e,n);return r?this.shouldUseIntlApi()?r.resolvedOptions().pluralCategories.sort((s,i)=>JR[s]-JR[i]).map(s=>`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:""}${s}`):r.numbers.map(s=>this.getSuffix(e,s,n)):[]}getSuffix(e,n){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};const s=this.getRule(e,r);return s?this.shouldUseIntlApi()?`${this.options.prepend}${r.ordinal?`ordinal${this.options.prepend}`:""}${s.select(n)}`:this.getSuffixRetroCompatible(s,n):(this.logger.warn(`no plural rule found for: ${e}`),"")}getSuffixRetroCompatible(e,n){const r=e.noAbs?e.plurals(n):e.plurals(Math.abs(n));let s=e.numbers[r];this.options.simplifyPluralSuffix&&e.numbers.length===2&&e.numbers[0]===1&&(s===2?s="plural":s===1&&(s=""));const i=()=>this.options.prepend&&s.toString()?this.options.prepend+s.toString():s.toString();return this.options.compatibilityJSON==="v1"?s===1?"":typeof s=="number"?`_plural_${s.toString()}`:i():this.options.compatibilityJSON==="v2"||this.options.simplifyPluralSuffix&&e.numbers.length===2&&e.numbers[0]===1?i():this.options.prepend&&r.toString()?this.options.prepend+r.toString():r.toString()}shouldUseIntlApi(){return!Jte.includes(this.options.compatibilityJSON)}}const QR=function(t,e,n){let r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:".",s=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,i=zte(t,e,n);return!i&&s&&Vt(n)&&(i=n_(t,n,r),i===void 0&&(i=n_(e,n,r))),i},HS=t=>t.replace(/\$/g,"$$$$");class Yte{constructor(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};this.logger=Po.create("interpolator"),this.options=e,this.format=e.interpolation&&e.interpolation.format||(n=>n),this.init(e)}init(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};e.interpolation||(e.interpolation={escapeValue:!0});const{escape:n,escapeValue:r,useRawValueToEscape:s,prefix:i,prefixEscaped:a,suffix:o,suffixEscaped:l,formatSeparator:c,unescapeSuffix:h,unescapePrefix:p,nestingPrefix:m,nestingPrefixEscaped:g,nestingSuffix:y,nestingSuffixEscaped:x,nestingOptionsSeparator:v,maxReplaces:k,alwaysFormat:C}=e.interpolation;this.escape=n!==void 0?n:Bte,this.escapeValue=r!==void 0?r:!0,this.useRawValueToEscape=s!==void 0?s:!1,this.prefix=i?Ah(i):a||"{{",this.suffix=o?Ah(o):l||"}}",this.formatSeparator=c||",",this.unescapePrefix=h?"":p||"-",this.unescapeSuffix=this.unescapePrefix?"":h||"",this.nestingPrefix=m?Ah(m):g||Ah("$t("),this.nestingSuffix=y?Ah(y):x||Ah(")"),this.nestingOptionsSeparator=v||",",this.maxReplaces=k||1e3,this.alwaysFormat=C!==void 0?C:!1,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){const e=(n,r)=>n&&n.source===r?(n.lastIndex=0,n):new RegExp(r,"g");this.regexp=e(this.regexp,`${this.prefix}(.+?)${this.suffix}`),this.regexpUnescape=e(this.regexpUnescape,`${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`),this.nestingRegexp=e(this.nestingRegexp,`${this.nestingPrefix}(.+?)${this.nestingSuffix}`)}interpolate(e,n,r,s){let i,a,o;const l=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},c=g=>{if(g.indexOf(this.formatSeparator)<0){const k=QR(n,l,g,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(k,void 0,r,{...s,...n,interpolationkey:g}):k}const y=g.split(this.formatSeparator),x=y.shift().trim(),v=y.join(this.formatSeparator).trim();return this.format(QR(n,l,x,this.options.keySeparator,this.options.ignoreJSONStructure),v,r,{...s,...n,interpolationkey:x})};this.resetRegExp();const h=s&&s.missingInterpolationHandler||this.options.missingInterpolationHandler,p=s&&s.interpolation&&s.interpolation.skipOnVariables!==void 0?s.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:g=>HS(g)},{regex:this.regexp,safeValue:g=>this.escapeValue?HS(this.escape(g)):HS(g)}].forEach(g=>{for(o=0;i=g.regex.exec(e);){const y=i[1].trim();if(a=c(y),a===void 0)if(typeof h=="function"){const v=h(e,i,s);a=Vt(v)?v:""}else if(s&&Object.prototype.hasOwnProperty.call(s,y))a="";else if(p){a=i[0];continue}else this.logger.warn(`missed to pass in variable ${y} for interpolating ${e}`),a="";else!Vt(a)&&!this.useRawValueToEscape&&(a=$R(a));const x=g.safeValue(a);if(e=e.replace(i[0],x),p?(g.regex.lastIndex+=a.length,g.regex.lastIndex-=i[0].length):g.regex.lastIndex=0,o++,o>=this.maxReplaces)break}}),e}nest(e,n){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},s,i,a;const o=(l,c)=>{const h=this.nestingOptionsSeparator;if(l.indexOf(h)<0)return l;const p=l.split(new RegExp(`${h}[ ]*{`));let m=`{${p[1]}`;l=p[0],m=this.interpolate(m,a);const g=m.match(/'/g),y=m.match(/"/g);(g&&g.length%2===0&&!y||y.length%2!==0)&&(m=m.replace(/'/g,'"'));try{a=JSON.parse(m),c&&(a={...c,...a})}catch(x){return this.logger.warn(`failed parsing options string in nesting for key ${l}`,x),`${l}${h}${m}`}return a.defaultValue&&a.defaultValue.indexOf(this.prefix)>-1&&delete a.defaultValue,l};for(;s=this.nestingRegexp.exec(e);){let l=[];a={...r},a=a.replace&&!Vt(a.replace)?a.replace:a,a.applyPostProcessor=!1,delete a.defaultValue;let c=!1;if(s[0].indexOf(this.formatSeparator)!==-1&&!/{.*}/.test(s[1])){const h=s[1].split(this.formatSeparator).map(p=>p.trim());s[1]=h.shift(),l=h,c=!0}if(i=n(o.call(this,s[1].trim(),a),a),i&&s[0]===e&&!Vt(i))return i;Vt(i)||(i=$R(i)),i||(this.logger.warn(`missed to resolve ${s[1]} for nesting ${e}`),i=""),c&&(i=l.reduce((h,p)=>this.format(h,p,r.lng,{...r,interpolationkey:s[1].trim()}),i.trim())),e=e.replace(s[0],i),this.regexp.lastIndex=0}return e}}const ene=t=>{let e=t.toLowerCase().trim();const n={};if(t.indexOf("(")>-1){const r=t.split("(");e=r[0].toLowerCase().trim();const s=r[1].substring(0,r[1].length-1);e==="currency"&&s.indexOf(":")<0?n.currency||(n.currency=s.trim()):e==="relativetime"&&s.indexOf(":")<0?n.range||(n.range=s.trim()):s.split(";").forEach(a=>{if(a){const[o,...l]=a.split(":"),c=l.join(":").trim().replace(/^'+|'+$/g,""),h=o.trim();n[h]||(n[h]=c),c==="false"&&(n[h]=!1),c==="true"&&(n[h]=!0),isNaN(c)||(n[h]=parseInt(c,10))}})}return{formatName:e,formatOptions:n}},Th=t=>{const e={};return(n,r,s)=>{let i=s;s&&s.interpolationkey&&s.formatParams&&s.formatParams[s.interpolationkey]&&s[s.interpolationkey]&&(i={...i,[s.interpolationkey]:void 0});const a=r+JSON.stringify(i);let o=e[a];return o||(o=t(Mv(r),s),e[a]=o),o(n)}};class tne{constructor(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};this.logger=Po.create("formatter"),this.options=e,this.formats={number:Th((n,r)=>{const s=new Intl.NumberFormat(n,{...r});return i=>s.format(i)}),currency:Th((n,r)=>{const s=new Intl.NumberFormat(n,{...r,style:"currency"});return i=>s.format(i)}),datetime:Th((n,r)=>{const s=new Intl.DateTimeFormat(n,{...r});return i=>s.format(i)}),relativetime:Th((n,r)=>{const s=new Intl.RelativeTimeFormat(n,{...r});return i=>s.format(i,r.range||"day")}),list:Th((n,r)=>{const s=new Intl.ListFormat(n,{...r});return i=>s.format(i)})},this.init(e)}init(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{interpolation:{}};this.formatSeparator=n.interpolation.formatSeparator||","}add(e,n){this.formats[e.toLowerCase().trim()]=n}addCached(e,n){this.formats[e.toLowerCase().trim()]=Th(n)}format(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};const i=n.split(this.formatSeparator);if(i.length>1&&i[0].indexOf("(")>1&&i[0].indexOf(")")<0&&i.find(o=>o.indexOf(")")>-1)){const o=i.findIndex(l=>l.indexOf(")")>-1);i[0]=[i[0],...i.splice(1,o)].join(this.formatSeparator)}return i.reduce((o,l)=>{const{formatName:c,formatOptions:h}=ene(l);if(this.formats[c]){let p=o;try{const m=s&&s.formatParams&&s.formatParams[s.interpolationkey]||{},g=m.locale||m.lng||s.locale||s.lng||r;p=this.formats[c](o,g,{...h,...s,...m})}catch(m){this.logger.warn(m)}return p}else this.logger.warn(`there was no format function for ${c}`);return o},e)}}const nne=(t,e)=>{t.pending[e]!==void 0&&(delete t.pending[e],t.pendingCount--)};class rne extends n1{constructor(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};super(),this.backend=e,this.store=n,this.services=r,this.languageUtils=r.languageUtils,this.options=s,this.logger=Po.create("backendConnector"),this.waitingReads=[],this.maxParallelReads=s.maxParallelReads||10,this.readingCalls=0,this.maxRetries=s.maxRetries>=0?s.maxRetries:5,this.retryTimeout=s.retryTimeout>=1?s.retryTimeout:350,this.state={},this.queue=[],this.backend&&this.backend.init&&this.backend.init(r,s.backend,s)}queueLoad(e,n,r,s){const i={},a={},o={},l={};return e.forEach(c=>{let h=!0;n.forEach(p=>{const m=`${c}|${p}`;!r.reload&&this.store.hasResourceBundle(c,p)?this.state[m]=2:this.state[m]<0||(this.state[m]===1?a[m]===void 0&&(a[m]=!0):(this.state[m]=1,h=!1,a[m]===void 0&&(a[m]=!0),i[m]===void 0&&(i[m]=!0),l[p]===void 0&&(l[p]=!0)))}),h||(o[c]=!0)}),(Object.keys(i).length||Object.keys(a).length)&&this.queue.push({pending:a,pendingCount:Object.keys(a).length,loaded:{},errors:[],callback:s}),{toLoad:Object.keys(i),pending:Object.keys(a),toLoadLanguages:Object.keys(o),toLoadNamespaces:Object.keys(l)}}loaded(e,n,r){const s=e.split("|"),i=s[0],a=s[1];n&&this.emit("failedLoading",i,a,n),!n&&r&&this.store.addResourceBundle(i,a,r,void 0,void 0,{skipCopy:!0}),this.state[e]=n?-1:2,n&&r&&(this.state[e]=0);const o={};this.queue.forEach(l=>{Ote(l.loaded,[i],a),nne(l,e),n&&l.errors.push(n),l.pendingCount===0&&!l.done&&(Object.keys(l.loaded).forEach(c=>{o[c]||(o[c]={});const h=l.loaded[c];h.length&&h.forEach(p=>{o[c][p]===void 0&&(o[c][p]=!0)})}),l.done=!0,l.errors.length?l.callback(l.errors):l.callback())}),this.emit("loaded",o),this.queue=this.queue.filter(l=>!l.done)}read(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:this.retryTimeout,a=arguments.length>5?arguments[5]:void 0;if(!e.length)return a(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:e,ns:n,fcName:r,tried:s,wait:i,callback:a});return}this.readingCalls++;const o=(c,h)=>{if(this.readingCalls--,this.waitingReads.length>0){const p=this.waitingReads.shift();this.read(p.lng,p.ns,p.fcName,p.tried,p.wait,p.callback)}if(c&&h&&s<this.maxRetries){setTimeout(()=>{this.read.call(this,e,n,r,s+1,i*2,a)},i);return}a(c,h)},l=this.backend[r].bind(this.backend);if(l.length===2){try{const c=l(e,n);c&&typeof c.then=="function"?c.then(h=>o(null,h)).catch(o):o(null,c)}catch(c){o(c)}return}return l(e,n,o)}prepareLoading(e,n){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},s=arguments.length>3?arguments[3]:void 0;if(!this.backend)return this.logger.warn("No backend was added via i18next.use. Will not load resources."),s&&s();Vt(e)&&(e=this.languageUtils.toResolveHierarchy(e)),Vt(n)&&(n=[n]);const i=this.queueLoad(e,n,r,s);if(!i.toLoad.length)return i.pending.length||s(),null;i.toLoad.forEach(a=>{this.loadOne(a)})}load(e,n,r){this.prepareLoading(e,n,{},r)}reload(e,n,r){this.prepareLoading(e,n,{reload:!0},r)}loadOne(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"";const r=e.split("|"),s=r[0],i=r[1];this.read(s,i,"read",void 0,void 0,(a,o)=>{a&&this.logger.warn(`${n}loading namespace ${i} for language ${s} failed`,a),!a&&o&&this.logger.log(`${n}loaded namespace ${i} for language ${s}`,o),this.loaded(e,a,o)})}saveMissing(e,n,r,s,i){let a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:{},o=arguments.length>6&&arguments[6]!==void 0?arguments[6]:()=>{};if(this.services.utils&&this.services.utils.hasLoadedNamespace&&!this.services.utils.hasLoadedNamespace(n)){this.logger.warn(`did not save key "${r}" as the namespace "${n}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");return}if(!(r==null||r==="")){if(this.backend&&this.backend.create){const l={...a,isUpdate:i},c=this.backend.create.bind(this.backend);if(c.length<6)try{let h;c.length===5?h=c(e,n,r,s,l):h=c(e,n,r,s),h&&typeof h.then=="function"?h.then(p=>o(null,p)).catch(o):o(null,h)}catch(h){o(h)}else c(e,n,r,s,o,l)}!e||!e[0]||this.store.addResource(e[0],n,r,s)}}}const XR=()=>({debug:!1,initImmediate:!0,ns:["translation"],defaultNS:["translation"],fallbackLng:["dev"],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:"all",preload:!1,simplifyPluralSuffix:!0,keySeparator:".",nsSeparator:":",pluralSeparator:"_",contextSeparator:"_",partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:"fallback",saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:t=>{let e={};if(typeof t[1]=="object"&&(e=t[1]),Vt(t[1])&&(e.defaultValue=t[1]),Vt(t[2])&&(e.tDescription=t[2]),typeof t[2]=="object"||typeof t[3]=="object"){const n=t[3]||t[2];Object.keys(n).forEach(r=>{e[r]=n[r]})}return e},interpolation:{escapeValue:!0,format:t=>t,prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!0}}),ZR=t=>(Vt(t.ns)&&(t.ns=[t.ns]),Vt(t.fallbackLng)&&(t.fallbackLng=[t.fallbackLng]),Vt(t.fallbackNS)&&(t.fallbackNS=[t.fallbackNS]),t.supportedLngs&&t.supportedLngs.indexOf("cimode")<0&&(t.supportedLngs=t.supportedLngs.concat(["cimode"])),t),ey=()=>{},sne=t=>{Object.getOwnPropertyNames(Object.getPrototypeOf(t)).forEach(n=>{typeof t[n]=="function"&&(t[n]=t[n].bind(t))})};class Cg extends n1{constructor(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0;if(super(),this.options=ZR(e),this.services={},this.logger=Po,this.modules={external:[]},sne(this),n&&!this.isInitialized&&!e.isClone){if(!this.options.initImmediate)return this.init(e,n),this;setTimeout(()=>{this.init(e,n)},0)}}init(){var e=this;let n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},r=arguments.length>1?arguments[1]:void 0;this.isInitializing=!0,typeof n=="function"&&(r=n,n={}),!n.defaultNS&&n.defaultNS!==!1&&n.ns&&(Vt(n.ns)?n.defaultNS=n.ns:n.ns.indexOf("translation")<0&&(n.defaultNS=n.ns[0]));const s=XR();this.options={...s,...this.options,...ZR(n)},this.options.compatibilityAPI!=="v1"&&(this.options.interpolation={...s.interpolation,...this.options.interpolation}),n.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=n.keySeparator),n.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=n.nsSeparator);const i=h=>h?typeof h=="function"?new h:h:null;if(!this.options.isClone){this.modules.logger?Po.init(i(this.modules.logger),this.options):Po.init(null,this.options);let h;this.modules.formatter?h=this.modules.formatter:typeof Intl<"u"&&(h=tne);const p=new KR(this.options);this.store=new WR(this.options.resources,this.options);const m=this.services;m.logger=Po,m.resourceStore=this.store,m.languageUtils=p,m.pluralResolver=new Zte(p,{prepend:this.options.pluralSeparator,compatibilityJSON:this.options.compatibilityJSON,simplifyPluralSuffix:this.options.simplifyPluralSuffix}),h&&(!this.options.interpolation.format||this.options.interpolation.format===s.interpolation.format)&&(m.formatter=i(h),m.formatter.init(m,this.options),this.options.interpolation.format=m.formatter.format.bind(m.formatter)),m.interpolator=new Yte(this.options),m.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},m.backendConnector=new rne(i(this.modules.backend),m.resourceStore,m,this.options),m.backendConnector.on("*",function(g){for(var y=arguments.length,x=new Array(y>1?y-1:0),v=1;v<y;v++)x[v-1]=arguments[v];e.emit(g,...x)}),this.modules.languageDetector&&(m.languageDetector=i(this.modules.languageDetector),m.languageDetector.init&&m.languageDetector.init(m,this.options.detection,this.options)),this.modules.i18nFormat&&(m.i18nFormat=i(this.modules.i18nFormat),m.i18nFormat.init&&m.i18nFormat.init(this)),this.translator=new Dv(this.services,this.options),this.translator.on("*",function(g){for(var y=arguments.length,x=new Array(y>1?y-1:0),v=1;v<y;v++)x[v-1]=arguments[v];e.emit(g,...x)}),this.modules.external.forEach(g=>{g.init&&g.init(this)})}if(this.format=this.options.interpolation.format,r||(r=ey),this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){const h=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);h.length>0&&h[0]!=="dev"&&(this.options.lng=h[0])}!this.services.languageDetector&&!this.options.lng&&this.logger.warn("init: no languageDetector is used and no lng is defined"),["getResource","hasResourceBundle","getResourceBundle","getDataByLanguage"].forEach(h=>{this[h]=function(){return e.store[h](...arguments)}}),["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(h=>{this[h]=function(){return e.store[h](...arguments),e}});const l=Jp(),c=()=>{const h=(p,m)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn("init: i18next is already initialized. You should call init just once!"),this.isInitialized=!0,this.options.isClone||this.logger.log("initialized",this.options),this.emit("initialized",this.options),l.resolve(m),r(p,m)};if(this.languages&&this.options.compatibilityAPI!=="v1"&&!this.isInitialized)return h(null,this.t.bind(this));this.changeLanguage(this.options.lng,h)};return this.options.resources||!this.options.initImmediate?c():setTimeout(c,0),l}loadResources(e){let r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:ey;const s=Vt(e)?e:this.language;if(typeof e=="function"&&(r=e),!this.options.resources||this.options.partialBundledLanguages){if(s&&s.toLowerCase()==="cimode"&&(!this.options.preload||this.options.preload.length===0))return r();const i=[],a=o=>{if(!o||o==="cimode")return;this.services.languageUtils.toResolveHierarchy(o).forEach(c=>{c!=="cimode"&&i.indexOf(c)<0&&i.push(c)})};s?a(s):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(l=>a(l)),this.options.preload&&this.options.preload.forEach(o=>a(o)),this.services.backendConnector.load(i,this.options.ns,o=>{!o&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),r(o)})}else r(null)}reloadResources(e,n,r){const s=Jp();return typeof e=="function"&&(r=e,e=void 0),typeof n=="function"&&(r=n,n=void 0),e||(e=this.languages),n||(n=this.options.ns),r||(r=ey),this.services.backendConnector.reload(e,n,i=>{s.resolve(),r(i)}),s}use(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(!e.type)throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()");return e.type==="backend"&&(this.modules.backend=e),(e.type==="logger"||e.log&&e.warn&&e.error)&&(this.modules.logger=e),e.type==="languageDetector"&&(this.modules.languageDetector=e),e.type==="i18nFormat"&&(this.modules.i18nFormat=e),e.type==="postProcessor"&&NO.addPostProcessor(e),e.type==="formatter"&&(this.modules.formatter=e),e.type==="3rdParty"&&this.modules.external.push(e),this}setResolvedLanguage(e){if(!(!e||!this.languages)&&!(["cimode","dev"].indexOf(e)>-1))for(let n=0;n<this.languages.length;n++){const r=this.languages[n];if(!(["cimode","dev"].indexOf(r)>-1)&&this.store.hasLanguageSomeTranslations(r)){this.resolvedLanguage=r;break}}}changeLanguage(e,n){var r=this;this.isLanguageChangingTo=e;const s=Jp();this.emit("languageChanging",e);const i=l=>{this.language=l,this.languages=this.services.languageUtils.toResolveHierarchy(l),this.resolvedLanguage=void 0,this.setResolvedLanguage(l)},a=(l,c)=>{c?(i(c),this.translator.changeLanguage(c),this.isLanguageChangingTo=void 0,this.emit("languageChanged",c),this.logger.log("languageChanged",c)):this.isLanguageChangingTo=void 0,s.resolve(function(){return r.t(...arguments)}),n&&n(l,function(){return r.t(...arguments)})},o=l=>{!e&&!l&&this.services.languageDetector&&(l=[]);const c=Vt(l)?l:this.services.languageUtils.getBestMatchFromCodes(l);c&&(this.language||i(c),this.translator.language||this.translator.changeLanguage(c),this.services.languageDetector&&this.services.languageDetector.cacheUserLanguage&&this.services.languageDetector.cacheUserLanguage(c)),this.loadResources(c,h=>{a(h,c)})};return!e&&this.services.languageDetector&&!this.services.languageDetector.async?o(this.services.languageDetector.detect()):!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(o):this.services.languageDetector.detect(o):o(e),s}getFixedT(e,n,r){var s=this;const i=function(a,o){let l;if(typeof o!="object"){for(var c=arguments.length,h=new Array(c>2?c-2:0),p=2;p<c;p++)h[p-2]=arguments[p];l=s.options.overloadTranslationOptionHandler([a,o].concat(h))}else l={...o};l.lng=l.lng||i.lng,l.lngs=l.lngs||i.lngs,l.ns=l.ns||i.ns,l.keyPrefix!==""&&(l.keyPrefix=l.keyPrefix||r||i.keyPrefix);const m=s.options.keySeparator||".";let g;return l.keyPrefix&&Array.isArray(a)?g=a.map(y=>`${l.keyPrefix}${m}${y}`):g=l.keyPrefix?`${l.keyPrefix}${m}${a}`:a,s.t(g,l)};return Vt(e)?i.lng=e:i.lngs=e,i.ns=n,i.keyPrefix=r,i}t(){return this.translator&&this.translator.translate(...arguments)}exists(){return this.translator&&this.translator.exists(...arguments)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(!this.isInitialized)return this.logger.warn("hasLoadedNamespace: i18next was not initialized",this.languages),!1;if(!this.languages||!this.languages.length)return this.logger.warn("hasLoadedNamespace: i18n.languages were undefined or empty",this.languages),!1;const r=n.lng||this.resolvedLanguage||this.languages[0],s=this.options?this.options.fallbackLng:!1,i=this.languages[this.languages.length-1];if(r.toLowerCase()==="cimode")return!0;const a=(o,l)=>{const c=this.services.backendConnector.state[`${o}|${l}`];return c===-1||c===0||c===2};if(n.precheck){const o=n.precheck(this,a);if(o!==void 0)return o}return!!(this.hasResourceBundle(r,e)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||a(r,e)&&(!s||a(i,e)))}loadNamespaces(e,n){const r=Jp();return this.options.ns?(Vt(e)&&(e=[e]),e.forEach(s=>{this.options.ns.indexOf(s)<0&&this.options.ns.push(s)}),this.loadResources(s=>{r.resolve(),n&&n(s)}),r):(n&&n(),Promise.resolve())}loadLanguages(e,n){const r=Jp();Vt(e)&&(e=[e]);const s=this.options.preload||[],i=e.filter(a=>s.indexOf(a)<0&&this.services.languageUtils.isSupportedCode(a));return i.length?(this.options.preload=s.concat(i),this.loadResources(a=>{r.resolve(),n&&n(a)}),r):(n&&n(),Promise.resolve())}dir(e){if(e||(e=this.resolvedLanguage||(this.languages&&this.languages.length>0?this.languages[0]:this.language)),!e)return"rtl";const n=["ar","shu","sqr","ssh","xaa","yhd","yud","aao","abh","abv","acm","acq","acw","acx","acy","adf","ads","aeb","aec","afb","ajp","apc","apd","arb","arq","ars","ary","arz","auz","avl","ayh","ayl","ayn","ayp","bbz","pga","he","iw","ps","pbt","pbu","pst","prp","prd","ug","ur","ydd","yds","yih","ji","yi","hbo","men","xmn","fa","jpr","peo","pes","prs","dv","sam","ckb"],r=this.services&&this.services.languageUtils||new KR(XR());return n.indexOf(r.getLanguagePartFromCode(e))>-1||e.toLowerCase().indexOf("-arab")>1?"rtl":"ltr"}static createInstance(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0;return new Cg(e,n)}cloneInstance(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:ey;const r=e.forkResourceStore;r&&delete e.forkResourceStore;const s={...this.options,...e,isClone:!0},i=new Cg(s);return(e.debug!==void 0||e.prefix!==void 0)&&(i.logger=i.logger.clone(e)),["store","services","language"].forEach(o=>{i[o]=this[o]}),i.services={...this.services},i.services.utils={hasLoadedNamespace:i.hasLoadedNamespace.bind(i)},r&&(i.store=new WR(this.store.data,s),i.services.resourceStore=i.store),i.translator=new Dv(i.services,s),i.translator.on("*",function(o){for(var l=arguments.length,c=new Array(l>1?l-1:0),h=1;h<l;h++)c[h-1]=arguments[h];i.emit(o,...c)}),i.init(s,n),i.translator.options=s,i.translator.backendConnector.services.utils={hasLoadedNamespace:i.hasLoadedNamespace.bind(i)},i}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}}const jt=Cg.createInstance();jt.createInstance=Cg.createInstance;jt.createInstance;jt.dir;jt.init;jt.loadResources;jt.reloadResources;jt.use;jt.changeLanguage;jt.getFixedT;jt.t;jt.exists;jt.setDefaultNamespace;jt.hasLoadedNamespace;jt.loadNamespaces;jt.loadLanguages;const ine={save:"Save",saving:"Saving…",saved:"Saved",cancel:"Cancel",delete:"Delete",deleting:"Deleting…",edit:"Edit",create:"Create",search:"Search",loading:"Loading…",yes:"Yes",no:"No",confirm:"Confirm",back:"Back",next:"Next",previous:"Previous",close:"Close",all:"All",none:"None",actions:"Actions",name:"Name",slug:"Slug",description:"Description",status:"Status",createdAt:"Created",updatedAt:"Updated",publishedAt:"Published",language:"Language",darkMode:"Dark mode",lightMode:"Light mode",signOut:"Sign out",administrator:"Administrator",editor:"Editor",appName:"Flexweg CMS"},ane={signIn:"Sign in",signingIn:"Signing in…",email:"Email",password:"Password",emailPlaceholder:"you@company.com",passwordPlaceholder:"••••••••",forgotPassword:"Forgot password?",resetEmailSent:"Password reset email sent to {{email}}.",enterEmailFirst:"Enter your email above first, then click reset.",emailPasswordRequired:"Email and password are required.",signInSubtitle:"Use your work email and password.",footer:"Account requests go through your administrator.",errors:{invalidEmail:"Invalid email address.",invalidCredentials:"Invalid email or password.",tooManyRequests:"Too many attempts. Try again later or reset your password.",userDisabled:"This account has been disabled.",networkFailed:"Network error. Check your connection.",generic:"Authentication failed."}},one={openMenu:"Open menu",closeMenu:"Close menu",dashboard:"Dashboard",posts:"Posts",pages:"Pages",taxonomies:"Categories & Tags",media:"Media",themes:"Themes",themeSettings:"Theme settings",plugins:"Plugins",menus:"Menus",users:"Users",settings:"Settings"},lne={title:"Dashboard",welcome:"Welcome back, {{email}}.",stats:{totalPosts:"Posts",totalPages:"Pages",online:"Online",drafts:"Drafts"}},cne={title:"Posts",newPost:"New post",noPosts:"No posts yet. Create your first one to get started.",noPostsInFilter:"No posts match the current filter.",search:{placeholder:"Search posts…",clear:"Clear search",noResults:"No posts match your search."},pagination:{previous:"Previous",next:"Next",showing:"Showing {{from}}–{{to}} of {{total}}",pageOf:"Page {{page}} of {{total}}"},bulk:{selectedCount_one:"{{count}} selected",selectedCount_other:"{{count}} selected",selectPage_one:"Select {{count}} on this page",selectPage_other:"Select all {{count}} on this page",deselectPage:"Deselect page",allOnPageSelected_one:"{{count}} on this page selected.",allOnPageSelected_other:"All {{count}} on this page selected.",selectAllMatching_one:"Select the {{count}} matching post",selectAllMatching_other:"Select all {{count}} matching posts",allMatchingSelected_one:"All {{count}} matching post selected.",allMatchingSelected_other:"All {{count}} matching posts selected.",selectOne:'Select "{{title}}"',publish:"Publish ({{count}})",publishing:"Publishing…",publishedCount:"Published {{ok}}, failed {{failed}}.",unpublish:"Unpublish ({{count}})",unpublishing:"Unpublishing…",unpublishedCount:"Unpublished {{ok}}, failed {{failed}}.",delete:"Delete",deleting:"Deleting…",deletedCount:"Deleted {{ok}}, failed {{failed}}.",confirmDelete_one:"Delete {{count}} post? This unpublishes from Flexweg and cannot be undone.",confirmDelete_other:"Delete {{count}} posts? This unpublishes from Flexweg and cannot be undone.",noDraftSelected:"No draft posts selected.",noOnlineSelected:"No online posts selected.",clear:"Clear selection"},filters:{all:"All",draft:"Draft",online:"Online"},fields:{title:"Title",slug:"Slug",excerpt:"Excerpt",content:"Content",category:"Category",tags:"Tags",heroImage:"Hero image",seoTitle:"SEO title",seoDescription:"SEO description",createdAt:"Created at",updatedAt:"Last updated",publishedAt:"Published at"},edit:{newTitle:"New post",editTitle:"Edit post",saved:"Saved.",savedAndRepublished:"Saved and republished.",saveFailed:"Save failed.",saveAndRepublish:"Save & republish",draftSaved:"Draft saved.",slugCollision:{post:'This URL is already used by post: "{{label}}".',page:'This URL is already used by page: "{{label}}".',category:'This URL is already used by category: "{{label}}".'},publish:"Publish",unpublish:"Unpublish",publishing:"Publishing…",unpublishing:"Unpublishing…",titlePlaceholder:"Add title",permalink:"Permalink",slugFormatHint:"Lower-case, ASCII, dash-separated only.",slugAutoSuffixed:'Auto-suffixed because "{{base}}" is already used by {{owner}}.',slugAutoSuffixedOwner:{post:'post: "{{label}}"',page:'page: "{{label}}"',category:'category: "{{label}}"'},saveBlocked:{titleRequired:"Add a title before saving.",slugRequired:"A title and URL slug are required to save.",slugInvalid:"Slug format is invalid (lower-case ASCII + dashes).",slugCollision:"Fix the URL conflict before saving."},viewPublished:"View",confirmDelete:"Delete this entry?",inspector:{document:"Document",block:"Block",blockEmpty:"Select a block in the editor to see its options.",publishing:"Publishing",permalink:"Permalink",categories:"Categories & tags",featured:"Featured image",seo:"SEO",excerpt:"Excerpt",dates:"Dates"},blocks:{addBlock:"Add block",transform:"Transform to",moveUp:"Move up",moveDown:"Move down",duplicate:"Duplicate",remove:"Delete block",paragraph:"Paragraph",heading2:"Heading 2",heading3:"Heading 3",bulletList:"Bullet list",orderedList:"Numbered list",blockquote:"Quote",codeBlock:"Code",image:"Image",horizontalRule:"Separator",categories:{text:"Text",media:"Media",layout:"Layout",embed:"Embeds",advanced:"Advanced"},noSettings:"This block has no settings.",noSelection:"Select a block in the editor to see its options.",slash:{noResults:"No matching block."}}},status:{draft:"Draft",online:"Online"},preview:{title:"Preview",rendering:"Rendering preview…",error:"Preview failed: {{error}}",viewports:{mobile:"Mobile",tablet:"Tablet",desktop:"Desktop"}}},une={title:"Pages",newPage:"New page",noPages:"No pages yet.",homeBadge:"Home",homeBadgeTooltip:"Used as the site's home page"},dne={title:"Categories & Tags",categories:"Categories",tags:"Tags",newCategory:"New category",newTag:"New tag",noCategories:"No categories yet.",noTags:"No tags yet.",slugCollision:'This slug is already used by "{{label}}".',seo:{button:"SEO",buttonTitle:"Edit SEO meta tags",title:"SEO meta tags",subtitle:'Custom title and description for the "{{name}}" archive page.',metaTitle:"Meta title",metaTitleHint:"Used as the page <title>. Defaults to the term name when blank.",metaDescription:"Meta description",metaDescriptionHint:"Used as the page meta description. Defaults to the term description when blank."}},hne={title:"Media library",upload:"Upload",uploading:"Uploading…",finalizing:"Finalizing…",uploadFailed:"Upload failed",retry:"Retry",noMedia:"No media yet.",alt:"Alt text",caption:"Caption",filename:"Filename",size:"Size",type:"Type"},fne={title:"Themes",active:"Active",activate:"Activate",installExternal:"Install theme",uninstallDisabledTitle:"Switch to another theme before uninstalling this one.",syncAssets:"Sync theme assets",regenerateSite:"Regenerate site",regenerating:"Regenerating…",regenerate:{button:"Regenerate",running:"Running…",groupBuiltins:"Site",groupPlugins:"Plugins",home:"Home page only",homeHelp:"Re-renders index.html only — fastest option.",allHtml:"All HTML pages",allHtmlHelp:"Every post, page, archive and listing — plus menu / posts / authors JSON snapshots.",repair:"Repair URLs",repairHelp:"Recompute every online post's canonical path and migrate files that landed at the wrong URL. Useful after an import that ran before terms had synced.",assets:"Theme assets",assetsHelp:"Pushes the active theme's CSS + companion scripts to /theme-assets/.",everything:"Everything",everythingHelp:"Theme assets + all HTML + every plugin output. Slowest option.",noPluginTargets:"No plugin regeneration targets — enable a plugin that supports regenerate."},confirmSwitch:{title:"Switch to {{theme}}?",body:"Switching theme requires re-uploading the theme's assets and regenerating every published page so the new look propagates everywhere. This may take a moment.",confirm:"Switch & regenerate",cancel:"Cancel"}},pne={title:"Plugins",enabled:"Enabled",disabled:"Disabled",enable:"Enable",disable:"Disable",configure:"Configure",author:"author",learnMore:"Learn more",mustUseBadge:"Must-use",installExternal:"Install plugin",tabs:{regular:"Plugins",mustUse:"Must-use"}},mne={titlePlugin:"Install a plugin",titleTheme:"Install a theme",labelPlugin:"plugin",labelTheme:"theme",intro:"Drop a ZIP file containing a {{label}} bundle (manifest.json + bundle.js at the ZIP root). The {{label}} will be uploaded to your Flexweg site and registered after a reload. Re-uploading a ZIP with the same manifest id upgrades the existing entry in place — no uninstall needed.",zipField:"Bundle ZIP file",install:"Install",installing:"Installing…",installSuccess:"{{name}} installed ({{count}} files uploaded). Reloading…",upgradeSuccess:"{{name}} upgraded from v{{previousVersion}} to v{{newVersion}} ({{count}} files uploaded). Reloading…",installedTitle:"Already installed",bundledDefaultsTitle:"Bundled defaults available",bundledDefaultsHint:"{{count}} bundled plugin/theme is currently uninstalled. Restore them to bring back what shipped with this admin version.",bundledDefaultsRestore:"Restore",bundledDefaultsRestored:"Restored {{plugins}} plugin(s) and {{themes}} theme(s). Reloading…",uninstall:"Uninstall",uninstallSuccess:"{{id}} uninstalled. Reloading…",confirmUninstall:"Uninstall {{id}}? Files will be deleted from Flexweg.",errors:{"no-manifest":"ZIP is missing manifest.json at its root.","invalid-manifest":"manifest.json is invalid (missing required fields or not valid JSON).","incompatible-api":"The bundle was built against an incompatible runtime API version.","no-bundle":"ZIP does not contain the entry file declared in the manifest.","fetch-manifest":"Could not read the current external.json on Flexweg.","upload-failed":"Upload failed — check your Flexweg API key + connection."}},gne={someFailed:"{{count}} external bundle(s) failed to load. Check the browser console."},bne={title:"Menus",header:"Header menu",footer:"Footer menu",label:"Label",saveAndPublish:"Save & generate",discard:"Discard",saved:"Menus saved and published.",saveFailed:"Could not save menus.",unsavedChanges:"You have unsaved changes."},yne={title:"Settings",tabs:{general:"General"},site:{title:"Site",siteTitle:"Site title",siteDescription:"Site description",siteLanguage:"Site language",siteLanguageHelp:'BCP-47 tag (e.g. en, fr-CA) injected into <html lang="…"> on every published page. The prefix is matched against supported translation locales for sitemap/RSS labels and theme-baked strings; unsupported locales fall back to English.',siteLanguageResolved:"Translations will use: {{label}}",baseUrl:"Public site URL",postsPerPage:"Posts per page",homeMode:"Home content",homeLatest:"Latest posts",homeStatic:"Static page",homePage:"Home page",discourageIndexing:"Discourage search engines from indexing this site",discourageIndexingHelp:"When enabled, every published page gets a noindex/nofollow meta tag and robots.txt is set to disallow all crawlers. Mirrors WordPress' behaviour — useful for staging sites or pre-launch reviews. Search engines that respect the directive will not index the site.",discourageRegenerateHint:"Indexing setting saved. Click 'Regenerate all' in Themes to apply the change to every published page and robots.txt."},flexweg:{title:"Flexweg API",apiKey:"API key",apiKeyHelp:"Generated from your Flexweg account → API.",siteUrl:"Site URL",siteUrlHelp:"Public URL of your Flexweg site without trailing slash.",apiBaseUrl:"API base URL",storageHelpFirebase:"Stored in Firestore (config/flexweg). Readable by any signed-in team member, writable by admins only.",storageHelpSqlite:"Stored in the local SQLite config table. Readable by any signed-in team member, writable by admins only."},backend:{title:"Data backend",active:"Active backend:",switchButton:"Switch backend…",confirmTitle:"All current data will be lost.",confirmBody:"Switching wipes the in-browser config and reloads into the setup form. The new backend starts empty — the previous backend's data stays where it was (in Firestore or as a .sqlite file on Flexweg), but the CMS will not read it anymore until you switch back.",confirmYes:"Yes, switch backend",downloadBackup:"Download a backup of the .sqlite file",downloadBackupHelp:"do this before switching backends.",markdownGit:"Markdown — {{source}}",localFolder:"local folder",localBrowser:"This browser (local, single user)",sqliteFile:"SQLite file — {{location}}"},performance:{title:"Performance",help:"How the admin loads posts and pages. Default works on the free Firestore plan with no setup; the paginated mode is for very large sites and requires a one-time index setup.",mode:"Loading mode",modeGlobal:"Standard (no setup required)",modePaginated:"Server-side paginated (requires Firestore indexes)",globalHelp:"Loads the whole posts collection in one live subscription. Sorting, filtering and search happen in memory. Best for sites under ~5 000 posts.",paginatedHelp:"Cursor-paginated subscriptions, one page at a time. Requires composite Firestore indexes — see README. Recommended for very large sites.",savedReload:"Saved. Reload the admin to apply the new mode."},editor:{title:"Editor",help:"Typography used inside the post / page editor. Independent of the public theme.",fontFamily:"Font family",bodySize:"Body size",h1Size:"H1 size",h2Size:"H2 size",h3Size:"H3 size",sizeHelp:"CSS length, e.g. 16px or 1rem. Leave empty for default.",reset:"Reset to defaults"},profile:{title:"Profile",adminLocale:"Admin language",adminLocaleHelp:"Language used by the admin interface. Saved to your profile.",firstName:"First name",lastName:"Last name",headline:"Title",headlinePlaceholder:"e.g. Senior Editor, Investigative Reporter…",headlineHelp:"Shown publicly under your name in author cards and on your archive page.",bio:"Bio",bioPlaceholder:"A short paragraph shown on your author page and below your articles.",bioHelp:"Visible on the public site in the author bio sidebar and the author archive page.",socials:"Social profiles",socialsHelp:'Add the URLs of the profiles you want to surface on the public site, then tick "Show" for the ones you want visible. Empty URLs are ignored.',socialsShow:"Show",socialsShowHelp:"Toggle the visibility of this network on the public site.",avatar:"Profile picture",avatarHelp:"Pick an image from your media library. Square images render best.",pickAvatar:"Pick from media",changeAvatar:"Change picture",removeAvatar:"Remove",save:"Save profile"},transfer:{title:"Move or back up content",help:"Export everything (posts, pages, categories, media metadata, profiles, settings) as one JSON file. On a Markdown or local backend you can import such a file, ids preserved — the way to migrate from Firebase or SQLite. Media files and secret keys are not included.",export:"Export content (JSON)",import:"Import content…",modeMerge:"Merge (overwrite same ids)",modeReplace:"Replace imported collections",replaceConfirm:"Replace mode deletes every existing item of the collections present in the file before importing. Continue?",invalidFile:"This file is not a Flexweg CMS content export.",imported:"Imported {{posts}} posts/pages, {{terms}} terms, {{media}} media. Run Regenerate → Everything to publish them."},encryption:{title:"Database encryption:",on:"on",off:"off",onHelp:"The database file is unreadable without the passphrase. Changing it re-saves the file with a new key; other browsers will ask for the new passphrase.",offHelp:"The database file is readable by anyone who can download it (a static host serves it like any page). Encrypt it with a passphrase.",enable:"Encrypt the database…",change:"Change the passphrase…",savedConfirm:"I saved this passphrase in my password manager — without it the content can't be opened.",enableConfirm:"Encrypt now",changeConfirm:"Change passphrase",done:"Database re-saved with the new passphrase."}},vne={title:"Users",noUsers:"No users yet.",role:"Role",disabled:"Disabled",editProfileTitle:"Edit profile — {{email}}",profileSaved:"Profile saved.",descriptionFirebase:"Manage your team. New accounts are created in the Firebase Console, then mirrored here on first sign-in.",descriptionSqlite:"Manage your team. Use the +Add user button below to create new accounts directly.",addUser:"Add user",addUserSuccess:"{{email}} added.",removeConfirmFirebase:"Delete the user record for {{email}}? This removes their profile + role from the CMS. To revoke sign-in access, also delete the account in the Firebase Console.",removeConfirmSqlite:"Permanently delete {{email}}? This revokes their sign-in access AND removes their profile + role. This cannot be undone.",empty:{title:"No team members yet",descriptionFirebase:"Create the first account in the Firebase Console, then sign in here once to register the profile.",descriptionSqlite:"Click +Add user above to invite the first team member."},help:{title:"How to add a new team member",bootstrapLine:"The bootstrap admin (always full access) is:",firebase:{step1:"Open the Firebase Console → Authentication → Add user.",step2:"Set an email and password and send them to the new team member.",step3:"Ask them to sign in here once — their profile appears in the list above and you can edit their role / details."},sqlite:{step1:"Click the +Add user button above.",step2:"Enter their email and a temporary password (8+ characters).",step3:"Share the credentials securely — they can change the password from their profile once signed in."},git:{step1:"Add the person as a collaborator of the content repository (write access = editor, admin / maintainer = admin).",step2:"They create their own personal access token on GitHub / GitLab.",step3:"They open the admin and sign in with that token — their profile is created here automatically."}},addUserModal:{title:"Add a new team member",intro:"Creates the account directly in the Flexweg SQLite Auth database. The new user defaults to the editor role; promote them from the list below if they need admin access.",submit:"Create user",submitting:"Creating…"},actions:{editProfile:"Edit profile",promote:"Promote to admin",demote:"Demote to editor",disable:"Disable",enable:"Enable",delete:"Delete record"},descriptionGit:"Team members are the people with write access to the content repository. They appear here after their first sign-in; their role follows their repository permissions.",descriptionLocal:"This admin runs in single-user mode: content is stored in this browser and there are no accounts.",descriptionSqliteFile:"No user accounts with this backend: anyone who can open the admin can edit. Protect the admin folder at your hosting level. Author profiles below are informational."},xne={title:"Firestore setup needed",intro:"The post and page list pages need a couple of Firestore composite indexes to query efficiently. They have to be created manually — Firebase reserves index creation for project admins.",checking:"Checking your Firestore indexes…",missingCount_one:"{{count}} index missing:",missingCount_other:"{{count}} indexes missing:",openConsole:"Open Firebase Console to create",noUrl:"Couldn't extract the auto-suggest URL — see the README for the gcloud command.",howItWorks:"How this works",step1:"Click the link for each missing index — Firebase Console opens with the index definition pre-filled.",step2:'Click "Create" and wait 1–5 minutes for the index to build (status badge in the console).',step3:"Come back here and click Retry. Once both queries succeed, the admin loads.",retry:"Retry",retrying:"Retrying…",buildHint:"Indexes can take up to a few minutes to build after creation.",allReady:"All indexes ready.",unexpectedTitle:"Couldn't reach Firestore",unexpectedHint:"Check your network connection and Firestore rules. If you just created the indexes, wait a moment for them to finish building, then retry."},wne={appError:"Application error",loadAccountFailed:"Could not load your account",loadAccountHint:"If the problem persists, sign out and try again.",accountDisabled:"Account disabled",accountDisabledMessage:"Your access to this CMS has been disabled. Contact your administrator.",firebaseNotConfigured:"Firebase is not configured",firebaseEnvMissing:`The following env variables are missing:
|
|
3847
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[e,t.type,t.name,t.slug,t.description??null,t.parentId??null,n,n,null,null,null]),Ir(),e}async function Pte(t,e){const n=[],r=[];if(e.name!==void 0&&(n.push("name = ?"),r.push(e.name)),e.slug!==void 0&&(n.push("slug = ?"),r.push(e.slug)),e.description!==void 0&&(n.push("description = ?"),r.push(e.description??null)),e.parentId!==void 0&&(n.push("parent_id = ?"),r.push(e.parentId??null)),e.translations!==void 0&&(n.push("translations = ?"),r.push(e.translations&&Object.keys(e.translations).length>0?JSON.stringify(e.translations):null)),e.seo!==void 0){n.push("seo = ?");const s=e.seo,i=s&&(s.title||s.description||s.ogImage);r.push(i?JSON.stringify(s):null)}n.push("updated_at = ?"),r.push(Date.now()),r.push(t),await Kn(`UPDATE terms SET ${n.join(", ")} WHERE id = ?`,r),Ir()}async function Rte(t){await Kn("DELETE FROM terms WHERE id = ?",[t]),Ir()}const jte=Object.freeze(Object.defineProperty({__proto__:null,createTerm:Nte,deleteTerm:Rte,fetchAllTerms:Ite,subscribeToTerms:Tte,updateTerm:Pte},Symbol.toStringTag,{value:"Module"})),Tu=["posts","terms","media","users","settings","config"];class e_ extends Error{constructor(e,n,r){super(e),this.collection=n,this.id=r,this.name="DocConflictError"}}function E0(){return Object.fromEntries(Tu.map(t=>[t,new Map]))}function TO(t){return Object.fromEntries(Tu.map(e=>[e,new Map(t[e])]))}function t_(t){if(Array.isArray(t))return Object.freeze(t.map(t_));if(t&&typeof t=="object"&&Object.getPrototypeOf(t)===Object.prototype){const e={};for(const[n,r]of Object.entries(t))r!==void 0&&(e[n]=t_(r));return Object.freeze(e)}return t}function Mte(t,e){const n=TO(t),r=new Set;for(const s of e)s.op==="set"?n[s.collection].set(s.doc.id,t_(s.doc)):n[s.collection].delete(s.id),r.add(s.collection);return{next:n,changed:r}}function Lte(t,e){const n=new Set;for(const r of Tu){if(t[r].size!==e[r].size){n.add(r);continue}for(const[s,i]of t[r]){const a=e[r].get(s);if(!a||JSON.stringify(a)!==JSON.stringify(i)){n.add(r);break}}}return n}function GA(t){let e=E0(),n=null,r=Promise.resolve(),s=0;const i=new Set;let a=null;function o(m){if(m.size!==0)for(const g of[...i])try{g(m)}catch(y){console.error("[docstore] listener failed:",y)}}function l(){return n||(n=t.load().then(m=>{e=m,o(new Set(Tu))},m=>{throw n=null,m})),n}async function c(){if(await l(),!t.poll||s>0)return;const m=await t.poll();if(!m||s>0)return;const g=Lte(e,m);e=m,o(g)}function h(){a||!t.poll||(a=setInterval(()=>{c().catch(m=>console.warn("[docstore] poll failed:",m))},t.pollIntervalMs??3e4))}function p(){a&&clearInterval(a),a=null}return{kind:t.kind,ready:l,refresh:c,identity:()=>t.identity(),list(m){return[...e[m].values()]},get(m,g){return e[m].get(g)},async write(m,g){if(await l(),m.length===0)return;const y=e,{next:x,changed:v}=Mte(y,m);e=x,o(v),s++;const k=r.then(()=>t.persist(m,y,x,(g==null?void 0:g.message)??"Update content"));r=k.catch(()=>{});try{await k}catch(C){const N=TO(e);for(const _ of m){const P=_.op==="set"?_.doc.id:_.id,D=y[_.collection].get(P);D?N[_.collection].set(P,D):N[_.collection].delete(P)}throw e=N,o(v),C}finally{s--}},subscribe(m){return i.add(m),h(),()=>{i.delete(m),i.size===0&&p()}}}}const Vt=t=>typeof t=="string",Jp=()=>{let t,e;const n=new Promise((r,s)=>{t=r,e=s});return n.resolve=t,n.reject=e,n},$R=t=>t==null?"":""+t,Dte=(t,e,n)=>{t.forEach(r=>{e[r]&&(n[r]=e[r])})},Fte=/###/g,HR=t=>t&&t.indexOf("###")>-1?t.replace(Fte,"."):t,VR=t=>!t||Vt(t),Om=(t,e,n)=>{const r=Vt(e)?e.split("."):e;let s=0;for(;s<r.length-1;){if(VR(t))return{};const i=HR(r[s]);!t[i]&&n&&(t[i]=new n),Object.prototype.hasOwnProperty.call(t,i)?t=t[i]:t={},++s}return VR(t)?{}:{obj:t,k:HR(r[s])}},qR=(t,e,n)=>{const{obj:r,k:s}=Om(t,e,Object);if(r!==void 0||e.length===1){r[s]=n;return}let i=e[e.length-1],a=e.slice(0,e.length-1),o=Om(t,a,Object);for(;o.obj===void 0&&a.length;)i=`${a[a.length-1]}.${i}`,a=a.slice(0,a.length-1),o=Om(t,a,Object),o&&o.obj&&typeof o.obj[`${o.k}.${i}`]<"u"&&(o.obj=void 0);o.obj[`${o.k}.${i}`]=n},Ote=(t,e,n,r)=>{const{obj:s,k:i}=Om(t,e,Object);s[i]=s[i]||[],s[i].push(n)},jv=(t,e)=>{const{obj:n,k:r}=Om(t,e);if(n)return n[r]},zte=(t,e,n)=>{const r=jv(t,n);return r!==void 0?r:jv(e,n)},IO=(t,e,n)=>{for(const r in e)r!=="__proto__"&&r!=="constructor"&&(r in t?Vt(t[r])||t[r]instanceof String||Vt(e[r])||e[r]instanceof String?n&&(t[r]=e[r]):IO(t[r],e[r],n):t[r]=e[r]);return t},Ah=t=>t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&");var Ute={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};const Bte=t=>Vt(t)?t.replace(/[&<>"'\/]/g,e=>Ute[e]):t;class $te{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){const n=this.regExpMap.get(e);if(n!==void 0)return n;const r=new RegExp(e);return this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,r),this.regExpQueue.push(e),r}}const Hte=[" ",",","?","!",";"],Vte=new $te(20),qte=(t,e,n)=>{e=e||"",n=n||"";const r=Hte.filter(a=>e.indexOf(a)<0&&n.indexOf(a)<0);if(r.length===0)return!0;const s=Vte.getRegExp(`(${r.map(a=>a==="?"?"\\?":a).join("|")})`);let i=!s.test(t);if(!i){const a=t.indexOf(n);a>0&&!s.test(t.substring(0,a))&&(i=!0)}return i},n_=function(t,e){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:".";if(!t)return;if(t[e])return t[e];const r=e.split(n);let s=t;for(let i=0;i<r.length;){if(!s||typeof s!="object")return;let a,o="";for(let l=i;l<r.length;++l)if(l!==i&&(o+=n),o+=r[l],a=s[o],a!==void 0){if(["string","number","boolean"].indexOf(typeof a)>-1&&l<r.length-1)continue;i+=l-i+1;break}s=a}return s},Mv=t=>t&&t.replace("_","-"),Wte={type:"logger",log(t){this.output("log",t)},warn(t){this.output("warn",t)},error(t){this.output("error",t)},output(t,e){console&&console[t]&&console[t].apply(console,e)}};class Lv{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.init(e,n)}init(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.prefix=n.prefix||"i18next:",this.logger=e||Wte,this.options=n,this.debug=n.debug}log(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return this.forward(n,"log","",!0)}warn(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return this.forward(n,"warn","",!0)}error(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return this.forward(n,"error","")}deprecate(){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];return this.forward(n,"warn","WARNING DEPRECATED: ",!0)}forward(e,n,r,s){return s&&!this.debug?null:(Vt(e[0])&&(e[0]=`${r}${this.prefix} ${e[0]}`),this.logger[n](e))}create(e){return new Lv(this.logger,{prefix:`${this.prefix}:${e}:`,...this.options})}clone(e){return e=e||this.options,e.prefix=e.prefix||this.prefix,new Lv(this.logger,e)}}var Po=new Lv;let n1=class{constructor(){this.observers={}}on(e,n){return e.split(" ").forEach(r=>{this.observers[r]||(this.observers[r]=new Map);const s=this.observers[r].get(n)||0;this.observers[r].set(n,s+1)}),this}off(e,n){if(this.observers[e]){if(!n){delete this.observers[e];return}this.observers[e].delete(n)}}emit(e){for(var n=arguments.length,r=new Array(n>1?n-1:0),s=1;s<n;s++)r[s-1]=arguments[s];this.observers[e]&&Array.from(this.observers[e].entries()).forEach(a=>{let[o,l]=a;for(let c=0;c<l;c++)o(...r)}),this.observers["*"]&&Array.from(this.observers["*"].entries()).forEach(a=>{let[o,l]=a;for(let c=0;c<l;c++)o.apply(o,[e,...r])})}};class WR extends n1{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{ns:["translation"],defaultNS:"translation"};super(),this.data=e||{},this.options=n,this.options.keySeparator===void 0&&(this.options.keySeparator="."),this.options.ignoreJSONStructure===void 0&&(this.options.ignoreJSONStructure=!0)}addNamespaces(e){this.options.ns.indexOf(e)<0&&this.options.ns.push(e)}removeNamespaces(e){const n=this.options.ns.indexOf(e);n>-1&&this.options.ns.splice(n,1)}getResource(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};const i=s.keySeparator!==void 0?s.keySeparator:this.options.keySeparator,a=s.ignoreJSONStructure!==void 0?s.ignoreJSONStructure:this.options.ignoreJSONStructure;let o;e.indexOf(".")>-1?o=e.split("."):(o=[e,n],r&&(Array.isArray(r)?o.push(...r):Vt(r)&&i?o.push(...r.split(i)):o.push(r)));const l=jv(this.data,o);return!l&&!n&&!r&&e.indexOf(".")>-1&&(e=o[0],n=o[1],r=o.slice(2).join(".")),l||!a||!Vt(r)?l:n_(this.data&&this.data[e]&&this.data[e][n],r,i)}addResource(e,n,r,s){let i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:{silent:!1};const a=i.keySeparator!==void 0?i.keySeparator:this.options.keySeparator;let o=[e,n];r&&(o=o.concat(a?r.split(a):r)),e.indexOf(".")>-1&&(o=e.split("."),s=n,n=o[1]),this.addNamespaces(n),qR(this.data,o,s),i.silent||this.emit("added",e,n,r,s)}addResources(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{silent:!1};for(const i in r)(Vt(r[i])||Array.isArray(r[i]))&&this.addResource(e,n,i,r[i],{silent:!0});s.silent||this.emit("added",e,n,r)}addResourceBundle(e,n,r,s,i){let a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:{silent:!1,skipCopy:!1},o=[e,n];e.indexOf(".")>-1&&(o=e.split("."),s=r,r=n,n=o[1]),this.addNamespaces(n);let l=jv(this.data,o)||{};a.skipCopy||(r=JSON.parse(JSON.stringify(r))),s?IO(l,r,i):l={...l,...r},qR(this.data,o,l),a.silent||this.emit("added",e,n,r)}removeResourceBundle(e,n){this.hasResourceBundle(e,n)&&delete this.data[e][n],this.removeNamespaces(n),this.emit("removed",e,n)}hasResourceBundle(e,n){return this.getResource(e,n)!==void 0}getResourceBundle(e,n){return n||(n=this.options.defaultNS),this.options.compatibilityAPI==="v1"?{...this.getResource(e,n)}:this.getResource(e,n)}getDataByLanguage(e){return this.data[e]}hasLanguageSomeTranslations(e){const n=this.getDataByLanguage(e);return!!(n&&Object.keys(n)||[]).find(s=>n[s]&&Object.keys(n[s]).length>0)}toJSON(){return this.data}}var NO={processors:{},addPostProcessor(t){this.processors[t.name]=t},handle(t,e,n,r,s){return t.forEach(i=>{this.processors[i]&&(e=this.processors[i].process(e,n,r,s))}),e}};const GR={};class Dv extends n1{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};super(),Dte(["resourceStore","languageUtils","pluralResolver","interpolator","backendConnector","i18nFormat","utils"],e,this),this.options=n,this.options.keySeparator===void 0&&(this.options.keySeparator="."),this.logger=Po.create("translator")}changeLanguage(e){e&&(this.language=e)}exists(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{interpolation:{}};if(e==null)return!1;const r=this.resolve(e,n);return r&&r.res!==void 0}extractFromKey(e,n){let r=n.nsSeparator!==void 0?n.nsSeparator:this.options.nsSeparator;r===void 0&&(r=":");const s=n.keySeparator!==void 0?n.keySeparator:this.options.keySeparator;let i=n.ns||this.options.defaultNS||[];const a=r&&e.indexOf(r)>-1,o=!this.options.userDefinedKeySeparator&&!n.keySeparator&&!this.options.userDefinedNsSeparator&&!n.nsSeparator&&!qte(e,r,s);if(a&&!o){const l=e.match(this.interpolator.nestingRegexp);if(l&&l.length>0)return{key:e,namespaces:Vt(i)?[i]:i};const c=e.split(r);(r!==s||r===s&&this.options.ns.indexOf(c[0])>-1)&&(i=c.shift()),e=c.join(s)}return{key:e,namespaces:Vt(i)?[i]:i}}translate(e,n,r){if(typeof n!="object"&&this.options.overloadTranslationOptionHandler&&(n=this.options.overloadTranslationOptionHandler(arguments)),typeof n=="object"&&(n={...n}),n||(n={}),e==null)return"";Array.isArray(e)||(e=[String(e)]);const s=n.returnDetails!==void 0?n.returnDetails:this.options.returnDetails,i=n.keySeparator!==void 0?n.keySeparator:this.options.keySeparator,{key:a,namespaces:o}=this.extractFromKey(e[e.length-1],n),l=o[o.length-1],c=n.lng||this.language,h=n.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(c&&c.toLowerCase()==="cimode"){if(h){const _=n.nsSeparator||this.options.nsSeparator;return s?{res:`${l}${_}${a}`,usedKey:a,exactUsedKey:a,usedLng:c,usedNS:l,usedParams:this.getUsedParamsDetails(n)}:`${l}${_}${a}`}return s?{res:a,usedKey:a,exactUsedKey:a,usedLng:c,usedNS:l,usedParams:this.getUsedParamsDetails(n)}:a}const p=this.resolve(e,n);let m=p&&p.res;const g=p&&p.usedKey||a,y=p&&p.exactUsedKey||a,x=Object.prototype.toString.apply(m),v=["[object Number]","[object Function]","[object RegExp]"],k=n.joinArrays!==void 0?n.joinArrays:this.options.joinArrays,C=!this.i18nFormat||this.i18nFormat.handleAsObject,N=!Vt(m)&&typeof m!="boolean"&&typeof m!="number";if(C&&m&&N&&v.indexOf(x)<0&&!(Vt(k)&&Array.isArray(m))){if(!n.returnObjects&&!this.options.returnObjects){this.options.returnedObjectHandler||this.logger.warn("accessing an object - but returnObjects options is not enabled!");const _=this.options.returnedObjectHandler?this.options.returnedObjectHandler(g,m,{...n,ns:o}):`key '${a} (${this.language})' returned an object instead of string.`;return s?(p.res=_,p.usedParams=this.getUsedParamsDetails(n),p):_}if(i){const _=Array.isArray(m),P=_?[]:{},D=_?y:g;for(const I in m)if(Object.prototype.hasOwnProperty.call(m,I)){const L=`${D}${i}${I}`;P[I]=this.translate(L,{...n,joinArrays:!1,ns:o}),P[I]===L&&(P[I]=m[I])}m=P}}else if(C&&Vt(k)&&Array.isArray(m))m=m.join(k),m&&(m=this.extendTranslation(m,e,n,r));else{let _=!1,P=!1;const D=n.count!==void 0&&!Vt(n.count),I=Dv.hasDefaultValue(n),L=D?this.pluralResolver.getSuffix(c,n.count,n):"",j=n.ordinal&&D?this.pluralResolver.getSuffix(c,n.count,{ordinal:!1}):"",q=D&&!n.ordinal&&n.count===0&&this.pluralResolver.shouldUseIntlApi(),V=q&&n[`defaultValue${this.options.pluralSeparator}zero`]||n[`defaultValue${L}`]||n[`defaultValue${j}`]||n.defaultValue;!this.isValidLookup(m)&&I&&(_=!0,m=V),this.isValidLookup(m)||(P=!0,m=a);const $=(n.missingKeyNoValueFallbackToKey||this.options.missingKeyNoValueFallbackToKey)&&P?void 0:m,B=I&&V!==m&&this.options.updateMissing;if(P||_||B){if(this.logger.log(B?"updateKey":"missingKey",c,l,a,B?V:m),i){const ae=this.resolve(a,{...n,keySeparator:!1});ae&&ae.res&&this.logger.warn("Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.")}let X=[];const fe=this.languageUtils.getFallbackCodes(this.options.fallbackLng,n.lng||this.language);if(this.options.saveMissingTo==="fallback"&&fe&&fe[0])for(let ae=0;ae<fe.length;ae++)X.push(fe[ae]);else this.options.saveMissingTo==="all"?X=this.languageUtils.toResolveHierarchy(n.lng||this.language):X.push(n.lng||this.language);const ie=(ae,ue,ve)=>{const K=I&&ve!==m?ve:$;this.options.missingKeyHandler?this.options.missingKeyHandler(ae,l,ue,K,B,n):this.backendConnector&&this.backendConnector.saveMissing&&this.backendConnector.saveMissing(ae,l,ue,K,B,n),this.emit("missingKey",ae,l,ue,m)};this.options.saveMissing&&(this.options.saveMissingPlurals&&D?X.forEach(ae=>{const ue=this.pluralResolver.getSuffixes(ae,n);q&&n[`defaultValue${this.options.pluralSeparator}zero`]&&ue.indexOf(`${this.options.pluralSeparator}zero`)<0&&ue.push(`${this.options.pluralSeparator}zero`),ue.forEach(ve=>{ie([ae],a+ve,n[`defaultValue${ve}`]||V)})}):ie(X,a,V))}m=this.extendTranslation(m,e,n,p,r),P&&m===a&&this.options.appendNamespaceToMissingKey&&(m=`${l}:${a}`),(P||_)&&this.options.parseMissingKeyHandler&&(this.options.compatibilityAPI!=="v1"?m=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${l}:${a}`:a,_?m:void 0):m=this.options.parseMissingKeyHandler(m))}return s?(p.res=m,p.usedParams=this.getUsedParamsDetails(n),p):m}extendTranslation(e,n,r,s,i){var a=this;if(this.i18nFormat&&this.i18nFormat.parse)e=this.i18nFormat.parse(e,{...this.options.interpolation.defaultVariables,...r},r.lng||this.language||s.usedLng,s.usedNS,s.usedKey,{resolved:s});else if(!r.skipInterpolation){r.interpolation&&this.interpolator.init({...r,interpolation:{...this.options.interpolation,...r.interpolation}});const c=Vt(e)&&(r&&r.interpolation&&r.interpolation.skipOnVariables!==void 0?r.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables);let h;if(c){const m=e.match(this.interpolator.nestingRegexp);h=m&&m.length}let p=r.replace&&!Vt(r.replace)?r.replace:r;if(this.options.interpolation.defaultVariables&&(p={...this.options.interpolation.defaultVariables,...p}),e=this.interpolator.interpolate(e,p,r.lng||this.language||s.usedLng,r),c){const m=e.match(this.interpolator.nestingRegexp),g=m&&m.length;h<g&&(r.nest=!1)}!r.lng&&this.options.compatibilityAPI!=="v1"&&s&&s.res&&(r.lng=this.language||s.usedLng),r.nest!==!1&&(e=this.interpolator.nest(e,function(){for(var m=arguments.length,g=new Array(m),y=0;y<m;y++)g[y]=arguments[y];return i&&i[0]===g[0]&&!r.context?(a.logger.warn(`It seems you are nesting recursively key: ${g[0]} in key: ${n[0]}`),null):a.translate(...g,n)},r)),r.interpolation&&this.interpolator.reset()}const o=r.postProcess||this.options.postProcess,l=Vt(o)?[o]:o;return e!=null&&l&&l.length&&r.applyPostProcessor!==!1&&(e=NO.handle(l,e,n,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...s,usedParams:this.getUsedParamsDetails(r)},...r}:r,this)),e}resolve(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r,s,i,a,o;return Vt(e)&&(e=[e]),e.forEach(l=>{if(this.isValidLookup(r))return;const c=this.extractFromKey(l,n),h=c.key;s=h;let p=c.namespaces;this.options.fallbackNS&&(p=p.concat(this.options.fallbackNS));const m=n.count!==void 0&&!Vt(n.count),g=m&&!n.ordinal&&n.count===0&&this.pluralResolver.shouldUseIntlApi(),y=n.context!==void 0&&(Vt(n.context)||typeof n.context=="number")&&n.context!=="",x=n.lngs?n.lngs:this.languageUtils.toResolveHierarchy(n.lng||this.language,n.fallbackLng);p.forEach(v=>{this.isValidLookup(r)||(o=v,!GR[`${x[0]}-${v}`]&&this.utils&&this.utils.hasLoadedNamespace&&!this.utils.hasLoadedNamespace(o)&&(GR[`${x[0]}-${v}`]=!0,this.logger.warn(`key "${s}" for languages "${x.join(", ")}" won't get resolved as namespace "${o}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!")),x.forEach(k=>{if(this.isValidLookup(r))return;a=k;const C=[h];if(this.i18nFormat&&this.i18nFormat.addLookupKeys)this.i18nFormat.addLookupKeys(C,h,k,v,n);else{let _;m&&(_=this.pluralResolver.getSuffix(k,n.count,n));const P=`${this.options.pluralSeparator}zero`,D=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(m&&(C.push(h+_),n.ordinal&&_.indexOf(D)===0&&C.push(h+_.replace(D,this.options.pluralSeparator)),g&&C.push(h+P)),y){const I=`${h}${this.options.contextSeparator}${n.context}`;C.push(I),m&&(C.push(I+_),n.ordinal&&_.indexOf(D)===0&&C.push(I+_.replace(D,this.options.pluralSeparator)),g&&C.push(I+P))}}let N;for(;N=C.pop();)this.isValidLookup(r)||(i=N,r=this.getResource(k,v,N,n))}))})}),{res:r,usedKey:s,exactUsedKey:i,usedLng:a,usedNS:o}}isValidLookup(e){return e!==void 0&&!(!this.options.returnNull&&e===null)&&!(!this.options.returnEmptyString&&e==="")}getResource(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};return this.i18nFormat&&this.i18nFormat.getResource?this.i18nFormat.getResource(e,n,r,s):this.resourceStore.getResource(e,n,r,s)}getUsedParamsDetails(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};const n=["defaultValue","ordinal","context","replace","lng","lngs","fallbackLng","ns","keySeparator","nsSeparator","returnObjects","returnDetails","joinArrays","postProcess","interpolation"],r=e.replace&&!Vt(e.replace);let s=r?e.replace:e;if(r&&typeof e.count<"u"&&(s.count=e.count),this.options.interpolation.defaultVariables&&(s={...this.options.interpolation.defaultVariables,...s}),!r){s={...s};for(const i of n)delete s[i]}return s}static hasDefaultValue(e){const n="defaultValue";for(const r in e)if(Object.prototype.hasOwnProperty.call(e,r)&&n===r.substring(0,n.length)&&e[r]!==void 0)return!0;return!1}}const $S=t=>t.charAt(0).toUpperCase()+t.slice(1);class KR{constructor(e){this.options=e,this.supportedLngs=this.options.supportedLngs||!1,this.logger=Po.create("languageUtils")}getScriptPartFromCode(e){if(e=Mv(e),!e||e.indexOf("-")<0)return null;const n=e.split("-");return n.length===2||(n.pop(),n[n.length-1].toLowerCase()==="x")?null:this.formatLanguageCode(n.join("-"))}getLanguagePartFromCode(e){if(e=Mv(e),!e||e.indexOf("-")<0)return e;const n=e.split("-");return this.formatLanguageCode(n[0])}formatLanguageCode(e){if(Vt(e)&&e.indexOf("-")>-1){if(typeof Intl<"u"&&typeof Intl.getCanonicalLocales<"u")try{let s=Intl.getCanonicalLocales(e)[0];if(s&&this.options.lowerCaseLng&&(s=s.toLowerCase()),s)return s}catch{}const n=["hans","hant","latn","cyrl","cans","mong","arab"];let r=e.split("-");return this.options.lowerCaseLng?r=r.map(s=>s.toLowerCase()):r.length===2?(r[0]=r[0].toLowerCase(),r[1]=r[1].toUpperCase(),n.indexOf(r[1].toLowerCase())>-1&&(r[1]=$S(r[1].toLowerCase()))):r.length===3&&(r[0]=r[0].toLowerCase(),r[1].length===2&&(r[1]=r[1].toUpperCase()),r[0]!=="sgn"&&r[2].length===2&&(r[2]=r[2].toUpperCase()),n.indexOf(r[1].toLowerCase())>-1&&(r[1]=$S(r[1].toLowerCase())),n.indexOf(r[2].toLowerCase())>-1&&(r[2]=$S(r[2].toLowerCase()))),r.join("-")}return this.options.cleanCode||this.options.lowerCaseLng?e.toLowerCase():e}isSupportedCode(e){return(this.options.load==="languageOnly"||this.options.nonExplicitSupportedLngs)&&(e=this.getLanguagePartFromCode(e)),!this.supportedLngs||!this.supportedLngs.length||this.supportedLngs.indexOf(e)>-1}getBestMatchFromCodes(e){if(!e)return null;let n;return e.forEach(r=>{if(n)return;const s=this.formatLanguageCode(r);(!this.options.supportedLngs||this.isSupportedCode(s))&&(n=s)}),!n&&this.options.supportedLngs&&e.forEach(r=>{if(n)return;const s=this.getLanguagePartFromCode(r);if(this.isSupportedCode(s))return n=s;n=this.options.supportedLngs.find(i=>{if(i===s)return i;if(!(i.indexOf("-")<0&&s.indexOf("-")<0)&&(i.indexOf("-")>0&&s.indexOf("-")<0&&i.substring(0,i.indexOf("-"))===s||i.indexOf(s)===0&&s.length>1))return i})}),n||(n=this.getFallbackCodes(this.options.fallbackLng)[0]),n}getFallbackCodes(e,n){if(!e)return[];if(typeof e=="function"&&(e=e(n)),Vt(e)&&(e=[e]),Array.isArray(e))return e;if(!n)return e.default||[];let r=e[n];return r||(r=e[this.getScriptPartFromCode(n)]),r||(r=e[this.formatLanguageCode(n)]),r||(r=e[this.getLanguagePartFromCode(n)]),r||(r=e.default),r||[]}toResolveHierarchy(e,n){const r=this.getFallbackCodes(n||this.options.fallbackLng||[],e),s=[],i=a=>{a&&(this.isSupportedCode(a)?s.push(a):this.logger.warn(`rejecting language code not found in supportedLngs: ${a}`))};return Vt(e)&&(e.indexOf("-")>-1||e.indexOf("_")>-1)?(this.options.load!=="languageOnly"&&i(this.formatLanguageCode(e)),this.options.load!=="languageOnly"&&this.options.load!=="currentOnly"&&i(this.getScriptPartFromCode(e)),this.options.load!=="currentOnly"&&i(this.getLanguagePartFromCode(e))):Vt(e)&&i(this.formatLanguageCode(e)),r.forEach(a=>{s.indexOf(a)<0&&i(this.formatLanguageCode(a))}),s}}let Gte=[{lngs:["ach","ak","am","arn","br","fil","gun","ln","mfe","mg","mi","oc","pt","pt-BR","tg","tl","ti","tr","uz","wa"],nr:[1,2],fc:1},{lngs:["af","an","ast","az","bg","bn","ca","da","de","dev","el","en","eo","es","et","eu","fi","fo","fur","fy","gl","gu","ha","hi","hu","hy","ia","it","kk","kn","ku","lb","mai","ml","mn","mr","nah","nap","nb","ne","nl","nn","no","nso","pa","pap","pms","ps","pt-PT","rm","sco","se","si","so","son","sq","sv","sw","ta","te","tk","ur","yo"],nr:[1,2],fc:2},{lngs:["ay","bo","cgg","fa","ht","id","ja","jbo","ka","km","ko","ky","lo","ms","sah","su","th","tt","ug","vi","wo","zh"],nr:[1],fc:3},{lngs:["be","bs","cnr","dz","hr","ru","sr","uk"],nr:[1,2,5],fc:4},{lngs:["ar"],nr:[0,1,2,3,11,100],fc:5},{lngs:["cs","sk"],nr:[1,2,5],fc:6},{lngs:["csb","pl"],nr:[1,2,5],fc:7},{lngs:["cy"],nr:[1,2,3,8],fc:8},{lngs:["fr"],nr:[1,2],fc:9},{lngs:["ga"],nr:[1,2,3,7,11],fc:10},{lngs:["gd"],nr:[1,2,3,20],fc:11},{lngs:["is"],nr:[1,2],fc:12},{lngs:["jv"],nr:[0,1],fc:13},{lngs:["kw"],nr:[1,2,3,4],fc:14},{lngs:["lt"],nr:[1,2,10],fc:15},{lngs:["lv"],nr:[1,2,0],fc:16},{lngs:["mk"],nr:[1,2],fc:17},{lngs:["mnk"],nr:[0,1,2],fc:18},{lngs:["mt"],nr:[1,2,11,20],fc:19},{lngs:["or"],nr:[2,1],fc:2},{lngs:["ro"],nr:[1,2,20],fc:20},{lngs:["sl"],nr:[5,1,2,3],fc:21},{lngs:["he","iw"],nr:[1,2,20,21],fc:22}],Kte={1:t=>+(t>1),2:t=>+(t!=1),3:t=>0,4:t=>t%10==1&&t%100!=11?0:t%10>=2&&t%10<=4&&(t%100<10||t%100>=20)?1:2,5:t=>t==0?0:t==1?1:t==2?2:t%100>=3&&t%100<=10?3:t%100>=11?4:5,6:t=>t==1?0:t>=2&&t<=4?1:2,7:t=>t==1?0:t%10>=2&&t%10<=4&&(t%100<10||t%100>=20)?1:2,8:t=>t==1?0:t==2?1:t!=8&&t!=11?2:3,9:t=>+(t>=2),10:t=>t==1?0:t==2?1:t<7?2:t<11?3:4,11:t=>t==1||t==11?0:t==2||t==12?1:t>2&&t<20?2:3,12:t=>+(t%10!=1||t%100==11),13:t=>+(t!==0),14:t=>t==1?0:t==2?1:t==3?2:3,15:t=>t%10==1&&t%100!=11?0:t%10>=2&&(t%100<10||t%100>=20)?1:2,16:t=>t%10==1&&t%100!=11?0:t!==0?1:2,17:t=>t==1||t%10==1&&t%100!=11?0:1,18:t=>t==0?0:t==1?1:2,19:t=>t==1?0:t==0||t%100>1&&t%100<11?1:t%100>10&&t%100<20?2:3,20:t=>t==1?0:t==0||t%100>0&&t%100<20?1:2,21:t=>t%100==1?1:t%100==2?2:t%100==3||t%100==4?3:0,22:t=>t==1?0:t==2?1:(t<0||t>10)&&t%10==0?2:3};const Jte=["v1","v2","v3"],Qte=["v4"],JR={zero:0,one:1,two:2,few:3,many:4,other:5},Xte=()=>{const t={};return Gte.forEach(e=>{e.lngs.forEach(n=>{t[n]={numbers:e.nr,plurals:Kte[e.fc]}})}),t};class Zte{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.languageUtils=e,this.options=n,this.logger=Po.create("pluralResolver"),(!this.options.compatibilityJSON||Qte.includes(this.options.compatibilityJSON))&&(typeof Intl>"u"||!Intl.PluralRules)&&(this.options.compatibilityJSON="v3",this.logger.error("Your environment seems not to be Intl API compatible, use an Intl.PluralRules polyfill. Will fallback to the compatibilityJSON v3 format handling.")),this.rules=Xte(),this.pluralRulesCache={}}addRule(e,n){this.rules[e]=n}clearCache(){this.pluralRulesCache={}}getRule(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(this.shouldUseIntlApi()){const r=Mv(e==="dev"?"en":e),s=n.ordinal?"ordinal":"cardinal",i=JSON.stringify({cleanedCode:r,type:s});if(i in this.pluralRulesCache)return this.pluralRulesCache[i];let a;try{a=new Intl.PluralRules(r,{type:s})}catch{if(!e.match(/-|_/))return;const l=this.languageUtils.getLanguagePartFromCode(e);a=this.getRule(l,n)}return this.pluralRulesCache[i]=a,a}return this.rules[e]||this.rules[this.languageUtils.getLanguagePartFromCode(e)]}needsPlural(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};const r=this.getRule(e,n);return this.shouldUseIntlApi()?r&&r.resolvedOptions().pluralCategories.length>1:r&&r.numbers.length>1}getPluralFormsOfKey(e,n){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return this.getSuffixes(e,r).map(s=>`${n}${s}`)}getSuffixes(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};const r=this.getRule(e,n);return r?this.shouldUseIntlApi()?r.resolvedOptions().pluralCategories.sort((s,i)=>JR[s]-JR[i]).map(s=>`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:""}${s}`):r.numbers.map(s=>this.getSuffix(e,s,n)):[]}getSuffix(e,n){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};const s=this.getRule(e,r);return s?this.shouldUseIntlApi()?`${this.options.prepend}${r.ordinal?`ordinal${this.options.prepend}`:""}${s.select(n)}`:this.getSuffixRetroCompatible(s,n):(this.logger.warn(`no plural rule found for: ${e}`),"")}getSuffixRetroCompatible(e,n){const r=e.noAbs?e.plurals(n):e.plurals(Math.abs(n));let s=e.numbers[r];this.options.simplifyPluralSuffix&&e.numbers.length===2&&e.numbers[0]===1&&(s===2?s="plural":s===1&&(s=""));const i=()=>this.options.prepend&&s.toString()?this.options.prepend+s.toString():s.toString();return this.options.compatibilityJSON==="v1"?s===1?"":typeof s=="number"?`_plural_${s.toString()}`:i():this.options.compatibilityJSON==="v2"||this.options.simplifyPluralSuffix&&e.numbers.length===2&&e.numbers[0]===1?i():this.options.prepend&&r.toString()?this.options.prepend+r.toString():r.toString()}shouldUseIntlApi(){return!Jte.includes(this.options.compatibilityJSON)}}const QR=function(t,e,n){let r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:".",s=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,i=zte(t,e,n);return!i&&s&&Vt(n)&&(i=n_(t,n,r),i===void 0&&(i=n_(e,n,r))),i},HS=t=>t.replace(/\$/g,"$$$$");class Yte{constructor(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};this.logger=Po.create("interpolator"),this.options=e,this.format=e.interpolation&&e.interpolation.format||(n=>n),this.init(e)}init(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};e.interpolation||(e.interpolation={escapeValue:!0});const{escape:n,escapeValue:r,useRawValueToEscape:s,prefix:i,prefixEscaped:a,suffix:o,suffixEscaped:l,formatSeparator:c,unescapeSuffix:h,unescapePrefix:p,nestingPrefix:m,nestingPrefixEscaped:g,nestingSuffix:y,nestingSuffixEscaped:x,nestingOptionsSeparator:v,maxReplaces:k,alwaysFormat:C}=e.interpolation;this.escape=n!==void 0?n:Bte,this.escapeValue=r!==void 0?r:!0,this.useRawValueToEscape=s!==void 0?s:!1,this.prefix=i?Ah(i):a||"{{",this.suffix=o?Ah(o):l||"}}",this.formatSeparator=c||",",this.unescapePrefix=h?"":p||"-",this.unescapeSuffix=this.unescapePrefix?"":h||"",this.nestingPrefix=m?Ah(m):g||Ah("$t("),this.nestingSuffix=y?Ah(y):x||Ah(")"),this.nestingOptionsSeparator=v||",",this.maxReplaces=k||1e3,this.alwaysFormat=C!==void 0?C:!1,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){const e=(n,r)=>n&&n.source===r?(n.lastIndex=0,n):new RegExp(r,"g");this.regexp=e(this.regexp,`${this.prefix}(.+?)${this.suffix}`),this.regexpUnescape=e(this.regexpUnescape,`${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`),this.nestingRegexp=e(this.nestingRegexp,`${this.nestingPrefix}(.+?)${this.nestingSuffix}`)}interpolate(e,n,r,s){let i,a,o;const l=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},c=g=>{if(g.indexOf(this.formatSeparator)<0){const k=QR(n,l,g,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(k,void 0,r,{...s,...n,interpolationkey:g}):k}const y=g.split(this.formatSeparator),x=y.shift().trim(),v=y.join(this.formatSeparator).trim();return this.format(QR(n,l,x,this.options.keySeparator,this.options.ignoreJSONStructure),v,r,{...s,...n,interpolationkey:x})};this.resetRegExp();const h=s&&s.missingInterpolationHandler||this.options.missingInterpolationHandler,p=s&&s.interpolation&&s.interpolation.skipOnVariables!==void 0?s.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:g=>HS(g)},{regex:this.regexp,safeValue:g=>this.escapeValue?HS(this.escape(g)):HS(g)}].forEach(g=>{for(o=0;i=g.regex.exec(e);){const y=i[1].trim();if(a=c(y),a===void 0)if(typeof h=="function"){const v=h(e,i,s);a=Vt(v)?v:""}else if(s&&Object.prototype.hasOwnProperty.call(s,y))a="";else if(p){a=i[0];continue}else this.logger.warn(`missed to pass in variable ${y} for interpolating ${e}`),a="";else!Vt(a)&&!this.useRawValueToEscape&&(a=$R(a));const x=g.safeValue(a);if(e=e.replace(i[0],x),p?(g.regex.lastIndex+=a.length,g.regex.lastIndex-=i[0].length):g.regex.lastIndex=0,o++,o>=this.maxReplaces)break}}),e}nest(e,n){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},s,i,a;const o=(l,c)=>{const h=this.nestingOptionsSeparator;if(l.indexOf(h)<0)return l;const p=l.split(new RegExp(`${h}[ ]*{`));let m=`{${p[1]}`;l=p[0],m=this.interpolate(m,a);const g=m.match(/'/g),y=m.match(/"/g);(g&&g.length%2===0&&!y||y.length%2!==0)&&(m=m.replace(/'/g,'"'));try{a=JSON.parse(m),c&&(a={...c,...a})}catch(x){return this.logger.warn(`failed parsing options string in nesting for key ${l}`,x),`${l}${h}${m}`}return a.defaultValue&&a.defaultValue.indexOf(this.prefix)>-1&&delete a.defaultValue,l};for(;s=this.nestingRegexp.exec(e);){let l=[];a={...r},a=a.replace&&!Vt(a.replace)?a.replace:a,a.applyPostProcessor=!1,delete a.defaultValue;let c=!1;if(s[0].indexOf(this.formatSeparator)!==-1&&!/{.*}/.test(s[1])){const h=s[1].split(this.formatSeparator).map(p=>p.trim());s[1]=h.shift(),l=h,c=!0}if(i=n(o.call(this,s[1].trim(),a),a),i&&s[0]===e&&!Vt(i))return i;Vt(i)||(i=$R(i)),i||(this.logger.warn(`missed to resolve ${s[1]} for nesting ${e}`),i=""),c&&(i=l.reduce((h,p)=>this.format(h,p,r.lng,{...r,interpolationkey:s[1].trim()}),i.trim())),e=e.replace(s[0],i),this.regexp.lastIndex=0}return e}}const ene=t=>{let e=t.toLowerCase().trim();const n={};if(t.indexOf("(")>-1){const r=t.split("(");e=r[0].toLowerCase().trim();const s=r[1].substring(0,r[1].length-1);e==="currency"&&s.indexOf(":")<0?n.currency||(n.currency=s.trim()):e==="relativetime"&&s.indexOf(":")<0?n.range||(n.range=s.trim()):s.split(";").forEach(a=>{if(a){const[o,...l]=a.split(":"),c=l.join(":").trim().replace(/^'+|'+$/g,""),h=o.trim();n[h]||(n[h]=c),c==="false"&&(n[h]=!1),c==="true"&&(n[h]=!0),isNaN(c)||(n[h]=parseInt(c,10))}})}return{formatName:e,formatOptions:n}},Th=t=>{const e={};return(n,r,s)=>{let i=s;s&&s.interpolationkey&&s.formatParams&&s.formatParams[s.interpolationkey]&&s[s.interpolationkey]&&(i={...i,[s.interpolationkey]:void 0});const a=r+JSON.stringify(i);let o=e[a];return o||(o=t(Mv(r),s),e[a]=o),o(n)}};class tne{constructor(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};this.logger=Po.create("formatter"),this.options=e,this.formats={number:Th((n,r)=>{const s=new Intl.NumberFormat(n,{...r});return i=>s.format(i)}),currency:Th((n,r)=>{const s=new Intl.NumberFormat(n,{...r,style:"currency"});return i=>s.format(i)}),datetime:Th((n,r)=>{const s=new Intl.DateTimeFormat(n,{...r});return i=>s.format(i)}),relativetime:Th((n,r)=>{const s=new Intl.RelativeTimeFormat(n,{...r});return i=>s.format(i,r.range||"day")}),list:Th((n,r)=>{const s=new Intl.ListFormat(n,{...r});return i=>s.format(i)})},this.init(e)}init(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{interpolation:{}};this.formatSeparator=n.interpolation.formatSeparator||","}add(e,n){this.formats[e.toLowerCase().trim()]=n}addCached(e,n){this.formats[e.toLowerCase().trim()]=Th(n)}format(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};const i=n.split(this.formatSeparator);if(i.length>1&&i[0].indexOf("(")>1&&i[0].indexOf(")")<0&&i.find(o=>o.indexOf(")")>-1)){const o=i.findIndex(l=>l.indexOf(")")>-1);i[0]=[i[0],...i.splice(1,o)].join(this.formatSeparator)}return i.reduce((o,l)=>{const{formatName:c,formatOptions:h}=ene(l);if(this.formats[c]){let p=o;try{const m=s&&s.formatParams&&s.formatParams[s.interpolationkey]||{},g=m.locale||m.lng||s.locale||s.lng||r;p=this.formats[c](o,g,{...h,...s,...m})}catch(m){this.logger.warn(m)}return p}else this.logger.warn(`there was no format function for ${c}`);return o},e)}}const nne=(t,e)=>{t.pending[e]!==void 0&&(delete t.pending[e],t.pendingCount--)};class rne extends n1{constructor(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:{};super(),this.backend=e,this.store=n,this.services=r,this.languageUtils=r.languageUtils,this.options=s,this.logger=Po.create("backendConnector"),this.waitingReads=[],this.maxParallelReads=s.maxParallelReads||10,this.readingCalls=0,this.maxRetries=s.maxRetries>=0?s.maxRetries:5,this.retryTimeout=s.retryTimeout>=1?s.retryTimeout:350,this.state={},this.queue=[],this.backend&&this.backend.init&&this.backend.init(r,s.backend,s)}queueLoad(e,n,r,s){const i={},a={},o={},l={};return e.forEach(c=>{let h=!0;n.forEach(p=>{const m=`${c}|${p}`;!r.reload&&this.store.hasResourceBundle(c,p)?this.state[m]=2:this.state[m]<0||(this.state[m]===1?a[m]===void 0&&(a[m]=!0):(this.state[m]=1,h=!1,a[m]===void 0&&(a[m]=!0),i[m]===void 0&&(i[m]=!0),l[p]===void 0&&(l[p]=!0)))}),h||(o[c]=!0)}),(Object.keys(i).length||Object.keys(a).length)&&this.queue.push({pending:a,pendingCount:Object.keys(a).length,loaded:{},errors:[],callback:s}),{toLoad:Object.keys(i),pending:Object.keys(a),toLoadLanguages:Object.keys(o),toLoadNamespaces:Object.keys(l)}}loaded(e,n,r){const s=e.split("|"),i=s[0],a=s[1];n&&this.emit("failedLoading",i,a,n),!n&&r&&this.store.addResourceBundle(i,a,r,void 0,void 0,{skipCopy:!0}),this.state[e]=n?-1:2,n&&r&&(this.state[e]=0);const o={};this.queue.forEach(l=>{Ote(l.loaded,[i],a),nne(l,e),n&&l.errors.push(n),l.pendingCount===0&&!l.done&&(Object.keys(l.loaded).forEach(c=>{o[c]||(o[c]={});const h=l.loaded[c];h.length&&h.forEach(p=>{o[c][p]===void 0&&(o[c][p]=!0)})}),l.done=!0,l.errors.length?l.callback(l.errors):l.callback())}),this.emit("loaded",o),this.queue=this.queue.filter(l=>!l.done)}read(e,n,r){let s=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0,i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:this.retryTimeout,a=arguments.length>5?arguments[5]:void 0;if(!e.length)return a(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:e,ns:n,fcName:r,tried:s,wait:i,callback:a});return}this.readingCalls++;const o=(c,h)=>{if(this.readingCalls--,this.waitingReads.length>0){const p=this.waitingReads.shift();this.read(p.lng,p.ns,p.fcName,p.tried,p.wait,p.callback)}if(c&&h&&s<this.maxRetries){setTimeout(()=>{this.read.call(this,e,n,r,s+1,i*2,a)},i);return}a(c,h)},l=this.backend[r].bind(this.backend);if(l.length===2){try{const c=l(e,n);c&&typeof c.then=="function"?c.then(h=>o(null,h)).catch(o):o(null,c)}catch(c){o(c)}return}return l(e,n,o)}prepareLoading(e,n){let r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},s=arguments.length>3?arguments[3]:void 0;if(!this.backend)return this.logger.warn("No backend was added via i18next.use. Will not load resources."),s&&s();Vt(e)&&(e=this.languageUtils.toResolveHierarchy(e)),Vt(n)&&(n=[n]);const i=this.queueLoad(e,n,r,s);if(!i.toLoad.length)return i.pending.length||s(),null;i.toLoad.forEach(a=>{this.loadOne(a)})}load(e,n,r){this.prepareLoading(e,n,{},r)}reload(e,n,r){this.prepareLoading(e,n,{reload:!0},r)}loadOne(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:"";const r=e.split("|"),s=r[0],i=r[1];this.read(s,i,"read",void 0,void 0,(a,o)=>{a&&this.logger.warn(`${n}loading namespace ${i} for language ${s} failed`,a),!a&&o&&this.logger.log(`${n}loaded namespace ${i} for language ${s}`,o),this.loaded(e,a,o)})}saveMissing(e,n,r,s,i){let a=arguments.length>5&&arguments[5]!==void 0?arguments[5]:{},o=arguments.length>6&&arguments[6]!==void 0?arguments[6]:()=>{};if(this.services.utils&&this.services.utils.hasLoadedNamespace&&!this.services.utils.hasLoadedNamespace(n)){this.logger.warn(`did not save key "${r}" as the namespace "${n}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");return}if(!(r==null||r==="")){if(this.backend&&this.backend.create){const l={...a,isUpdate:i},c=this.backend.create.bind(this.backend);if(c.length<6)try{let h;c.length===5?h=c(e,n,r,s,l):h=c(e,n,r,s),h&&typeof h.then=="function"?h.then(p=>o(null,p)).catch(o):o(null,h)}catch(h){o(h)}else c(e,n,r,s,o,l)}!e||!e[0]||this.store.addResource(e[0],n,r,s)}}}const XR=()=>({debug:!1,initImmediate:!0,ns:["translation"],defaultNS:["translation"],fallbackLng:["dev"],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:"all",preload:!1,simplifyPluralSuffix:!0,keySeparator:".",nsSeparator:":",pluralSeparator:"_",contextSeparator:"_",partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:"fallback",saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:t=>{let e={};if(typeof t[1]=="object"&&(e=t[1]),Vt(t[1])&&(e.defaultValue=t[1]),Vt(t[2])&&(e.tDescription=t[2]),typeof t[2]=="object"||typeof t[3]=="object"){const n=t[3]||t[2];Object.keys(n).forEach(r=>{e[r]=n[r]})}return e},interpolation:{escapeValue:!0,format:t=>t,prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!0}}),ZR=t=>(Vt(t.ns)&&(t.ns=[t.ns]),Vt(t.fallbackLng)&&(t.fallbackLng=[t.fallbackLng]),Vt(t.fallbackNS)&&(t.fallbackNS=[t.fallbackNS]),t.supportedLngs&&t.supportedLngs.indexOf("cimode")<0&&(t.supportedLngs=t.supportedLngs.concat(["cimode"])),t),ey=()=>{},sne=t=>{Object.getOwnPropertyNames(Object.getPrototypeOf(t)).forEach(n=>{typeof t[n]=="function"&&(t[n]=t[n].bind(t))})};class Cg extends n1{constructor(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0;if(super(),this.options=ZR(e),this.services={},this.logger=Po,this.modules={external:[]},sne(this),n&&!this.isInitialized&&!e.isClone){if(!this.options.initImmediate)return this.init(e,n),this;setTimeout(()=>{this.init(e,n)},0)}}init(){var e=this;let n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},r=arguments.length>1?arguments[1]:void 0;this.isInitializing=!0,typeof n=="function"&&(r=n,n={}),!n.defaultNS&&n.defaultNS!==!1&&n.ns&&(Vt(n.ns)?n.defaultNS=n.ns:n.ns.indexOf("translation")<0&&(n.defaultNS=n.ns[0]));const s=XR();this.options={...s,...this.options,...ZR(n)},this.options.compatibilityAPI!=="v1"&&(this.options.interpolation={...s.interpolation,...this.options.interpolation}),n.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=n.keySeparator),n.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=n.nsSeparator);const i=h=>h?typeof h=="function"?new h:h:null;if(!this.options.isClone){this.modules.logger?Po.init(i(this.modules.logger),this.options):Po.init(null,this.options);let h;this.modules.formatter?h=this.modules.formatter:typeof Intl<"u"&&(h=tne);const p=new KR(this.options);this.store=new WR(this.options.resources,this.options);const m=this.services;m.logger=Po,m.resourceStore=this.store,m.languageUtils=p,m.pluralResolver=new Zte(p,{prepend:this.options.pluralSeparator,compatibilityJSON:this.options.compatibilityJSON,simplifyPluralSuffix:this.options.simplifyPluralSuffix}),h&&(!this.options.interpolation.format||this.options.interpolation.format===s.interpolation.format)&&(m.formatter=i(h),m.formatter.init(m,this.options),this.options.interpolation.format=m.formatter.format.bind(m.formatter)),m.interpolator=new Yte(this.options),m.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},m.backendConnector=new rne(i(this.modules.backend),m.resourceStore,m,this.options),m.backendConnector.on("*",function(g){for(var y=arguments.length,x=new Array(y>1?y-1:0),v=1;v<y;v++)x[v-1]=arguments[v];e.emit(g,...x)}),this.modules.languageDetector&&(m.languageDetector=i(this.modules.languageDetector),m.languageDetector.init&&m.languageDetector.init(m,this.options.detection,this.options)),this.modules.i18nFormat&&(m.i18nFormat=i(this.modules.i18nFormat),m.i18nFormat.init&&m.i18nFormat.init(this)),this.translator=new Dv(this.services,this.options),this.translator.on("*",function(g){for(var y=arguments.length,x=new Array(y>1?y-1:0),v=1;v<y;v++)x[v-1]=arguments[v];e.emit(g,...x)}),this.modules.external.forEach(g=>{g.init&&g.init(this)})}if(this.format=this.options.interpolation.format,r||(r=ey),this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){const h=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);h.length>0&&h[0]!=="dev"&&(this.options.lng=h[0])}!this.services.languageDetector&&!this.options.lng&&this.logger.warn("init: no languageDetector is used and no lng is defined"),["getResource","hasResourceBundle","getResourceBundle","getDataByLanguage"].forEach(h=>{this[h]=function(){return e.store[h](...arguments)}}),["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(h=>{this[h]=function(){return e.store[h](...arguments),e}});const l=Jp(),c=()=>{const h=(p,m)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn("init: i18next is already initialized. You should call init just once!"),this.isInitialized=!0,this.options.isClone||this.logger.log("initialized",this.options),this.emit("initialized",this.options),l.resolve(m),r(p,m)};if(this.languages&&this.options.compatibilityAPI!=="v1"&&!this.isInitialized)return h(null,this.t.bind(this));this.changeLanguage(this.options.lng,h)};return this.options.resources||!this.options.initImmediate?c():setTimeout(c,0),l}loadResources(e){let r=arguments.length>1&&arguments[1]!==void 0?arguments[1]:ey;const s=Vt(e)?e:this.language;if(typeof e=="function"&&(r=e),!this.options.resources||this.options.partialBundledLanguages){if(s&&s.toLowerCase()==="cimode"&&(!this.options.preload||this.options.preload.length===0))return r();const i=[],a=o=>{if(!o||o==="cimode")return;this.services.languageUtils.toResolveHierarchy(o).forEach(c=>{c!=="cimode"&&i.indexOf(c)<0&&i.push(c)})};s?a(s):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(l=>a(l)),this.options.preload&&this.options.preload.forEach(o=>a(o)),this.services.backendConnector.load(i,this.options.ns,o=>{!o&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),r(o)})}else r(null)}reloadResources(e,n,r){const s=Jp();return typeof e=="function"&&(r=e,e=void 0),typeof n=="function"&&(r=n,n=void 0),e||(e=this.languages),n||(n=this.options.ns),r||(r=ey),this.services.backendConnector.reload(e,n,i=>{s.resolve(),r(i)}),s}use(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(!e.type)throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()");return e.type==="backend"&&(this.modules.backend=e),(e.type==="logger"||e.log&&e.warn&&e.error)&&(this.modules.logger=e),e.type==="languageDetector"&&(this.modules.languageDetector=e),e.type==="i18nFormat"&&(this.modules.i18nFormat=e),e.type==="postProcessor"&&NO.addPostProcessor(e),e.type==="formatter"&&(this.modules.formatter=e),e.type==="3rdParty"&&this.modules.external.push(e),this}setResolvedLanguage(e){if(!(!e||!this.languages)&&!(["cimode","dev"].indexOf(e)>-1))for(let n=0;n<this.languages.length;n++){const r=this.languages[n];if(!(["cimode","dev"].indexOf(r)>-1)&&this.store.hasLanguageSomeTranslations(r)){this.resolvedLanguage=r;break}}}changeLanguage(e,n){var r=this;this.isLanguageChangingTo=e;const s=Jp();this.emit("languageChanging",e);const i=l=>{this.language=l,this.languages=this.services.languageUtils.toResolveHierarchy(l),this.resolvedLanguage=void 0,this.setResolvedLanguage(l)},a=(l,c)=>{c?(i(c),this.translator.changeLanguage(c),this.isLanguageChangingTo=void 0,this.emit("languageChanged",c),this.logger.log("languageChanged",c)):this.isLanguageChangingTo=void 0,s.resolve(function(){return r.t(...arguments)}),n&&n(l,function(){return r.t(...arguments)})},o=l=>{!e&&!l&&this.services.languageDetector&&(l=[]);const c=Vt(l)?l:this.services.languageUtils.getBestMatchFromCodes(l);c&&(this.language||i(c),this.translator.language||this.translator.changeLanguage(c),this.services.languageDetector&&this.services.languageDetector.cacheUserLanguage&&this.services.languageDetector.cacheUserLanguage(c)),this.loadResources(c,h=>{a(h,c)})};return!e&&this.services.languageDetector&&!this.services.languageDetector.async?o(this.services.languageDetector.detect()):!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(o):this.services.languageDetector.detect(o):o(e),s}getFixedT(e,n,r){var s=this;const i=function(a,o){let l;if(typeof o!="object"){for(var c=arguments.length,h=new Array(c>2?c-2:0),p=2;p<c;p++)h[p-2]=arguments[p];l=s.options.overloadTranslationOptionHandler([a,o].concat(h))}else l={...o};l.lng=l.lng||i.lng,l.lngs=l.lngs||i.lngs,l.ns=l.ns||i.ns,l.keyPrefix!==""&&(l.keyPrefix=l.keyPrefix||r||i.keyPrefix);const m=s.options.keySeparator||".";let g;return l.keyPrefix&&Array.isArray(a)?g=a.map(y=>`${l.keyPrefix}${m}${y}`):g=l.keyPrefix?`${l.keyPrefix}${m}${a}`:a,s.t(g,l)};return Vt(e)?i.lng=e:i.lngs=e,i.ns=n,i.keyPrefix=r,i}t(){return this.translator&&this.translator.translate(...arguments)}exists(){return this.translator&&this.translator.exists(...arguments)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};if(!this.isInitialized)return this.logger.warn("hasLoadedNamespace: i18next was not initialized",this.languages),!1;if(!this.languages||!this.languages.length)return this.logger.warn("hasLoadedNamespace: i18n.languages were undefined or empty",this.languages),!1;const r=n.lng||this.resolvedLanguage||this.languages[0],s=this.options?this.options.fallbackLng:!1,i=this.languages[this.languages.length-1];if(r.toLowerCase()==="cimode")return!0;const a=(o,l)=>{const c=this.services.backendConnector.state[`${o}|${l}`];return c===-1||c===0||c===2};if(n.precheck){const o=n.precheck(this,a);if(o!==void 0)return o}return!!(this.hasResourceBundle(r,e)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||a(r,e)&&(!s||a(i,e)))}loadNamespaces(e,n){const r=Jp();return this.options.ns?(Vt(e)&&(e=[e]),e.forEach(s=>{this.options.ns.indexOf(s)<0&&this.options.ns.push(s)}),this.loadResources(s=>{r.resolve(),n&&n(s)}),r):(n&&n(),Promise.resolve())}loadLanguages(e,n){const r=Jp();Vt(e)&&(e=[e]);const s=this.options.preload||[],i=e.filter(a=>s.indexOf(a)<0&&this.services.languageUtils.isSupportedCode(a));return i.length?(this.options.preload=s.concat(i),this.loadResources(a=>{r.resolve(),n&&n(a)}),r):(n&&n(),Promise.resolve())}dir(e){if(e||(e=this.resolvedLanguage||(this.languages&&this.languages.length>0?this.languages[0]:this.language)),!e)return"rtl";const n=["ar","shu","sqr","ssh","xaa","yhd","yud","aao","abh","abv","acm","acq","acw","acx","acy","adf","ads","aeb","aec","afb","ajp","apc","apd","arb","arq","ars","ary","arz","auz","avl","ayh","ayl","ayn","ayp","bbz","pga","he","iw","ps","pbt","pbu","pst","prp","prd","ug","ur","ydd","yds","yih","ji","yi","hbo","men","xmn","fa","jpr","peo","pes","prs","dv","sam","ckb"],r=this.services&&this.services.languageUtils||new KR(XR());return n.indexOf(r.getLanguagePartFromCode(e))>-1||e.toLowerCase().indexOf("-arab")>1?"rtl":"ltr"}static createInstance(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1?arguments[1]:void 0;return new Cg(e,n)}cloneInstance(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:ey;const r=e.forkResourceStore;r&&delete e.forkResourceStore;const s={...this.options,...e,isClone:!0},i=new Cg(s);return(e.debug!==void 0||e.prefix!==void 0)&&(i.logger=i.logger.clone(e)),["store","services","language"].forEach(o=>{i[o]=this[o]}),i.services={...this.services},i.services.utils={hasLoadedNamespace:i.hasLoadedNamespace.bind(i)},r&&(i.store=new WR(this.store.data,s),i.services.resourceStore=i.store),i.translator=new Dv(i.services,s),i.translator.on("*",function(o){for(var l=arguments.length,c=new Array(l>1?l-1:0),h=1;h<l;h++)c[h-1]=arguments[h];i.emit(o,...c)}),i.init(s,n),i.translator.options=s,i.translator.backendConnector.services.utils={hasLoadedNamespace:i.hasLoadedNamespace.bind(i)},i}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}}const jt=Cg.createInstance();jt.createInstance=Cg.createInstance;jt.createInstance;jt.dir;jt.init;jt.loadResources;jt.reloadResources;jt.use;jt.changeLanguage;jt.getFixedT;jt.t;jt.exists;jt.setDefaultNamespace;jt.hasLoadedNamespace;jt.loadNamespaces;jt.loadLanguages;const ine={save:"Save",saving:"Saving…",saved:"Saved",cancel:"Cancel",delete:"Delete",deleting:"Deleting…",edit:"Edit",create:"Create",search:"Search",loading:"Loading…",yes:"Yes",no:"No",confirm:"Confirm",back:"Back",next:"Next",previous:"Previous",close:"Close",all:"All",none:"None",actions:"Actions",name:"Name",slug:"Slug",description:"Description",status:"Status",createdAt:"Created",updatedAt:"Updated",publishedAt:"Published",language:"Language",darkMode:"Dark mode",lightMode:"Light mode",signOut:"Sign out",administrator:"Administrator",editor:"Editor",appName:"AgentCMS"},ane={signIn:"Sign in",signingIn:"Signing in…",email:"Email",password:"Password",emailPlaceholder:"you@company.com",passwordPlaceholder:"••••••••",forgotPassword:"Forgot password?",resetEmailSent:"Password reset email sent to {{email}}.",enterEmailFirst:"Enter your email above first, then click reset.",emailPasswordRequired:"Email and password are required.",signInSubtitle:"Use your work email and password.",footer:"Account requests go through your administrator.",errors:{invalidEmail:"Invalid email address.",invalidCredentials:"Invalid email or password.",tooManyRequests:"Too many attempts. Try again later or reset your password.",userDisabled:"This account has been disabled.",networkFailed:"Network error. Check your connection.",generic:"Authentication failed."}},one={openMenu:"Open menu",closeMenu:"Close menu",dashboard:"Dashboard",posts:"Posts",pages:"Pages",taxonomies:"Categories & Tags",media:"Media",themes:"Themes",themeSettings:"Theme settings",plugins:"Plugins",menus:"Menus",users:"Users",settings:"Settings"},lne={title:"Dashboard",welcome:"Welcome back, {{email}}.",stats:{totalPosts:"Posts",totalPages:"Pages",online:"Online",drafts:"Drafts"}},cne={title:"Posts",newPost:"New post",noPosts:"No posts yet. Create your first one to get started.",noPostsInFilter:"No posts match the current filter.",search:{placeholder:"Search posts…",clear:"Clear search",noResults:"No posts match your search."},pagination:{previous:"Previous",next:"Next",showing:"Showing {{from}}–{{to}} of {{total}}",pageOf:"Page {{page}} of {{total}}"},bulk:{selectedCount_one:"{{count}} selected",selectedCount_other:"{{count}} selected",selectPage_one:"Select {{count}} on this page",selectPage_other:"Select all {{count}} on this page",deselectPage:"Deselect page",allOnPageSelected_one:"{{count}} on this page selected.",allOnPageSelected_other:"All {{count}} on this page selected.",selectAllMatching_one:"Select the {{count}} matching post",selectAllMatching_other:"Select all {{count}} matching posts",allMatchingSelected_one:"All {{count}} matching post selected.",allMatchingSelected_other:"All {{count}} matching posts selected.",selectOne:'Select "{{title}}"',publish:"Publish ({{count}})",publishing:"Publishing…",publishedCount:"Published {{ok}}, failed {{failed}}.",unpublish:"Unpublish ({{count}})",unpublishing:"Unpublishing…",unpublishedCount:"Unpublished {{ok}}, failed {{failed}}.",delete:"Delete",deleting:"Deleting…",deletedCount:"Deleted {{ok}}, failed {{failed}}.",confirmDelete_one:"Delete {{count}} post? This unpublishes from Flexweg and cannot be undone.",confirmDelete_other:"Delete {{count}} posts? This unpublishes from Flexweg and cannot be undone.",noDraftSelected:"No draft posts selected.",noOnlineSelected:"No online posts selected.",clear:"Clear selection"},filters:{all:"All",draft:"Draft",online:"Online"},fields:{title:"Title",slug:"Slug",excerpt:"Excerpt",content:"Content",category:"Category",tags:"Tags",heroImage:"Hero image",seoTitle:"SEO title",seoDescription:"SEO description",createdAt:"Created at",updatedAt:"Last updated",publishedAt:"Published at"},edit:{newTitle:"New post",editTitle:"Edit post",saved:"Saved.",savedAndRepublished:"Saved and republished.",saveFailed:"Save failed.",saveAndRepublish:"Save & republish",draftSaved:"Draft saved.",slugCollision:{post:'This URL is already used by post: "{{label}}".',page:'This URL is already used by page: "{{label}}".',category:'This URL is already used by category: "{{label}}".'},publish:"Publish",unpublish:"Unpublish",publishing:"Publishing…",unpublishing:"Unpublishing…",titlePlaceholder:"Add title",permalink:"Permalink",slugFormatHint:"Lower-case, ASCII, dash-separated only.",slugAutoSuffixed:'Auto-suffixed because "{{base}}" is already used by {{owner}}.',slugAutoSuffixedOwner:{post:'post: "{{label}}"',page:'page: "{{label}}"',category:'category: "{{label}}"'},saveBlocked:{titleRequired:"Add a title before saving.",slugRequired:"A title and URL slug are required to save.",slugInvalid:"Slug format is invalid (lower-case ASCII + dashes).",slugCollision:"Fix the URL conflict before saving."},viewPublished:"View",confirmDelete:"Delete this entry?",inspector:{document:"Document",block:"Block",blockEmpty:"Select a block in the editor to see its options.",publishing:"Publishing",permalink:"Permalink",categories:"Categories & tags",featured:"Featured image",seo:"SEO",excerpt:"Excerpt",dates:"Dates"},blocks:{addBlock:"Add block",transform:"Transform to",moveUp:"Move up",moveDown:"Move down",duplicate:"Duplicate",remove:"Delete block",paragraph:"Paragraph",heading2:"Heading 2",heading3:"Heading 3",bulletList:"Bullet list",orderedList:"Numbered list",blockquote:"Quote",codeBlock:"Code",image:"Image",horizontalRule:"Separator",categories:{text:"Text",media:"Media",layout:"Layout",embed:"Embeds",advanced:"Advanced"},noSettings:"This block has no settings.",noSelection:"Select a block in the editor to see its options.",slash:{noResults:"No matching block."}}},status:{draft:"Draft",online:"Online"},preview:{title:"Preview",rendering:"Rendering preview…",error:"Preview failed: {{error}}",viewports:{mobile:"Mobile",tablet:"Tablet",desktop:"Desktop"}}},une={title:"Pages",newPage:"New page",noPages:"No pages yet.",homeBadge:"Home",homeBadgeTooltip:"Used as the site's home page"},dne={title:"Categories & Tags",categories:"Categories",tags:"Tags",newCategory:"New category",newTag:"New tag",noCategories:"No categories yet.",noTags:"No tags yet.",slugCollision:'This slug is already used by "{{label}}".',seo:{button:"SEO",buttonTitle:"Edit SEO meta tags",title:"SEO meta tags",subtitle:'Custom title and description for the "{{name}}" archive page.',metaTitle:"Meta title",metaTitleHint:"Used as the page <title>. Defaults to the term name when blank.",metaDescription:"Meta description",metaDescriptionHint:"Used as the page meta description. Defaults to the term description when blank."}},hne={title:"Media library",upload:"Upload",uploading:"Uploading…",finalizing:"Finalizing…",uploadFailed:"Upload failed",retry:"Retry",noMedia:"No media yet.",alt:"Alt text",caption:"Caption",filename:"Filename",size:"Size",type:"Type"},fne={title:"Themes",active:"Active",activate:"Activate",installExternal:"Install theme",uninstallDisabledTitle:"Switch to another theme before uninstalling this one.",syncAssets:"Sync theme assets",regenerateSite:"Regenerate site",regenerating:"Regenerating…",regenerate:{button:"Regenerate",running:"Running…",groupBuiltins:"Site",groupPlugins:"Plugins",home:"Home page only",homeHelp:"Re-renders index.html only — fastest option.",allHtml:"All HTML pages",allHtmlHelp:"Every post, page, archive and listing — plus menu / posts / authors JSON snapshots.",repair:"Repair URLs",repairHelp:"Recompute every online post's canonical path and migrate files that landed at the wrong URL. Useful after an import that ran before terms had synced.",assets:"Theme assets",assetsHelp:"Pushes the active theme's CSS + companion scripts to /theme-assets/.",everything:"Everything",everythingHelp:"Theme assets + all HTML + every plugin output. Slowest option.",noPluginTargets:"No plugin regeneration targets — enable a plugin that supports regenerate."},confirmSwitch:{title:"Switch to {{theme}}?",body:"Switching theme requires re-uploading the theme's assets and regenerating every published page so the new look propagates everywhere. This may take a moment.",confirm:"Switch & regenerate",cancel:"Cancel"}},pne={title:"Plugins",enabled:"Enabled",disabled:"Disabled",enable:"Enable",disable:"Disable",configure:"Configure",author:"author",learnMore:"Learn more",mustUseBadge:"Must-use",installExternal:"Install plugin",tabs:{regular:"Plugins",mustUse:"Must-use"}},mne={titlePlugin:"Install a plugin",titleTheme:"Install a theme",labelPlugin:"plugin",labelTheme:"theme",intro:"Drop a ZIP file containing a {{label}} bundle (manifest.json + bundle.js at the ZIP root). The {{label}} will be uploaded to your Flexweg site and registered after a reload. Re-uploading a ZIP with the same manifest id upgrades the existing entry in place — no uninstall needed.",zipField:"Bundle ZIP file",install:"Install",installing:"Installing…",installSuccess:"{{name}} installed ({{count}} files uploaded). Reloading…",upgradeSuccess:"{{name}} upgraded from v{{previousVersion}} to v{{newVersion}} ({{count}} files uploaded). Reloading…",installedTitle:"Already installed",bundledDefaultsTitle:"Bundled defaults available",bundledDefaultsHint:"{{count}} bundled plugin/theme is currently uninstalled. Restore them to bring back what shipped with this admin version.",bundledDefaultsRestore:"Restore",bundledDefaultsRestored:"Restored {{plugins}} plugin(s) and {{themes}} theme(s). Reloading…",uninstall:"Uninstall",uninstallSuccess:"{{id}} uninstalled. Reloading…",confirmUninstall:"Uninstall {{id}}? Files will be deleted from Flexweg.",errors:{"no-manifest":"ZIP is missing manifest.json at its root.","invalid-manifest":"manifest.json is invalid (missing required fields or not valid JSON).","incompatible-api":"The bundle was built against an incompatible runtime API version.","no-bundle":"ZIP does not contain the entry file declared in the manifest.","fetch-manifest":"Could not read the current external.json on Flexweg.","upload-failed":"Upload failed — check your Flexweg API key + connection."}},gne={someFailed:"{{count}} external bundle(s) failed to load. Check the browser console."},bne={title:"Menus",header:"Header menu",footer:"Footer menu",label:"Label",saveAndPublish:"Save & generate",discard:"Discard",saved:"Menus saved and published.",saveFailed:"Could not save menus.",unsavedChanges:"You have unsaved changes."},yne={title:"Settings",tabs:{general:"General"},site:{title:"Site",siteTitle:"Site title",siteDescription:"Site description",siteLanguage:"Site language",siteLanguageHelp:'BCP-47 tag (e.g. en, fr-CA) injected into <html lang="…"> on every published page. The prefix is matched against supported translation locales for sitemap/RSS labels and theme-baked strings; unsupported locales fall back to English.',siteLanguageResolved:"Translations will use: {{label}}",baseUrl:"Public site URL",postsPerPage:"Posts per page",homeMode:"Home content",homeLatest:"Latest posts",homeStatic:"Static page",homePage:"Home page",discourageIndexing:"Discourage search engines from indexing this site",discourageIndexingHelp:"When enabled, every published page gets a noindex/nofollow meta tag and robots.txt is set to disallow all crawlers. Mirrors WordPress' behaviour — useful for staging sites or pre-launch reviews. Search engines that respect the directive will not index the site.",discourageRegenerateHint:"Indexing setting saved. Click 'Regenerate all' in Themes to apply the change to every published page and robots.txt."},flexweg:{title:"Flexweg API",apiKey:"API key",apiKeyHelp:"Generated from your Flexweg account → API.",siteUrl:"Site URL",siteUrlHelp:"Public URL of your Flexweg site without trailing slash.",apiBaseUrl:"API base URL",storageHelpFirebase:"Stored in Firestore (config/flexweg). Readable by any signed-in team member, writable by admins only.",storageHelpSqlite:"Stored in the local SQLite config table. Readable by any signed-in team member, writable by admins only."},backend:{title:"Data backend",active:"Active backend:",switchButton:"Switch backend…",confirmTitle:"All current data will be lost.",confirmBody:"Switching wipes the in-browser config and reloads into the setup form. The new backend starts empty — the previous backend's data stays where it was (in Firestore or as a .sqlite file on Flexweg), but the CMS will not read it anymore until you switch back.",confirmYes:"Yes, switch backend",downloadBackup:"Download a backup of the .sqlite file",downloadBackupHelp:"do this before switching backends.",markdownGit:"Markdown — {{source}}",localFolder:"local folder",localBrowser:"This browser (local, single user)",sqliteFile:"SQLite file — {{location}}"},performance:{title:"Performance",help:"How the admin loads posts and pages. Default works on the free Firestore plan with no setup; the paginated mode is for very large sites and requires a one-time index setup.",mode:"Loading mode",modeGlobal:"Standard (no setup required)",modePaginated:"Server-side paginated (requires Firestore indexes)",globalHelp:"Loads the whole posts collection in one live subscription. Sorting, filtering and search happen in memory. Best for sites under ~5 000 posts.",paginatedHelp:"Cursor-paginated subscriptions, one page at a time. Requires composite Firestore indexes — see README. Recommended for very large sites.",savedReload:"Saved. Reload the admin to apply the new mode."},editor:{title:"Editor",help:"Typography used inside the post / page editor. Independent of the public theme.",fontFamily:"Font family",bodySize:"Body size",h1Size:"H1 size",h2Size:"H2 size",h3Size:"H3 size",sizeHelp:"CSS length, e.g. 16px or 1rem. Leave empty for default.",reset:"Reset to defaults"},profile:{title:"Profile",adminLocale:"Admin language",adminLocaleHelp:"Language used by the admin interface. Saved to your profile.",firstName:"First name",lastName:"Last name",headline:"Title",headlinePlaceholder:"e.g. Senior Editor, Investigative Reporter…",headlineHelp:"Shown publicly under your name in author cards and on your archive page.",bio:"Bio",bioPlaceholder:"A short paragraph shown on your author page and below your articles.",bioHelp:"Visible on the public site in the author bio sidebar and the author archive page.",socials:"Social profiles",socialsHelp:'Add the URLs of the profiles you want to surface on the public site, then tick "Show" for the ones you want visible. Empty URLs are ignored.',socialsShow:"Show",socialsShowHelp:"Toggle the visibility of this network on the public site.",avatar:"Profile picture",avatarHelp:"Pick an image from your media library. Square images render best.",pickAvatar:"Pick from media",changeAvatar:"Change picture",removeAvatar:"Remove",save:"Save profile"},transfer:{title:"Move or back up content",help:"Export everything (posts, pages, categories, media metadata, profiles, settings) as one JSON file. On a Markdown or local backend you can import such a file, ids preserved — the way to migrate from Firebase or SQLite. Media files and secret keys are not included.",export:"Export content (JSON)",import:"Import content…",modeMerge:"Merge (overwrite same ids)",modeReplace:"Replace imported collections",replaceConfirm:"Replace mode deletes every existing item of the collections present in the file before importing. Continue?",invalidFile:"This file is not a AgentCMS content export.",imported:"Imported {{posts}} posts/pages, {{terms}} terms, {{media}} media. Run Regenerate → Everything to publish them."},encryption:{title:"Database encryption:",on:"on",off:"off",onHelp:"The database file is unreadable without the passphrase. Changing it re-saves the file with a new key; other browsers will ask for the new passphrase.",offHelp:"The database file is readable by anyone who can download it (a static host serves it like any page). Encrypt it with a passphrase.",enable:"Encrypt the database…",change:"Change the passphrase…",savedConfirm:"I saved this passphrase in my password manager — without it the content can't be opened.",enableConfirm:"Encrypt now",changeConfirm:"Change passphrase",done:"Database re-saved with the new passphrase."}},vne={title:"Users",noUsers:"No users yet.",role:"Role",disabled:"Disabled",editProfileTitle:"Edit profile — {{email}}",profileSaved:"Profile saved.",descriptionFirebase:"Manage your team. New accounts are created in the Firebase Console, then mirrored here on first sign-in.",descriptionSqlite:"Manage your team. Use the +Add user button below to create new accounts directly.",addUser:"Add user",addUserSuccess:"{{email}} added.",removeConfirmFirebase:"Delete the user record for {{email}}? This removes their profile + role from the CMS. To revoke sign-in access, also delete the account in the Firebase Console.",removeConfirmSqlite:"Permanently delete {{email}}? This revokes their sign-in access AND removes their profile + role. This cannot be undone.",empty:{title:"No team members yet",descriptionFirebase:"Create the first account in the Firebase Console, then sign in here once to register the profile.",descriptionSqlite:"Click +Add user above to invite the first team member."},help:{title:"How to add a new team member",bootstrapLine:"The bootstrap admin (always full access) is:",firebase:{step1:"Open the Firebase Console → Authentication → Add user.",step2:"Set an email and password and send them to the new team member.",step3:"Ask them to sign in here once — their profile appears in the list above and you can edit their role / details."},sqlite:{step1:"Click the +Add user button above.",step2:"Enter their email and a temporary password (8+ characters).",step3:"Share the credentials securely — they can change the password from their profile once signed in."},git:{step1:"Add the person as a collaborator of the content repository (write access = editor, admin / maintainer = admin).",step2:"They create their own personal access token on GitHub / GitLab.",step3:"They open the admin and sign in with that token — their profile is created here automatically."}},addUserModal:{title:"Add a new team member",intro:"Creates the account directly in the Flexweg SQLite Auth database. The new user defaults to the editor role; promote them from the list below if they need admin access.",submit:"Create user",submitting:"Creating…"},actions:{editProfile:"Edit profile",promote:"Promote to admin",demote:"Demote to editor",disable:"Disable",enable:"Enable",delete:"Delete record"},descriptionGit:"Team members are the people with write access to the content repository. They appear here after their first sign-in; their role follows their repository permissions.",descriptionLocal:"This admin runs in single-user mode: content is stored in this browser and there are no accounts.",descriptionSqliteFile:"No user accounts with this backend: anyone who can open the admin can edit. Protect the admin folder at your hosting level. Author profiles below are informational."},xne={title:"Firestore setup needed",intro:"The post and page list pages need a couple of Firestore composite indexes to query efficiently. They have to be created manually — Firebase reserves index creation for project admins.",checking:"Checking your Firestore indexes…",missingCount_one:"{{count}} index missing:",missingCount_other:"{{count}} indexes missing:",openConsole:"Open Firebase Console to create",noUrl:"Couldn't extract the auto-suggest URL — see the README for the gcloud command.",howItWorks:"How this works",step1:"Click the link for each missing index — Firebase Console opens with the index definition pre-filled.",step2:'Click "Create" and wait 1–5 minutes for the index to build (status badge in the console).',step3:"Come back here and click Retry. Once both queries succeed, the admin loads.",retry:"Retry",retrying:"Retrying…",buildHint:"Indexes can take up to a few minutes to build after creation.",allReady:"All indexes ready.",unexpectedTitle:"Couldn't reach Firestore",unexpectedHint:"Check your network connection and Firestore rules. If you just created the indexes, wait a moment for them to finish building, then retry."},wne={appError:"Application error",loadAccountFailed:"Could not load your account",loadAccountHint:"If the problem persists, sign out and try again.",accountDisabled:"Account disabled",accountDisabledMessage:"Your access to this CMS has been disabled. Contact your administrator.",firebaseNotConfigured:"Firebase is not configured",firebaseEnvMissing:`The following env variables are missing:
|
|
3848
3848
|
{{vars}}
|
|
3849
3849
|
|
|
3850
|
-
Copy .env.example to .env, fill in your Firebase project credentials, and restart the dev server.`,adminEmailNotConfigured:"Admin email is not configured",adminEmailMessage:"VITE_ADMIN_EMAIL is missing in .env. Set it to the email of the bootstrap administrator.",consoleHint:"Check the browser console and your .env configuration. See the README for setup instructions."},kne={brandTitle:"Flexweg CMS",brandSubtitle:"Static publisher",login:{heading:"Sign in",intro:"Use the email and password your admin shared with you.",submit:"Sign in",submitting:"Signing in…"},fields:{name:"Display name (optional)",namePlaceholder:"Jane Doe",email:"Email",password:"Password",passwordHint:"At least 8 characters."},footer:"New accounts are created by an admin from the Users page.",errors:{invalidEmail:"Please enter a valid email address.",missingPassword:"Password is required.",passwordTooShort:"Password must be at least 8 characters."}},Sne=JSON.parse(`{"title":"Welcome to Flexweg CMS","subtitle":"First-time setup","intro":"Fill in your Firebase credentials, the bootstrap administrator account, and your Flexweg API key. The values are validated, written to your project (Firestore + a config.js file on Flexweg), and the admin reloads into the normal sign-in flow. You only do this once.","introFirebase":"Step 1 — Firebase. Fill in your Firebase project credentials and the bootstrap administrator account. We'll sign in, verify the email, and check that your Firestore rules pin this admin before continuing to the Flexweg step.","introFlexweg":"Step 2 — Flexweg. Fill in your Flexweg API key and site URL. We'll test the API, save the configuration to Firestore, upload config.js to your site, and sync theme assets.","continueToFlexweg":"Validate Firebase & continue","stepper":{"terms":"Terms","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Content & publishing","data":"Data","hosting":"Hosting","install":"Install"},"backend":{"title":"Choose a data backend","intro":"Pick where the CMS will store your posts, pages, users and settings. You can switch later from the Settings page (data is not migrated).","sqliteTitle":"Flexweg SQLite (recommended)","sqliteHint":"All data stays on your Flexweg site as a SQLite file. No external service. Auth is provided by Flexweg's SQLite API.","firebaseTitle":"Firebase","firebaseHint":"Use a Firebase project for Firestore + Auth. Free under the Spark plan. Real-time updates via onSnapshot.","continue":"Continue","markdownGitTitle":"Markdown files in a Git repository","markdownGitHint":"Posts as .md files on GitHub / GitLab (or a local clone). Each editor signs in with their own access token; every change is a commit. No database, works with several editors and machines.","localTitle":"This browser only","localHint":"Single user, no login, nothing to set up. Content stays in this browser (export it from Settings). Best for an admin running on your own computer."},"sqlite":{"heading":"Connect your Flexweg site","intro":"We'll use your master Flexweg API key ONCE to create a scoped token for the SQLite database. After install, the master key is discarded and only the scoped token (limited to this one SQLite file) is stored.","apiKeyHint":"Master Flexweg API key. Used only to install — never stored after.","detectedFromUrl":"Detected from URL","advanced":"Advanced settings (Site URL, SQLite path…)","pathHint":"Where the SQLite file lives on your Flexweg site. Folders are created automatically.","adminHeading":"Admin account","adminIntro":"Create the first user — this account gets admin rights automatically. Subsequent members are onboarded from the Users page once you're signed in.","passwordHint":"At least 8 characters.","submit":"Install SQLite database"},"terms":{"title":"Terms of use","intro":"Please read and accept the terms below before using Flexweg CMS. They are written in plain language to be quick to read.","section1":{"title":"1. Free service","body":"Flexweg CMS is provided to you free of charge by Flexweg. You can use it without limits with your Flexweg hosting — Flexweg will never bill you for using the CMS itself. Standard charges for your Flexweg hosting plan and your Firebase plan still apply, on the respective accounts you own."},"section2":{"title":"2. Provided as-is, no warranty","body":"The CMS is provided as-is. We work to keep it stable and improve it over time, but we cannot guarantee it will be free of bugs, defects or interruptions. Use it with the same caution you would any tool you didn't write yourself: keep backups of important content."},"section3":{"title":"3. Your content, your responsibility","body":"You are solely responsible for the content you publish through the CMS — text, images, videos, forms, code embeds, and any other media. You must comply with applicable law in your jurisdiction (and in the jurisdictions you target), copyright, image and personality rights, personal data protection rules, and any third-party terms (e.g. embedded fonts or videos). Flexweg is not responsible for content published by users of the CMS."},"section4":{"title":"4. Your Firebase account, your security","body":"The CMS stores its data in your own Firebase project. You are responsible for securing that project: choose a strong password for the bootstrap admin account, set up Firestore security rules as documented, rotate your API keys when needed, and review who has access. Flexweg cannot be held responsible for unauthorised access, data leaks, hacks or losses caused by misconfiguration or compromise of your Firebase account."},"section5":{"title":"5. Limitation of liability","body":"Flexweg cannot be held responsible for any loss of revenue, loss of data, loss of business opportunity, or any direct or indirect damages arising from the use, misuse, or unavailability of the CMS. Where applicable law requires Flexweg to assume some liability for the CMS, that liability is limited to the amount actually paid to Flexweg for the CMS over the past 12 months — which is zero, since the CMS is free."},"section6":{"title":"6. Your data stays yours","body":"Content you create with the CMS is stored in your own Firebase project (text, settings, media metadata) and on your own Flexweg hosting (the published HTML, images, theme assets). The CMS itself does not transmit your content to any third-party service. Plugins or themes you choose to enable may have their own behaviour — review what they do before activating them."},"section7":{"title":"7. Fair use","body":"Use of the CMS for unlawful, fraudulent, or harmful activities, or in ways that breach Flexweg's general terms of use, may result in suspension of your Flexweg hosting access. We may also update these CMS terms over time; significant changes will be communicated through the admin or via email."},"accept":"I have read and accept the Terms of use.","continue":"Continue to configuration","back":"Back"},"sections":{"firebase":"Firebase","admin":"Bootstrap administrator","flexweg":"Flexweg API"},"help":{"firebase":"Find these values in Firebase Console → Project settings → General → Your apps → SDK setup and configuration.","admin":"Use an existing user from Firebase Authentication. Anyone signing in with this email is treated as admin and bypasses the user-record check. Create the user via Firebase Console → Authentication if it doesn't exist yet.","flexweg":"Generate a permanent API key in your Flexweg account → API. The site URL is the public address of your Flexweg site (e.g. https://your-site.flexweg.com).","flexwegApiKeyHint":"Get your API key from your Flexweg account settings.","flexwegApiKeyLink":"Open account settings"},"fields":{"apiKey":"API key","authDomain":"Auth domain","projectId":"Project ID","storageBucket":"Storage bucket","messagingSenderId":"Messaging sender ID","appId":"App ID","adminEmail":"Email","adminPassword":"Password","flexwegApiKey":"API key","flexwegSiteUrl":"Site URL","flexwegApiBaseUrl":"API base URL","sqlitePath":"SQLite path"},"submit":"Save & continue","submitting":"Setting up…","success":"Setup complete!","reloadingHint":"Reloading the admin in a moment — sit tight.","footer":"These values are saved on your project (Firestore + Flexweg). They are not sent anywhere else.","steps":{"signInFirebase":"Signing in to Firebase…","testFlexweg":"Testing Flexweg API…","writeFirestore":"Saving configuration…","uploadConfig":"Uploading config.js to Flexweg…","syncThemes":"Syncing theme assets to Flexweg…","sqliteInstall":"Creating scoped SQLite token…","sqliteRegisterAdmin":"Registering the admin account…","sqliteSchema":"Bootstrapping SQLite schema…"},"stepsDone":{"sqliteInstall":"Scoped SQLite token issued","sqliteRegisterAdmin":"Admin registered and signed in","sqliteSchema":"SQLite schema ready"},"errors":{"missingFields":"Please fill every field.","rootDeploymentTitle":"The admin must live in a subfolder, not at the site root.","rootDeploymentHint":"Move the admin files (index.html, config.js, runtime/, …) into a subfolder on Flexweg — for example /admin/ or any random name like /erf34f654GH3/ for obscurity. Then reload the admin from that subfolder URL and re-run the setup.","firebaseAuthGeneric":"Could not sign in to Firebase.","firebaseAuthInvalidCredential":"Firebase rejected the email + password combination.","firebaseAuthInvalidCredentialHint":"Modern Firebase projects ship with email-enumeration protection on, which returns the same error whether the password is wrong, the user doesn't exist, or the user signs in with a different provider. Things to check:\\n• Re-enter the password — copy/paste from a password manager to rule out typos. Minimum length is 6 characters.\\n• Open Firebase Console → Authentication → Users and confirm the email exists. Check the 'Providers' column: if it shows only Google (or another provider) and not 'Email/Password', set or reset the password from the user's row menu (⋮ → Reset password).\\n• Verify the email spelling matches exactly what's stored in Firebase.","firebaseAuthUserNotFound":"No Firebase user with this email. Create one in Firebase Console → Authentication → Users first.","firebaseAuthInvalidEmail":"The admin email is not a valid email address.","firebaseInvalidApiKey":"The Firebase API key is invalid. Double-check the value from Firebase Console.","firebaseNetwork":"Network error while signing in to Firebase. Check your connection.","firebaseTooManyRequests":"Too many sign-in attempts. Try again in a moment or reset the password from Firebase Console.","firebaseOperationNotAllowed":"Email/password sign-in is not enabled on this Firebase project. Open Firebase Console → Authentication → Sign-in method and enable the Email/Password provider.","firebaseUserDisabled":"This Firebase user account is disabled. Re-enable it from Firebase Console → Authentication → Users.","wrongAdminEmail":"The Firebase account you signed in with does not match the admin email you typed. Try again.","rulesNotPinnedTitle":"Firestore rules don't recognize you as bootstrap admin yet.","rulesNotPinnedHint":"Open Firebase Console → Firestore → Rules and replace the value of \`bootstrapAdminEmail()\` with: {{email}} — then click Publish. The rules template in the README ships with a \`you@example.com\` placeholder that must be replaced with your real admin email. After publishing the updated rules, click Submit here again.","flexwegAuth":"Flexweg API key rejected. Check the value from your Flexweg account → API.","flexwegNetwork":"Network error while contacting Flexweg. Check the API base URL and your connection.","flexwegHttp":"Flexweg API error ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore rejected the configuration write.","firestoreRulesHint":"Open Firebase Console → Firestore → Rules and make sure the bootstrap admin email is set to '{{email}}'. The README has a copy-pastable rules template.","firestoreOther":"Firestore write failed","uploadFailed":"Could not upload config.js to Flexweg","generic":"Something went wrong."},"docstore":{"contentTitle":"Content repository","contentIntro":"Where your posts, pages and settings are stored as Markdown + JSON files. An empty repository is fine — the CMS creates the files.","provider":"Repository","localClone":"Local folder (git clone)","localCloneHint":"Pick the folder of your clone. Sync it with your usual git client — the CMS reads and writes files, it doesn't run git.","contentDir":"Content folder in the repo","privateRepo":"Use a private repository: drafts are stored there.","folderRequired":"Choose the content folder first.","checking":"Checking repository access…","publishIntro":"Where the generated site is published. You can change it later in Settings.","existingSite":"This repository is already set up — the site keeps publishing to: {{target}}. You can change it later in Settings (secret keys, if any, must be entered again there).","install":"Install","steps":{"config":"Saving configuration…","content":"Loading content…","target":"Saving publish target…","testTarget":"Testing the publish target…"},"doneTitle":"All set!","doneBody":"The configuration is saved in this browser. To spare other editors this setup, download config.js and replace the one in the admin folder of your hosting.","downloadConfig":"Download config.js","open":"Open the admin","footer":"Content stays in your repository or in this browser; access tokens never leave this browser."},"data":{"title":"1. Where do you store your data?","intro":"Your posts, pages, users and settings — the admin's own data. This is independent from where the public site is hosted (next step).","localNote":"Nothing to configure: content is stored in this browser. Export it from Settings to back it up or move it later.","options":{"sqlite-file":{"title":"SQLite","hint":"A SQLite database stored on the hosting you choose in the next step (Flexweg, your server, S3, Git…). No user accounts — or Flexweg's SQLite service with accounts if you host on Flexweg."},"flexweg-sqlite":{"title":"SQLite (Flexweg service)","hint":"A SQLite database run by Flexweg's service, with built-in user accounts. Needs a Flexweg account, wherever the site is hosted."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth in your Google project. Real-time, free Spark plan."},"markdown-git":{"title":"Markdown files in Git","hint":"Posts as .md files in a GitHub / GitLab repo (or a local clone). Each editor uses their own token; every change is a commit."},"local":{"title":"This browser","hint":"Single user, no login, nothing to set up. Ideal for an admin running on your computer."}}},"hosting":{"title":"2. Where is the site published?","intro":"Where the generated static site (HTML, CSS, images) is uploaded each time you publish. You can change it later in Settings.","existing":"This content repository already publishes to the target below. Keep it or pick another one."},"install":{"title":"3. Install","intro":"Check the summary, then install.","data":"Data","hosting":"Hosting","saveTarget":"Saving the publish target…","noteConfigJs":"The admin configuration (config.js) is uploaded next to the admin on Flexweg when possible; otherwise you'll be offered to download it.","noteLocalConfig":"The configuration is saved in this browser; you'll be offered config.js to put in the admin folder so other editors skip this setup."},"sqliteFile":{"security":"No user accounts: anyone who can open this admin can edit the content — protect the admin folder at your hosting level. The database file is served like any other file: keep it encrypted, or store it in a separate private location.","intro":"Where the database file is stored. It is read and saved by this admin through the same connectors as the hosting.","path":"Database file path","pathHint":"Created on first save if it doesn't exist yet. With a Git repository, every save is a commit — prefer a repository or branch that doesn't trigger a site build.","existing":"existing database","new":"new database","dataNote":"Nothing to configure here: the database will be stored on the hosting you choose in the next step.","heading":"SQLite database","flexwegService":"Use Flexweg's SQLite service","flexwegServiceHint":"The database is run by Flexweg and comes with built-in user accounts (email + password). Otherwise it is a plain file on this hosting, without accounts.","summaryFile":"File {{path}} on this hosting","summaryService":"Flexweg SQLite service ({{path}})","encrypt":"Encrypt the database","encryptHint":"Recommended on a public hosting: the file is unreadable without the passphrase. Each new browser asks for it once.","passphrase":"Passphrase","passphraseHint":"Save it in your password manager now: without it, nobody can open the database — not even you.","copy":"Copy","copied":"Copied","generate":"New","passphraseTooShort":"The passphrase must be at least 12 characters long.","existingEncrypted":"An encrypted database already exists at this path: enter its passphrase.","separate":"Store the database in a separate private location","separateHint":"E.g. a private S3 / R2 bucket or a private Git repository: the database is then never served by the public site.","summaryEncrypted":"encrypted","summaryLocation":"stored in {{location}}","locationLabel":"Database location","gitBranchNote":"The database is kept on the branch {{branch}} of this repository, which is never published: saving content doesn't rebuild the site.","summaryBranch":"on branch {{branch}}"},"adminHosting":{"deploying":"Copying the admin to the site…","label":"Also host the admin on this site","hint":"The admin is copied to {{url}} with its config.js (no secrets inside) — every editor can then open it there. Each editor still signs in with their own access.","folder":"Admin folder","alreadyHere":"This admin already runs from this site: its config.js will be updated in place.","doneBody":"The admin is now on your site. On GitHub Pages, enable Pages for the repository first if it isn't yet (Settings → Pages), then open it:","open":"Open the online admin","continueHere":"Continue in this admin"}}`),Ene={actions:{upload:"Uploading file",delete:"Deleting file",rename:"Renaming file",get:"Reading file",list:"Listing files",createFolder:"Creating folder",renameFolder:"Renaming folder",deleteFolder:"Deleting folder",storageLimits:"Reading storage limits",commit:"Publishing changes"},errors:{configMissing:"The publish target is not configured. Set it up in admin Settings before publishing.",network:"{{action}}: network error or CORS blocked. Check your connection.",auth:"{{action}}: authentication failed. Check the publish target credentials in Settings.",notFound:"{{action}}: target not found on the publish target.",tooLarge:"{{action}}: file too large for the publish target.",rateLimited:"{{action}}: too many requests, please retry in a moment.",serverError:"{{action}}: publish target server error ({{status}}). Please retry.",generic:"{{action}} failed ({{status}}){{detail}}.",unsupported:'{{action}}: not supported by the "{{connector}}" publish target.',unknownConnector:'Unknown publish target "{{connector}}". Check Settings → Publish target.',folderAccess:"No access to the local folder. Open Settings → Publish target and click “Reconnect folder”."}},_ne={log:{rendering:"Rendering page…",uploading:"Uploading {{path}}…",deleting:"Deleting {{path}}…",regenerating:"Regenerating listings…",skipped:"Skipped {{path}} (no changes)",done:"Published to {{url}}",failed:"Failed: {{error}}"}},Cne={errors:{notConnected:"Not connected to the content repository. Sign in again with your access token.",conflict:"Someone else changed this item in the meantime. Their version is now shown — re-apply your change.",sqliteUnsupported:`The "{{connector}}" target can't store a database file.`}},Ane={target:"Publish target",settingsTitle:"Publish target",settingsHelp:"Where the rendered site is uploaded when you publish. Credentials are stored with your content backend (or kept in this browser for Git content repositories) and are readable by every admin.",saved:"Publish target saved. Run Regenerate → Everything to publish the whole site to the new target.",test:"Test connection",testOk:"Connection OK",testFailed:"Connection failed",names:{flexweg:"Flexweg","git-pages":"Git repository (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"S3-compatible bucket (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Your own server (PHP bridge)","browser-mirror":"Download as ZIP","local-folder":"Local folder on this computer"},hints:{flexweg:"Uploads through the Flexweg Files API.","git-pages":"Each publish is one commit to the repo; the host rebuilds the site from it.",s3:"Needs a CORS rule on the bucket allowing this admin's origin, and website hosting (or a CDN) to serve index.html files.","php-bridge":"Upload external/bridges/php/flexweg-bridge.php to your server, set its API key, then fill in its URL here.","browser-mirror":"The site is kept in this browser; download the ZIP and upload it anywhere by hand.","local-folder":"Writes the site straight into a folder (Chrome / Edge). Serve it locally or push it with your own tools."},fields:{flexweg:{apiKey:"API key",siteUrl:"Site URL",apiBaseUrl:"API base URL"},"git-pages":{host:"Hosting",provider:"Git provider",owner:"Owner (user or organisation)",repo:"Repository",project:"Project path",branch:"Branch",dir:"Folder in the repo",token:"Access token",siteUrl:"Public site URL",apiBaseUrl:"API URL (self-hosted only)"},s3:{endpoint:"Endpoint",region:"Region",bucket:"Bucket",prefix:"Key prefix (optional)",accessKeyId:"Access key ID",secretAccessKey:"Secret access key",siteUrl:"Public site URL",forcePathStyle:"Path-style URLs (MinIO, R2, most compatibles)",publicRead:"Make uploaded files public (public-read ACL) — for buckets not made public by a bucket policy (OVHcloud, Scaleway…). Leave off on AWS buckets that enforce bucket-owner ownership."},"php-bridge":{apiBaseUrl:"Bridge URL",apiKey:"Bridge API key",siteUrl:"Public site URL"},"browser-mirror":{siteUrl:"Public site URL (optional)"},"local-folder":{siteUrl:"URL the folder is served at (optional)"}},help:{flexweg:{apiKey:"Generated from your Flexweg account → API."},"git-pages":{host:"Cloudflare Pages: connect the project to this repo with no build command and the output folder below. Works with private repos.",dir:'Leave empty for the repo root. GitHub Pages: "" or "docs". GitLab Pages: "public".',token:"Fine-grained token on this repo with Contents: read & write (GitHub) — add Pages: read & write to let the CMS switch GitHub Pages on — or a token with the api scope (GitLab). Leave empty to use each editor's own token when content is on the same provider.",siteUrl:"e.g. https://user.github.io/repo — a sub-folder URL is fine, links are adjusted automatically."},s3:{endpoint:"Leave empty for AWS (built from the region). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"The bucket website URL or your CDN domain."},"php-bridge":{apiBaseUrl:"The full URL of flexweg-bridge.php on your server (HTTPS)."},"browser-mirror":{siteUrl:"Where you will upload the ZIP — used for absolute URLs (sitemaps, RSS, media)."},"local-folder":{siteUrl:"e.g. http://localhost:8080 when a local web server serves the folder."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (connected to the repo)","gitlab-pages":"GitLab Pages",other:"Other (Netlify, Vercel, server git pull…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Choose folder…",change:"Change folder…",reconnect:"Reconnect folder",unsupported:"This browser can't write to local folders. Use Chrome or Edge."},mirror:{download:"Download site (ZIP)",count:"{{count}} files in this browser"},adminHosting:{title:"Admin on this site",help:"Copy this admin to the publish target (first deployment, or update after a new version). Its config.js holds no secrets.",deploy:"Deploy / update the admin",deployed:"Admin deployed ({{count}} files) — {{url}}"},pages:{enabled:"GitHub Pages enabled for this repository — the site will be online in about a minute.",enableHint:'Publish succeeded. To put the site online, enable GitHub Pages for {{repo}}: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Or give the token the "Pages: read and write" permission and the CMS will do it.)'},siteUrl:{mismatch:"The site's public URL (Settings → Site) is {{site}}, but this target serves the site at {{target}}. Links, CSS and sitemaps follow the site URL — they will be wrong on this hosting.",use:"Use {{url}} for the site",updated:"Site URL updated. Run Regenerate → Everything to republish the pages with the new links."}},Tne={heading:"Connect to the content repository",tokenIntro:"Content is stored in the {{provider}} repository {{repo}}. Sign in with your own personal access token — your repository permissions decide your role (write access = editor, admin / maintainer = admin).",token:"Personal access token",tokenHelpGithub:"Fine-grained token, access to this repository only, permission Contents: read and write.",tokenHelpGitlab:"Token with the api scope, Developer role or higher on this project.",createToken:"Create a token",connect:"Connect",tokenStorage:"The token is kept in this browser only. Signing out forgets it.",failed:"This token can't write to the repository (invalid, expired, or read-only). Check its permissions.",folderIntro:"Content is stored in a folder on this computer (typically a git clone you sync with your own git client). Grant this browser access to it — browsers ask again after every reload.",openFolder:"Open content folder"},Ine={flexweg:{title:"Flexweg",short:"Flexweg hosting",hint:"Uploads through the Flexweg Files API. API key from your Flexweg account."},"github-pages":{title:"GitHub Pages",short:"Free, from a GitHub repo",hint:"Each publish is one commit to the repo; GitHub Pages serves it. Settings → Pages → Deploy from a branch. Public repos on the free plan."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Free, private repos OK",hint:"The CMS commits the site to a GitHub / GitLab repo; connect a Cloudflare Pages project to it (no build command, output folder = the folder below)."},"gitlab-pages":{title:"GitLab Pages",short:"Free, from a GitLab repo",hint:"Each publish is one commit; the CMS adds a minimal .gitlab-ci.yml that publishes the public/ folder."},"git-other":{title:"Netlify, Vercel…",short:"Any host that deploys a repo",hint:"The CMS commits the site to a Git repo; connect your host (Netlify, Vercel, a server running git pull…) to that repo."},s3:{title:"S3 / R2 / B2…",short:"Object storage bucket",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Needs a CORS rule on the bucket and website hosting or a CDN in front."},"own-server":{title:"Your own server (FTP / SFTP)",short:"Shared hosting, VPS…",hint:"Browsers can't speak FTP or SFTP: upload the PHP bridge (external/bridges/php/flexweg-bridge.php) once with your FTP client, set its API key, then fill in its URL here. Works on any PHP host."},"local-folder":{title:"Local folder",short:"On this computer",hint:"Writes the site into a folder of this computer (Chrome / Edge). Serve it locally or push it with your own tools."},zip:{title:"Download as ZIP",short:"Upload it by hand",hint:"The site is kept in this browser; download a ZIP from Settings and upload it anywhere (Netlify Drop, FTP client…)."}},Nne={heading:"Connect to the database",intro:"This admin stores its content in {{path}}. Enter the access credentials for this browser.",storage:"Credentials are kept in this browser only. Signing out forgets them.",passphrase:"Database passphrase",passphraseHint:"The database is encrypted. Enter the passphrase chosen at install (kept in this browser only).",passphraseWrong:"Wrong passphrase: the database could not be opened.",passphraseMissing:"Enter the database passphrase."},Pne={common:ine,auth:ane,nav:one,dashboard:lne,posts:cne,pages:une,taxonomies:dne,media:hne,themes:fne,plugins:pne,externalInstall:mne,externalLoader:gne,menus:bne,settings:yne,users:vne,firestoreSetup:xne,errors:wne,identity:kne,setup:Sne,flexweg:Ene,publish:_ne,docstore:Cne,connectors:Ane,gitAccess:Tne,hosting:Ine,sqliteAccess:Nne},Rne={save:"Enregistrer",saving:"Enregistrement…",saved:"Enregistré",cancel:"Annuler",delete:"Supprimer",deleting:"Suppression…",edit:"Modifier",create:"Créer",search:"Rechercher",loading:"Chargement…",yes:"Oui",no:"Non",confirm:"Confirmer",back:"Retour",next:"Suivant",previous:"Précédent",close:"Fermer",all:"Tous",none:"Aucun",actions:"Actions",name:"Nom",slug:"Slug",description:"Description",status:"Statut",createdAt:"Créé le",updatedAt:"Mis à jour",publishedAt:"Publié le",language:"Langue",darkMode:"Mode sombre",lightMode:"Mode clair",signOut:"Déconnexion",administrator:"Administrateur",editor:"Éditeur",appName:"Flexweg CMS"},jne={signIn:"Connexion",signingIn:"Connexion…",email:"Email",password:"Mot de passe",emailPlaceholder:"vous@entreprise.com",passwordPlaceholder:"••••••••",forgotPassword:"Mot de passe oublié ?",resetEmailSent:"Email de réinitialisation envoyé à {{email}}.",enterEmailFirst:"Saisissez d'abord votre email, puis cliquez sur réinitialiser.",emailPasswordRequired:"Email et mot de passe requis.",signInSubtitle:"Utilisez votre email professionnel et votre mot de passe.",footer:"Les demandes de compte passent par votre administrateur.",errors:{invalidEmail:"Adresse email invalide.",invalidCredentials:"Email ou mot de passe invalide.",tooManyRequests:"Trop de tentatives. Réessayez plus tard ou réinitialisez votre mot de passe.",userDisabled:"Ce compte a été désactivé.",networkFailed:"Erreur réseau. Vérifiez votre connexion.",generic:"Échec de l'authentification."}},Mne={openMenu:"Ouvrir le menu",closeMenu:"Fermer le menu",dashboard:"Tableau de bord",posts:"Articles",pages:"Pages",taxonomies:"Catégories & Tags",media:"Médias",themes:"Thèmes",themeSettings:"Réglages du thème",plugins:"Plugins",menus:"Menus",users:"Utilisateurs",settings:"Réglages"},Lne={title:"Tableau de bord",welcome:"Bienvenue, {{email}}.",stats:{totalPosts:"Articles",totalPages:"Pages",online:"En ligne",drafts:"Brouillons"}},Dne={title:"Articles",newPost:"Nouvel article",noPosts:"Aucun article. Créez le premier pour commencer.",noPostsInFilter:"Aucun article ne correspond au filtre courant.",search:{placeholder:"Rechercher des articles…",clear:"Effacer la recherche",noResults:"Aucun article ne correspond à votre recherche."},pagination:{previous:"Précédent",next:"Suivant",showing:"Affichage {{from}}–{{to}} sur {{total}}",pageOf:"Page {{page}} sur {{total}}"},bulk:{selectedCount_one:"{{count}} sélectionné",selectedCount_other:"{{count}} sélectionnés",selectPage_one:"Sélectionner {{count}} sur cette page",selectPage_other:"Sélectionner les {{count}} de cette page",deselectPage:"Désélectionner la page",allOnPageSelected_one:"{{count}} sur cette page sélectionné.",allOnPageSelected_other:"Les {{count}} de cette page sont sélectionnés.",selectAllMatching_one:"Sélectionner l'article correspondant",selectAllMatching_other:"Sélectionner les {{count}} articles correspondants",allMatchingSelected_one:"L'article correspondant est sélectionné.",allMatchingSelected_other:"Les {{count}} articles correspondants sont sélectionnés.",selectOne:"Sélectionner « {{title}} »",publish:"Publier ({{count}})",publishing:"Publication…",publishedCount:"{{ok}} publié(s), {{failed}} échec(s).",unpublish:"Dépublier ({{count}})",unpublishing:"Dépublication…",unpublishedCount:"{{ok}} dépublié(s), {{failed}} échec(s).",delete:"Supprimer",deleting:"Suppression…",deletedCount:"{{ok}} supprimé(s), {{failed}} échec(s).",confirmDelete_one:"Supprimer {{count}} article ? Cette action dépublie de Flexweg et ne peut pas être annulée.",confirmDelete_other:"Supprimer {{count}} articles ? Cette action dépublie de Flexweg et ne peut pas être annulée.",noDraftSelected:"Aucun article en brouillon sélectionné.",noOnlineSelected:"Aucun article en ligne sélectionné.",clear:"Effacer la sélection"},filters:{all:"Tous",draft:"Brouillon",online:"En ligne"},fields:{title:"Titre",slug:"Slug",excerpt:"Extrait",content:"Contenu",category:"Catégorie",tags:"Tags",heroImage:"Image d'en-tête",seoTitle:"Titre SEO",seoDescription:"Description SEO",createdAt:"Date de création",updatedAt:"Dernière mise à jour",publishedAt:"Date de publication"},edit:{newTitle:"Nouvel article",editTitle:"Modifier l'article",saved:"Enregistré.",savedAndRepublished:"Enregistré et republié.",saveFailed:"Échec de l'enregistrement.",saveAndRepublish:"Enregistrer & republier",draftSaved:"Brouillon enregistré.",slugCollision:{post:"Cette URL est déjà utilisée par l'article : « {{label}} ».",page:"Cette URL est déjà utilisée par la page : « {{label}} ».",category:"Cette URL est déjà utilisée par la catégorie : « {{label}} »."},publish:"Publier",unpublish:"Dépublier",publishing:"Publication…",unpublishing:"Dépublication…",titlePlaceholder:"Ajouter un titre",permalink:"Permalien",slugFormatHint:"Minuscules ASCII séparées par des tirets uniquement.",slugAutoSuffixed:"Suffixe ajouté car « {{base}} » est déjà utilisé par {{owner}}.",slugAutoSuffixedOwner:{post:"le post : « {{label}} »",page:"la page : « {{label}} »",category:"la catégorie : « {{label}} »"},saveBlocked:{titleRequired:"Ajoutez un titre avant d'enregistrer.",slugRequired:"Un titre et un slug d'URL sont requis pour enregistrer.",slugInvalid:"Format de slug invalide (minuscules ASCII + tirets).",slugCollision:"Résolvez le conflit d'URL avant d'enregistrer."},viewPublished:"Voir",confirmDelete:"Supprimer cet élément ?",inspector:{document:"Document",block:"Bloc",blockEmpty:"Sélectionnez un bloc dans l'éditeur pour voir ses options.",publishing:"Publication",permalink:"Permalien",categories:"Catégories & tags",featured:"Image à la une",seo:"SEO",excerpt:"Extrait",dates:"Dates"},blocks:{addBlock:"Ajouter un bloc",transform:"Transformer en",moveUp:"Déplacer vers le haut",moveDown:"Déplacer vers le bas",duplicate:"Dupliquer",remove:"Supprimer le bloc",paragraph:"Paragraphe",heading2:"Titre 2",heading3:"Titre 3",bulletList:"Liste à puces",orderedList:"Liste numérotée",blockquote:"Citation",codeBlock:"Code",image:"Image",horizontalRule:"Séparateur",categories:{text:"Texte",media:"Médias",layout:"Mise en page",embed:"Intégrations",advanced:"Avancé"},noSettings:"Ce bloc n'a pas de réglages.",noSelection:"Sélectionnez un bloc dans l'éditeur pour voir ses options.",slash:{noResults:"Aucun bloc ne correspond."}}},status:{draft:"Brouillon",online:"En ligne"},preview:{title:"Aperçu",rendering:"Génération de l'aperçu…",error:"Échec de l'aperçu : {{error}}",viewports:{mobile:"Mobile",tablet:"Tablette",desktop:"Bureau"}}},Fne={title:"Pages",newPage:"Nouvelle page",noPages:"Aucune page.",homeBadge:"Accueil",homeBadgeTooltip:"Utilisée comme page d'accueil du site"},One={title:"Catégories & Tags",categories:"Catégories",tags:"Tags",newCategory:"Nouvelle catégorie",newTag:"Nouveau tag",noCategories:"Aucune catégorie.",noTags:"Aucun tag.",slugCollision:"Ce slug est déjà utilisé par « {{label}} ».",seo:{button:"SEO",buttonTitle:"Modifier les balises SEO",title:"Balises SEO",subtitle:"Titre et description personnalisés pour la page d'archive « {{name}} ».",metaTitle:"Titre meta",metaTitleHint:"Utilisé comme balise <title>. Valeur par défaut : le nom du terme.",metaDescription:"Description meta",metaDescriptionHint:"Utilisée comme méta-description de la page. Valeur par défaut : la description du terme."}},zne={title:"Médiathèque",upload:"Téléverser",uploading:"Téléversement…",finalizing:"Finalisation…",uploadFailed:"Échec du téléversement",retry:"Réessayer",noMedia:"Aucun média.",alt:"Texte alternatif",caption:"Légende",filename:"Nom du fichier",size:"Taille",type:"Type"},Une={title:"Thèmes",active:"Actif",activate:"Activer",installExternal:"Installer un thème",uninstallDisabledTitle:"Activez un autre thème avant de désinstaller celui-ci.",syncAssets:"Synchroniser le thème",regenerateSite:"Régénérer le site",regenerating:"Régénération…",regenerate:{button:"Régénérer",running:"En cours…",groupBuiltins:"Site",groupPlugins:"Plugins",home:"Page d'accueil uniquement",homeHelp:"Régénère index.html seulement — l'option la plus rapide.",allHtml:"Toutes les pages HTML",allHtmlHelp:"Tous les posts, pages, archives et listings — plus les snapshots menu / posts / authors JSON.",repair:"Réparer les URLs",repairHelp:"Recalcule l'URL canonique de chaque post en ligne et déplace les fichiers qui ont atterri au mauvais endroit. Utile après un import effectué avant que les termes ne soient synchronisés.",assets:"Assets du thème",assetsHelp:"Envoie le CSS et les scripts du thème actif vers /theme-assets/.",everything:"Tout",everythingHelp:"Assets thème + tous les HTML + chaque sortie plugin. Option la plus lente.",noPluginTargets:"Aucune régénération de plugin — activez un plugin qui supporte la régénération."},confirmSwitch:{title:"Passer à {{theme}} ?",body:"Le changement de thème nécessite de re-pousser les assets du thème et de régénérer toutes les pages publiées pour que le nouveau look se propage partout. Cela peut prendre un moment.",confirm:"Changer & régénérer",cancel:"Annuler"}},Bne={title:"Plugins",enabled:"Activé",disabled:"Désactivé",enable:"Activer",disable:"Désactiver",configure:"Configurer",author:"auteur",learnMore:"En savoir plus",mustUseBadge:"Indispensable",installExternal:"Installer un plugin",tabs:{regular:"Plugins",mustUse:"Indispensables"}},$ne={titlePlugin:"Installer un plugin",titleTheme:"Installer un thème",labelPlugin:"plugin",labelTheme:"thème",intro:"Déposez un fichier ZIP contenant un bundle de {{label}} (manifest.json + bundle.js à la racine). Le {{label}} sera uploadé sur votre site Flexweg et enregistré après un rechargement. Ré-uploader un ZIP avec le même id de manifest met à jour l'entrée existante en place — pas besoin de désinstaller.",zipField:"Fichier ZIP du bundle",install:"Installer",installing:"Installation…",installSuccess:"{{name}} installé ({{count}} fichiers uploadés). Rechargement…",upgradeSuccess:"{{name}} mis à jour de v{{previousVersion}} à v{{newVersion}} ({{count}} fichiers uploadés). Rechargement…",installedTitle:"Déjà installé",bundledDefaultsTitle:"Plugins/thèmes bundlés disponibles",bundledDefaultsHint:"{{count}} plugin/thème bundlé est actuellement désinstallé. Restaurez-les pour récupérer ce qui était livré avec cette version de l'admin.",bundledDefaultsRestore:"Restaurer",bundledDefaultsRestored:"{{plugins}} plugin(s) et {{themes}} thème(s) restaurés. Rechargement…",uninstall:"Désinstaller",uninstallSuccess:"{{id}} désinstallé. Rechargement…",confirmUninstall:"Désinstaller {{id}} ? Les fichiers seront supprimés de Flexweg.",errors:{"no-manifest":"Le ZIP n'a pas de manifest.json à sa racine.","invalid-manifest":"Le manifest.json est invalide (champ requis manquant ou JSON cassé).","incompatible-api":"Le bundle a été buildé pour une version d'API runtime incompatible.","no-bundle":"Le ZIP ne contient pas le fichier d'entrée déclaré dans le manifest.","fetch-manifest":"Impossible de lire le external.json actuel sur Flexweg.","upload-failed":"Échec de l'upload — vérifiez votre clé API Flexweg et votre connexion."}},Hne={someFailed:"{{count}} bundle(s) externe(s) ont échoué au chargement. Voir la console du navigateur."},Vne={title:"Menus",header:"Menu d'en-tête",footer:"Menu de pied de page",label:"Libellé",saveAndPublish:"Enregistrer & générer",discard:"Annuler",saved:"Menus enregistrés et publiés.",saveFailed:"Impossible d'enregistrer les menus.",unsavedChanges:"Modifications non enregistrées."},qne={title:"Réglages",tabs:{general:"Général"},site:{title:"Site",siteTitle:"Titre du site",siteDescription:"Description du site",siteLanguage:"Langue du site",siteLanguageHelp:`Code BCP-47 (ex. en, fr-CA) injecté dans <html lang="…"> de chaque page publiée. Le préfixe est utilisé pour résoudre la langue des libellés sitemap / RSS et des chaînes intégrées au thème ; les locales non supportées retombent sur l'anglais.`,siteLanguageResolved:"Les traductions utiliseront : {{label}}",baseUrl:"URL publique du site",postsPerPage:"Articles par page",homeMode:"Contenu de la page d'accueil",homeLatest:"Derniers articles",homeStatic:"Page statique",homePage:"Page d'accueil",discourageIndexing:"Décourager les moteurs de recherche d'indexer ce site",discourageIndexingHelp:"Si activé, chaque page publiée porte une balise meta noindex/nofollow et le robots.txt interdit tous les robots. Reproduit le comportement de WordPress — utile pour les sites de préproduction ou les revues avant lancement. Les moteurs qui respectent la directive n'indexeront pas le site.",discourageRegenerateHint:"Réglage d'indexation sauvegardé. Cliquez sur « Tout régénérer » dans Thèmes pour appliquer le changement à toutes les pages publiées et au robots.txt."},flexweg:{title:"API Flexweg",apiKey:"Clé API",apiKeyHelp:"Générée depuis votre compte Flexweg → API.",siteUrl:"URL du site",siteUrlHelp:"URL publique de votre site Flexweg sans slash final.",apiBaseUrl:"URL de base de l'API",storageHelpFirebase:"Stockée dans Firestore (config/flexweg). Lecture par tout membre connecté, écriture admin uniquement.",storageHelpSqlite:"Stockée dans la table SQLite locale config. Lecture par tout membre connecté, écriture admin uniquement."},backend:{title:"Backend de données",active:"Backend actif :",switchButton:"Changer de backend…",confirmTitle:"Les données actuelles seront perdues.",confirmBody:"Le basculement efface la configuration en mémoire et recharge sur le formulaire de configuration. Le nouveau backend démarre vide — les données du backend précédent restent où elles sont (dans Firestore ou en tant que fichier .sqlite sur Flexweg), mais le CMS ne les lira plus jusqu'au prochain basculement.",confirmYes:"Oui, changer de backend",downloadBackup:"Télécharger une sauvegarde du fichier .sqlite",downloadBackupHelp:"à faire avant de changer de backend.",markdownGit:"Markdown — {{source}}",localFolder:"dossier local",localBrowser:"Ce navigateur (local, un seul utilisateur)",sqliteFile:"Fichier SQLite — {{location}}"},performance:{title:"Performance",help:"Comment l'admin charge articles et pages. Le mode par défaut fonctionne sur le plan gratuit de Firestore sans configuration ; le mode paginé est destiné aux très gros sites et exige une création d'index ponctuelle.",mode:"Mode de chargement",modeGlobal:"Standard (aucune configuration requise)",modePaginated:"Pagination côté serveur (index Firestore requis)",globalHelp:"Charge toute la collection d'articles dans une subscription temps réel. Tri, filtre et recherche se font en mémoire. Recommandé pour les sites de moins de ~5 000 articles.",paginatedHelp:"Subscriptions paginées par curseur, une page à la fois. Exige des index composites Firestore — voir README. Recommandé pour les très gros sites.",savedReload:"Enregistré. Rechargez l'admin pour appliquer le nouveau mode."},editor:{title:"Éditeur",help:"Typographie utilisée dans l'éditeur d'articles / pages. Indépendante du thème public.",fontFamily:"Police",bodySize:"Taille du corps",h1Size:"Taille H1",h2Size:"Taille H2",h3Size:"Taille H3",sizeHelp:"Longueur CSS, ex. 16px ou 1rem. Laisser vide pour la valeur par défaut.",reset:"Réinitialiser"},profile:{title:"Profil",adminLocale:"Langue de l'administration",adminLocaleHelp:"Langue utilisée par l'interface d'administration. Sauvegardée dans votre profil.",firstName:"Prénom",lastName:"Nom",headline:"Titre",headlinePlaceholder:"ex. Journaliste, Rédacteur en chef…",headlineHelp:"Affiché publiquement sous votre nom dans les cartes auteur et sur votre page d'archive.",bio:"Biographie",bioPlaceholder:"Un court paragraphe affiché sur votre page d'auteur et sous vos articles.",bioHelp:"Visible sur le site public dans la barre latérale d'auteur et la page d'archive d'auteur.",socials:"Profils sociaux",socialsHelp:"Renseignez les URL des profils à exposer publiquement, puis cochez « Afficher » pour ceux que vous voulez rendre visibles. Les URL vides sont ignorées.",socialsShow:"Afficher",socialsShowHelp:"Bascule la visibilité de ce réseau sur le site public.",avatar:"Photo de profil",avatarHelp:"Choisissez une image dans votre médiathèque. Les images carrées rendent le mieux.",pickAvatar:"Choisir depuis la médiathèque",changeAvatar:"Changer l'image",removeAvatar:"Retirer",save:"Enregistrer le profil"},transfer:{title:"Déplacer ou sauvegarder le contenu",help:"Exportez tout (articles, pages, catégories, métadonnées des médias, profils, réglages) dans un seul fichier JSON. Sur un backend Markdown ou local, vous pouvez importer un tel fichier en conservant les identifiants — c'est la façon de migrer depuis Firebase ou SQLite. Les fichiers médias et les clés secrètes ne sont pas inclus.",export:"Exporter le contenu (JSON)",import:"Importer du contenu…",modeMerge:"Fusionner (écrase les mêmes identifiants)",modeReplace:"Remplacer les collections importées",replaceConfirm:"Le mode Remplacer supprime tous les éléments existants des collections présentes dans le fichier avant l'import. Continuer ?",invalidFile:"Ce fichier n'est pas un export de contenu Flexweg CMS.",imported:"{{posts}} articles/pages, {{terms}} termes et {{media}} médias importés. Lancez Régénérer → Tout pour les publier."},encryption:{title:"Chiffrement de la base :",on:"activé",off:"désactivé",onHelp:"Le fichier de la base est illisible sans la phrase secrète. La changer ré-enregistre le fichier avec une nouvelle clé ; les autres navigateurs demanderont la nouvelle phrase.",offHelp:"Le fichier de la base est lisible par quiconque peut le télécharger (un hébergement statique le sert comme n'importe quelle page). Chiffrez-le avec une phrase secrète.",enable:"Chiffrer la base…",change:"Changer la phrase secrète…",savedConfirm:"J'ai enregistré cette phrase dans mon gestionnaire de mots de passe — sans elle, le contenu ne peut pas être ouvert.",enableConfirm:"Chiffrer maintenant",changeConfirm:"Changer la phrase",done:"Base ré-enregistrée avec la nouvelle phrase secrète."}},Wne={title:"Utilisateurs",noUsers:"Aucun utilisateur.",role:"Rôle",disabled:"Désactivé",editProfileTitle:"Modifier le profil — {{email}}",profileSaved:"Profil enregistré.",descriptionFirebase:"Gérez votre équipe. Les nouveaux comptes sont créés depuis la Firebase Console, puis miroir-rés ici à la première connexion.",descriptionSqlite:"Gérez votre équipe. Utilisez le bouton +Ajouter ci-dessous pour créer des comptes directement.",addUser:"Ajouter un utilisateur",addUserSuccess:"{{email}} ajouté.",removeConfirmFirebase:"Supprimer la fiche de {{email}} ? Cela retire son profil + son rôle du CMS. Pour révoquer son accès, supprimez aussi le compte dans la Firebase Console.",removeConfirmSqlite:"Supprimer définitivement {{email}} ? Cela révoque son accès ET retire son profil + son rôle. Action irréversible.",empty:{title:"Aucun membre pour l'instant",descriptionFirebase:"Créez le premier compte dans la Firebase Console, puis connectez-vous ici une fois pour enregistrer le profil.",descriptionSqlite:"Cliquez sur +Ajouter ci-dessus pour inviter le premier membre."},help:{title:"Comment ajouter un nouveau membre",bootstrapLine:"L'admin initial (toujours admin complet) est :",firebase:{step1:"Ouvrez la Firebase Console → Authentication → Add user.",step2:"Définissez un email et un mot de passe, transmettez-les au nouveau membre.",step3:"Demandez-lui de se connecter ici une fois — son profil apparaît dans la liste et vous pouvez gérer son rôle et ses détails."},sqlite:{step1:"Cliquez sur le bouton +Ajouter ci-dessus.",step2:"Saisissez son email et un mot de passe temporaire (8+ caractères).",step3:"Partagez les identifiants de manière sécurisée — il pourra changer son mot de passe depuis son profil une fois connecté."},git:{step1:"Ajoutez la personne comme collaborateur du dépôt de contenu (écriture = éditeur, admin / maintainer = admin).",step2:"Elle crée son propre jeton d'accès personnel sur GitHub / GitLab.",step3:"Elle ouvre l'admin et se connecte avec ce jeton — son profil est créé ici automatiquement."}},addUserModal:{title:"Ajouter un nouveau membre",intro:"Crée le compte directement dans la base d'auth SQLite Flexweg. Le nouvel utilisateur est éditeur par défaut ; promouvez-le depuis la liste s'il lui faut un accès admin.",submit:"Créer l'utilisateur",submitting:"Création…"},actions:{editProfile:"Modifier le profil",promote:"Promouvoir admin",demote:"Rétrograder éditeur",disable:"Désactiver",enable:"Activer",delete:"Supprimer"},descriptionGit:"Les membres de l'équipe sont les personnes ayant un accès en écriture au dépôt de contenu. Ils apparaissent ici après leur première connexion ; leur rôle suit leurs droits sur le dépôt.",descriptionLocal:"Cet admin fonctionne en mode mono-utilisateur : le contenu est stocké dans ce navigateur et il n'y a pas de comptes.",descriptionSqliteFile:"Pas de comptes utilisateurs avec ce backend : toute personne qui peut ouvrir l'admin peut modifier. Protégez le dossier de l'admin au niveau de l'hébergement. Les profils d'auteurs ci-dessous sont informatifs."},Gne={title:"Configuration Firestore requise",intro:"Les pages de listing posts/pages ont besoin de quelques index composites Firestore pour fonctionner. Ils doivent être créés manuellement — Firebase réserve cette opération aux admins du projet.",checking:"Vérification de vos index Firestore…",missingCount_one:"{{count}} index manquant :",missingCount_other:"{{count}} index manquants :",openConsole:"Ouvrir Firebase Console pour créer",noUrl:"URL d'auto-suggestion introuvable — voir le README pour la commande gcloud.",howItWorks:"Comment ça marche",step1:"Cliquez sur le lien de chaque index manquant — Firebase Console ouvre avec la définition pré-remplie.",step2:"Cliquez sur « Create » et attendez 1 à 5 minutes la construction de l'index (statut dans la console).",step3:"Revenez ici et cliquez sur Réessayer. Une fois les deux queries OK, l'admin se charge.",retry:"Réessayer",retrying:"Vérification…",buildHint:"La construction d'un index peut prendre quelques minutes après création.",allReady:"Tous les index sont prêts.",unexpectedTitle:"Impossible de joindre Firestore",unexpectedHint:"Vérifiez votre connexion et les règles Firestore. Si vous venez de créer les index, attendez la fin de leur construction puis réessayez."},Kne={appError:"Erreur applicative",loadAccountFailed:"Impossible de charger votre compte",loadAccountHint:"Si le problème persiste, déconnectez-vous puis réessayez.",accountDisabled:"Compte désactivé",accountDisabledMessage:"Votre accès au CMS a été désactivé. Contactez votre administrateur.",firebaseNotConfigured:"Firebase n'est pas configuré",firebaseEnvMissing:`Les variables d'environnement suivantes sont manquantes :
|
|
3850
|
+
Copy .env.example to .env, fill in your Firebase project credentials, and restart the dev server.`,adminEmailNotConfigured:"Admin email is not configured",adminEmailMessage:"VITE_ADMIN_EMAIL is missing in .env. Set it to the email of the bootstrap administrator.",consoleHint:"Check the browser console and your .env configuration. See the README for setup instructions."},kne={brandTitle:"AgentCMS",brandSubtitle:"Static publisher",login:{heading:"Sign in",intro:"Use the email and password your admin shared with you.",submit:"Sign in",submitting:"Signing in…"},fields:{name:"Display name (optional)",namePlaceholder:"Jane Doe",email:"Email",password:"Password",passwordHint:"At least 8 characters."},footer:"New accounts are created by an admin from the Users page.",errors:{invalidEmail:"Please enter a valid email address.",missingPassword:"Password is required.",passwordTooShort:"Password must be at least 8 characters."}},Sne=JSON.parse(`{"title":"Welcome to AgentCMS","subtitle":"First-time setup","intro":"Fill in your Firebase credentials, the bootstrap administrator account, and your Flexweg API key. The values are validated, written to your project (Firestore + a config.js file on Flexweg), and the admin reloads into the normal sign-in flow. You only do this once.","introFirebase":"Step 1 — Firebase. Fill in your Firebase project credentials and the bootstrap administrator account. We'll sign in, verify the email, and check that your Firestore rules pin this admin before continuing to the Flexweg step.","introFlexweg":"Step 2 — Flexweg. Fill in your Flexweg API key and site URL. We'll test the API, save the configuration to Firestore, upload config.js to your site, and sync theme assets.","continueToFlexweg":"Validate Firebase & continue","stepper":{"terms":"Terms","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Content & publishing","data":"Data","hosting":"Hosting","install":"Install"},"backend":{"title":"Choose a data backend","intro":"Pick where the CMS will store your posts, pages, users and settings. You can switch later from the Settings page (data is not migrated).","sqliteTitle":"Flexweg SQLite (recommended)","sqliteHint":"All data stays on your Flexweg site as a SQLite file. No external service. Auth is provided by Flexweg's SQLite API.","firebaseTitle":"Firebase","firebaseHint":"Use a Firebase project for Firestore + Auth. Free under the Spark plan. Real-time updates via onSnapshot.","continue":"Continue","markdownGitTitle":"Markdown files in a Git repository","markdownGitHint":"Posts as .md files on GitHub / GitLab (or a local clone). Each editor signs in with their own access token; every change is a commit. No database, works with several editors and machines.","localTitle":"This browser only","localHint":"Single user, no login, nothing to set up. Content stays in this browser (export it from Settings). Best for an admin running on your own computer."},"sqlite":{"heading":"Connect your Flexweg site","intro":"We'll use your master Flexweg API key ONCE to create a scoped token for the SQLite database. After install, the master key is discarded and only the scoped token (limited to this one SQLite file) is stored.","apiKeyHint":"Master Flexweg API key. Used only to install — never stored after.","detectedFromUrl":"Detected from URL","advanced":"Advanced settings (Site URL, SQLite path…)","pathHint":"Where the SQLite file lives on your Flexweg site. Folders are created automatically.","adminHeading":"Admin account","adminIntro":"Create the first user — this account gets admin rights automatically. Subsequent members are onboarded from the Users page once you're signed in.","passwordHint":"At least 8 characters.","submit":"Install SQLite database"},"terms":{"title":"Terms of use","intro":"Please read and accept the terms below before using AgentCMS. They are written in plain language to be quick to read.","section1":{"title":"1. Free service","body":"AgentCMS is provided to you free of charge by Flexweg. You can use it without limits with your Flexweg hosting — Flexweg will never bill you for using the CMS itself. Standard charges for your Flexweg hosting plan and your Firebase plan still apply, on the respective accounts you own."},"section2":{"title":"2. Provided as-is, no warranty","body":"The CMS is provided as-is. We work to keep it stable and improve it over time, but we cannot guarantee it will be free of bugs, defects or interruptions. Use it with the same caution you would any tool you didn't write yourself: keep backups of important content."},"section3":{"title":"3. Your content, your responsibility","body":"You are solely responsible for the content you publish through the CMS — text, images, videos, forms, code embeds, and any other media. You must comply with applicable law in your jurisdiction (and in the jurisdictions you target), copyright, image and personality rights, personal data protection rules, and any third-party terms (e.g. embedded fonts or videos). Flexweg is not responsible for content published by users of the CMS."},"section4":{"title":"4. Your Firebase account, your security","body":"The CMS stores its data in your own Firebase project. You are responsible for securing that project: choose a strong password for the bootstrap admin account, set up Firestore security rules as documented, rotate your API keys when needed, and review who has access. Flexweg cannot be held responsible for unauthorised access, data leaks, hacks or losses caused by misconfiguration or compromise of your Firebase account."},"section5":{"title":"5. Limitation of liability","body":"Flexweg cannot be held responsible for any loss of revenue, loss of data, loss of business opportunity, or any direct or indirect damages arising from the use, misuse, or unavailability of the CMS. Where applicable law requires Flexweg to assume some liability for the CMS, that liability is limited to the amount actually paid to Flexweg for the CMS over the past 12 months — which is zero, since the CMS is free."},"section6":{"title":"6. Your data stays yours","body":"Content you create with the CMS is stored in your own Firebase project (text, settings, media metadata) and on your own Flexweg hosting (the published HTML, images, theme assets). The CMS itself does not transmit your content to any third-party service. Plugins or themes you choose to enable may have their own behaviour — review what they do before activating them."},"section7":{"title":"7. Fair use","body":"Use of the CMS for unlawful, fraudulent, or harmful activities, or in ways that breach Flexweg's general terms of use, may result in suspension of your Flexweg hosting access. We may also update these CMS terms over time; significant changes will be communicated through the admin or via email."},"accept":"I have read and accept the Terms of use.","continue":"Continue to configuration","back":"Back"},"sections":{"firebase":"Firebase","admin":"Bootstrap administrator","flexweg":"Flexweg API"},"help":{"firebase":"Find these values in Firebase Console → Project settings → General → Your apps → SDK setup and configuration.","admin":"Use an existing user from Firebase Authentication. Anyone signing in with this email is treated as admin and bypasses the user-record check. Create the user via Firebase Console → Authentication if it doesn't exist yet.","flexweg":"Generate a permanent API key in your Flexweg account → API. The site URL is the public address of your Flexweg site (e.g. https://your-site.flexweg.com).","flexwegApiKeyHint":"Get your API key from your Flexweg account settings.","flexwegApiKeyLink":"Open account settings"},"fields":{"apiKey":"API key","authDomain":"Auth domain","projectId":"Project ID","storageBucket":"Storage bucket","messagingSenderId":"Messaging sender ID","appId":"App ID","adminEmail":"Email","adminPassword":"Password","flexwegApiKey":"API key","flexwegSiteUrl":"Site URL","flexwegApiBaseUrl":"API base URL","sqlitePath":"SQLite path"},"submit":"Save & continue","submitting":"Setting up…","success":"Setup complete!","reloadingHint":"Reloading the admin in a moment — sit tight.","footer":"These values are saved on your project (Firestore + Flexweg). They are not sent anywhere else.","steps":{"signInFirebase":"Signing in to Firebase…","testFlexweg":"Testing Flexweg API…","writeFirestore":"Saving configuration…","uploadConfig":"Uploading config.js to Flexweg…","syncThemes":"Syncing theme assets to Flexweg…","sqliteInstall":"Creating scoped SQLite token…","sqliteRegisterAdmin":"Registering the admin account…","sqliteSchema":"Bootstrapping SQLite schema…"},"stepsDone":{"sqliteInstall":"Scoped SQLite token issued","sqliteRegisterAdmin":"Admin registered and signed in","sqliteSchema":"SQLite schema ready"},"errors":{"missingFields":"Please fill every field.","rootDeploymentTitle":"The admin must live in a subfolder, not at the site root.","rootDeploymentHint":"Move the admin files (index.html, config.js, runtime/, …) into a subfolder on Flexweg — for example /admin/ or any random name like /erf34f654GH3/ for obscurity. Then reload the admin from that subfolder URL and re-run the setup.","firebaseAuthGeneric":"Could not sign in to Firebase.","firebaseAuthInvalidCredential":"Firebase rejected the email + password combination.","firebaseAuthInvalidCredentialHint":"Modern Firebase projects ship with email-enumeration protection on, which returns the same error whether the password is wrong, the user doesn't exist, or the user signs in with a different provider. Things to check:\\n• Re-enter the password — copy/paste from a password manager to rule out typos. Minimum length is 6 characters.\\n• Open Firebase Console → Authentication → Users and confirm the email exists. Check the 'Providers' column: if it shows only Google (or another provider) and not 'Email/Password', set or reset the password from the user's row menu (⋮ → Reset password).\\n• Verify the email spelling matches exactly what's stored in Firebase.","firebaseAuthUserNotFound":"No Firebase user with this email. Create one in Firebase Console → Authentication → Users first.","firebaseAuthInvalidEmail":"The admin email is not a valid email address.","firebaseInvalidApiKey":"The Firebase API key is invalid. Double-check the value from Firebase Console.","firebaseNetwork":"Network error while signing in to Firebase. Check your connection.","firebaseTooManyRequests":"Too many sign-in attempts. Try again in a moment or reset the password from Firebase Console.","firebaseOperationNotAllowed":"Email/password sign-in is not enabled on this Firebase project. Open Firebase Console → Authentication → Sign-in method and enable the Email/Password provider.","firebaseUserDisabled":"This Firebase user account is disabled. Re-enable it from Firebase Console → Authentication → Users.","wrongAdminEmail":"The Firebase account you signed in with does not match the admin email you typed. Try again.","rulesNotPinnedTitle":"Firestore rules don't recognize you as bootstrap admin yet.","rulesNotPinnedHint":"Open Firebase Console → Firestore → Rules and replace the value of \`bootstrapAdminEmail()\` with: {{email}} — then click Publish. The rules template in the README ships with a \`you@example.com\` placeholder that must be replaced with your real admin email. After publishing the updated rules, click Submit here again.","flexwegAuth":"Flexweg API key rejected. Check the value from your Flexweg account → API.","flexwegNetwork":"Network error while contacting Flexweg. Check the API base URL and your connection.","flexwegHttp":"Flexweg API error ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore rejected the configuration write.","firestoreRulesHint":"Open Firebase Console → Firestore → Rules and make sure the bootstrap admin email is set to '{{email}}'. The README has a copy-pastable rules template.","firestoreOther":"Firestore write failed","uploadFailed":"Could not upload config.js to Flexweg","generic":"Something went wrong."},"docstore":{"contentTitle":"Content repository","contentIntro":"Where your posts, pages and settings are stored as Markdown + JSON files. An empty repository is fine — the CMS creates the files.","provider":"Repository","localClone":"Local folder (git clone)","localCloneHint":"Pick the folder of your clone. Sync it with your usual git client — the CMS reads and writes files, it doesn't run git.","contentDir":"Content folder in the repo","privateRepo":"Use a private repository: drafts are stored there.","folderRequired":"Choose the content folder first.","checking":"Checking repository access…","publishIntro":"Where the generated site is published. You can change it later in Settings.","existingSite":"This repository is already set up — the site keeps publishing to: {{target}}. You can change it later in Settings (secret keys, if any, must be entered again there).","install":"Install","steps":{"config":"Saving configuration…","content":"Loading content…","target":"Saving publish target…","testTarget":"Testing the publish target…"},"doneTitle":"All set!","doneBody":"The configuration is saved in this browser. To spare other editors this setup, download config.js and replace the one in the admin folder of your hosting.","downloadConfig":"Download config.js","open":"Open the admin","footer":"Content stays in your repository or in this browser; access tokens never leave this browser."},"data":{"title":"1. Where do you store your data?","intro":"Your posts, pages, users and settings — the admin's own data. This is independent from where the public site is hosted (next step).","localNote":"Nothing to configure: content is stored in this browser. Export it from Settings to back it up or move it later.","options":{"sqlite-file":{"title":"SQLite","hint":"A SQLite database stored on the hosting you choose in the next step (Flexweg, your server, S3, Git…). No user accounts — or Flexweg's SQLite service with accounts if you host on Flexweg."},"flexweg-sqlite":{"title":"SQLite (Flexweg service)","hint":"A SQLite database run by Flexweg's service, with built-in user accounts. Needs a Flexweg account, wherever the site is hosted."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth in your Google project. Real-time, free Spark plan."},"markdown-git":{"title":"Markdown files in Git","hint":"Posts as .md files in a GitHub / GitLab repo (or a local clone). Each editor uses their own token; every change is a commit."},"local":{"title":"This browser","hint":"Single user, no login, nothing to set up. Ideal for an admin running on your computer."}}},"hosting":{"title":"2. Where is the site published?","intro":"Where the generated static site (HTML, CSS, images) is uploaded each time you publish. You can change it later in Settings.","existing":"This content repository already publishes to the target below. Keep it or pick another one."},"install":{"title":"3. Install","intro":"Check the summary, then install.","data":"Data","hosting":"Hosting","saveTarget":"Saving the publish target…","noteConfigJs":"The admin configuration (config.js) is uploaded next to the admin on Flexweg when possible; otherwise you'll be offered to download it.","noteLocalConfig":"The configuration is saved in this browser; you'll be offered config.js to put in the admin folder so other editors skip this setup."},"sqliteFile":{"security":"No user accounts: anyone who can open this admin can edit the content — protect the admin folder at your hosting level. The database file is served like any other file: keep it encrypted, or store it in a separate private location.","intro":"Where the database file is stored. It is read and saved by this admin through the same connectors as the hosting.","path":"Database file path","pathHint":"Created on first save if it doesn't exist yet. With a Git repository, every save is a commit — prefer a repository or branch that doesn't trigger a site build.","existing":"existing database","new":"new database","dataNote":"Nothing to configure here: the database will be stored on the hosting you choose in the next step.","heading":"SQLite database","flexwegService":"Use Flexweg's SQLite service","flexwegServiceHint":"The database is run by Flexweg and comes with built-in user accounts (email + password). Otherwise it is a plain file on this hosting, without accounts.","summaryFile":"File {{path}} on this hosting","summaryService":"Flexweg SQLite service ({{path}})","encrypt":"Encrypt the database","encryptHint":"Recommended on a public hosting: the file is unreadable without the passphrase. Each new browser asks for it once.","passphrase":"Passphrase","passphraseHint":"Save it in your password manager now: without it, nobody can open the database — not even you.","copy":"Copy","copied":"Copied","generate":"New","passphraseTooShort":"The passphrase must be at least 12 characters long.","existingEncrypted":"An encrypted database already exists at this path: enter its passphrase.","separate":"Store the database in a separate private location","separateHint":"E.g. a private S3 / R2 bucket or a private Git repository: the database is then never served by the public site.","summaryEncrypted":"encrypted","summaryLocation":"stored in {{location}}","locationLabel":"Database location","gitBranchNote":"The database is kept on the branch {{branch}} of this repository, which is never published: saving content doesn't rebuild the site.","summaryBranch":"on branch {{branch}}"},"adminHosting":{"deploying":"Copying the admin to the site…","label":"Also host the admin on this site","hint":"The admin is copied to {{url}} with its config.js (no secrets inside) — every editor can then open it there. Each editor still signs in with their own access.","folder":"Admin folder","alreadyHere":"This admin already runs from this site: its config.js will be updated in place.","doneBody":"The admin is now on your site. On GitHub Pages, enable Pages for the repository first if it isn't yet (Settings → Pages), then open it:","open":"Open the online admin","continueHere":"Continue in this admin"}}`),Ene={actions:{upload:"Uploading file",delete:"Deleting file",rename:"Renaming file",get:"Reading file",list:"Listing files",createFolder:"Creating folder",renameFolder:"Renaming folder",deleteFolder:"Deleting folder",storageLimits:"Reading storage limits",commit:"Publishing changes"},errors:{configMissing:"The publish target is not configured. Set it up in admin Settings before publishing.",network:"{{action}}: network error or CORS blocked. Check your connection.",auth:"{{action}}: authentication failed. Check the publish target credentials in Settings.",notFound:"{{action}}: target not found on the publish target.",tooLarge:"{{action}}: file too large for the publish target.",rateLimited:"{{action}}: too many requests, please retry in a moment.",serverError:"{{action}}: publish target server error ({{status}}). Please retry.",generic:"{{action}} failed ({{status}}){{detail}}.",unsupported:'{{action}}: not supported by the "{{connector}}" publish target.',unknownConnector:'Unknown publish target "{{connector}}". Check Settings → Publish target.',folderAccess:"No access to the local folder. Open Settings → Publish target and click “Reconnect folder”."}},_ne={log:{rendering:"Rendering page…",uploading:"Uploading {{path}}…",deleting:"Deleting {{path}}…",regenerating:"Regenerating listings…",skipped:"Skipped {{path}} (no changes)",done:"Published to {{url}}",failed:"Failed: {{error}}"}},Cne={errors:{notConnected:"Not connected to the content repository. Sign in again with your access token.",conflict:"Someone else changed this item in the meantime. Their version is now shown — re-apply your change.",sqliteUnsupported:`The "{{connector}}" target can't store a database file.`}},Ane={target:"Publish target",settingsTitle:"Publish target",settingsHelp:"Where the rendered site is uploaded when you publish. Credentials are stored with your content backend (or kept in this browser for Git content repositories) and are readable by every admin.",saved:"Publish target saved. Run Regenerate → Everything to publish the whole site to the new target.",test:"Test connection",testOk:"Connection OK",testFailed:"Connection failed",names:{flexweg:"Flexweg","git-pages":"Git repository (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"S3-compatible bucket (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Your own server (PHP bridge)","browser-mirror":"Download as ZIP","local-folder":"Local folder on this computer"},hints:{flexweg:"Uploads through the Flexweg Files API.","git-pages":"Each publish is one commit to the repo; the host rebuilds the site from it.",s3:"Needs a CORS rule on the bucket allowing this admin's origin, and website hosting (or a CDN) to serve index.html files.","php-bridge":"Upload external/bridges/php/flexweg-bridge.php to your server, set its API key, then fill in its URL here.","browser-mirror":"The site is kept in this browser; download the ZIP and upload it anywhere by hand.","local-folder":"Writes the site straight into a folder (Chrome / Edge). Serve it locally or push it with your own tools."},fields:{flexweg:{apiKey:"API key",siteUrl:"Site URL",apiBaseUrl:"API base URL"},"git-pages":{host:"Hosting",provider:"Git provider",owner:"Owner (user or organisation)",repo:"Repository",project:"Project path",branch:"Branch",dir:"Folder in the repo",token:"Access token",siteUrl:"Public site URL",apiBaseUrl:"API URL (self-hosted only)"},s3:{endpoint:"Endpoint",region:"Region",bucket:"Bucket",prefix:"Key prefix (optional)",accessKeyId:"Access key ID",secretAccessKey:"Secret access key",siteUrl:"Public site URL",forcePathStyle:"Path-style URLs (MinIO, R2, most compatibles)",publicRead:"Make uploaded files public (public-read ACL) — for buckets not made public by a bucket policy (OVHcloud, Scaleway…). Leave off on AWS buckets that enforce bucket-owner ownership."},"php-bridge":{apiBaseUrl:"Bridge URL",apiKey:"Bridge API key",siteUrl:"Public site URL"},"browser-mirror":{siteUrl:"Public site URL (optional)"},"local-folder":{siteUrl:"URL the folder is served at (optional)"}},help:{flexweg:{apiKey:"Generated from your Flexweg account → API."},"git-pages":{host:"Cloudflare Pages: connect the project to this repo with no build command and the output folder below. Works with private repos.",dir:'Leave empty for the repo root. GitHub Pages: "" or "docs". GitLab Pages: "public".',token:"Fine-grained token on this repo with Contents: read & write (GitHub) — add Pages: read & write to let the CMS switch GitHub Pages on — or a token with the api scope (GitLab). Leave empty to use each editor's own token when content is on the same provider.",siteUrl:"e.g. https://user.github.io/repo — a sub-folder URL is fine, links are adjusted automatically."},s3:{endpoint:"Leave empty for AWS (built from the region). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"The bucket website URL or your CDN domain."},"php-bridge":{apiBaseUrl:"The full URL of flexweg-bridge.php on your server (HTTPS)."},"browser-mirror":{siteUrl:"Where you will upload the ZIP — used for absolute URLs (sitemaps, RSS, media)."},"local-folder":{siteUrl:"e.g. http://localhost:8080 when a local web server serves the folder."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (connected to the repo)","gitlab-pages":"GitLab Pages",other:"Other (Netlify, Vercel, server git pull…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Choose folder…",change:"Change folder…",reconnect:"Reconnect folder",unsupported:"This browser can't write to local folders. Use Chrome or Edge."},mirror:{download:"Download site (ZIP)",count:"{{count}} files in this browser"},adminHosting:{title:"Admin on this site",help:"Copy this admin to the publish target (first deployment, or update after a new version). Its config.js holds no secrets.",deploy:"Deploy / update the admin",deployed:"Admin deployed ({{count}} files) — {{url}}"},pages:{enabled:"GitHub Pages enabled for this repository — the site will be online in about a minute.",enableHint:'Publish succeeded. To put the site online, enable GitHub Pages for {{repo}}: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Or give the token the "Pages: read and write" permission and the CMS will do it.)'},siteUrl:{mismatch:"The site's public URL (Settings → Site) is {{site}}, but this target serves the site at {{target}}. Links, CSS and sitemaps follow the site URL — they will be wrong on this hosting.",use:"Use {{url}} for the site",updated:"Site URL updated. Run Regenerate → Everything to republish the pages with the new links."}},Tne={heading:"Connect to the content repository",tokenIntro:"Content is stored in the {{provider}} repository {{repo}}. Sign in with your own personal access token — your repository permissions decide your role (write access = editor, admin / maintainer = admin).",token:"Personal access token",tokenHelpGithub:"Fine-grained token, access to this repository only, permission Contents: read and write.",tokenHelpGitlab:"Token with the api scope, Developer role or higher on this project.",createToken:"Create a token",connect:"Connect",tokenStorage:"The token is kept in this browser only. Signing out forgets it.",failed:"This token can't write to the repository (invalid, expired, or read-only). Check its permissions.",folderIntro:"Content is stored in a folder on this computer (typically a git clone you sync with your own git client). Grant this browser access to it — browsers ask again after every reload.",openFolder:"Open content folder"},Ine={flexweg:{title:"Flexweg",short:"Flexweg hosting",hint:"Uploads through the Flexweg Files API. API key from your Flexweg account."},"github-pages":{title:"GitHub Pages",short:"Free, from a GitHub repo",hint:"Each publish is one commit to the repo; GitHub Pages serves it. Settings → Pages → Deploy from a branch. Public repos on the free plan."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Free, private repos OK",hint:"The CMS commits the site to a GitHub / GitLab repo; connect a Cloudflare Pages project to it (no build command, output folder = the folder below)."},"gitlab-pages":{title:"GitLab Pages",short:"Free, from a GitLab repo",hint:"Each publish is one commit; the CMS adds a minimal .gitlab-ci.yml that publishes the public/ folder."},"git-other":{title:"Netlify, Vercel…",short:"Any host that deploys a repo",hint:"The CMS commits the site to a Git repo; connect your host (Netlify, Vercel, a server running git pull…) to that repo."},s3:{title:"S3 / R2 / B2…",short:"Object storage bucket",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Needs a CORS rule on the bucket and website hosting or a CDN in front."},"own-server":{title:"Your own server (FTP / SFTP)",short:"Shared hosting, VPS…",hint:"Browsers can't speak FTP or SFTP: upload the PHP bridge (external/bridges/php/flexweg-bridge.php) once with your FTP client, set its API key, then fill in its URL here. Works on any PHP host."},"local-folder":{title:"Local folder",short:"On this computer",hint:"Writes the site into a folder of this computer (Chrome / Edge). Serve it locally or push it with your own tools."},zip:{title:"Download as ZIP",short:"Upload it by hand",hint:"The site is kept in this browser; download a ZIP from Settings and upload it anywhere (Netlify Drop, FTP client…)."}},Nne={heading:"Connect to the database",intro:"This admin stores its content in {{path}}. Enter the access credentials for this browser.",storage:"Credentials are kept in this browser only. Signing out forgets them.",passphrase:"Database passphrase",passphraseHint:"The database is encrypted. Enter the passphrase chosen at install (kept in this browser only).",passphraseWrong:"Wrong passphrase: the database could not be opened.",passphraseMissing:"Enter the database passphrase."},Pne={common:ine,auth:ane,nav:one,dashboard:lne,posts:cne,pages:une,taxonomies:dne,media:hne,themes:fne,plugins:pne,externalInstall:mne,externalLoader:gne,menus:bne,settings:yne,users:vne,firestoreSetup:xne,errors:wne,identity:kne,setup:Sne,flexweg:Ene,publish:_ne,docstore:Cne,connectors:Ane,gitAccess:Tne,hosting:Ine,sqliteAccess:Nne},Rne={save:"Enregistrer",saving:"Enregistrement…",saved:"Enregistré",cancel:"Annuler",delete:"Supprimer",deleting:"Suppression…",edit:"Modifier",create:"Créer",search:"Rechercher",loading:"Chargement…",yes:"Oui",no:"Non",confirm:"Confirmer",back:"Retour",next:"Suivant",previous:"Précédent",close:"Fermer",all:"Tous",none:"Aucun",actions:"Actions",name:"Nom",slug:"Slug",description:"Description",status:"Statut",createdAt:"Créé le",updatedAt:"Mis à jour",publishedAt:"Publié le",language:"Langue",darkMode:"Mode sombre",lightMode:"Mode clair",signOut:"Déconnexion",administrator:"Administrateur",editor:"Éditeur",appName:"AgentCMS"},jne={signIn:"Connexion",signingIn:"Connexion…",email:"Email",password:"Mot de passe",emailPlaceholder:"vous@entreprise.com",passwordPlaceholder:"••••••••",forgotPassword:"Mot de passe oublié ?",resetEmailSent:"Email de réinitialisation envoyé à {{email}}.",enterEmailFirst:"Saisissez d'abord votre email, puis cliquez sur réinitialiser.",emailPasswordRequired:"Email et mot de passe requis.",signInSubtitle:"Utilisez votre email professionnel et votre mot de passe.",footer:"Les demandes de compte passent par votre administrateur.",errors:{invalidEmail:"Adresse email invalide.",invalidCredentials:"Email ou mot de passe invalide.",tooManyRequests:"Trop de tentatives. Réessayez plus tard ou réinitialisez votre mot de passe.",userDisabled:"Ce compte a été désactivé.",networkFailed:"Erreur réseau. Vérifiez votre connexion.",generic:"Échec de l'authentification."}},Mne={openMenu:"Ouvrir le menu",closeMenu:"Fermer le menu",dashboard:"Tableau de bord",posts:"Articles",pages:"Pages",taxonomies:"Catégories & Tags",media:"Médias",themes:"Thèmes",themeSettings:"Réglages du thème",plugins:"Plugins",menus:"Menus",users:"Utilisateurs",settings:"Réglages"},Lne={title:"Tableau de bord",welcome:"Bienvenue, {{email}}.",stats:{totalPosts:"Articles",totalPages:"Pages",online:"En ligne",drafts:"Brouillons"}},Dne={title:"Articles",newPost:"Nouvel article",noPosts:"Aucun article. Créez le premier pour commencer.",noPostsInFilter:"Aucun article ne correspond au filtre courant.",search:{placeholder:"Rechercher des articles…",clear:"Effacer la recherche",noResults:"Aucun article ne correspond à votre recherche."},pagination:{previous:"Précédent",next:"Suivant",showing:"Affichage {{from}}–{{to}} sur {{total}}",pageOf:"Page {{page}} sur {{total}}"},bulk:{selectedCount_one:"{{count}} sélectionné",selectedCount_other:"{{count}} sélectionnés",selectPage_one:"Sélectionner {{count}} sur cette page",selectPage_other:"Sélectionner les {{count}} de cette page",deselectPage:"Désélectionner la page",allOnPageSelected_one:"{{count}} sur cette page sélectionné.",allOnPageSelected_other:"Les {{count}} de cette page sont sélectionnés.",selectAllMatching_one:"Sélectionner l'article correspondant",selectAllMatching_other:"Sélectionner les {{count}} articles correspondants",allMatchingSelected_one:"L'article correspondant est sélectionné.",allMatchingSelected_other:"Les {{count}} articles correspondants sont sélectionnés.",selectOne:"Sélectionner « {{title}} »",publish:"Publier ({{count}})",publishing:"Publication…",publishedCount:"{{ok}} publié(s), {{failed}} échec(s).",unpublish:"Dépublier ({{count}})",unpublishing:"Dépublication…",unpublishedCount:"{{ok}} dépublié(s), {{failed}} échec(s).",delete:"Supprimer",deleting:"Suppression…",deletedCount:"{{ok}} supprimé(s), {{failed}} échec(s).",confirmDelete_one:"Supprimer {{count}} article ? Cette action dépublie de Flexweg et ne peut pas être annulée.",confirmDelete_other:"Supprimer {{count}} articles ? Cette action dépublie de Flexweg et ne peut pas être annulée.",noDraftSelected:"Aucun article en brouillon sélectionné.",noOnlineSelected:"Aucun article en ligne sélectionné.",clear:"Effacer la sélection"},filters:{all:"Tous",draft:"Brouillon",online:"En ligne"},fields:{title:"Titre",slug:"Slug",excerpt:"Extrait",content:"Contenu",category:"Catégorie",tags:"Tags",heroImage:"Image d'en-tête",seoTitle:"Titre SEO",seoDescription:"Description SEO",createdAt:"Date de création",updatedAt:"Dernière mise à jour",publishedAt:"Date de publication"},edit:{newTitle:"Nouvel article",editTitle:"Modifier l'article",saved:"Enregistré.",savedAndRepublished:"Enregistré et republié.",saveFailed:"Échec de l'enregistrement.",saveAndRepublish:"Enregistrer & republier",draftSaved:"Brouillon enregistré.",slugCollision:{post:"Cette URL est déjà utilisée par l'article : « {{label}} ».",page:"Cette URL est déjà utilisée par la page : « {{label}} ».",category:"Cette URL est déjà utilisée par la catégorie : « {{label}} »."},publish:"Publier",unpublish:"Dépublier",publishing:"Publication…",unpublishing:"Dépublication…",titlePlaceholder:"Ajouter un titre",permalink:"Permalien",slugFormatHint:"Minuscules ASCII séparées par des tirets uniquement.",slugAutoSuffixed:"Suffixe ajouté car « {{base}} » est déjà utilisé par {{owner}}.",slugAutoSuffixedOwner:{post:"le post : « {{label}} »",page:"la page : « {{label}} »",category:"la catégorie : « {{label}} »"},saveBlocked:{titleRequired:"Ajoutez un titre avant d'enregistrer.",slugRequired:"Un titre et un slug d'URL sont requis pour enregistrer.",slugInvalid:"Format de slug invalide (minuscules ASCII + tirets).",slugCollision:"Résolvez le conflit d'URL avant d'enregistrer."},viewPublished:"Voir",confirmDelete:"Supprimer cet élément ?",inspector:{document:"Document",block:"Bloc",blockEmpty:"Sélectionnez un bloc dans l'éditeur pour voir ses options.",publishing:"Publication",permalink:"Permalien",categories:"Catégories & tags",featured:"Image à la une",seo:"SEO",excerpt:"Extrait",dates:"Dates"},blocks:{addBlock:"Ajouter un bloc",transform:"Transformer en",moveUp:"Déplacer vers le haut",moveDown:"Déplacer vers le bas",duplicate:"Dupliquer",remove:"Supprimer le bloc",paragraph:"Paragraphe",heading2:"Titre 2",heading3:"Titre 3",bulletList:"Liste à puces",orderedList:"Liste numérotée",blockquote:"Citation",codeBlock:"Code",image:"Image",horizontalRule:"Séparateur",categories:{text:"Texte",media:"Médias",layout:"Mise en page",embed:"Intégrations",advanced:"Avancé"},noSettings:"Ce bloc n'a pas de réglages.",noSelection:"Sélectionnez un bloc dans l'éditeur pour voir ses options.",slash:{noResults:"Aucun bloc ne correspond."}}},status:{draft:"Brouillon",online:"En ligne"},preview:{title:"Aperçu",rendering:"Génération de l'aperçu…",error:"Échec de l'aperçu : {{error}}",viewports:{mobile:"Mobile",tablet:"Tablette",desktop:"Bureau"}}},Fne={title:"Pages",newPage:"Nouvelle page",noPages:"Aucune page.",homeBadge:"Accueil",homeBadgeTooltip:"Utilisée comme page d'accueil du site"},One={title:"Catégories & Tags",categories:"Catégories",tags:"Tags",newCategory:"Nouvelle catégorie",newTag:"Nouveau tag",noCategories:"Aucune catégorie.",noTags:"Aucun tag.",slugCollision:"Ce slug est déjà utilisé par « {{label}} ».",seo:{button:"SEO",buttonTitle:"Modifier les balises SEO",title:"Balises SEO",subtitle:"Titre et description personnalisés pour la page d'archive « {{name}} ».",metaTitle:"Titre meta",metaTitleHint:"Utilisé comme balise <title>. Valeur par défaut : le nom du terme.",metaDescription:"Description meta",metaDescriptionHint:"Utilisée comme méta-description de la page. Valeur par défaut : la description du terme."}},zne={title:"Médiathèque",upload:"Téléverser",uploading:"Téléversement…",finalizing:"Finalisation…",uploadFailed:"Échec du téléversement",retry:"Réessayer",noMedia:"Aucun média.",alt:"Texte alternatif",caption:"Légende",filename:"Nom du fichier",size:"Taille",type:"Type"},Une={title:"Thèmes",active:"Actif",activate:"Activer",installExternal:"Installer un thème",uninstallDisabledTitle:"Activez un autre thème avant de désinstaller celui-ci.",syncAssets:"Synchroniser le thème",regenerateSite:"Régénérer le site",regenerating:"Régénération…",regenerate:{button:"Régénérer",running:"En cours…",groupBuiltins:"Site",groupPlugins:"Plugins",home:"Page d'accueil uniquement",homeHelp:"Régénère index.html seulement — l'option la plus rapide.",allHtml:"Toutes les pages HTML",allHtmlHelp:"Tous les posts, pages, archives et listings — plus les snapshots menu / posts / authors JSON.",repair:"Réparer les URLs",repairHelp:"Recalcule l'URL canonique de chaque post en ligne et déplace les fichiers qui ont atterri au mauvais endroit. Utile après un import effectué avant que les termes ne soient synchronisés.",assets:"Assets du thème",assetsHelp:"Envoie le CSS et les scripts du thème actif vers /theme-assets/.",everything:"Tout",everythingHelp:"Assets thème + tous les HTML + chaque sortie plugin. Option la plus lente.",noPluginTargets:"Aucune régénération de plugin — activez un plugin qui supporte la régénération."},confirmSwitch:{title:"Passer à {{theme}} ?",body:"Le changement de thème nécessite de re-pousser les assets du thème et de régénérer toutes les pages publiées pour que le nouveau look se propage partout. Cela peut prendre un moment.",confirm:"Changer & régénérer",cancel:"Annuler"}},Bne={title:"Plugins",enabled:"Activé",disabled:"Désactivé",enable:"Activer",disable:"Désactiver",configure:"Configurer",author:"auteur",learnMore:"En savoir plus",mustUseBadge:"Indispensable",installExternal:"Installer un plugin",tabs:{regular:"Plugins",mustUse:"Indispensables"}},$ne={titlePlugin:"Installer un plugin",titleTheme:"Installer un thème",labelPlugin:"plugin",labelTheme:"thème",intro:"Déposez un fichier ZIP contenant un bundle de {{label}} (manifest.json + bundle.js à la racine). Le {{label}} sera uploadé sur votre site Flexweg et enregistré après un rechargement. Ré-uploader un ZIP avec le même id de manifest met à jour l'entrée existante en place — pas besoin de désinstaller.",zipField:"Fichier ZIP du bundle",install:"Installer",installing:"Installation…",installSuccess:"{{name}} installé ({{count}} fichiers uploadés). Rechargement…",upgradeSuccess:"{{name}} mis à jour de v{{previousVersion}} à v{{newVersion}} ({{count}} fichiers uploadés). Rechargement…",installedTitle:"Déjà installé",bundledDefaultsTitle:"Plugins/thèmes bundlés disponibles",bundledDefaultsHint:"{{count}} plugin/thème bundlé est actuellement désinstallé. Restaurez-les pour récupérer ce qui était livré avec cette version de l'admin.",bundledDefaultsRestore:"Restaurer",bundledDefaultsRestored:"{{plugins}} plugin(s) et {{themes}} thème(s) restaurés. Rechargement…",uninstall:"Désinstaller",uninstallSuccess:"{{id}} désinstallé. Rechargement…",confirmUninstall:"Désinstaller {{id}} ? Les fichiers seront supprimés de Flexweg.",errors:{"no-manifest":"Le ZIP n'a pas de manifest.json à sa racine.","invalid-manifest":"Le manifest.json est invalide (champ requis manquant ou JSON cassé).","incompatible-api":"Le bundle a été buildé pour une version d'API runtime incompatible.","no-bundle":"Le ZIP ne contient pas le fichier d'entrée déclaré dans le manifest.","fetch-manifest":"Impossible de lire le external.json actuel sur Flexweg.","upload-failed":"Échec de l'upload — vérifiez votre clé API Flexweg et votre connexion."}},Hne={someFailed:"{{count}} bundle(s) externe(s) ont échoué au chargement. Voir la console du navigateur."},Vne={title:"Menus",header:"Menu d'en-tête",footer:"Menu de pied de page",label:"Libellé",saveAndPublish:"Enregistrer & générer",discard:"Annuler",saved:"Menus enregistrés et publiés.",saveFailed:"Impossible d'enregistrer les menus.",unsavedChanges:"Modifications non enregistrées."},qne={title:"Réglages",tabs:{general:"Général"},site:{title:"Site",siteTitle:"Titre du site",siteDescription:"Description du site",siteLanguage:"Langue du site",siteLanguageHelp:`Code BCP-47 (ex. en, fr-CA) injecté dans <html lang="…"> de chaque page publiée. Le préfixe est utilisé pour résoudre la langue des libellés sitemap / RSS et des chaînes intégrées au thème ; les locales non supportées retombent sur l'anglais.`,siteLanguageResolved:"Les traductions utiliseront : {{label}}",baseUrl:"URL publique du site",postsPerPage:"Articles par page",homeMode:"Contenu de la page d'accueil",homeLatest:"Derniers articles",homeStatic:"Page statique",homePage:"Page d'accueil",discourageIndexing:"Décourager les moteurs de recherche d'indexer ce site",discourageIndexingHelp:"Si activé, chaque page publiée porte une balise meta noindex/nofollow et le robots.txt interdit tous les robots. Reproduit le comportement de WordPress — utile pour les sites de préproduction ou les revues avant lancement. Les moteurs qui respectent la directive n'indexeront pas le site.",discourageRegenerateHint:"Réglage d'indexation sauvegardé. Cliquez sur « Tout régénérer » dans Thèmes pour appliquer le changement à toutes les pages publiées et au robots.txt."},flexweg:{title:"API Flexweg",apiKey:"Clé API",apiKeyHelp:"Générée depuis votre compte Flexweg → API.",siteUrl:"URL du site",siteUrlHelp:"URL publique de votre site Flexweg sans slash final.",apiBaseUrl:"URL de base de l'API",storageHelpFirebase:"Stockée dans Firestore (config/flexweg). Lecture par tout membre connecté, écriture admin uniquement.",storageHelpSqlite:"Stockée dans la table SQLite locale config. Lecture par tout membre connecté, écriture admin uniquement."},backend:{title:"Backend de données",active:"Backend actif :",switchButton:"Changer de backend…",confirmTitle:"Les données actuelles seront perdues.",confirmBody:"Le basculement efface la configuration en mémoire et recharge sur le formulaire de configuration. Le nouveau backend démarre vide — les données du backend précédent restent où elles sont (dans Firestore ou en tant que fichier .sqlite sur Flexweg), mais le CMS ne les lira plus jusqu'au prochain basculement.",confirmYes:"Oui, changer de backend",downloadBackup:"Télécharger une sauvegarde du fichier .sqlite",downloadBackupHelp:"à faire avant de changer de backend.",markdownGit:"Markdown — {{source}}",localFolder:"dossier local",localBrowser:"Ce navigateur (local, un seul utilisateur)",sqliteFile:"Fichier SQLite — {{location}}"},performance:{title:"Performance",help:"Comment l'admin charge articles et pages. Le mode par défaut fonctionne sur le plan gratuit de Firestore sans configuration ; le mode paginé est destiné aux très gros sites et exige une création d'index ponctuelle.",mode:"Mode de chargement",modeGlobal:"Standard (aucune configuration requise)",modePaginated:"Pagination côté serveur (index Firestore requis)",globalHelp:"Charge toute la collection d'articles dans une subscription temps réel. Tri, filtre et recherche se font en mémoire. Recommandé pour les sites de moins de ~5 000 articles.",paginatedHelp:"Subscriptions paginées par curseur, une page à la fois. Exige des index composites Firestore — voir README. Recommandé pour les très gros sites.",savedReload:"Enregistré. Rechargez l'admin pour appliquer le nouveau mode."},editor:{title:"Éditeur",help:"Typographie utilisée dans l'éditeur d'articles / pages. Indépendante du thème public.",fontFamily:"Police",bodySize:"Taille du corps",h1Size:"Taille H1",h2Size:"Taille H2",h3Size:"Taille H3",sizeHelp:"Longueur CSS, ex. 16px ou 1rem. Laisser vide pour la valeur par défaut.",reset:"Réinitialiser"},profile:{title:"Profil",adminLocale:"Langue de l'administration",adminLocaleHelp:"Langue utilisée par l'interface d'administration. Sauvegardée dans votre profil.",firstName:"Prénom",lastName:"Nom",headline:"Titre",headlinePlaceholder:"ex. Journaliste, Rédacteur en chef…",headlineHelp:"Affiché publiquement sous votre nom dans les cartes auteur et sur votre page d'archive.",bio:"Biographie",bioPlaceholder:"Un court paragraphe affiché sur votre page d'auteur et sous vos articles.",bioHelp:"Visible sur le site public dans la barre latérale d'auteur et la page d'archive d'auteur.",socials:"Profils sociaux",socialsHelp:"Renseignez les URL des profils à exposer publiquement, puis cochez « Afficher » pour ceux que vous voulez rendre visibles. Les URL vides sont ignorées.",socialsShow:"Afficher",socialsShowHelp:"Bascule la visibilité de ce réseau sur le site public.",avatar:"Photo de profil",avatarHelp:"Choisissez une image dans votre médiathèque. Les images carrées rendent le mieux.",pickAvatar:"Choisir depuis la médiathèque",changeAvatar:"Changer l'image",removeAvatar:"Retirer",save:"Enregistrer le profil"},transfer:{title:"Déplacer ou sauvegarder le contenu",help:"Exportez tout (articles, pages, catégories, métadonnées des médias, profils, réglages) dans un seul fichier JSON. Sur un backend Markdown ou local, vous pouvez importer un tel fichier en conservant les identifiants — c'est la façon de migrer depuis Firebase ou SQLite. Les fichiers médias et les clés secrètes ne sont pas inclus.",export:"Exporter le contenu (JSON)",import:"Importer du contenu…",modeMerge:"Fusionner (écrase les mêmes identifiants)",modeReplace:"Remplacer les collections importées",replaceConfirm:"Le mode Remplacer supprime tous les éléments existants des collections présentes dans le fichier avant l'import. Continuer ?",invalidFile:"Ce fichier n'est pas un export de contenu AgentCMS.",imported:"{{posts}} articles/pages, {{terms}} termes et {{media}} médias importés. Lancez Régénérer → Tout pour les publier."},encryption:{title:"Chiffrement de la base :",on:"activé",off:"désactivé",onHelp:"Le fichier de la base est illisible sans la phrase secrète. La changer ré-enregistre le fichier avec une nouvelle clé ; les autres navigateurs demanderont la nouvelle phrase.",offHelp:"Le fichier de la base est lisible par quiconque peut le télécharger (un hébergement statique le sert comme n'importe quelle page). Chiffrez-le avec une phrase secrète.",enable:"Chiffrer la base…",change:"Changer la phrase secrète…",savedConfirm:"J'ai enregistré cette phrase dans mon gestionnaire de mots de passe — sans elle, le contenu ne peut pas être ouvert.",enableConfirm:"Chiffrer maintenant",changeConfirm:"Changer la phrase",done:"Base ré-enregistrée avec la nouvelle phrase secrète."}},Wne={title:"Utilisateurs",noUsers:"Aucun utilisateur.",role:"Rôle",disabled:"Désactivé",editProfileTitle:"Modifier le profil — {{email}}",profileSaved:"Profil enregistré.",descriptionFirebase:"Gérez votre équipe. Les nouveaux comptes sont créés depuis la Firebase Console, puis miroir-rés ici à la première connexion.",descriptionSqlite:"Gérez votre équipe. Utilisez le bouton +Ajouter ci-dessous pour créer des comptes directement.",addUser:"Ajouter un utilisateur",addUserSuccess:"{{email}} ajouté.",removeConfirmFirebase:"Supprimer la fiche de {{email}} ? Cela retire son profil + son rôle du CMS. Pour révoquer son accès, supprimez aussi le compte dans la Firebase Console.",removeConfirmSqlite:"Supprimer définitivement {{email}} ? Cela révoque son accès ET retire son profil + son rôle. Action irréversible.",empty:{title:"Aucun membre pour l'instant",descriptionFirebase:"Créez le premier compte dans la Firebase Console, puis connectez-vous ici une fois pour enregistrer le profil.",descriptionSqlite:"Cliquez sur +Ajouter ci-dessus pour inviter le premier membre."},help:{title:"Comment ajouter un nouveau membre",bootstrapLine:"L'admin initial (toujours admin complet) est :",firebase:{step1:"Ouvrez la Firebase Console → Authentication → Add user.",step2:"Définissez un email et un mot de passe, transmettez-les au nouveau membre.",step3:"Demandez-lui de se connecter ici une fois — son profil apparaît dans la liste et vous pouvez gérer son rôle et ses détails."},sqlite:{step1:"Cliquez sur le bouton +Ajouter ci-dessus.",step2:"Saisissez son email et un mot de passe temporaire (8+ caractères).",step3:"Partagez les identifiants de manière sécurisée — il pourra changer son mot de passe depuis son profil une fois connecté."},git:{step1:"Ajoutez la personne comme collaborateur du dépôt de contenu (écriture = éditeur, admin / maintainer = admin).",step2:"Elle crée son propre jeton d'accès personnel sur GitHub / GitLab.",step3:"Elle ouvre l'admin et se connecte avec ce jeton — son profil est créé ici automatiquement."}},addUserModal:{title:"Ajouter un nouveau membre",intro:"Crée le compte directement dans la base d'auth SQLite Flexweg. Le nouvel utilisateur est éditeur par défaut ; promouvez-le depuis la liste s'il lui faut un accès admin.",submit:"Créer l'utilisateur",submitting:"Création…"},actions:{editProfile:"Modifier le profil",promote:"Promouvoir admin",demote:"Rétrograder éditeur",disable:"Désactiver",enable:"Activer",delete:"Supprimer"},descriptionGit:"Les membres de l'équipe sont les personnes ayant un accès en écriture au dépôt de contenu. Ils apparaissent ici après leur première connexion ; leur rôle suit leurs droits sur le dépôt.",descriptionLocal:"Cet admin fonctionne en mode mono-utilisateur : le contenu est stocké dans ce navigateur et il n'y a pas de comptes.",descriptionSqliteFile:"Pas de comptes utilisateurs avec ce backend : toute personne qui peut ouvrir l'admin peut modifier. Protégez le dossier de l'admin au niveau de l'hébergement. Les profils d'auteurs ci-dessous sont informatifs."},Gne={title:"Configuration Firestore requise",intro:"Les pages de listing posts/pages ont besoin de quelques index composites Firestore pour fonctionner. Ils doivent être créés manuellement — Firebase réserve cette opération aux admins du projet.",checking:"Vérification de vos index Firestore…",missingCount_one:"{{count}} index manquant :",missingCount_other:"{{count}} index manquants :",openConsole:"Ouvrir Firebase Console pour créer",noUrl:"URL d'auto-suggestion introuvable — voir le README pour la commande gcloud.",howItWorks:"Comment ça marche",step1:"Cliquez sur le lien de chaque index manquant — Firebase Console ouvre avec la définition pré-remplie.",step2:"Cliquez sur « Create » et attendez 1 à 5 minutes la construction de l'index (statut dans la console).",step3:"Revenez ici et cliquez sur Réessayer. Une fois les deux queries OK, l'admin se charge.",retry:"Réessayer",retrying:"Vérification…",buildHint:"La construction d'un index peut prendre quelques minutes après création.",allReady:"Tous les index sont prêts.",unexpectedTitle:"Impossible de joindre Firestore",unexpectedHint:"Vérifiez votre connexion et les règles Firestore. Si vous venez de créer les index, attendez la fin de leur construction puis réessayez."},Kne={appError:"Erreur applicative",loadAccountFailed:"Impossible de charger votre compte",loadAccountHint:"Si le problème persiste, déconnectez-vous puis réessayez.",accountDisabled:"Compte désactivé",accountDisabledMessage:"Votre accès au CMS a été désactivé. Contactez votre administrateur.",firebaseNotConfigured:"Firebase n'est pas configuré",firebaseEnvMissing:`Les variables d'environnement suivantes sont manquantes :
|
|
3851
3851
|
{{vars}}
|
|
3852
3852
|
|
|
3853
|
-
Copiez .env.example vers .env, renseignez vos identifiants Firebase, puis relancez le serveur de dev.`,adminEmailNotConfigured:"Email administrateur non configuré",adminEmailMessage:"VITE_ADMIN_EMAIL est manquant dans .env. Renseignez l'email de l'administrateur initial.",consoleHint:"Consultez la console du navigateur et votre .env. Voir le README pour la configuration."},Jne={brandTitle:"Flexweg CMS",brandSubtitle:"Publication statique",login:{heading:"Connexion",intro:"Utilisez l'email et le mot de passe transmis par votre administrateur.",submit:"Se connecter",submitting:"Connexion…"},fields:{name:"Nom affiché (optionnel)",namePlaceholder:"Jane Doe",email:"Email",password:"Mot de passe",passwordHint:"Au moins 8 caractères."},footer:"Les nouveaux comptes sont créés par un administrateur depuis la page Utilisateurs.",errors:{invalidEmail:"Veuillez entrer une adresse email valide.",missingPassword:"Le mot de passe est requis.",passwordTooShort:"Le mot de passe doit faire au moins 8 caractères."}},Qne=JSON.parse(`{"title":"Bienvenue sur Flexweg CMS","subtitle":"Configuration initiale","intro":"Renseignez vos identifiants Firebase, le compte administrateur initial, et votre clé API Flexweg. Les valeurs sont validées, sauvegardées sur votre projet (Firestore + un fichier config.js sur Flexweg), puis l'admin recharge sur le flux de connexion habituel. Vous ne le faites qu'une seule fois.","introFirebase":"Étape 1 — Firebase. Renseignez les identifiants de votre projet Firebase et le compte administrateur bootstrap. Nous vérifions la connexion, l'email et que vos règles Firestore reconnaissent cet admin avant de passer à l'étape Flexweg.","introFlexweg":"Étape 2 — Flexweg. Renseignez votre clé API Flexweg et l'URL du site. Nous testons l'API, sauvegardons la configuration dans Firestore, uploadons config.js sur votre site et synchronisons les assets de thème.","continueToFlexweg":"Valider Firebase et continuer","stepper":{"terms":"CGU","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Contenu et publication","data":"Données","hosting":"Hébergement","install":"Installation"},"backend":{"title":"Choisir le backend de données","intro":"Choisissez où le CMS stockera vos articles, pages, utilisateurs et paramètres. Vous pourrez changer plus tard depuis les Paramètres (les données ne sont pas migrées).","sqliteTitle":"Flexweg SQLite (recommandé)","sqliteHint":"Toutes les données restent sur votre site Flexweg sous forme de fichier SQLite. Aucun service externe. L'auth est fournie par l'API SQLite Flexweg.","firebaseTitle":"Firebase","firebaseHint":"Utilisez un projet Firebase pour Firestore + Auth. Gratuit avec le plan Spark. Mises à jour temps réel via onSnapshot.","continue":"Continuer","markdownGitTitle":"Fichiers Markdown dans un dépôt Git","markdownGitHint":"Les articles sont des fichiers .md sur GitHub / GitLab (ou un clone local). Chaque éditeur se connecte avec son propre jeton ; chaque modification est un commit. Pas de base de données, fonctionne à plusieurs et sur plusieurs postes.","localTitle":"Ce navigateur uniquement","localHint":"Un seul utilisateur, sans connexion, rien à configurer. Le contenu reste dans ce navigateur (exportez-le depuis les Réglages). Idéal pour un admin qui tourne sur votre ordinateur."},"sqlite":{"heading":"Connecter votre site Flexweg","intro":"Nous utiliserons votre clé API maître Flexweg UNE SEULE FOIS pour créer un token limité à la base SQLite. Après l'installation, la clé maître est jetée et seul le token limité (à ce seul fichier SQLite) est stocké.","apiKeyHint":"Clé API maître Flexweg. Utilisée uniquement pour l'installation — jamais stockée après.","detectedFromUrl":"Détecté depuis l'URL","advanced":"Réglages avancés (URL du site, chemin SQLite…)","pathHint":"Emplacement du fichier SQLite sur votre site Flexweg. Les dossiers sont créés automatiquement.","adminHeading":"Compte administrateur","adminIntro":"Créez le premier utilisateur — ce compte obtient automatiquement les droits d'admin. Les membres suivants sont créés depuis la page Utilisateurs une fois connecté.","passwordHint":"Au moins 8 caractères.","submit":"Installer la base SQLite"},"terms":{"title":"Conditions générales d'utilisation","intro":"Merci de lire et d'accepter les conditions ci-dessous avant d'utiliser Flexweg CMS. Elles sont rédigées en langage clair pour être rapides à lire.","section1":{"title":"1. Service gratuit","body":"Flexweg CMS est mis à votre disposition gratuitement par Flexweg. Vous pouvez l'utiliser sans limite avec votre hébergement Flexweg — Flexweg ne vous facturera jamais l'utilisation du CMS lui-même. Les frais habituels de votre offre d'hébergement Flexweg et de votre plan Firebase restent applicables, chacun sur le compte concerné."},"section2":{"title":"2. Service fourni « en l'état », sans garantie","body":"Le CMS est fourni en l'état. Nous travaillons à le garder stable et à l'améliorer dans le temps, mais nous ne pouvons garantir qu'il sera exempt de bugs, de défauts ou d'interruptions. Utilisez-le avec la même prudence qu'un outil que vous n'avez pas écrit vous-même : conservez des sauvegardes de vos contenus importants."},"section3":{"title":"3. Vos contenus, votre responsabilité","body":"Vous êtes seul responsable des contenus que vous publiez via le CMS — textes, images, vidéos, formulaires, intégrations de code, et tout autre média. Vous devez respecter la loi applicable dans votre juridiction (et dans celles que vous ciblez), les droits d'auteur, les droits à l'image et à la personnalité, les règles de protection des données personnelles, ainsi que les conditions de tout service tiers utilisé (polices intégrées, vidéos, etc.). Flexweg n'est pas responsable des contenus publiés par les utilisateurs du CMS."},"section4":{"title":"4. Votre compte Firebase, votre sécurité","body":"Le CMS stocke ses données dans votre propre projet Firebase. Vous êtes responsable de la sécurité de ce projet : choisissez un mot de passe robuste pour le compte administrateur initial, configurez les règles Firestore comme documenté, faites tourner vos clés API si nécessaire, et contrôlez qui y a accès. Flexweg ne pourra en aucun cas être tenu responsable d'un accès non autorisé, d'une fuite de données, d'un piratage ou d'une perte résultant d'une mauvaise configuration ou d'une compromission de votre compte Firebase."},"section5":{"title":"5. Limitation de responsabilité","body":"Flexweg ne pourra être tenu responsable d'aucune perte de revenus, perte de données, perte d'opportunité commerciale, ni d'aucun dommage direct ou indirect lié à l'utilisation, au mauvais usage ou à l'indisponibilité du CMS. Lorsque la loi applicable impose à Flexweg une responsabilité, celle-ci est limitée au montant effectivement payé à Flexweg pour le CMS au cours des 12 derniers mois — soit zéro, le CMS étant gratuit."},"section6":{"title":"6. Vos données restent les vôtres","body":"Les contenus que vous créez avec le CMS sont stockés dans votre propre projet Firebase (textes, réglages, métadonnées des médias) et sur votre propre hébergement Flexweg (HTML publié, images, assets de thème). Le CMS lui-même ne transmet vos contenus à aucun service tiers. Les plugins ou thèmes que vous choisissez d'activer peuvent avoir leur propre comportement — vérifiez ce qu'ils font avant de les activer."},"section7":{"title":"7. Bon usage","body":"L'utilisation du CMS pour des activités illégales, frauduleuses ou nuisibles, ou contraires aux conditions générales d'utilisation de Flexweg, peut entraîner la suspension de votre accès à l'hébergement Flexweg. Nous pouvons également mettre à jour les présentes conditions ; les changements significatifs seront communiqués via l'admin ou par email."},"accept":"J'ai lu et j'accepte les CGU.","continue":"Continuer vers la configuration","back":"Retour"},"sections":{"firebase":"Firebase","admin":"Administrateur initial","flexweg":"API Flexweg"},"help":{"firebase":"Retrouvez ces valeurs dans Firebase Console → Paramètres du projet → Général → Vos applications → Configuration du SDK.","admin":"Utilisez un utilisateur existant dans Firebase Authentication. Toute personne se connectant avec cet email est traitée comme administrateur et n'a pas besoin d'enregistrement utilisateur. Créez l'utilisateur via Firebase Console → Authentication s'il n'existe pas.","flexweg":"Générez une clé API permanente dans votre compte Flexweg → API. L'URL du site est l'adresse publique de votre site Flexweg (ex. https://votre-site.flexweg.com).","flexwegApiKeyHint":"Récupérez votre clé API depuis vos paramètres de compte Flexweg.","flexwegApiKeyLink":"Ouvrir les paramètres du compte"},"fields":{"apiKey":"Clé API","authDomain":"Domaine d'authentification","projectId":"ID du projet","storageBucket":"Bucket de stockage","messagingSenderId":"ID expéditeur de messagerie","appId":"ID de l'application","adminEmail":"Email","adminPassword":"Mot de passe","flexwegApiKey":"Clé API","flexwegSiteUrl":"URL du site","flexwegApiBaseUrl":"URL de base de l'API","sqlitePath":"Chemin SQLite"},"submit":"Enregistrer et continuer","submitting":"Configuration…","success":"Configuration terminée !","reloadingHint":"Rechargement de l'admin dans un instant — patientez.","footer":"Ces valeurs sont enregistrées sur votre projet (Firestore + Flexweg). Elles ne sont envoyées nulle part ailleurs.","steps":{"signInFirebase":"Connexion à Firebase…","testFlexweg":"Test de l'API Flexweg…","writeFirestore":"Sauvegarde de la configuration…","uploadConfig":"Upload de config.js sur Flexweg…","syncThemes":"Synchronisation des assets de thème sur Flexweg…","sqliteInstall":"Création du token SQLite limité…","sqliteRegisterAdmin":"Enregistrement du compte admin…","sqliteSchema":"Initialisation du schéma SQLite…"},"stepsDone":{"sqliteInstall":"Token SQLite limité créé","sqliteRegisterAdmin":"Admin enregistré et connecté","sqliteSchema":"Schéma SQLite prêt"},"errors":{"missingFields":"Veuillez remplir tous les champs.","rootDeploymentTitle":"L'admin doit être dans un sous-dossier, pas à la racine du site.","rootDeploymentHint":"Déplacez les fichiers de l'admin (index.html, config.js, runtime/, …) dans un sous-dossier sur Flexweg — par exemple /admin/ ou un nom aléatoire comme /erf34f654GH3/ pour plus de discrétion. Puis rechargez l'admin depuis l'URL du sous-dossier et relancez la configuration.","firebaseAuthGeneric":"Impossible de se connecter à Firebase.","firebaseAuthInvalidCredential":"Firebase a refusé la combinaison email + mot de passe.","firebaseAuthInvalidCredentialHint":"Les projets Firebase récents activent par défaut la protection contre l'énumération d'emails, qui renvoie la même erreur que le mot de passe soit incorrect, que l'utilisateur n'existe pas, ou qu'il se connecte avec un autre fournisseur. À vérifier :\\n• Re-saisis le mot de passe — fais un copier/coller depuis un gestionnaire de mots de passe pour éliminer toute faute de frappe. Le minimum est 6 caractères.\\n• Ouvre Firebase Console → Authentication → Users et vérifie que l'email existe. Regarde la colonne « Providers » : si elle n'affiche que Google (ou un autre fournisseur) sans « Email/Password », définis ou réinitialise le mot de passe via le menu de la ligne (⋮ → Réinitialiser le mot de passe).\\n• Vérifie que l'orthographe de l'email correspond exactement à ce qui est stocké dans Firebase.","firebaseAuthUserNotFound":"Aucun utilisateur Firebase avec cet email. Créez-le d'abord dans Firebase Console → Authentication → Users.","firebaseAuthInvalidEmail":"L'email administrateur n'est pas une adresse valide.","firebaseInvalidApiKey":"La clé API Firebase est invalide. Vérifiez la valeur dans Firebase Console.","firebaseNetwork":"Erreur réseau lors de la connexion à Firebase. Vérifiez votre connexion.","firebaseTooManyRequests":"Trop de tentatives de connexion. Réessayez dans un instant ou réinitialisez le mot de passe depuis Firebase Console.","firebaseOperationNotAllowed":"L'authentification email/mot de passe n'est pas activée sur ce projet Firebase. Ouvrez Firebase Console → Authentication → Sign-in method et activez le fournisseur Email/Password.","firebaseUserDisabled":"Ce compte utilisateur Firebase est désactivé. Réactivez-le depuis Firebase Console → Authentication → Users.","wrongAdminEmail":"Le compte Firebase auquel vous vous êtes connecté ne correspond pas à l'email admin saisi. Réessayez.","rulesNotPinnedTitle":"Les règles Firestore ne vous reconnaissent pas comme bootstrap admin.","rulesNotPinnedHint":"Ouvrez Firebase Console → Firestore → Règles et remplacez la valeur de \`bootstrapAdminEmail()\` par : {{email}} — puis cliquez sur Publier. Le template de règles du README contient un placeholder \`you@example.com\` qui doit être remplacé par votre vrai email admin. Une fois les règles publiées, cliquez à nouveau sur Soumettre ici.","flexwegAuth":"Clé API Flexweg refusée. Vérifiez la valeur dans votre compte Flexweg → API.","flexwegNetwork":"Erreur réseau lors du contact avec Flexweg. Vérifiez l'URL de base de l'API et votre connexion.","flexwegHttp":"Erreur API Flexweg ({{status}}) : {{detail}}","firestoreRulesTitle":"Firestore a refusé l'écriture de la configuration.","firestoreRulesHint":"Ouvrez Firebase Console → Firestore → Règles et vérifiez que l'email admin de bootstrap est bien '{{email}}'. Le README contient un modèle de règles à copier-coller.","firestoreOther":"Échec de l'écriture Firestore","uploadFailed":"Impossible d'uploader config.js sur Flexweg","generic":"Une erreur s'est produite."},"docstore":{"contentTitle":"Dépôt de contenu","contentIntro":"Là où vos articles, pages et réglages sont stockés en fichiers Markdown + JSON. Un dépôt vide convient — le CMS crée les fichiers.","provider":"Dépôt","localClone":"Dossier local (clone git)","localCloneHint":"Choisissez le dossier de votre clone. Synchronisez-le avec votre client git habituel — le CMS lit et écrit les fichiers, il n'exécute pas git.","contentDir":"Dossier du contenu dans le dépôt","privateRepo":"Utilisez un dépôt privé : les brouillons y sont stockés.","folderRequired":"Choisissez d'abord le dossier de contenu.","checking":"Vérification de l'accès au dépôt…","publishIntro":"Là où le site généré est publié. Modifiable plus tard dans les Réglages.","existingSite":"Ce dépôt est déjà configuré — le site continue d'être publié sur : {{target}}. Modifiable plus tard dans les Réglages (les clés secrètes éventuelles doivent y être ressaisies).","install":"Installer","steps":{"config":"Enregistrement de la configuration…","content":"Chargement du contenu…","target":"Enregistrement de la cible de publication…","testTarget":"Test de la cible de publication…"},"doneTitle":"C'est prêt !","doneBody":"La configuration est enregistrée dans ce navigateur. Pour éviter cette étape aux autres éditeurs, téléchargez config.js et remplacez celui du dossier admin de votre hébergement.","downloadConfig":"Télécharger config.js","open":"Ouvrir l'admin","footer":"Le contenu reste dans votre dépôt ou dans ce navigateur ; les jetons d'accès ne quittent jamais ce navigateur."},"data":{"title":"1. Où stocker vos données ?","intro":"Vos articles, pages, utilisateurs et réglages — les données de l'admin. C'est indépendant de l'endroit où le site public est hébergé (étape suivante).","localNote":"Rien à configurer : le contenu est stocké dans ce navigateur. Exportez-le depuis les Réglages pour le sauvegarder ou le déplacer plus tard.","options":{"sqlite-file":{"title":"SQLite","hint":"Une base SQLite stockée sur l'hébergement choisi à l'étape suivante (Flexweg, votre serveur, S3, Git…). Sans comptes utilisateurs — ou le service SQLite de Flexweg, avec comptes, si vous hébergez sur Flexweg."},"flexweg-sqlite":{"title":"SQLite (service Flexweg)","hint":"Une base SQLite gérée par le service Flexweg, avec comptes utilisateurs intégrés. Nécessite un compte Flexweg, quel que soit l'hébergement du site."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth dans votre projet Google. Temps réel, plan Spark gratuit."},"markdown-git":{"title":"Fichiers Markdown dans Git","hint":"Les articles sont des fichiers .md dans un dépôt GitHub / GitLab (ou un clone local). Chaque éditeur utilise son propre jeton ; chaque modification est un commit."},"local":{"title":"Ce navigateur","hint":"Un seul utilisateur, sans connexion, rien à configurer. Idéal pour un admin qui tourne sur votre ordinateur."}}},"hosting":{"title":"2. Où publier le site ?","intro":"Là où le site statique généré (HTML, CSS, images) est envoyé à chaque publication. Modifiable plus tard dans les Réglages.","existing":"Ce dépôt de contenu publie déjà sur la cible ci-dessous. Gardez-la ou choisissez-en une autre."},"install":{"title":"3. Installation","intro":"Vérifiez le récapitulatif, puis installez.","data":"Données","hosting":"Hébergement","saveTarget":"Enregistrement de la cible de publication…","noteConfigJs":"La configuration de l'admin (config.js) est envoyée à côté de l'admin sur Flexweg quand c'est possible ; sinon, vous pourrez la télécharger.","noteLocalConfig":"La configuration est enregistrée dans ce navigateur ; vous pourrez télécharger config.js à placer dans le dossier admin pour éviter cette étape aux autres éditeurs."},"sqliteFile":{"security":"Pas de comptes utilisateurs : toute personne qui peut ouvrir cet admin peut modifier le contenu — protégez le dossier de l'admin au niveau de l'hébergement. Le fichier de base est servi comme n'importe quel fichier : gardez-le chiffré, ou stockez-le dans un emplacement privé séparé.","intro":"Là où le fichier de base est stocké. Il est lu et enregistré par cet admin via les mêmes connecteurs que l'hébergement.","path":"Chemin du fichier de base","pathHint":"Créé au premier enregistrement s'il n'existe pas encore. Avec un dépôt Git, chaque enregistrement est un commit — préférez un dépôt ou une branche qui ne déclenche pas de build du site.","existing":"base existante","new":"nouvelle base","dataNote":"Rien à configurer ici : la base sera stockée sur l'hébergement choisi à l'étape suivante.","heading":"Base de données SQLite","flexwegService":"Utiliser le service SQLite de Flexweg","flexwegServiceHint":"La base est gérée par Flexweg et dispose de comptes utilisateurs intégrés (e-mail + mot de passe). Sinon, c'est un simple fichier sur cet hébergement, sans comptes.","summaryFile":"Fichier {{path}} sur cet hébergement","summaryService":"Service SQLite de Flexweg ({{path}})","encrypt":"Chiffrer la base","encryptHint":"Recommandé sur un hébergement public : le fichier est illisible sans la phrase secrète. Chaque nouveau navigateur la demande une fois.","passphrase":"Phrase secrète","passphraseHint":"Enregistrez-la maintenant dans votre gestionnaire de mots de passe : sans elle, personne ne peut ouvrir la base, pas même vous.","copy":"Copier","copied":"Copiée","generate":"Nouvelle","passphraseTooShort":"La phrase secrète doit faire au moins 12 caractères.","existingEncrypted":"Une base chiffrée existe déjà à cet emplacement : saisissez sa phrase secrète.","separate":"Stocker la base dans un emplacement privé séparé","separateHint":"Par ex. un bucket S3 / R2 privé ou un dépôt Git privé : la base n'est alors jamais servie par le site public.","summaryEncrypted":"chiffrée","summaryLocation":"stockée dans {{location}}","locationLabel":"Emplacement de la base","gitBranchNote":"La base est conservée sur la branche {{branch}} de ce dépôt, qui n'est jamais publiée : enregistrer un contenu ne relance pas la construction du site.","summaryBranch":"sur la branche {{branch}}"},"adminHosting":{"deploying":"Copie de l'admin sur le site…","label":"Héberger aussi l'admin sur ce site","hint":"L'admin est copié dans {{url}} avec son config.js (aucun secret dedans) — chaque éditeur pourra l'ouvrir là. Chacun se connecte toujours avec ses propres accès.","folder":"Dossier de l'admin","alreadyHere":"Cet admin tourne déjà depuis ce site : son config.js sera mis à jour sur place.","doneBody":"L'admin est maintenant sur votre site. Sur GitHub Pages, activez d'abord Pages pour le dépôt si ce n'est pas fait (Settings → Pages), puis ouvrez-le :","open":"Ouvrir l'admin en ligne","continueHere":"Continuer dans cet admin"}}`),Xne={actions:{upload:"Upload du fichier",delete:"Suppression du fichier",rename:"Renommage du fichier",get:"Lecture du fichier",list:"Listing des fichiers",createFolder:"Création du dossier",renameFolder:"Renommage du dossier",deleteFolder:"Suppression du dossier",storageLimits:"Lecture des quotas de stockage",commit:"Publication des modifications"},errors:{configMissing:"La cible de publication n'est pas configurée. Configurez-la dans les Réglages avant de publier.",network:"{{action}} : erreur réseau ou CORS bloqué. Vérifiez votre connexion.",auth:"{{action}} : authentification échouée. Vérifiez les identifiants de la cible de publication dans les Réglages.",notFound:"{{action}} : la cible est introuvable sur la cible de publication.",tooLarge:"{{action}} : fichier trop volumineux pour la cible de publication.",rateLimited:"{{action}} : trop de requêtes, veuillez réessayer dans un instant.",serverError:"{{action}} : erreur serveur de la cible de publication ({{status}}). Veuillez réessayer.",generic:"{{action}} a échoué ({{status}}){{detail}}.",unsupported:"{{action}} : non pris en charge par la cible de publication « {{connector}} ».",unknownConnector:"Cible de publication inconnue « {{connector}} ». Vérifiez Réglages → Cible de publication.",folderAccess:"Pas d'accès au dossier local. Ouvrez Réglages → Cible de publication et cliquez sur « Reconnecter le dossier »."}},Zne={log:{rendering:"Rendu de la page…",uploading:"Upload de {{path}}…",deleting:"Suppression de {{path}}…",regenerating:"Régénération des listings…",skipped:"{{path}} ignoré (aucun changement)",done:"Publié sur {{url}}",failed:"Échec : {{error}}"}},Yne={errors:{notConnected:"Non connecté au dépôt de contenu. Reconnectez-vous avec votre jeton d'accès.",conflict:"Quelqu'un d'autre a modifié cet élément entre-temps. Sa version est maintenant affichée — réappliquez votre modification.",sqliteUnsupported:"La cible « {{connector}} » ne peut pas stocker de fichier de base."}},ere={target:"Cible de publication",settingsTitle:"Cible de publication",settingsHelp:"Là où le site rendu est envoyé lors d'une publication. Les identifiants sont stockés avec votre backend de contenu (ou gardés dans ce navigateur pour les dépôts Git de contenu) et lisibles par tous les admins.",saved:"Cible de publication enregistrée. Lancez Régénérer → Tout pour publier le site complet sur la nouvelle cible.",test:"Tester la connexion",testOk:"Connexion OK",testFailed:"Échec de la connexion",names:{flexweg:"Flexweg","git-pages":"Dépôt Git (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"Bucket compatible S3 (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Votre propre serveur (bridge PHP)","browser-mirror":"Télécharger en ZIP","local-folder":"Dossier local sur cet ordinateur"},hints:{flexweg:"Envoi via l'API Files de Flexweg.","git-pages":"Chaque publication est un commit dans le dépôt ; l'hébergeur reconstruit le site à partir de lui.",s3:"Nécessite une règle CORS sur le bucket autorisant l'origine de cet admin, et l'hébergement de site (ou un CDN) pour servir les index.html.","php-bridge":"Déposez external/bridges/php/flexweg-bridge.php sur votre serveur, définissez sa clé d'API, puis renseignez son URL ici.","browser-mirror":"Le site est conservé dans ce navigateur ; téléchargez le ZIP et déposez-le où vous voulez.","local-folder":"Écrit le site directement dans un dossier (Chrome / Edge). Servez-le en local ou poussez-le avec vos outils."},fields:{flexweg:{apiKey:"Clé d'API",siteUrl:"URL du site",apiBaseUrl:"URL de base de l'API"},"git-pages":{host:"Hébergement",provider:"Fournisseur Git",owner:"Propriétaire (utilisateur ou organisation)",repo:"Dépôt",project:"Chemin du projet",branch:"Branche",dir:"Dossier dans le dépôt",token:"Jeton d'accès",siteUrl:"URL publique du site",apiBaseUrl:"URL de l'API (auto-hébergé uniquement)"},s3:{endpoint:"Endpoint",region:"Région",bucket:"Bucket",prefix:"Préfixe des clés (optionnel)",accessKeyId:"ID de clé d'accès",secretAccessKey:"Clé d'accès secrète",siteUrl:"URL publique du site",forcePathStyle:"URL de type chemin (MinIO, R2, la plupart des compatibles)",publicRead:"Rendre les fichiers publics (ACL public-read) — pour les buckets qui ne sont pas publics via une politique (OVHcloud, Scaleway…). À laisser décoché sur les buckets AWS qui imposent « bucket owner enforced »."},"php-bridge":{apiBaseUrl:"URL du bridge",apiKey:"Clé d'API du bridge",siteUrl:"URL publique du site"},"browser-mirror":{siteUrl:"URL publique du site (optionnel)"},"local-folder":{siteUrl:"URL où le dossier est servi (optionnel)"}},help:{flexweg:{apiKey:"Générée depuis votre compte Flexweg → API."},"git-pages":{host:"Cloudflare Pages : reliez le projet à ce dépôt sans commande de build, avec le dossier de sortie ci-dessous. Fonctionne avec les dépôts privés.",dir:'Laissez vide pour la racine. GitHub Pages : "" ou "docs". GitLab Pages : "public".',token:"Jeton fine-grained sur ce dépôt avec Contents : lecture/écriture (GitHub) — ajoutez Pages : lecture/écriture pour que le CMS active GitHub Pages — ou jeton avec le scope api (GitLab). Laissez vide pour utiliser le jeton de chaque éditeur quand le contenu est chez le même fournisseur.",siteUrl:"ex. https://user.github.io/repo — une URL avec sous-dossier fonctionne, les liens sont ajustés automatiquement."},s3:{endpoint:"Laissez vide pour AWS (déduit de la région). R2 : https://<account-id>.r2.cloudflarestorage.com",siteUrl:"L'URL d'hébergement du bucket ou votre domaine CDN."},"php-bridge":{apiBaseUrl:"L'URL complète de flexweg-bridge.php sur votre serveur (HTTPS)."},"browser-mirror":{siteUrl:"Là où vous déposerez le ZIP — sert aux URL absolues (sitemaps, RSS, médias)."},"local-folder":{siteUrl:"ex. http://localhost:8080 quand un serveur web local sert le dossier."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (relié au dépôt)","gitlab-pages":"GitLab Pages",other:"Autre (Netlify, Vercel, git pull serveur…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Choisir un dossier…",change:"Changer de dossier…",reconnect:"Reconnecter le dossier",unsupported:"Ce navigateur ne peut pas écrire dans un dossier local. Utilisez Chrome ou Edge."},mirror:{download:"Télécharger le site (ZIP)",count:"{{count}} fichiers dans ce navigateur"},adminHosting:{title:"Admin sur ce site",help:"Copie cet admin sur la cible de publication (premier déploiement, ou mise à jour après une nouvelle version). Son config.js ne contient aucun secret.",deploy:"Déployer / mettre à jour l'admin",deployed:"Admin déployé ({{count}} fichiers) — {{url}}"},pages:{enabled:"GitHub Pages activé pour ce dépôt — le site sera en ligne dans une minute environ.",enableHint:"Publication réussie. Pour mettre le site en ligne, activez GitHub Pages pour {{repo}} : Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Ou donnez au jeton la permission « Pages : read and write » et le CMS le fera.)"},siteUrl:{mismatch:"L'URL publique du site (Réglages → Site) est {{site}}, mais cette cible sert le site à {{target}}. Les liens, le CSS et les sitemaps suivent l'URL du site — ils seront faux sur cet hébergement.",use:"Utiliser {{url}} pour le site",updated:"URL du site mise à jour. Lancez Régénérer → Tout pour republier les pages avec les nouveaux liens."}},tre={heading:"Connexion au dépôt de contenu",tokenIntro:"Le contenu est stocké dans le dépôt {{provider}} {{repo}}. Connectez-vous avec votre propre jeton d'accès personnel — vos droits sur le dépôt déterminent votre rôle (écriture = éditeur, admin / maintainer = admin).",token:"Jeton d'accès personnel",tokenHelpGithub:"Jeton fine-grained, limité à ce dépôt, permission Contents : lecture et écriture.",tokenHelpGitlab:"Jeton avec le scope api, rôle Developer ou plus sur ce projet.",createToken:"Créer un jeton",connect:"Se connecter",tokenStorage:"Le jeton est conservé dans ce navigateur uniquement. La déconnexion l'efface.",failed:"Ce jeton ne permet pas d'écrire dans le dépôt (invalide, expiré ou en lecture seule). Vérifiez ses permissions.",folderIntro:"Le contenu est stocké dans un dossier de cet ordinateur (en général un clone git que vous synchronisez avec votre client git). Autorisez ce navigateur à y accéder — il redemande l'accès après chaque rechargement.",openFolder:"Ouvrir le dossier de contenu"},nre={flexweg:{title:"Flexweg",short:"Hébergement Flexweg",hint:"Envoi via l'API Files de Flexweg. Clé d'API depuis votre compte Flexweg."},"github-pages":{title:"GitHub Pages",short:"Gratuit, depuis un dépôt GitHub",hint:"Chaque publication est un commit dans le dépôt ; GitHub Pages le sert. Settings → Pages → Deploy from a branch. Dépôts publics sur le plan gratuit."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Gratuit, dépôts privés OK",hint:"Le CMS commite le site dans un dépôt GitHub / GitLab ; reliez-y un projet Cloudflare Pages (sans commande de build, dossier de sortie = le dossier ci-dessous)."},"gitlab-pages":{title:"GitLab Pages",short:"Gratuit, depuis un dépôt GitLab",hint:"Chaque publication est un commit ; le CMS ajoute un .gitlab-ci.yml minimal qui publie le dossier public/."},"git-other":{title:"Netlify, Vercel…",short:"Tout hébergeur qui déploie un dépôt",hint:"Le CMS commite le site dans un dépôt Git ; reliez votre hébergeur (Netlify, Vercel, serveur avec git pull…) à ce dépôt."},s3:{title:"S3 / R2 / B2…",short:"Bucket de stockage objet",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Nécessite une règle CORS sur le bucket et l'hébergement de site ou un CDN devant."},"own-server":{title:"Votre serveur (FTP / SFTP)",short:"Mutualisé, VPS…",hint:"Un navigateur ne sait pas parler FTP ni SFTP : déposez une fois le bridge PHP (external/bridges/php/flexweg-bridge.php) avec votre client FTP, définissez sa clé d'API, puis renseignez son URL ici. Fonctionne sur tout hébergement PHP."},"local-folder":{title:"Dossier local",short:"Sur cet ordinateur",hint:"Écrit le site dans un dossier de cet ordinateur (Chrome / Edge). Servez-le en local ou poussez-le avec vos outils."},zip:{title:"Télécharger en ZIP",short:"À déposer à la main",hint:"Le site est conservé dans ce navigateur ; téléchargez un ZIP depuis les Réglages et déposez-le où vous voulez (Netlify Drop, client FTP…)."}},rre={heading:"Connexion à la base de données",intro:"Cet admin stocke son contenu dans {{path}}. Saisissez les identifiants d'accès pour ce navigateur.",storage:"Les identifiants sont conservés dans ce navigateur uniquement. La déconnexion les efface.",passphrase:"Phrase secrète de la base",passphraseHint:"La base est chiffrée. Saisissez la phrase secrète choisie à l'installation (conservée dans ce navigateur uniquement).",passphraseWrong:"Phrase secrète incorrecte : la base n'a pas pu être ouverte.",passphraseMissing:"Saisissez la phrase secrète de la base."},sre={common:Rne,auth:jne,nav:Mne,dashboard:Lne,posts:Dne,pages:Fne,taxonomies:One,media:zne,themes:Une,plugins:Bne,externalInstall:$ne,externalLoader:Hne,menus:Vne,settings:qne,users:Wne,firestoreSetup:Gne,errors:Kne,identity:Jne,setup:Qne,flexweg:Xne,publish:Zne,docstore:Yne,connectors:ere,gitAccess:tre,hosting:nre,sqliteAccess:rre},ire={save:"Speichern",saving:"Speichert…",saved:"Gespeichert",cancel:"Abbrechen",delete:"Löschen",deleting:"Wird gelöscht…",edit:"Bearbeiten",create:"Erstellen",search:"Suchen",loading:"Lädt…",yes:"Ja",no:"Nein",confirm:"Bestätigen",back:"Zurück",next:"Weiter",previous:"Vorherige",close:"Schließen",all:"Alle",none:"Keine",actions:"Aktionen",name:"Name",slug:"Slug",description:"Beschreibung",status:"Status",createdAt:"Erstellt",updatedAt:"Aktualisiert",publishedAt:"Veröffentlicht",language:"Sprache",darkMode:"Dunkelmodus",lightMode:"Hellmodus",signOut:"Abmelden",administrator:"Administrator",editor:"Redakteur",appName:"Flexweg CMS"},are={signIn:"Anmelden",signingIn:"Anmeldung läuft…",email:"E-Mail",password:"Passwort",emailPlaceholder:"sie@firma.com",passwordPlaceholder:"••••••••",forgotPassword:"Passwort vergessen?",resetEmailSent:"E-Mail zum Zurücksetzen des Passworts wurde an {{email}} gesendet.",enterEmailFirst:"Geben Sie zuerst Ihre E-Mail-Adresse oben ein und klicken Sie dann auf Zurücksetzen.",emailPasswordRequired:"E-Mail und Passwort sind erforderlich.",signInSubtitle:"Verwenden Sie Ihre Geschäfts-E-Mail und Ihr Passwort.",footer:"Kontoanfragen erfolgen über Ihren Administrator.",errors:{invalidEmail:"Ungültige E-Mail-Adresse.",invalidCredentials:"Ungültige E-Mail-Adresse oder ungültiges Passwort.",tooManyRequests:"Zu viele Versuche. Versuchen Sie es später erneut oder setzen Sie Ihr Passwort zurück.",userDisabled:"Dieses Konto wurde deaktiviert.",networkFailed:"Netzwerkfehler. Überprüfen Sie Ihre Verbindung.",generic:"Authentifizierung fehlgeschlagen."}},ore={openMenu:"Menü öffnen",closeMenu:"Menü schließen",dashboard:"Übersicht",posts:"Artikel",pages:"Seiten",taxonomies:"Kategorien & Schlagwörter",media:"Medien",themes:"Themes",themeSettings:"Theme-Einstellungen",plugins:"Plugins",menus:"Menüs",users:"Benutzer",settings:"Einstellungen"},lre={title:"Übersicht",welcome:"Willkommen zurück, {{email}}.",stats:{totalPosts:"Artikel",totalPages:"Seiten",online:"Online",drafts:"Entwürfe"}},cre={title:"Artikel",newPost:"Neuer Artikel",noPosts:"Noch keine Artikel. Erstellen Sie Ihren ersten Artikel, um zu beginnen.",noPostsInFilter:"Keine Artikel entsprechen dem aktuellen Filter.",search:{placeholder:"Artikel suchen…",clear:"Suche leeren",noResults:"Keine Artikel entsprechen Ihrer Suche."},pagination:{previous:"Zurück",next:"Weiter",showing:"Zeige {{from}}–{{to}} von {{total}}",pageOf:"Seite {{page}} von {{total}}"},bulk:{selectedCount_one:"{{count}} ausgewählt",selectedCount_other:"{{count}} ausgewählt",selectPage_one:"{{count}} auf dieser Seite auswählen",selectPage_other:"Alle {{count}} auf dieser Seite auswählen",deselectPage:"Seite abwählen",allOnPageSelected_one:"{{count}} auf dieser Seite ausgewählt.",allOnPageSelected_other:"Alle {{count}} auf dieser Seite ausgewählt.",selectAllMatching_one:"Den passenden Artikel auswählen",selectAllMatching_other:"Alle {{count}} passenden Artikel auswählen",allMatchingSelected_one:"Der passende Artikel ist ausgewählt.",allMatchingSelected_other:"Alle {{count}} passenden Artikel sind ausgewählt.",selectOne:'„{{title}}" auswählen',publish:"Veröffentlichen ({{count}})",publishing:"Wird veröffentlicht…",publishedCount:"{{ok}} veröffentlicht, {{failed}} fehlgeschlagen.",unpublish:"Zurückziehen ({{count}})",unpublishing:"Wird zurückgezogen…",unpublishedCount:"{{ok}} zurückgezogen, {{failed}} fehlgeschlagen.",delete:"Löschen",deleting:"Wird gelöscht…",deletedCount:"{{ok}} gelöscht, {{failed}} fehlgeschlagen.",confirmDelete_one:"{{count}} Artikel löschen? Damit wird er von Flexweg zurückgezogen und kann nicht wiederhergestellt werden.",confirmDelete_other:"{{count}} Artikel löschen? Damit werden sie von Flexweg zurückgezogen und können nicht wiederhergestellt werden.",noDraftSelected:"Keine Entwürfe ausgewählt.",noOnlineSelected:"Keine veröffentlichten Artikel ausgewählt.",clear:"Auswahl leeren"},filters:{all:"Alle",draft:"Entwurf",online:"Online"},fields:{title:"Titel",slug:"Slug",excerpt:"Auszug",content:"Inhalt",category:"Kategorie",tags:"Schlagwörter",heroImage:"Beitragsbild",seoTitle:"SEO-Titel",seoDescription:"SEO-Beschreibung",createdAt:"Erstellt am",updatedAt:"Zuletzt aktualisiert",publishedAt:"Veröffentlicht am"},edit:{newTitle:"Neuer Artikel",editTitle:"Artikel bearbeiten",saved:"Gespeichert.",savedAndRepublished:"Gespeichert und neu veröffentlicht.",saveFailed:"Speichern fehlgeschlagen.",saveAndRepublish:"Speichern & neu veröffentlichen",draftSaved:"Entwurf gespeichert.",slugCollision:{post:'Diese URL wird bereits vom Artikel verwendet: "{{label}}".',page:'Diese URL wird bereits von der Seite verwendet: "{{label}}".',category:'Diese URL wird bereits von der Kategorie verwendet: "{{label}}".'},publish:"Veröffentlichen",unpublish:"Zurückziehen",publishing:"Veröffentlicht…",unpublishing:"Wird zurückgezogen…",titlePlaceholder:"Titel hinzufügen",permalink:"Permalink",slugFormatHint:"Nur Kleinbuchstaben, ASCII, Bindestriche.",slugAutoSuffixed:'Suffix hinzugefügt, da "{{base}}" bereits von {{owner}} verwendet wird.',slugAutoSuffixedOwner:{post:'Beitrag: "{{label}}"',page:'Seite: "{{label}}"',category:'Kategorie: "{{label}}"'},saveBlocked:{titleRequired:"Fügen Sie vor dem Speichern einen Titel hinzu.",slugRequired:"Ein Titel und ein URL-Slug sind zum Speichern erforderlich.",slugInvalid:"Ungültiges Slug-Format (Kleinbuchstaben ASCII + Bindestriche).",slugCollision:"Lösen Sie den URL-Konflikt vor dem Speichern."},viewPublished:"Ansehen",confirmDelete:"Diesen Eintrag löschen?",inspector:{document:"Dokument",block:"Block",blockEmpty:"Wählen Sie einen Block im Editor, um seine Optionen anzuzeigen.",publishing:"Veröffentlichung",permalink:"Permalink",categories:"Kategorien & Schlagwörter",featured:"Beitragsbild",seo:"SEO",excerpt:"Auszug",dates:"Datumsangaben"},blocks:{addBlock:"Block hinzufügen",transform:"Umwandeln in",moveUp:"Nach oben verschieben",moveDown:"Nach unten verschieben",duplicate:"Duplizieren",remove:"Block löschen",paragraph:"Absatz",heading2:"Überschrift 2",heading3:"Überschrift 3",bulletList:"Aufzählung",orderedList:"Nummerierte Liste",blockquote:"Zitat",codeBlock:"Code",image:"Bild",horizontalRule:"Trenner",categories:{text:"Text",media:"Medien",layout:"Layout",embed:"Einbettungen",advanced:"Erweitert"},noSettings:"Dieser Block hat keine Einstellungen.",noSelection:"Wählen Sie einen Block im Editor, um seine Optionen anzuzeigen.",slash:{noResults:"Kein passender Block."}}},status:{draft:"Entwurf",online:"Online"},preview:{title:"Vorschau",rendering:"Vorschau wird gerendert…",error:"Vorschau fehlgeschlagen: {{error}}",viewports:{mobile:"Mobil",tablet:"Tablet",desktop:"Desktop"}}},ure={title:"Seiten",newPage:"Neue Seite",noPages:"Noch keine Seiten.",homeBadge:"Startseite",homeBadgeTooltip:"Wird als Startseite der Website verwendet"},dre={title:"Kategorien & Schlagwörter",categories:"Kategorien",tags:"Schlagwörter",newCategory:"Neue Kategorie",newTag:"Neues Schlagwort",noCategories:"Noch keine Kategorien.",noTags:"Noch keine Schlagwörter.",slugCollision:'Dieser Slug wird bereits von "{{label}}" verwendet.',seo:{button:"SEO",buttonTitle:"SEO-Meta-Tags bearbeiten",title:"SEO-Meta-Tags",subtitle:'Eigener Titel und Beschreibung für die Archivseite "{{name}}".',metaTitle:"Meta-Titel",metaTitleHint:"Wird als Seiten-<title> verwendet. Standard: der Name des Begriffs.",metaDescription:"Meta-Beschreibung",metaDescriptionHint:"Wird als Meta-Beschreibung der Seite verwendet. Standard: die Beschreibung des Begriffs."}},hre={title:"Medienbibliothek",upload:"Hochladen",uploading:"Lädt hoch…",finalizing:"Wird abgeschlossen…",uploadFailed:"Hochladen fehlgeschlagen",retry:"Erneut versuchen",noMedia:"Noch keine Medien.",alt:"Alt-Text",caption:"Bildunterschrift",filename:"Dateiname",size:"Größe",type:"Typ"},fre={title:"Themes",active:"Aktiv",activate:"Aktivieren",installExternal:"Theme installieren",uninstallDisabledTitle:"Wechseln Sie zu einem anderen Theme, bevor Sie dieses deinstallieren.",syncAssets:"Theme-Assets synchronisieren",regenerateSite:"Website neu generieren",regenerating:"Generiert neu…",regenerate:{button:"Neu generieren",running:"Wird ausgeführt…",groupBuiltins:"Website",groupPlugins:"Plugins",home:"Nur Startseite",homeHelp:"Generiert nur index.html neu — schnellste Option.",allHtml:"Alle HTML-Seiten",allHtmlHelp:"Alle Beiträge, Seiten, Archive und Listen — plus Menu / Posts / Authors JSON-Snapshots.",repair:"URLs reparieren",repairHelp:"Berechnet die kanonische URL jedes veröffentlichten Beitrags neu und verschiebt Dateien, die unter der falschen URL gelandet sind. Nützlich nach einem Import, der vor der Synchronisierung der Begriffe lief.",assets:"Theme-Assets",assetsHelp:"Lädt CSS + Begleit-Skripte des aktiven Themes nach /theme-assets/ hoch.",everything:"Alles",everythingHelp:"Theme-Assets + alle HTML + jede Plugin-Ausgabe. Langsamste Option.",noPluginTargets:"Keine Plugin-Neugenerierungen — aktivieren Sie ein Plugin, das Neugenerieren unterstützt."},confirmSwitch:{title:"Zu {{theme}} wechseln?",body:"Beim Theme-Wechsel müssen die Theme-Assets erneut hochgeladen und alle veröffentlichten Seiten neu generiert werden, damit das neue Aussehen überall greift. Das kann einen Moment dauern.",confirm:"Wechseln & neu generieren",cancel:"Abbrechen"}},pre={title:"Plugins",enabled:"Aktiviert",disabled:"Deaktiviert",enable:"Aktivieren",disable:"Deaktivieren",configure:"Konfigurieren",author:"Autor",learnMore:"Mehr erfahren",mustUseBadge:"Pflicht",installExternal:"Plugin installieren",tabs:{regular:"Plugins",mustUse:"Pflicht-Plugins"}},mre={titlePlugin:"Plugin installieren",titleTheme:"Theme installieren",labelPlugin:"Plugin",labelTheme:"Theme",intro:"Ziehen Sie eine ZIP-Datei mit einem {{label}}-Bundle hierher (manifest.json + bundle.js im ZIP-Root). Das {{label}} wird auf Ihre Flexweg-Site hochgeladen und nach einem Neuladen registriert. Ein erneuter Upload eines ZIP mit derselben Manifest-ID aktualisiert den vorhandenen Eintrag direkt — keine Deinstallation nötig.",zipField:"Bundle-ZIP-Datei",install:"Installieren",installing:"Installiert…",installSuccess:"{{name}} installiert ({{count}} Dateien hochgeladen). Lädt neu…",upgradeSuccess:"{{name}} von v{{previousVersion}} auf v{{newVersion}} aktualisiert ({{count}} Dateien hochgeladen). Lädt neu…",installedTitle:"Bereits installiert",bundledDefaultsTitle:"Mitgelieferte Standard-Plugins/Themes verfügbar",bundledDefaultsHint:"{{count}} mitgeliefertes Plugin/Theme ist derzeit deinstalliert. Stellen Sie sie wieder her, um den Auslieferungszustand dieser Admin-Version wiederherzustellen.",bundledDefaultsRestore:"Wiederherstellen",bundledDefaultsRestored:"{{plugins}} Plugin(s) und {{themes}} Theme(s) wiederhergestellt. Lädt neu…",uninstall:"Deinstallieren",uninstallSuccess:"{{id}} deinstalliert. Lädt neu…",confirmUninstall:"{{id}} deinstallieren? Die Dateien werden von Flexweg gelöscht.",errors:{"no-manifest":"Im ZIP fehlt manifest.json im Root.","invalid-manifest":"manifest.json ist ungültig (fehlende Pflichtfelder oder kein gültiges JSON).","incompatible-api":"Das Bundle wurde gegen eine inkompatible Runtime-API-Version gebaut.","no-bundle":"Das ZIP enthält die im Manifest deklarierte Einstiegsdatei nicht.","fetch-manifest":"Die aktuelle external.json auf Flexweg konnte nicht gelesen werden.","upload-failed":"Upload fehlgeschlagen — prüfen Sie Ihren Flexweg-API-Schlüssel und Ihre Verbindung."}},gre={someFailed:"{{count}} externe(s) Bundle(s) konnten nicht geladen werden. Siehe Browser-Konsole."},bre={title:"Menüs",header:"Kopfzeilen-Menü",footer:"Fußzeilen-Menü",label:"Beschriftung",saveAndPublish:"Speichern & generieren",discard:"Verwerfen",saved:"Menüs gespeichert und veröffentlicht.",saveFailed:"Menüs konnten nicht gespeichert werden.",unsavedChanges:"Sie haben ungespeicherte Änderungen."},yre={title:"Einstellungen",tabs:{general:"Allgemein"},site:{title:"Website",siteTitle:"Website-Titel",siteDescription:"Website-Beschreibung",siteLanguage:"Website-Sprache",siteLanguageHelp:'BCP-47-Tag (z. B. en, fr-CA), der auf jeder veröffentlichten Seite in <html lang="…"> eingefügt wird. Der Präfix wird mit den unterstützten Übersetzungslocales für Sitemap-/RSS-Labels und im Theme eingebaute Texte abgeglichen; nicht unterstützte Locales fallen auf Englisch zurück.',siteLanguageResolved:"Übersetzungen verwenden: {{label}}",baseUrl:"Öffentliche Website-URL",postsPerPage:"Artikel pro Seite",homeMode:"Startseiten-Inhalt",homeLatest:"Neueste Artikel",homeStatic:"Statische Seite",homePage:"Startseite",discourageIndexing:"Suchmaschinen davon abhalten, diese Website zu indexieren",discourageIndexingHelp:"Wenn aktiviert, erhält jede veröffentlichte Seite ein noindex/nofollow-Meta-Tag und robots.txt sperrt alle Crawler aus. Entspricht dem Verhalten von WordPress — nützlich für Staging-Websites oder Prüfungen vor dem Launch. Suchmaschinen, die die Anweisung respektieren, indexieren die Website nicht.",discourageRegenerateHint:"Indexierungseinstellung gespeichert. Klicken Sie unter Themes auf „Alles neu generieren“, um die Änderung auf alle veröffentlichten Seiten und robots.txt anzuwenden."},flexweg:{title:"Flexweg-API",apiKey:"API-Schlüssel",apiKeyHelp:"Erstellt in Ihrem Flexweg-Konto → API.",siteUrl:"Website-URL",siteUrlHelp:"Öffentliche URL Ihrer Flexweg-Website ohne abschließenden Schrägstrich.",apiBaseUrl:"API-Basis-URL",storageHelpFirebase:"In Firestore gespeichert (config/flexweg). Lesbar für jedes angemeldete Teammitglied, schreibbar nur für Administratoren.",storageHelpSqlite:"In der lokalen SQLite-Tabelle config gespeichert. Lesbar für jedes angemeldete Teammitglied, schreibbar nur für Administratoren."},backend:{title:"Daten-Backend",active:"Aktives Backend:",switchButton:"Backend wechseln…",confirmTitle:"Alle aktuellen Daten gehen verloren.",confirmBody:"Beim Wechsel wird die In-Browser-Konfiguration gelöscht und das Setup-Formular erneut geladen. Das neue Backend startet leer — die Daten des vorherigen Backends bleiben an Ort und Stelle (in Firestore oder als .sqlite-Datei auf Flexweg), aber das CMS liest sie erst wieder, wenn Sie zurückwechseln.",confirmYes:"Ja, Backend wechseln",downloadBackup:"Backup der .sqlite-Datei herunterladen",downloadBackupHelp:"vor dem Wechsel des Backends durchführen.",markdownGit:"Markdown — {{source}}",localFolder:"lokaler Ordner",localBrowser:"Dieser Browser (lokal, ein Benutzer)",sqliteFile:"SQLite-Datei — {{location}}"},performance:{title:"Leistung",help:"Wie das Admin-Backend Beiträge und Seiten lädt. Der Standardmodus funktioniert auf dem kostenlosen Firestore-Plan ohne Setup; der paginierte Modus ist für sehr große Sites und erfordert eine einmalige Index-Einrichtung.",mode:"Lademodus",modeGlobal:"Standard (keine Einrichtung erforderlich)",modePaginated:"Serverseitige Paginierung (Firestore-Indizes erforderlich)",globalHelp:"Lädt die gesamte Posts-Sammlung in einem Live-Abonnement. Sortierung, Filter und Suche im Speicher. Empfohlen für Sites mit weniger als ~5 000 Beiträgen.",paginatedHelp:"Cursor-paginierte Abonnements, eine Seite gleichzeitig. Erfordert zusammengesetzte Firestore-Indizes — siehe README. Empfohlen für sehr große Sites.",savedReload:"Gespeichert. Lade das Admin neu, um den neuen Modus anzuwenden."},editor:{title:"Editor",help:"Typografie für den Artikel-/Seiten-Editor. Unabhängig vom öffentlichen Theme.",fontFamily:"Schriftfamilie",bodySize:"Textgröße",h1Size:"H1-Größe",h2Size:"H2-Größe",h3Size:"H3-Größe",sizeHelp:"CSS-Länge, z. B. 16px oder 1rem. Leer lassen für Standard.",reset:"Auf Standard zurücksetzen"},profile:{title:"Profil",adminLocale:"Admin-Sprache",adminLocaleHelp:"Sprache, die von der Admin-Oberfläche verwendet wird. Im Profil gespeichert.",firstName:"Vorname",lastName:"Nachname",headline:"Titel",headlinePlaceholder:"z. B. Journalist, Chefredakteur…",headlineHelp:"Wird öffentlich unter Ihrem Namen in Autorenkarten und auf Ihrer Archivseite angezeigt.",bio:"Biografie",bioPlaceholder:"Ein kurzer Absatz, der auf Ihrer Autorenseite und unter Ihren Artikeln angezeigt wird.",bioHelp:"Sichtbar auf der öffentlichen Website in der Autoren-Seitenleiste und auf der Autoren-Archivseite.",socials:"Soziale Profile",socialsHelp:'Geben Sie die URLs der Profile ein, die Sie auf der öffentlichen Website zeigen möchten, und aktivieren Sie „Anzeigen" für die sichtbaren. Leere URLs werden ignoriert.',socialsShow:"Anzeigen",socialsShowHelp:"Schaltet die Sichtbarkeit dieses Netzwerks auf der öffentlichen Website um.",avatar:"Profilbild",avatarHelp:"Wählen Sie ein Bild aus Ihrer Medienbibliothek. Quadratische Bilder werden am besten dargestellt.",pickAvatar:"Aus Medien auswählen",changeAvatar:"Bild ändern",removeAvatar:"Entfernen",save:"Profil speichern"},transfer:{title:"Inhalte verschieben oder sichern",help:"Exportieren Sie alles (Beiträge, Seiten, Kategorien, Medien-Metadaten, Profile, Einstellungen) als eine JSON-Datei. Bei einem Markdown- oder lokalen Backend können Sie eine solche Datei importieren, wobei die IDs erhalten bleiben — so migrieren Sie von Firebase oder SQLite. Mediendateien und geheime Schlüssel sind nicht enthalten.",export:"Inhalte exportieren (JSON)",import:"Inhalte importieren…",modeMerge:"Zusammenführen (gleiche IDs überschreiben)",modeReplace:"Importierte Sammlungen ersetzen",replaceConfirm:"Der Ersetzen-Modus löscht vor dem Import alle vorhandenen Einträge der in der Datei enthaltenen Sammlungen. Fortfahren?",invalidFile:"Diese Datei ist kein Inhaltsexport von Flexweg CMS.",imported:"{{posts}} Beiträge/Seiten, {{terms}} Begriffe und {{media}} Medien importiert. Führen Sie Neu generieren → Alles aus, um sie zu veröffentlichen."},encryption:{title:"Datenbankverschlüsselung:",on:"an",off:"aus",onHelp:"Die Datenbankdatei ist ohne Passphrase unlesbar. Eine Änderung speichert die Datei mit neuem Schlüssel; andere Browser fragen nach der neuen Passphrase.",offHelp:"Die Datenbankdatei ist für jeden lesbar, der sie herunterladen kann (ein statisches Hosting liefert sie wie jede Seite aus). Verschlüssele sie mit einer Passphrase.",enable:"Datenbank verschlüsseln…",change:"Passphrase ändern…",savedConfirm:"Ich habe diese Passphrase in meinem Passwort-Manager gespeichert — ohne sie lässt sich der Inhalt nicht öffnen.",enableConfirm:"Jetzt verschlüsseln",changeConfirm:"Passphrase ändern",done:"Datenbank mit der neuen Passphrase gespeichert."}},vre={title:"Benutzer",noUsers:"Noch keine Benutzer.",role:"Rolle",disabled:"Deaktiviert",editProfileTitle:"Profil bearbeiten — {{email}}",profileSaved:"Profil gespeichert.",descriptionFirebase:"Verwalten Sie Ihr Team. Neue Konten werden in der Firebase Console angelegt und beim ersten Login hier gespiegelt.",descriptionSqlite:"Verwalten Sie Ihr Team. Nutzen Sie unten den Knopf +Benutzer hinzufügen, um Konten direkt anzulegen.",addUser:"Benutzer hinzufügen",addUserSuccess:"{{email}} hinzugefügt.",removeConfirmFirebase:"Datensatz von {{email}} löschen? Damit werden Profil und Rolle aus dem CMS entfernt. Um den Login-Zugang zu entziehen, löschen Sie das Konto zusätzlich in der Firebase Console.",removeConfirmSqlite:"{{email}} dauerhaft löschen? Damit wird der Login-Zugang entzogen UND Profil sowie Rolle entfernt. Diese Aktion kann nicht rückgängig gemacht werden.",empty:{title:"Noch keine Teammitglieder",descriptionFirebase:"Legen Sie das erste Konto in der Firebase Console an und melden Sie sich hier einmal an, um das Profil zu registrieren.",descriptionSqlite:"Klicken Sie oben auf +Benutzer hinzufügen, um das erste Teammitglied einzuladen."},help:{title:"So fügen Sie ein neues Teammitglied hinzu",bootstrapLine:"Der Bootstrap-Admin (immer voller Zugriff) ist:",firebase:{step1:"Öffnen Sie Firebase Console → Authentication → Add user.",step2:"Legen Sie E-Mail und Passwort fest und übermitteln Sie diese dem neuen Mitglied.",step3:"Bitten Sie es, sich hier einmal anzumelden — das Profil erscheint in der Liste oben und Sie können Rolle und Details bearbeiten."},sqlite:{step1:"Klicken Sie oben auf den Knopf +Benutzer hinzufügen.",step2:"Geben Sie die E-Mail und ein temporäres Passwort (mindestens 8 Zeichen) ein.",step3:"Teilen Sie die Zugangsdaten sicher mit — das Passwort kann nach dem Login aus dem Profil heraus geändert werden."},git:{step1:"Fügen Sie die Person als Mitwirkende des Content-Repositorys hinzu (Schreibzugriff = Redakteur, Admin / Maintainer = Admin).",step2:"Die Person erstellt ihr eigenes persönliches Zugriffstoken auf GitHub / GitLab.",step3:"Sie öffnet den Admin-Bereich und meldet sich mit diesem Token an — ihr Profil wird hier automatisch angelegt."}},addUserModal:{title:"Neues Teammitglied hinzufügen",intro:"Legt das Konto direkt in der Flexweg SQLite Auth-Datenbank an. Der neue Benutzer erhält standardmäßig die Editor-Rolle; befördern Sie ihn aus der Liste unten, wenn er Admin-Zugriff benötigt.",submit:"Benutzer anlegen",submitting:"Wird angelegt…"},actions:{editProfile:"Profil bearbeiten",promote:"Zum Administrator befördern",demote:"Auf Redakteur herabstufen",disable:"Deaktivieren",enable:"Aktivieren",delete:"Datensatz löschen"},descriptionGit:"Teammitglieder sind die Personen mit Schreibzugriff auf das Content-Repository. Sie erscheinen hier nach ihrer ersten Anmeldung; ihre Rolle richtet sich nach ihren Repository-Berechtigungen.",descriptionLocal:"Dieser Admin läuft im Einzelbenutzermodus: Inhalte werden in diesem Browser gespeichert und es gibt keine Konten.",descriptionSqliteFile:"Keine Benutzerkonten mit diesem Backend: Jeder, der den Admin öffnen kann, kann bearbeiten. Schützen Sie den Admin-Ordner auf Ebene Ihres Hostings. Die Autorenprofile unten dienen nur zur Information."},xre={title:"Firestore-Setup erforderlich",intro:"Die Artikel- und Seiten-Listenseiten benötigen einige Firestore-Composite-Indexes für effiziente Abfragen. Diese müssen manuell erstellt werden — Firebase reserviert die Index-Erstellung für Projekt-Admins.",checking:"Firestore-Indexes werden geprüft…",missingCount_one:"{{count}} Index fehlt:",missingCount_other:"{{count}} Indexes fehlen:",openConsole:"Firebase Console zum Erstellen öffnen",noUrl:"Auto-Vorschlag-URL nicht extrahierbar — siehe README für den gcloud-Befehl.",howItWorks:"Wie es funktioniert",step1:"Klicken Sie für jeden fehlenden Index auf den Link — Firebase Console öffnet sich mit der vorausgefüllten Index-Definition.",step2:'Klicken Sie auf „Create" und warten Sie 1–5 Minuten, bis der Index aufgebaut ist (Status in der Console).',step3:"Kommen Sie zurück und klicken Sie auf Wiederholen. Sobald beide Abfragen erfolgreich sind, lädt der Admin.",retry:"Wiederholen",retrying:"Wiederholt…",buildHint:"Der Aufbau eines Indexes kann nach der Erstellung einige Minuten dauern.",allReady:"Alle Indexes bereit.",unexpectedTitle:"Firestore nicht erreichbar",unexpectedHint:"Prüfen Sie Ihre Verbindung und die Firestore-Regeln. Wenn Sie die Indexes gerade erstellt haben, warten Sie auf den Abschluss des Aufbaus und versuchen Sie es erneut."},wre={appError:"Anwendungsfehler",loadAccountFailed:"Konto konnte nicht geladen werden",loadAccountHint:"Wenn das Problem weiterhin besteht, melden Sie sich ab und versuchen Sie es erneut.",accountDisabled:"Konto deaktiviert",accountDisabledMessage:"Ihr Zugriff auf dieses CMS wurde deaktiviert. Wenden Sie sich an Ihren Administrator.",firebaseNotConfigured:"Firebase ist nicht konfiguriert",firebaseEnvMissing:`Die folgenden Umgebungsvariablen fehlen:
|
|
3853
|
+
Copiez .env.example vers .env, renseignez vos identifiants Firebase, puis relancez le serveur de dev.`,adminEmailNotConfigured:"Email administrateur non configuré",adminEmailMessage:"VITE_ADMIN_EMAIL est manquant dans .env. Renseignez l'email de l'administrateur initial.",consoleHint:"Consultez la console du navigateur et votre .env. Voir le README pour la configuration."},Jne={brandTitle:"AgentCMS",brandSubtitle:"Publication statique",login:{heading:"Connexion",intro:"Utilisez l'email et le mot de passe transmis par votre administrateur.",submit:"Se connecter",submitting:"Connexion…"},fields:{name:"Nom affiché (optionnel)",namePlaceholder:"Jane Doe",email:"Email",password:"Mot de passe",passwordHint:"Au moins 8 caractères."},footer:"Les nouveaux comptes sont créés par un administrateur depuis la page Utilisateurs.",errors:{invalidEmail:"Veuillez entrer une adresse email valide.",missingPassword:"Le mot de passe est requis.",passwordTooShort:"Le mot de passe doit faire au moins 8 caractères."}},Qne=JSON.parse(`{"title":"Bienvenue sur AgentCMS","subtitle":"Configuration initiale","intro":"Renseignez vos identifiants Firebase, le compte administrateur initial, et votre clé API Flexweg. Les valeurs sont validées, sauvegardées sur votre projet (Firestore + un fichier config.js sur Flexweg), puis l'admin recharge sur le flux de connexion habituel. Vous ne le faites qu'une seule fois.","introFirebase":"Étape 1 — Firebase. Renseignez les identifiants de votre projet Firebase et le compte administrateur bootstrap. Nous vérifions la connexion, l'email et que vos règles Firestore reconnaissent cet admin avant de passer à l'étape Flexweg.","introFlexweg":"Étape 2 — Flexweg. Renseignez votre clé API Flexweg et l'URL du site. Nous testons l'API, sauvegardons la configuration dans Firestore, uploadons config.js sur votre site et synchronisons les assets de thème.","continueToFlexweg":"Valider Firebase et continuer","stepper":{"terms":"CGU","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Contenu et publication","data":"Données","hosting":"Hébergement","install":"Installation"},"backend":{"title":"Choisir le backend de données","intro":"Choisissez où le CMS stockera vos articles, pages, utilisateurs et paramètres. Vous pourrez changer plus tard depuis les Paramètres (les données ne sont pas migrées).","sqliteTitle":"Flexweg SQLite (recommandé)","sqliteHint":"Toutes les données restent sur votre site Flexweg sous forme de fichier SQLite. Aucun service externe. L'auth est fournie par l'API SQLite Flexweg.","firebaseTitle":"Firebase","firebaseHint":"Utilisez un projet Firebase pour Firestore + Auth. Gratuit avec le plan Spark. Mises à jour temps réel via onSnapshot.","continue":"Continuer","markdownGitTitle":"Fichiers Markdown dans un dépôt Git","markdownGitHint":"Les articles sont des fichiers .md sur GitHub / GitLab (ou un clone local). Chaque éditeur se connecte avec son propre jeton ; chaque modification est un commit. Pas de base de données, fonctionne à plusieurs et sur plusieurs postes.","localTitle":"Ce navigateur uniquement","localHint":"Un seul utilisateur, sans connexion, rien à configurer. Le contenu reste dans ce navigateur (exportez-le depuis les Réglages). Idéal pour un admin qui tourne sur votre ordinateur."},"sqlite":{"heading":"Connecter votre site Flexweg","intro":"Nous utiliserons votre clé API maître Flexweg UNE SEULE FOIS pour créer un token limité à la base SQLite. Après l'installation, la clé maître est jetée et seul le token limité (à ce seul fichier SQLite) est stocké.","apiKeyHint":"Clé API maître Flexweg. Utilisée uniquement pour l'installation — jamais stockée après.","detectedFromUrl":"Détecté depuis l'URL","advanced":"Réglages avancés (URL du site, chemin SQLite…)","pathHint":"Emplacement du fichier SQLite sur votre site Flexweg. Les dossiers sont créés automatiquement.","adminHeading":"Compte administrateur","adminIntro":"Créez le premier utilisateur — ce compte obtient automatiquement les droits d'admin. Les membres suivants sont créés depuis la page Utilisateurs une fois connecté.","passwordHint":"Au moins 8 caractères.","submit":"Installer la base SQLite"},"terms":{"title":"Conditions générales d'utilisation","intro":"Merci de lire et d'accepter les conditions ci-dessous avant d'utiliser AgentCMS. Elles sont rédigées en langage clair pour être rapides à lire.","section1":{"title":"1. Service gratuit","body":"AgentCMS est mis à votre disposition gratuitement par Flexweg. Vous pouvez l'utiliser sans limite avec votre hébergement Flexweg — Flexweg ne vous facturera jamais l'utilisation du CMS lui-même. Les frais habituels de votre offre d'hébergement Flexweg et de votre plan Firebase restent applicables, chacun sur le compte concerné."},"section2":{"title":"2. Service fourni « en l'état », sans garantie","body":"Le CMS est fourni en l'état. Nous travaillons à le garder stable et à l'améliorer dans le temps, mais nous ne pouvons garantir qu'il sera exempt de bugs, de défauts ou d'interruptions. Utilisez-le avec la même prudence qu'un outil que vous n'avez pas écrit vous-même : conservez des sauvegardes de vos contenus importants."},"section3":{"title":"3. Vos contenus, votre responsabilité","body":"Vous êtes seul responsable des contenus que vous publiez via le CMS — textes, images, vidéos, formulaires, intégrations de code, et tout autre média. Vous devez respecter la loi applicable dans votre juridiction (et dans celles que vous ciblez), les droits d'auteur, les droits à l'image et à la personnalité, les règles de protection des données personnelles, ainsi que les conditions de tout service tiers utilisé (polices intégrées, vidéos, etc.). Flexweg n'est pas responsable des contenus publiés par les utilisateurs du CMS."},"section4":{"title":"4. Votre compte Firebase, votre sécurité","body":"Le CMS stocke ses données dans votre propre projet Firebase. Vous êtes responsable de la sécurité de ce projet : choisissez un mot de passe robuste pour le compte administrateur initial, configurez les règles Firestore comme documenté, faites tourner vos clés API si nécessaire, et contrôlez qui y a accès. Flexweg ne pourra en aucun cas être tenu responsable d'un accès non autorisé, d'une fuite de données, d'un piratage ou d'une perte résultant d'une mauvaise configuration ou d'une compromission de votre compte Firebase."},"section5":{"title":"5. Limitation de responsabilité","body":"Flexweg ne pourra être tenu responsable d'aucune perte de revenus, perte de données, perte d'opportunité commerciale, ni d'aucun dommage direct ou indirect lié à l'utilisation, au mauvais usage ou à l'indisponibilité du CMS. Lorsque la loi applicable impose à Flexweg une responsabilité, celle-ci est limitée au montant effectivement payé à Flexweg pour le CMS au cours des 12 derniers mois — soit zéro, le CMS étant gratuit."},"section6":{"title":"6. Vos données restent les vôtres","body":"Les contenus que vous créez avec le CMS sont stockés dans votre propre projet Firebase (textes, réglages, métadonnées des médias) et sur votre propre hébergement Flexweg (HTML publié, images, assets de thème). Le CMS lui-même ne transmet vos contenus à aucun service tiers. Les plugins ou thèmes que vous choisissez d'activer peuvent avoir leur propre comportement — vérifiez ce qu'ils font avant de les activer."},"section7":{"title":"7. Bon usage","body":"L'utilisation du CMS pour des activités illégales, frauduleuses ou nuisibles, ou contraires aux conditions générales d'utilisation de Flexweg, peut entraîner la suspension de votre accès à l'hébergement Flexweg. Nous pouvons également mettre à jour les présentes conditions ; les changements significatifs seront communiqués via l'admin ou par email."},"accept":"J'ai lu et j'accepte les CGU.","continue":"Continuer vers la configuration","back":"Retour"},"sections":{"firebase":"Firebase","admin":"Administrateur initial","flexweg":"API Flexweg"},"help":{"firebase":"Retrouvez ces valeurs dans Firebase Console → Paramètres du projet → Général → Vos applications → Configuration du SDK.","admin":"Utilisez un utilisateur existant dans Firebase Authentication. Toute personne se connectant avec cet email est traitée comme administrateur et n'a pas besoin d'enregistrement utilisateur. Créez l'utilisateur via Firebase Console → Authentication s'il n'existe pas.","flexweg":"Générez une clé API permanente dans votre compte Flexweg → API. L'URL du site est l'adresse publique de votre site Flexweg (ex. https://votre-site.flexweg.com).","flexwegApiKeyHint":"Récupérez votre clé API depuis vos paramètres de compte Flexweg.","flexwegApiKeyLink":"Ouvrir les paramètres du compte"},"fields":{"apiKey":"Clé API","authDomain":"Domaine d'authentification","projectId":"ID du projet","storageBucket":"Bucket de stockage","messagingSenderId":"ID expéditeur de messagerie","appId":"ID de l'application","adminEmail":"Email","adminPassword":"Mot de passe","flexwegApiKey":"Clé API","flexwegSiteUrl":"URL du site","flexwegApiBaseUrl":"URL de base de l'API","sqlitePath":"Chemin SQLite"},"submit":"Enregistrer et continuer","submitting":"Configuration…","success":"Configuration terminée !","reloadingHint":"Rechargement de l'admin dans un instant — patientez.","footer":"Ces valeurs sont enregistrées sur votre projet (Firestore + Flexweg). Elles ne sont envoyées nulle part ailleurs.","steps":{"signInFirebase":"Connexion à Firebase…","testFlexweg":"Test de l'API Flexweg…","writeFirestore":"Sauvegarde de la configuration…","uploadConfig":"Upload de config.js sur Flexweg…","syncThemes":"Synchronisation des assets de thème sur Flexweg…","sqliteInstall":"Création du token SQLite limité…","sqliteRegisterAdmin":"Enregistrement du compte admin…","sqliteSchema":"Initialisation du schéma SQLite…"},"stepsDone":{"sqliteInstall":"Token SQLite limité créé","sqliteRegisterAdmin":"Admin enregistré et connecté","sqliteSchema":"Schéma SQLite prêt"},"errors":{"missingFields":"Veuillez remplir tous les champs.","rootDeploymentTitle":"L'admin doit être dans un sous-dossier, pas à la racine du site.","rootDeploymentHint":"Déplacez les fichiers de l'admin (index.html, config.js, runtime/, …) dans un sous-dossier sur Flexweg — par exemple /admin/ ou un nom aléatoire comme /erf34f654GH3/ pour plus de discrétion. Puis rechargez l'admin depuis l'URL du sous-dossier et relancez la configuration.","firebaseAuthGeneric":"Impossible de se connecter à Firebase.","firebaseAuthInvalidCredential":"Firebase a refusé la combinaison email + mot de passe.","firebaseAuthInvalidCredentialHint":"Les projets Firebase récents activent par défaut la protection contre l'énumération d'emails, qui renvoie la même erreur que le mot de passe soit incorrect, que l'utilisateur n'existe pas, ou qu'il se connecte avec un autre fournisseur. À vérifier :\\n• Re-saisis le mot de passe — fais un copier/coller depuis un gestionnaire de mots de passe pour éliminer toute faute de frappe. Le minimum est 6 caractères.\\n• Ouvre Firebase Console → Authentication → Users et vérifie que l'email existe. Regarde la colonne « Providers » : si elle n'affiche que Google (ou un autre fournisseur) sans « Email/Password », définis ou réinitialise le mot de passe via le menu de la ligne (⋮ → Réinitialiser le mot de passe).\\n• Vérifie que l'orthographe de l'email correspond exactement à ce qui est stocké dans Firebase.","firebaseAuthUserNotFound":"Aucun utilisateur Firebase avec cet email. Créez-le d'abord dans Firebase Console → Authentication → Users.","firebaseAuthInvalidEmail":"L'email administrateur n'est pas une adresse valide.","firebaseInvalidApiKey":"La clé API Firebase est invalide. Vérifiez la valeur dans Firebase Console.","firebaseNetwork":"Erreur réseau lors de la connexion à Firebase. Vérifiez votre connexion.","firebaseTooManyRequests":"Trop de tentatives de connexion. Réessayez dans un instant ou réinitialisez le mot de passe depuis Firebase Console.","firebaseOperationNotAllowed":"L'authentification email/mot de passe n'est pas activée sur ce projet Firebase. Ouvrez Firebase Console → Authentication → Sign-in method et activez le fournisseur Email/Password.","firebaseUserDisabled":"Ce compte utilisateur Firebase est désactivé. Réactivez-le depuis Firebase Console → Authentication → Users.","wrongAdminEmail":"Le compte Firebase auquel vous vous êtes connecté ne correspond pas à l'email admin saisi. Réessayez.","rulesNotPinnedTitle":"Les règles Firestore ne vous reconnaissent pas comme bootstrap admin.","rulesNotPinnedHint":"Ouvrez Firebase Console → Firestore → Règles et remplacez la valeur de \`bootstrapAdminEmail()\` par : {{email}} — puis cliquez sur Publier. Le template de règles du README contient un placeholder \`you@example.com\` qui doit être remplacé par votre vrai email admin. Une fois les règles publiées, cliquez à nouveau sur Soumettre ici.","flexwegAuth":"Clé API Flexweg refusée. Vérifiez la valeur dans votre compte Flexweg → API.","flexwegNetwork":"Erreur réseau lors du contact avec Flexweg. Vérifiez l'URL de base de l'API et votre connexion.","flexwegHttp":"Erreur API Flexweg ({{status}}) : {{detail}}","firestoreRulesTitle":"Firestore a refusé l'écriture de la configuration.","firestoreRulesHint":"Ouvrez Firebase Console → Firestore → Règles et vérifiez que l'email admin de bootstrap est bien '{{email}}'. Le README contient un modèle de règles à copier-coller.","firestoreOther":"Échec de l'écriture Firestore","uploadFailed":"Impossible d'uploader config.js sur Flexweg","generic":"Une erreur s'est produite."},"docstore":{"contentTitle":"Dépôt de contenu","contentIntro":"Là où vos articles, pages et réglages sont stockés en fichiers Markdown + JSON. Un dépôt vide convient — le CMS crée les fichiers.","provider":"Dépôt","localClone":"Dossier local (clone git)","localCloneHint":"Choisissez le dossier de votre clone. Synchronisez-le avec votre client git habituel — le CMS lit et écrit les fichiers, il n'exécute pas git.","contentDir":"Dossier du contenu dans le dépôt","privateRepo":"Utilisez un dépôt privé : les brouillons y sont stockés.","folderRequired":"Choisissez d'abord le dossier de contenu.","checking":"Vérification de l'accès au dépôt…","publishIntro":"Là où le site généré est publié. Modifiable plus tard dans les Réglages.","existingSite":"Ce dépôt est déjà configuré — le site continue d'être publié sur : {{target}}. Modifiable plus tard dans les Réglages (les clés secrètes éventuelles doivent y être ressaisies).","install":"Installer","steps":{"config":"Enregistrement de la configuration…","content":"Chargement du contenu…","target":"Enregistrement de la cible de publication…","testTarget":"Test de la cible de publication…"},"doneTitle":"C'est prêt !","doneBody":"La configuration est enregistrée dans ce navigateur. Pour éviter cette étape aux autres éditeurs, téléchargez config.js et remplacez celui du dossier admin de votre hébergement.","downloadConfig":"Télécharger config.js","open":"Ouvrir l'admin","footer":"Le contenu reste dans votre dépôt ou dans ce navigateur ; les jetons d'accès ne quittent jamais ce navigateur."},"data":{"title":"1. Où stocker vos données ?","intro":"Vos articles, pages, utilisateurs et réglages — les données de l'admin. C'est indépendant de l'endroit où le site public est hébergé (étape suivante).","localNote":"Rien à configurer : le contenu est stocké dans ce navigateur. Exportez-le depuis les Réglages pour le sauvegarder ou le déplacer plus tard.","options":{"sqlite-file":{"title":"SQLite","hint":"Une base SQLite stockée sur l'hébergement choisi à l'étape suivante (Flexweg, votre serveur, S3, Git…). Sans comptes utilisateurs — ou le service SQLite de Flexweg, avec comptes, si vous hébergez sur Flexweg."},"flexweg-sqlite":{"title":"SQLite (service Flexweg)","hint":"Une base SQLite gérée par le service Flexweg, avec comptes utilisateurs intégrés. Nécessite un compte Flexweg, quel que soit l'hébergement du site."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth dans votre projet Google. Temps réel, plan Spark gratuit."},"markdown-git":{"title":"Fichiers Markdown dans Git","hint":"Les articles sont des fichiers .md dans un dépôt GitHub / GitLab (ou un clone local). Chaque éditeur utilise son propre jeton ; chaque modification est un commit."},"local":{"title":"Ce navigateur","hint":"Un seul utilisateur, sans connexion, rien à configurer. Idéal pour un admin qui tourne sur votre ordinateur."}}},"hosting":{"title":"2. Où publier le site ?","intro":"Là où le site statique généré (HTML, CSS, images) est envoyé à chaque publication. Modifiable plus tard dans les Réglages.","existing":"Ce dépôt de contenu publie déjà sur la cible ci-dessous. Gardez-la ou choisissez-en une autre."},"install":{"title":"3. Installation","intro":"Vérifiez le récapitulatif, puis installez.","data":"Données","hosting":"Hébergement","saveTarget":"Enregistrement de la cible de publication…","noteConfigJs":"La configuration de l'admin (config.js) est envoyée à côté de l'admin sur Flexweg quand c'est possible ; sinon, vous pourrez la télécharger.","noteLocalConfig":"La configuration est enregistrée dans ce navigateur ; vous pourrez télécharger config.js à placer dans le dossier admin pour éviter cette étape aux autres éditeurs."},"sqliteFile":{"security":"Pas de comptes utilisateurs : toute personne qui peut ouvrir cet admin peut modifier le contenu — protégez le dossier de l'admin au niveau de l'hébergement. Le fichier de base est servi comme n'importe quel fichier : gardez-le chiffré, ou stockez-le dans un emplacement privé séparé.","intro":"Là où le fichier de base est stocké. Il est lu et enregistré par cet admin via les mêmes connecteurs que l'hébergement.","path":"Chemin du fichier de base","pathHint":"Créé au premier enregistrement s'il n'existe pas encore. Avec un dépôt Git, chaque enregistrement est un commit — préférez un dépôt ou une branche qui ne déclenche pas de build du site.","existing":"base existante","new":"nouvelle base","dataNote":"Rien à configurer ici : la base sera stockée sur l'hébergement choisi à l'étape suivante.","heading":"Base de données SQLite","flexwegService":"Utiliser le service SQLite de Flexweg","flexwegServiceHint":"La base est gérée par Flexweg et dispose de comptes utilisateurs intégrés (e-mail + mot de passe). Sinon, c'est un simple fichier sur cet hébergement, sans comptes.","summaryFile":"Fichier {{path}} sur cet hébergement","summaryService":"Service SQLite de Flexweg ({{path}})","encrypt":"Chiffrer la base","encryptHint":"Recommandé sur un hébergement public : le fichier est illisible sans la phrase secrète. Chaque nouveau navigateur la demande une fois.","passphrase":"Phrase secrète","passphraseHint":"Enregistrez-la maintenant dans votre gestionnaire de mots de passe : sans elle, personne ne peut ouvrir la base, pas même vous.","copy":"Copier","copied":"Copiée","generate":"Nouvelle","passphraseTooShort":"La phrase secrète doit faire au moins 12 caractères.","existingEncrypted":"Une base chiffrée existe déjà à cet emplacement : saisissez sa phrase secrète.","separate":"Stocker la base dans un emplacement privé séparé","separateHint":"Par ex. un bucket S3 / R2 privé ou un dépôt Git privé : la base n'est alors jamais servie par le site public.","summaryEncrypted":"chiffrée","summaryLocation":"stockée dans {{location}}","locationLabel":"Emplacement de la base","gitBranchNote":"La base est conservée sur la branche {{branch}} de ce dépôt, qui n'est jamais publiée : enregistrer un contenu ne relance pas la construction du site.","summaryBranch":"sur la branche {{branch}}"},"adminHosting":{"deploying":"Copie de l'admin sur le site…","label":"Héberger aussi l'admin sur ce site","hint":"L'admin est copié dans {{url}} avec son config.js (aucun secret dedans) — chaque éditeur pourra l'ouvrir là. Chacun se connecte toujours avec ses propres accès.","folder":"Dossier de l'admin","alreadyHere":"Cet admin tourne déjà depuis ce site : son config.js sera mis à jour sur place.","doneBody":"L'admin est maintenant sur votre site. Sur GitHub Pages, activez d'abord Pages pour le dépôt si ce n'est pas fait (Settings → Pages), puis ouvrez-le :","open":"Ouvrir l'admin en ligne","continueHere":"Continuer dans cet admin"}}`),Xne={actions:{upload:"Upload du fichier",delete:"Suppression du fichier",rename:"Renommage du fichier",get:"Lecture du fichier",list:"Listing des fichiers",createFolder:"Création du dossier",renameFolder:"Renommage du dossier",deleteFolder:"Suppression du dossier",storageLimits:"Lecture des quotas de stockage",commit:"Publication des modifications"},errors:{configMissing:"La cible de publication n'est pas configurée. Configurez-la dans les Réglages avant de publier.",network:"{{action}} : erreur réseau ou CORS bloqué. Vérifiez votre connexion.",auth:"{{action}} : authentification échouée. Vérifiez les identifiants de la cible de publication dans les Réglages.",notFound:"{{action}} : la cible est introuvable sur la cible de publication.",tooLarge:"{{action}} : fichier trop volumineux pour la cible de publication.",rateLimited:"{{action}} : trop de requêtes, veuillez réessayer dans un instant.",serverError:"{{action}} : erreur serveur de la cible de publication ({{status}}). Veuillez réessayer.",generic:"{{action}} a échoué ({{status}}){{detail}}.",unsupported:"{{action}} : non pris en charge par la cible de publication « {{connector}} ».",unknownConnector:"Cible de publication inconnue « {{connector}} ». Vérifiez Réglages → Cible de publication.",folderAccess:"Pas d'accès au dossier local. Ouvrez Réglages → Cible de publication et cliquez sur « Reconnecter le dossier »."}},Zne={log:{rendering:"Rendu de la page…",uploading:"Upload de {{path}}…",deleting:"Suppression de {{path}}…",regenerating:"Régénération des listings…",skipped:"{{path}} ignoré (aucun changement)",done:"Publié sur {{url}}",failed:"Échec : {{error}}"}},Yne={errors:{notConnected:"Non connecté au dépôt de contenu. Reconnectez-vous avec votre jeton d'accès.",conflict:"Quelqu'un d'autre a modifié cet élément entre-temps. Sa version est maintenant affichée — réappliquez votre modification.",sqliteUnsupported:"La cible « {{connector}} » ne peut pas stocker de fichier de base."}},ere={target:"Cible de publication",settingsTitle:"Cible de publication",settingsHelp:"Là où le site rendu est envoyé lors d'une publication. Les identifiants sont stockés avec votre backend de contenu (ou gardés dans ce navigateur pour les dépôts Git de contenu) et lisibles par tous les admins.",saved:"Cible de publication enregistrée. Lancez Régénérer → Tout pour publier le site complet sur la nouvelle cible.",test:"Tester la connexion",testOk:"Connexion OK",testFailed:"Échec de la connexion",names:{flexweg:"Flexweg","git-pages":"Dépôt Git (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"Bucket compatible S3 (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Votre propre serveur (bridge PHP)","browser-mirror":"Télécharger en ZIP","local-folder":"Dossier local sur cet ordinateur"},hints:{flexweg:"Envoi via l'API Files de Flexweg.","git-pages":"Chaque publication est un commit dans le dépôt ; l'hébergeur reconstruit le site à partir de lui.",s3:"Nécessite une règle CORS sur le bucket autorisant l'origine de cet admin, et l'hébergement de site (ou un CDN) pour servir les index.html.","php-bridge":"Déposez external/bridges/php/flexweg-bridge.php sur votre serveur, définissez sa clé d'API, puis renseignez son URL ici.","browser-mirror":"Le site est conservé dans ce navigateur ; téléchargez le ZIP et déposez-le où vous voulez.","local-folder":"Écrit le site directement dans un dossier (Chrome / Edge). Servez-le en local ou poussez-le avec vos outils."},fields:{flexweg:{apiKey:"Clé d'API",siteUrl:"URL du site",apiBaseUrl:"URL de base de l'API"},"git-pages":{host:"Hébergement",provider:"Fournisseur Git",owner:"Propriétaire (utilisateur ou organisation)",repo:"Dépôt",project:"Chemin du projet",branch:"Branche",dir:"Dossier dans le dépôt",token:"Jeton d'accès",siteUrl:"URL publique du site",apiBaseUrl:"URL de l'API (auto-hébergé uniquement)"},s3:{endpoint:"Endpoint",region:"Région",bucket:"Bucket",prefix:"Préfixe des clés (optionnel)",accessKeyId:"ID de clé d'accès",secretAccessKey:"Clé d'accès secrète",siteUrl:"URL publique du site",forcePathStyle:"URL de type chemin (MinIO, R2, la plupart des compatibles)",publicRead:"Rendre les fichiers publics (ACL public-read) — pour les buckets qui ne sont pas publics via une politique (OVHcloud, Scaleway…). À laisser décoché sur les buckets AWS qui imposent « bucket owner enforced »."},"php-bridge":{apiBaseUrl:"URL du bridge",apiKey:"Clé d'API du bridge",siteUrl:"URL publique du site"},"browser-mirror":{siteUrl:"URL publique du site (optionnel)"},"local-folder":{siteUrl:"URL où le dossier est servi (optionnel)"}},help:{flexweg:{apiKey:"Générée depuis votre compte Flexweg → API."},"git-pages":{host:"Cloudflare Pages : reliez le projet à ce dépôt sans commande de build, avec le dossier de sortie ci-dessous. Fonctionne avec les dépôts privés.",dir:'Laissez vide pour la racine. GitHub Pages : "" ou "docs". GitLab Pages : "public".',token:"Jeton fine-grained sur ce dépôt avec Contents : lecture/écriture (GitHub) — ajoutez Pages : lecture/écriture pour que le CMS active GitHub Pages — ou jeton avec le scope api (GitLab). Laissez vide pour utiliser le jeton de chaque éditeur quand le contenu est chez le même fournisseur.",siteUrl:"ex. https://user.github.io/repo — une URL avec sous-dossier fonctionne, les liens sont ajustés automatiquement."},s3:{endpoint:"Laissez vide pour AWS (déduit de la région). R2 : https://<account-id>.r2.cloudflarestorage.com",siteUrl:"L'URL d'hébergement du bucket ou votre domaine CDN."},"php-bridge":{apiBaseUrl:"L'URL complète de flexweg-bridge.php sur votre serveur (HTTPS)."},"browser-mirror":{siteUrl:"Là où vous déposerez le ZIP — sert aux URL absolues (sitemaps, RSS, médias)."},"local-folder":{siteUrl:"ex. http://localhost:8080 quand un serveur web local sert le dossier."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (relié au dépôt)","gitlab-pages":"GitLab Pages",other:"Autre (Netlify, Vercel, git pull serveur…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Choisir un dossier…",change:"Changer de dossier…",reconnect:"Reconnecter le dossier",unsupported:"Ce navigateur ne peut pas écrire dans un dossier local. Utilisez Chrome ou Edge."},mirror:{download:"Télécharger le site (ZIP)",count:"{{count}} fichiers dans ce navigateur"},adminHosting:{title:"Admin sur ce site",help:"Copie cet admin sur la cible de publication (premier déploiement, ou mise à jour après une nouvelle version). Son config.js ne contient aucun secret.",deploy:"Déployer / mettre à jour l'admin",deployed:"Admin déployé ({{count}} fichiers) — {{url}}"},pages:{enabled:"GitHub Pages activé pour ce dépôt — le site sera en ligne dans une minute environ.",enableHint:"Publication réussie. Pour mettre le site en ligne, activez GitHub Pages pour {{repo}} : Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Ou donnez au jeton la permission « Pages : read and write » et le CMS le fera.)"},siteUrl:{mismatch:"L'URL publique du site (Réglages → Site) est {{site}}, mais cette cible sert le site à {{target}}. Les liens, le CSS et les sitemaps suivent l'URL du site — ils seront faux sur cet hébergement.",use:"Utiliser {{url}} pour le site",updated:"URL du site mise à jour. Lancez Régénérer → Tout pour republier les pages avec les nouveaux liens."}},tre={heading:"Connexion au dépôt de contenu",tokenIntro:"Le contenu est stocké dans le dépôt {{provider}} {{repo}}. Connectez-vous avec votre propre jeton d'accès personnel — vos droits sur le dépôt déterminent votre rôle (écriture = éditeur, admin / maintainer = admin).",token:"Jeton d'accès personnel",tokenHelpGithub:"Jeton fine-grained, limité à ce dépôt, permission Contents : lecture et écriture.",tokenHelpGitlab:"Jeton avec le scope api, rôle Developer ou plus sur ce projet.",createToken:"Créer un jeton",connect:"Se connecter",tokenStorage:"Le jeton est conservé dans ce navigateur uniquement. La déconnexion l'efface.",failed:"Ce jeton ne permet pas d'écrire dans le dépôt (invalide, expiré ou en lecture seule). Vérifiez ses permissions.",folderIntro:"Le contenu est stocké dans un dossier de cet ordinateur (en général un clone git que vous synchronisez avec votre client git). Autorisez ce navigateur à y accéder — il redemande l'accès après chaque rechargement.",openFolder:"Ouvrir le dossier de contenu"},nre={flexweg:{title:"Flexweg",short:"Hébergement Flexweg",hint:"Envoi via l'API Files de Flexweg. Clé d'API depuis votre compte Flexweg."},"github-pages":{title:"GitHub Pages",short:"Gratuit, depuis un dépôt GitHub",hint:"Chaque publication est un commit dans le dépôt ; GitHub Pages le sert. Settings → Pages → Deploy from a branch. Dépôts publics sur le plan gratuit."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Gratuit, dépôts privés OK",hint:"Le CMS commite le site dans un dépôt GitHub / GitLab ; reliez-y un projet Cloudflare Pages (sans commande de build, dossier de sortie = le dossier ci-dessous)."},"gitlab-pages":{title:"GitLab Pages",short:"Gratuit, depuis un dépôt GitLab",hint:"Chaque publication est un commit ; le CMS ajoute un .gitlab-ci.yml minimal qui publie le dossier public/."},"git-other":{title:"Netlify, Vercel…",short:"Tout hébergeur qui déploie un dépôt",hint:"Le CMS commite le site dans un dépôt Git ; reliez votre hébergeur (Netlify, Vercel, serveur avec git pull…) à ce dépôt."},s3:{title:"S3 / R2 / B2…",short:"Bucket de stockage objet",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Nécessite une règle CORS sur le bucket et l'hébergement de site ou un CDN devant."},"own-server":{title:"Votre serveur (FTP / SFTP)",short:"Mutualisé, VPS…",hint:"Un navigateur ne sait pas parler FTP ni SFTP : déposez une fois le bridge PHP (external/bridges/php/flexweg-bridge.php) avec votre client FTP, définissez sa clé d'API, puis renseignez son URL ici. Fonctionne sur tout hébergement PHP."},"local-folder":{title:"Dossier local",short:"Sur cet ordinateur",hint:"Écrit le site dans un dossier de cet ordinateur (Chrome / Edge). Servez-le en local ou poussez-le avec vos outils."},zip:{title:"Télécharger en ZIP",short:"À déposer à la main",hint:"Le site est conservé dans ce navigateur ; téléchargez un ZIP depuis les Réglages et déposez-le où vous voulez (Netlify Drop, client FTP…)."}},rre={heading:"Connexion à la base de données",intro:"Cet admin stocke son contenu dans {{path}}. Saisissez les identifiants d'accès pour ce navigateur.",storage:"Les identifiants sont conservés dans ce navigateur uniquement. La déconnexion les efface.",passphrase:"Phrase secrète de la base",passphraseHint:"La base est chiffrée. Saisissez la phrase secrète choisie à l'installation (conservée dans ce navigateur uniquement).",passphraseWrong:"Phrase secrète incorrecte : la base n'a pas pu être ouverte.",passphraseMissing:"Saisissez la phrase secrète de la base."},sre={common:Rne,auth:jne,nav:Mne,dashboard:Lne,posts:Dne,pages:Fne,taxonomies:One,media:zne,themes:Une,plugins:Bne,externalInstall:$ne,externalLoader:Hne,menus:Vne,settings:qne,users:Wne,firestoreSetup:Gne,errors:Kne,identity:Jne,setup:Qne,flexweg:Xne,publish:Zne,docstore:Yne,connectors:ere,gitAccess:tre,hosting:nre,sqliteAccess:rre},ire={save:"Speichern",saving:"Speichert…",saved:"Gespeichert",cancel:"Abbrechen",delete:"Löschen",deleting:"Wird gelöscht…",edit:"Bearbeiten",create:"Erstellen",search:"Suchen",loading:"Lädt…",yes:"Ja",no:"Nein",confirm:"Bestätigen",back:"Zurück",next:"Weiter",previous:"Vorherige",close:"Schließen",all:"Alle",none:"Keine",actions:"Aktionen",name:"Name",slug:"Slug",description:"Beschreibung",status:"Status",createdAt:"Erstellt",updatedAt:"Aktualisiert",publishedAt:"Veröffentlicht",language:"Sprache",darkMode:"Dunkelmodus",lightMode:"Hellmodus",signOut:"Abmelden",administrator:"Administrator",editor:"Redakteur",appName:"AgentCMS"},are={signIn:"Anmelden",signingIn:"Anmeldung läuft…",email:"E-Mail",password:"Passwort",emailPlaceholder:"sie@firma.com",passwordPlaceholder:"••••••••",forgotPassword:"Passwort vergessen?",resetEmailSent:"E-Mail zum Zurücksetzen des Passworts wurde an {{email}} gesendet.",enterEmailFirst:"Geben Sie zuerst Ihre E-Mail-Adresse oben ein und klicken Sie dann auf Zurücksetzen.",emailPasswordRequired:"E-Mail und Passwort sind erforderlich.",signInSubtitle:"Verwenden Sie Ihre Geschäfts-E-Mail und Ihr Passwort.",footer:"Kontoanfragen erfolgen über Ihren Administrator.",errors:{invalidEmail:"Ungültige E-Mail-Adresse.",invalidCredentials:"Ungültige E-Mail-Adresse oder ungültiges Passwort.",tooManyRequests:"Zu viele Versuche. Versuchen Sie es später erneut oder setzen Sie Ihr Passwort zurück.",userDisabled:"Dieses Konto wurde deaktiviert.",networkFailed:"Netzwerkfehler. Überprüfen Sie Ihre Verbindung.",generic:"Authentifizierung fehlgeschlagen."}},ore={openMenu:"Menü öffnen",closeMenu:"Menü schließen",dashboard:"Übersicht",posts:"Artikel",pages:"Seiten",taxonomies:"Kategorien & Schlagwörter",media:"Medien",themes:"Themes",themeSettings:"Theme-Einstellungen",plugins:"Plugins",menus:"Menüs",users:"Benutzer",settings:"Einstellungen"},lre={title:"Übersicht",welcome:"Willkommen zurück, {{email}}.",stats:{totalPosts:"Artikel",totalPages:"Seiten",online:"Online",drafts:"Entwürfe"}},cre={title:"Artikel",newPost:"Neuer Artikel",noPosts:"Noch keine Artikel. Erstellen Sie Ihren ersten Artikel, um zu beginnen.",noPostsInFilter:"Keine Artikel entsprechen dem aktuellen Filter.",search:{placeholder:"Artikel suchen…",clear:"Suche leeren",noResults:"Keine Artikel entsprechen Ihrer Suche."},pagination:{previous:"Zurück",next:"Weiter",showing:"Zeige {{from}}–{{to}} von {{total}}",pageOf:"Seite {{page}} von {{total}}"},bulk:{selectedCount_one:"{{count}} ausgewählt",selectedCount_other:"{{count}} ausgewählt",selectPage_one:"{{count}} auf dieser Seite auswählen",selectPage_other:"Alle {{count}} auf dieser Seite auswählen",deselectPage:"Seite abwählen",allOnPageSelected_one:"{{count}} auf dieser Seite ausgewählt.",allOnPageSelected_other:"Alle {{count}} auf dieser Seite ausgewählt.",selectAllMatching_one:"Den passenden Artikel auswählen",selectAllMatching_other:"Alle {{count}} passenden Artikel auswählen",allMatchingSelected_one:"Der passende Artikel ist ausgewählt.",allMatchingSelected_other:"Alle {{count}} passenden Artikel sind ausgewählt.",selectOne:'„{{title}}" auswählen',publish:"Veröffentlichen ({{count}})",publishing:"Wird veröffentlicht…",publishedCount:"{{ok}} veröffentlicht, {{failed}} fehlgeschlagen.",unpublish:"Zurückziehen ({{count}})",unpublishing:"Wird zurückgezogen…",unpublishedCount:"{{ok}} zurückgezogen, {{failed}} fehlgeschlagen.",delete:"Löschen",deleting:"Wird gelöscht…",deletedCount:"{{ok}} gelöscht, {{failed}} fehlgeschlagen.",confirmDelete_one:"{{count}} Artikel löschen? Damit wird er von Flexweg zurückgezogen und kann nicht wiederhergestellt werden.",confirmDelete_other:"{{count}} Artikel löschen? Damit werden sie von Flexweg zurückgezogen und können nicht wiederhergestellt werden.",noDraftSelected:"Keine Entwürfe ausgewählt.",noOnlineSelected:"Keine veröffentlichten Artikel ausgewählt.",clear:"Auswahl leeren"},filters:{all:"Alle",draft:"Entwurf",online:"Online"},fields:{title:"Titel",slug:"Slug",excerpt:"Auszug",content:"Inhalt",category:"Kategorie",tags:"Schlagwörter",heroImage:"Beitragsbild",seoTitle:"SEO-Titel",seoDescription:"SEO-Beschreibung",createdAt:"Erstellt am",updatedAt:"Zuletzt aktualisiert",publishedAt:"Veröffentlicht am"},edit:{newTitle:"Neuer Artikel",editTitle:"Artikel bearbeiten",saved:"Gespeichert.",savedAndRepublished:"Gespeichert und neu veröffentlicht.",saveFailed:"Speichern fehlgeschlagen.",saveAndRepublish:"Speichern & neu veröffentlichen",draftSaved:"Entwurf gespeichert.",slugCollision:{post:'Diese URL wird bereits vom Artikel verwendet: "{{label}}".',page:'Diese URL wird bereits von der Seite verwendet: "{{label}}".',category:'Diese URL wird bereits von der Kategorie verwendet: "{{label}}".'},publish:"Veröffentlichen",unpublish:"Zurückziehen",publishing:"Veröffentlicht…",unpublishing:"Wird zurückgezogen…",titlePlaceholder:"Titel hinzufügen",permalink:"Permalink",slugFormatHint:"Nur Kleinbuchstaben, ASCII, Bindestriche.",slugAutoSuffixed:'Suffix hinzugefügt, da "{{base}}" bereits von {{owner}} verwendet wird.',slugAutoSuffixedOwner:{post:'Beitrag: "{{label}}"',page:'Seite: "{{label}}"',category:'Kategorie: "{{label}}"'},saveBlocked:{titleRequired:"Fügen Sie vor dem Speichern einen Titel hinzu.",slugRequired:"Ein Titel und ein URL-Slug sind zum Speichern erforderlich.",slugInvalid:"Ungültiges Slug-Format (Kleinbuchstaben ASCII + Bindestriche).",slugCollision:"Lösen Sie den URL-Konflikt vor dem Speichern."},viewPublished:"Ansehen",confirmDelete:"Diesen Eintrag löschen?",inspector:{document:"Dokument",block:"Block",blockEmpty:"Wählen Sie einen Block im Editor, um seine Optionen anzuzeigen.",publishing:"Veröffentlichung",permalink:"Permalink",categories:"Kategorien & Schlagwörter",featured:"Beitragsbild",seo:"SEO",excerpt:"Auszug",dates:"Datumsangaben"},blocks:{addBlock:"Block hinzufügen",transform:"Umwandeln in",moveUp:"Nach oben verschieben",moveDown:"Nach unten verschieben",duplicate:"Duplizieren",remove:"Block löschen",paragraph:"Absatz",heading2:"Überschrift 2",heading3:"Überschrift 3",bulletList:"Aufzählung",orderedList:"Nummerierte Liste",blockquote:"Zitat",codeBlock:"Code",image:"Bild",horizontalRule:"Trenner",categories:{text:"Text",media:"Medien",layout:"Layout",embed:"Einbettungen",advanced:"Erweitert"},noSettings:"Dieser Block hat keine Einstellungen.",noSelection:"Wählen Sie einen Block im Editor, um seine Optionen anzuzeigen.",slash:{noResults:"Kein passender Block."}}},status:{draft:"Entwurf",online:"Online"},preview:{title:"Vorschau",rendering:"Vorschau wird gerendert…",error:"Vorschau fehlgeschlagen: {{error}}",viewports:{mobile:"Mobil",tablet:"Tablet",desktop:"Desktop"}}},ure={title:"Seiten",newPage:"Neue Seite",noPages:"Noch keine Seiten.",homeBadge:"Startseite",homeBadgeTooltip:"Wird als Startseite der Website verwendet"},dre={title:"Kategorien & Schlagwörter",categories:"Kategorien",tags:"Schlagwörter",newCategory:"Neue Kategorie",newTag:"Neues Schlagwort",noCategories:"Noch keine Kategorien.",noTags:"Noch keine Schlagwörter.",slugCollision:'Dieser Slug wird bereits von "{{label}}" verwendet.',seo:{button:"SEO",buttonTitle:"SEO-Meta-Tags bearbeiten",title:"SEO-Meta-Tags",subtitle:'Eigener Titel und Beschreibung für die Archivseite "{{name}}".',metaTitle:"Meta-Titel",metaTitleHint:"Wird als Seiten-<title> verwendet. Standard: der Name des Begriffs.",metaDescription:"Meta-Beschreibung",metaDescriptionHint:"Wird als Meta-Beschreibung der Seite verwendet. Standard: die Beschreibung des Begriffs."}},hre={title:"Medienbibliothek",upload:"Hochladen",uploading:"Lädt hoch…",finalizing:"Wird abgeschlossen…",uploadFailed:"Hochladen fehlgeschlagen",retry:"Erneut versuchen",noMedia:"Noch keine Medien.",alt:"Alt-Text",caption:"Bildunterschrift",filename:"Dateiname",size:"Größe",type:"Typ"},fre={title:"Themes",active:"Aktiv",activate:"Aktivieren",installExternal:"Theme installieren",uninstallDisabledTitle:"Wechseln Sie zu einem anderen Theme, bevor Sie dieses deinstallieren.",syncAssets:"Theme-Assets synchronisieren",regenerateSite:"Website neu generieren",regenerating:"Generiert neu…",regenerate:{button:"Neu generieren",running:"Wird ausgeführt…",groupBuiltins:"Website",groupPlugins:"Plugins",home:"Nur Startseite",homeHelp:"Generiert nur index.html neu — schnellste Option.",allHtml:"Alle HTML-Seiten",allHtmlHelp:"Alle Beiträge, Seiten, Archive und Listen — plus Menu / Posts / Authors JSON-Snapshots.",repair:"URLs reparieren",repairHelp:"Berechnet die kanonische URL jedes veröffentlichten Beitrags neu und verschiebt Dateien, die unter der falschen URL gelandet sind. Nützlich nach einem Import, der vor der Synchronisierung der Begriffe lief.",assets:"Theme-Assets",assetsHelp:"Lädt CSS + Begleit-Skripte des aktiven Themes nach /theme-assets/ hoch.",everything:"Alles",everythingHelp:"Theme-Assets + alle HTML + jede Plugin-Ausgabe. Langsamste Option.",noPluginTargets:"Keine Plugin-Neugenerierungen — aktivieren Sie ein Plugin, das Neugenerieren unterstützt."},confirmSwitch:{title:"Zu {{theme}} wechseln?",body:"Beim Theme-Wechsel müssen die Theme-Assets erneut hochgeladen und alle veröffentlichten Seiten neu generiert werden, damit das neue Aussehen überall greift. Das kann einen Moment dauern.",confirm:"Wechseln & neu generieren",cancel:"Abbrechen"}},pre={title:"Plugins",enabled:"Aktiviert",disabled:"Deaktiviert",enable:"Aktivieren",disable:"Deaktivieren",configure:"Konfigurieren",author:"Autor",learnMore:"Mehr erfahren",mustUseBadge:"Pflicht",installExternal:"Plugin installieren",tabs:{regular:"Plugins",mustUse:"Pflicht-Plugins"}},mre={titlePlugin:"Plugin installieren",titleTheme:"Theme installieren",labelPlugin:"Plugin",labelTheme:"Theme",intro:"Ziehen Sie eine ZIP-Datei mit einem {{label}}-Bundle hierher (manifest.json + bundle.js im ZIP-Root). Das {{label}} wird auf Ihre Flexweg-Site hochgeladen und nach einem Neuladen registriert. Ein erneuter Upload eines ZIP mit derselben Manifest-ID aktualisiert den vorhandenen Eintrag direkt — keine Deinstallation nötig.",zipField:"Bundle-ZIP-Datei",install:"Installieren",installing:"Installiert…",installSuccess:"{{name}} installiert ({{count}} Dateien hochgeladen). Lädt neu…",upgradeSuccess:"{{name}} von v{{previousVersion}} auf v{{newVersion}} aktualisiert ({{count}} Dateien hochgeladen). Lädt neu…",installedTitle:"Bereits installiert",bundledDefaultsTitle:"Mitgelieferte Standard-Plugins/Themes verfügbar",bundledDefaultsHint:"{{count}} mitgeliefertes Plugin/Theme ist derzeit deinstalliert. Stellen Sie sie wieder her, um den Auslieferungszustand dieser Admin-Version wiederherzustellen.",bundledDefaultsRestore:"Wiederherstellen",bundledDefaultsRestored:"{{plugins}} Plugin(s) und {{themes}} Theme(s) wiederhergestellt. Lädt neu…",uninstall:"Deinstallieren",uninstallSuccess:"{{id}} deinstalliert. Lädt neu…",confirmUninstall:"{{id}} deinstallieren? Die Dateien werden von Flexweg gelöscht.",errors:{"no-manifest":"Im ZIP fehlt manifest.json im Root.","invalid-manifest":"manifest.json ist ungültig (fehlende Pflichtfelder oder kein gültiges JSON).","incompatible-api":"Das Bundle wurde gegen eine inkompatible Runtime-API-Version gebaut.","no-bundle":"Das ZIP enthält die im Manifest deklarierte Einstiegsdatei nicht.","fetch-manifest":"Die aktuelle external.json auf Flexweg konnte nicht gelesen werden.","upload-failed":"Upload fehlgeschlagen — prüfen Sie Ihren Flexweg-API-Schlüssel und Ihre Verbindung."}},gre={someFailed:"{{count}} externe(s) Bundle(s) konnten nicht geladen werden. Siehe Browser-Konsole."},bre={title:"Menüs",header:"Kopfzeilen-Menü",footer:"Fußzeilen-Menü",label:"Beschriftung",saveAndPublish:"Speichern & generieren",discard:"Verwerfen",saved:"Menüs gespeichert und veröffentlicht.",saveFailed:"Menüs konnten nicht gespeichert werden.",unsavedChanges:"Sie haben ungespeicherte Änderungen."},yre={title:"Einstellungen",tabs:{general:"Allgemein"},site:{title:"Website",siteTitle:"Website-Titel",siteDescription:"Website-Beschreibung",siteLanguage:"Website-Sprache",siteLanguageHelp:'BCP-47-Tag (z. B. en, fr-CA), der auf jeder veröffentlichten Seite in <html lang="…"> eingefügt wird. Der Präfix wird mit den unterstützten Übersetzungslocales für Sitemap-/RSS-Labels und im Theme eingebaute Texte abgeglichen; nicht unterstützte Locales fallen auf Englisch zurück.',siteLanguageResolved:"Übersetzungen verwenden: {{label}}",baseUrl:"Öffentliche Website-URL",postsPerPage:"Artikel pro Seite",homeMode:"Startseiten-Inhalt",homeLatest:"Neueste Artikel",homeStatic:"Statische Seite",homePage:"Startseite",discourageIndexing:"Suchmaschinen davon abhalten, diese Website zu indexieren",discourageIndexingHelp:"Wenn aktiviert, erhält jede veröffentlichte Seite ein noindex/nofollow-Meta-Tag und robots.txt sperrt alle Crawler aus. Entspricht dem Verhalten von WordPress — nützlich für Staging-Websites oder Prüfungen vor dem Launch. Suchmaschinen, die die Anweisung respektieren, indexieren die Website nicht.",discourageRegenerateHint:"Indexierungseinstellung gespeichert. Klicken Sie unter Themes auf „Alles neu generieren“, um die Änderung auf alle veröffentlichten Seiten und robots.txt anzuwenden."},flexweg:{title:"Flexweg-API",apiKey:"API-Schlüssel",apiKeyHelp:"Erstellt in Ihrem Flexweg-Konto → API.",siteUrl:"Website-URL",siteUrlHelp:"Öffentliche URL Ihrer Flexweg-Website ohne abschließenden Schrägstrich.",apiBaseUrl:"API-Basis-URL",storageHelpFirebase:"In Firestore gespeichert (config/flexweg). Lesbar für jedes angemeldete Teammitglied, schreibbar nur für Administratoren.",storageHelpSqlite:"In der lokalen SQLite-Tabelle config gespeichert. Lesbar für jedes angemeldete Teammitglied, schreibbar nur für Administratoren."},backend:{title:"Daten-Backend",active:"Aktives Backend:",switchButton:"Backend wechseln…",confirmTitle:"Alle aktuellen Daten gehen verloren.",confirmBody:"Beim Wechsel wird die In-Browser-Konfiguration gelöscht und das Setup-Formular erneut geladen. Das neue Backend startet leer — die Daten des vorherigen Backends bleiben an Ort und Stelle (in Firestore oder als .sqlite-Datei auf Flexweg), aber das CMS liest sie erst wieder, wenn Sie zurückwechseln.",confirmYes:"Ja, Backend wechseln",downloadBackup:"Backup der .sqlite-Datei herunterladen",downloadBackupHelp:"vor dem Wechsel des Backends durchführen.",markdownGit:"Markdown — {{source}}",localFolder:"lokaler Ordner",localBrowser:"Dieser Browser (lokal, ein Benutzer)",sqliteFile:"SQLite-Datei — {{location}}"},performance:{title:"Leistung",help:"Wie das Admin-Backend Beiträge und Seiten lädt. Der Standardmodus funktioniert auf dem kostenlosen Firestore-Plan ohne Setup; der paginierte Modus ist für sehr große Sites und erfordert eine einmalige Index-Einrichtung.",mode:"Lademodus",modeGlobal:"Standard (keine Einrichtung erforderlich)",modePaginated:"Serverseitige Paginierung (Firestore-Indizes erforderlich)",globalHelp:"Lädt die gesamte Posts-Sammlung in einem Live-Abonnement. Sortierung, Filter und Suche im Speicher. Empfohlen für Sites mit weniger als ~5 000 Beiträgen.",paginatedHelp:"Cursor-paginierte Abonnements, eine Seite gleichzeitig. Erfordert zusammengesetzte Firestore-Indizes — siehe README. Empfohlen für sehr große Sites.",savedReload:"Gespeichert. Lade das Admin neu, um den neuen Modus anzuwenden."},editor:{title:"Editor",help:"Typografie für den Artikel-/Seiten-Editor. Unabhängig vom öffentlichen Theme.",fontFamily:"Schriftfamilie",bodySize:"Textgröße",h1Size:"H1-Größe",h2Size:"H2-Größe",h3Size:"H3-Größe",sizeHelp:"CSS-Länge, z. B. 16px oder 1rem. Leer lassen für Standard.",reset:"Auf Standard zurücksetzen"},profile:{title:"Profil",adminLocale:"Admin-Sprache",adminLocaleHelp:"Sprache, die von der Admin-Oberfläche verwendet wird. Im Profil gespeichert.",firstName:"Vorname",lastName:"Nachname",headline:"Titel",headlinePlaceholder:"z. B. Journalist, Chefredakteur…",headlineHelp:"Wird öffentlich unter Ihrem Namen in Autorenkarten und auf Ihrer Archivseite angezeigt.",bio:"Biografie",bioPlaceholder:"Ein kurzer Absatz, der auf Ihrer Autorenseite und unter Ihren Artikeln angezeigt wird.",bioHelp:"Sichtbar auf der öffentlichen Website in der Autoren-Seitenleiste und auf der Autoren-Archivseite.",socials:"Soziale Profile",socialsHelp:'Geben Sie die URLs der Profile ein, die Sie auf der öffentlichen Website zeigen möchten, und aktivieren Sie „Anzeigen" für die sichtbaren. Leere URLs werden ignoriert.',socialsShow:"Anzeigen",socialsShowHelp:"Schaltet die Sichtbarkeit dieses Netzwerks auf der öffentlichen Website um.",avatar:"Profilbild",avatarHelp:"Wählen Sie ein Bild aus Ihrer Medienbibliothek. Quadratische Bilder werden am besten dargestellt.",pickAvatar:"Aus Medien auswählen",changeAvatar:"Bild ändern",removeAvatar:"Entfernen",save:"Profil speichern"},transfer:{title:"Inhalte verschieben oder sichern",help:"Exportieren Sie alles (Beiträge, Seiten, Kategorien, Medien-Metadaten, Profile, Einstellungen) als eine JSON-Datei. Bei einem Markdown- oder lokalen Backend können Sie eine solche Datei importieren, wobei die IDs erhalten bleiben — so migrieren Sie von Firebase oder SQLite. Mediendateien und geheime Schlüssel sind nicht enthalten.",export:"Inhalte exportieren (JSON)",import:"Inhalte importieren…",modeMerge:"Zusammenführen (gleiche IDs überschreiben)",modeReplace:"Importierte Sammlungen ersetzen",replaceConfirm:"Der Ersetzen-Modus löscht vor dem Import alle vorhandenen Einträge der in der Datei enthaltenen Sammlungen. Fortfahren?",invalidFile:"Diese Datei ist kein Inhaltsexport von AgentCMS.",imported:"{{posts}} Beiträge/Seiten, {{terms}} Begriffe und {{media}} Medien importiert. Führen Sie Neu generieren → Alles aus, um sie zu veröffentlichen."},encryption:{title:"Datenbankverschlüsselung:",on:"an",off:"aus",onHelp:"Die Datenbankdatei ist ohne Passphrase unlesbar. Eine Änderung speichert die Datei mit neuem Schlüssel; andere Browser fragen nach der neuen Passphrase.",offHelp:"Die Datenbankdatei ist für jeden lesbar, der sie herunterladen kann (ein statisches Hosting liefert sie wie jede Seite aus). Verschlüssele sie mit einer Passphrase.",enable:"Datenbank verschlüsseln…",change:"Passphrase ändern…",savedConfirm:"Ich habe diese Passphrase in meinem Passwort-Manager gespeichert — ohne sie lässt sich der Inhalt nicht öffnen.",enableConfirm:"Jetzt verschlüsseln",changeConfirm:"Passphrase ändern",done:"Datenbank mit der neuen Passphrase gespeichert."}},vre={title:"Benutzer",noUsers:"Noch keine Benutzer.",role:"Rolle",disabled:"Deaktiviert",editProfileTitle:"Profil bearbeiten — {{email}}",profileSaved:"Profil gespeichert.",descriptionFirebase:"Verwalten Sie Ihr Team. Neue Konten werden in der Firebase Console angelegt und beim ersten Login hier gespiegelt.",descriptionSqlite:"Verwalten Sie Ihr Team. Nutzen Sie unten den Knopf +Benutzer hinzufügen, um Konten direkt anzulegen.",addUser:"Benutzer hinzufügen",addUserSuccess:"{{email}} hinzugefügt.",removeConfirmFirebase:"Datensatz von {{email}} löschen? Damit werden Profil und Rolle aus dem CMS entfernt. Um den Login-Zugang zu entziehen, löschen Sie das Konto zusätzlich in der Firebase Console.",removeConfirmSqlite:"{{email}} dauerhaft löschen? Damit wird der Login-Zugang entzogen UND Profil sowie Rolle entfernt. Diese Aktion kann nicht rückgängig gemacht werden.",empty:{title:"Noch keine Teammitglieder",descriptionFirebase:"Legen Sie das erste Konto in der Firebase Console an und melden Sie sich hier einmal an, um das Profil zu registrieren.",descriptionSqlite:"Klicken Sie oben auf +Benutzer hinzufügen, um das erste Teammitglied einzuladen."},help:{title:"So fügen Sie ein neues Teammitglied hinzu",bootstrapLine:"Der Bootstrap-Admin (immer voller Zugriff) ist:",firebase:{step1:"Öffnen Sie Firebase Console → Authentication → Add user.",step2:"Legen Sie E-Mail und Passwort fest und übermitteln Sie diese dem neuen Mitglied.",step3:"Bitten Sie es, sich hier einmal anzumelden — das Profil erscheint in der Liste oben und Sie können Rolle und Details bearbeiten."},sqlite:{step1:"Klicken Sie oben auf den Knopf +Benutzer hinzufügen.",step2:"Geben Sie die E-Mail und ein temporäres Passwort (mindestens 8 Zeichen) ein.",step3:"Teilen Sie die Zugangsdaten sicher mit — das Passwort kann nach dem Login aus dem Profil heraus geändert werden."},git:{step1:"Fügen Sie die Person als Mitwirkende des Content-Repositorys hinzu (Schreibzugriff = Redakteur, Admin / Maintainer = Admin).",step2:"Die Person erstellt ihr eigenes persönliches Zugriffstoken auf GitHub / GitLab.",step3:"Sie öffnet den Admin-Bereich und meldet sich mit diesem Token an — ihr Profil wird hier automatisch angelegt."}},addUserModal:{title:"Neues Teammitglied hinzufügen",intro:"Legt das Konto direkt in der Flexweg SQLite Auth-Datenbank an. Der neue Benutzer erhält standardmäßig die Editor-Rolle; befördern Sie ihn aus der Liste unten, wenn er Admin-Zugriff benötigt.",submit:"Benutzer anlegen",submitting:"Wird angelegt…"},actions:{editProfile:"Profil bearbeiten",promote:"Zum Administrator befördern",demote:"Auf Redakteur herabstufen",disable:"Deaktivieren",enable:"Aktivieren",delete:"Datensatz löschen"},descriptionGit:"Teammitglieder sind die Personen mit Schreibzugriff auf das Content-Repository. Sie erscheinen hier nach ihrer ersten Anmeldung; ihre Rolle richtet sich nach ihren Repository-Berechtigungen.",descriptionLocal:"Dieser Admin läuft im Einzelbenutzermodus: Inhalte werden in diesem Browser gespeichert und es gibt keine Konten.",descriptionSqliteFile:"Keine Benutzerkonten mit diesem Backend: Jeder, der den Admin öffnen kann, kann bearbeiten. Schützen Sie den Admin-Ordner auf Ebene Ihres Hostings. Die Autorenprofile unten dienen nur zur Information."},xre={title:"Firestore-Setup erforderlich",intro:"Die Artikel- und Seiten-Listenseiten benötigen einige Firestore-Composite-Indexes für effiziente Abfragen. Diese müssen manuell erstellt werden — Firebase reserviert die Index-Erstellung für Projekt-Admins.",checking:"Firestore-Indexes werden geprüft…",missingCount_one:"{{count}} Index fehlt:",missingCount_other:"{{count}} Indexes fehlen:",openConsole:"Firebase Console zum Erstellen öffnen",noUrl:"Auto-Vorschlag-URL nicht extrahierbar — siehe README für den gcloud-Befehl.",howItWorks:"Wie es funktioniert",step1:"Klicken Sie für jeden fehlenden Index auf den Link — Firebase Console öffnet sich mit der vorausgefüllten Index-Definition.",step2:'Klicken Sie auf „Create" und warten Sie 1–5 Minuten, bis der Index aufgebaut ist (Status in der Console).',step3:"Kommen Sie zurück und klicken Sie auf Wiederholen. Sobald beide Abfragen erfolgreich sind, lädt der Admin.",retry:"Wiederholen",retrying:"Wiederholt…",buildHint:"Der Aufbau eines Indexes kann nach der Erstellung einige Minuten dauern.",allReady:"Alle Indexes bereit.",unexpectedTitle:"Firestore nicht erreichbar",unexpectedHint:"Prüfen Sie Ihre Verbindung und die Firestore-Regeln. Wenn Sie die Indexes gerade erstellt haben, warten Sie auf den Abschluss des Aufbaus und versuchen Sie es erneut."},wre={appError:"Anwendungsfehler",loadAccountFailed:"Konto konnte nicht geladen werden",loadAccountHint:"Wenn das Problem weiterhin besteht, melden Sie sich ab und versuchen Sie es erneut.",accountDisabled:"Konto deaktiviert",accountDisabledMessage:"Ihr Zugriff auf dieses CMS wurde deaktiviert. Wenden Sie sich an Ihren Administrator.",firebaseNotConfigured:"Firebase ist nicht konfiguriert",firebaseEnvMissing:`Die folgenden Umgebungsvariablen fehlen:
|
|
3854
3854
|
{{vars}}
|
|
3855
3855
|
|
|
3856
|
-
Kopieren Sie .env.example nach .env, tragen Sie Ihre Firebase-Projektdaten ein und starten Sie den Dev-Server neu.`,adminEmailNotConfigured:"Admin-E-Mail ist nicht konfiguriert",adminEmailMessage:"VITE_ADMIN_EMAIL fehlt in .env. Setzen Sie sie auf die E-Mail-Adresse des Bootstrap-Administrators.",consoleHint:"Überprüfen Sie die Browser-Konsole und Ihre .env-Konfiguration. Siehe README für Setup-Anweisungen."},kre={brandTitle:"Flexweg CMS",brandSubtitle:"Statischer Publisher",login:{heading:"Anmelden",intro:"Verwenden Sie die E-Mail-Adresse und das Passwort, die Ihr Administrator Ihnen mitgeteilt hat.",submit:"Anmelden",submitting:"Anmeldung läuft…"},fields:{name:"Anzeigename (optional)",namePlaceholder:"Erika Mustermann",email:"E-Mail",password:"Passwort",passwordHint:"Mindestens 8 Zeichen."},footer:"Neue Konten werden von einem Administrator über die Benutzerseite angelegt.",errors:{invalidEmail:"Bitte geben Sie eine gültige E-Mail-Adresse ein.",missingPassword:"Passwort ist erforderlich.",passwordTooShort:"Das Passwort muss mindestens 8 Zeichen lang sein."}},Sre=JSON.parse('{"title":"Willkommen bei Flexweg CMS","subtitle":"Erstkonfiguration","intro":"Geben Sie Ihre Firebase-Zugangsdaten, das Bootstrap-Administratorkonto und Ihren Flexweg-API-Schlüssel ein. Die Werte werden geprüft, in Ihrem Projekt gespeichert (Firestore + eine config.js-Datei auf Flexweg), und die Admin-Oberfläche lädt im normalen Anmeldeablauf neu. Sie machen das nur einmal.","introFirebase":"Schritt 1 — Firebase. Geben Sie Ihre Firebase-Projektdaten und das Bootstrap-Administratorkonto ein. Wir melden Sie an, prüfen die E-Mail und ob Ihre Firestore-Regeln diesen Admin pinnen, bevor wir zum Flexweg-Schritt weitergehen.","introFlexweg":"Schritt 2 — Flexweg. Geben Sie Ihren Flexweg-API-Schlüssel und die Site-URL ein. Wir testen die API, speichern die Konfiguration in Firestore, laden config.js auf Ihre Site hoch und synchronisieren die Theme-Assets.","continueToFlexweg":"Firebase prüfen und fortfahren","stepper":{"terms":"AGB","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Inhalte & Veröffentlichung","data":"Daten","hosting":"Hosting","install":"Installation"},"backend":{"title":"Daten-Backend wählen","intro":"Wählen Sie, wo das CMS Ihre Beiträge, Seiten, Benutzer und Einstellungen speichert. Sie können später über die Einstellungen wechseln (Daten werden nicht migriert).","sqliteTitle":"Flexweg SQLite (empfohlen)","sqliteHint":"Alle Daten verbleiben auf Ihrer Flexweg-Site als SQLite-Datei. Kein externer Dienst. Auth wird von der Flexweg SQLite-API bereitgestellt.","firebaseTitle":"Firebase","firebaseHint":"Verwenden Sie ein Firebase-Projekt für Firestore + Auth. Kostenlos im Spark-Plan. Echtzeit-Updates per onSnapshot.","continue":"Weiter","markdownGitTitle":"Markdown-Dateien in einem Git-Repository","markdownGitHint":"Beiträge als .md-Dateien auf GitHub / GitLab (oder in einem lokalen Klon). Jeder Redakteur meldet sich mit seinem eigenen Zugriffstoken an; jede Änderung ist ein Commit. Keine Datenbank, funktioniert mit mehreren Redakteuren und Rechnern.","localTitle":"Nur dieser Browser","localHint":"Ein Benutzer, keine Anmeldung, nichts einzurichten. Inhalte bleiben in diesem Browser (Export über die Einstellungen). Ideal für einen Admin, der auf Ihrem eigenen Computer läuft."},"sqlite":{"heading":"Verbinden Sie Ihre Flexweg-Site","intro":"Wir verwenden Ihren Flexweg-Master-API-Schlüssel EINMAL, um ein Token mit eingeschränktem Geltungsbereich für die SQLite-Datenbank zu erzeugen. Nach der Installation wird der Master-Schlüssel verworfen und nur das beschränkte Token (auf diese eine SQLite-Datei begrenzt) gespeichert.","apiKeyHint":"Flexweg-Master-API-Schlüssel. Wird nur zur Installation verwendet — danach nie gespeichert.","detectedFromUrl":"Aus URL erkannt","advanced":"Erweiterte Einstellungen (Site-URL, SQLite-Pfad…)","pathHint":"Wo die SQLite-Datei auf Ihrer Flexweg-Site liegt. Ordner werden automatisch erstellt.","adminHeading":"Administratorkonto","adminIntro":"Legen Sie den ersten Benutzer an — dieses Konto erhält automatisch Admin-Rechte. Weitere Mitglieder werden nach der Anmeldung über die Benutzerseite onboardet.","passwordHint":"Mindestens 8 Zeichen.","submit":"SQLite-Datenbank installieren"},"terms":{"title":"Nutzungsbedingungen","intro":"Bitte lesen und akzeptieren Sie die folgenden Bedingungen, bevor Sie Flexweg CMS verwenden. Sie sind in einfacher Sprache verfasst, um schnell lesbar zu sein.","section1":{"title":"1. Kostenloser Service","body":"Flexweg CMS wird Ihnen von Flexweg kostenlos zur Verfügung gestellt. Sie können es ohne Einschränkungen mit Ihrem Flexweg-Hosting nutzen — Flexweg wird Ihnen die Nutzung des CMS selbst niemals in Rechnung stellen. Die üblichen Gebühren Ihres Flexweg-Hosting-Plans und Ihres Firebase-Plans bleiben weiterhin anwendbar, jeweils auf dem entsprechenden Konto."},"section2":{"title":"2. Bereitstellung „wie besehen“, ohne Garantie","body":"Das CMS wird wie besehen bereitgestellt. Wir arbeiten daran, es stabil zu halten und im Laufe der Zeit zu verbessern, können jedoch nicht garantieren, dass es frei von Bugs, Mängeln oder Unterbrechungen ist. Verwenden Sie es mit derselben Vorsicht wie bei jedem Tool, das Sie nicht selbst geschrieben haben: Bewahren Sie Backups wichtiger Inhalte auf."},"section3":{"title":"3. Ihre Inhalte, Ihre Verantwortung","body":"Sie sind allein verantwortlich für die Inhalte, die Sie über das CMS veröffentlichen — Texte, Bilder, Videos, Formulare, Code-Einbettungen und alle anderen Medien. Sie müssen das anwendbare Recht in Ihrer Jurisdiktion (und in den von Ihnen anvisierten Jurisdiktionen) einhalten, ebenso wie Urheberrechte, Bild- und Persönlichkeitsrechte, Datenschutzbestimmungen sowie die Bedingungen jeglicher Drittanbieterdienste (z. B. eingebettete Schriften oder Videos). Flexweg ist nicht verantwortlich für die von den Nutzern des CMS veröffentlichten Inhalte."},"section4":{"title":"4. Ihr Firebase-Konto, Ihre Sicherheit","body":"Das CMS speichert seine Daten in Ihrem eigenen Firebase-Projekt. Sie sind für die Sicherheit dieses Projekts verantwortlich: Wählen Sie ein starkes Passwort für das Bootstrap-Administratorkonto, konfigurieren Sie die Firestore-Sicherheitsregeln wie dokumentiert, rotieren Sie Ihre API-Schlüssel bei Bedarf und prüfen Sie, wer Zugriff hat. Flexweg kann in keinem Fall für unbefugten Zugriff, Datenlecks, Hacks oder Verluste haftbar gemacht werden, die durch Fehlkonfiguration oder Kompromittierung Ihres Firebase-Kontos entstehen."},"section5":{"title":"5. Haftungsbeschränkung","body":"Flexweg kann nicht haftbar gemacht werden für Einnahmeverluste, Datenverluste, entgangene Geschäftsmöglichkeiten oder direkte oder indirekte Schäden, die aus der Nutzung, dem Missbrauch oder der Nichtverfügbarkeit des CMS entstehen. Soweit das anwendbare Recht eine Haftung von Flexweg vorschreibt, ist diese auf den Betrag beschränkt, der tatsächlich in den letzten 12 Monaten an Flexweg für das CMS gezahlt wurde — also null, da das CMS kostenlos ist."},"section6":{"title":"6. Ihre Daten bleiben bei Ihnen","body":"Inhalte, die Sie mit dem CMS erstellen, werden in Ihrem eigenen Firebase-Projekt (Texte, Einstellungen, Medienmetadaten) und auf Ihrem eigenen Flexweg-Hosting (veröffentlichtes HTML, Bilder, Theme-Assets) gespeichert. Das CMS selbst übermittelt Ihre Inhalte an keinen Drittanbieterdienst. Plugins oder Themes, die Sie aktivieren, können ihr eigenes Verhalten haben — prüfen Sie, was sie tun, bevor Sie sie aktivieren."},"section7":{"title":"7. Faire Nutzung","body":"Die Nutzung des CMS für rechtswidrige, betrügerische oder schädliche Aktivitäten oder auf eine Weise, die gegen die allgemeinen Nutzungsbedingungen von Flexweg verstößt, kann zur Sperrung Ihres Zugriffs auf das Flexweg-Hosting führen. Wir können diese CMS-Bedingungen auch im Laufe der Zeit aktualisieren; wesentliche Änderungen werden über das Admin-Panel oder per E-Mail kommuniziert."},"accept":"Ich habe die Nutzungsbedingungen gelesen und akzeptiere sie.","continue":"Weiter zur Konfiguration","back":"Zurück"},"sections":{"firebase":"Firebase","admin":"Bootstrap-Administrator","flexweg":"Flexweg-API"},"help":{"firebase":"Diese Werte finden Sie in Firebase Console → Projekteinstellungen → Allgemein → Ihre Apps → SDK-Setup und Konfiguration.","admin":"Verwenden Sie einen vorhandenen Benutzer aus Firebase Authentication. Wer sich mit dieser E-Mail anmeldet, wird als Administrator behandelt und umgeht die Benutzerdatensatz-Prüfung. Erstellen Sie den Benutzer bei Bedarf über Firebase Console → Authentication.","flexweg":"Erstellen Sie einen permanenten API-Schlüssel in Ihrem Flexweg-Konto → API. Die Site-URL ist die öffentliche Adresse Ihrer Flexweg-Site (z. B. https://ihre-site.flexweg.com).","flexwegApiKeyHint":"Ihren API-Schlüssel finden Sie in Ihren Flexweg-Kontoeinstellungen.","flexwegApiKeyLink":"Kontoeinstellungen öffnen"},"fields":{"apiKey":"API-Schlüssel","authDomain":"Auth-Domain","projectId":"Projekt-ID","storageBucket":"Storage-Bucket","messagingSenderId":"Messaging-Absender-ID","appId":"App-ID","adminEmail":"E-Mail","adminPassword":"Passwort","flexwegApiKey":"API-Schlüssel","flexwegSiteUrl":"Site-URL","flexwegApiBaseUrl":"API-Basis-URL","sqlitePath":"SQLite-Pfad"},"submit":"Speichern und fortfahren","submitting":"Konfiguration läuft…","success":"Setup abgeschlossen!","reloadingHint":"Die Admin-Oberfläche wird gleich neu geladen — bitte warten.","footer":"Diese Werte werden in Ihrem Projekt gespeichert (Firestore + Flexweg). Sie werden nirgendwo anders gesendet.","steps":{"signInFirebase":"Anmeldung bei Firebase…","testFlexweg":"Flexweg-API wird getestet…","writeFirestore":"Konfiguration wird gespeichert…","uploadConfig":"config.js wird zu Flexweg hochgeladen…","syncThemes":"Theme-Assets werden zu Flexweg synchronisiert…","sqliteInstall":"Beschränktes SQLite-Token wird erstellt…","sqliteRegisterAdmin":"Admin-Konto wird registriert…","sqliteSchema":"SQLite-Schema wird initialisiert…"},"stepsDone":{"sqliteInstall":"Beschränktes SQLite-Token ausgestellt","sqliteRegisterAdmin":"Admin registriert und angemeldet","sqliteSchema":"SQLite-Schema bereit"},"errors":{"missingFields":"Bitte füllen Sie alle Felder aus.","rootDeploymentTitle":"Die Admin-Oberfläche muss in einem Unterordner liegen, nicht im Stammverzeichnis der Site.","rootDeploymentHint":"Verschieben Sie die Admin-Dateien (index.html, config.js, runtime/, …) in einen Unterordner auf Flexweg — zum Beispiel /admin/ oder einen zufälligen Namen wie /erf34f654GH3/ aus Tarngründen. Laden Sie die Admin-Oberfläche dann von der URL des Unterordners neu und führen Sie das Setup erneut aus.","firebaseAuthGeneric":"Anmeldung bei Firebase fehlgeschlagen.","firebaseAuthInvalidCredential":"Firebase hat die Kombination aus E-Mail und Passwort abgelehnt.","firebaseAuthInvalidCredentialHint":"Neuere Firebase-Projekte aktivieren standardmäßig den Schutz vor E-Mail-Aufzählung, der denselben Fehler zurückgibt, egal ob das Passwort falsch ist, der Benutzer nicht existiert oder sich mit einem anderen Anbieter anmeldet. Zu prüfen:\\n• Geben Sie das Passwort erneut ein — kopieren/einfügen aus einem Passwortmanager, um Tippfehler auszuschließen. Mindestlänge sind 6 Zeichen.\\n• Öffnen Sie Firebase Console → Authentication → Users und bestätigen Sie, dass die E-Mail existiert. Prüfen Sie die Spalte „Providers“: Wird nur Google (oder ein anderer Anbieter) ohne „Email/Password“ angezeigt, setzen oder zurücksetzen Sie das Passwort über das Zeilenmenü (⋮ → Passwort zurücksetzen).\\n• Prüfen Sie, dass die Schreibweise der E-Mail exakt mit dem in Firebase gespeicherten Wert übereinstimmt.","firebaseAuthUserNotFound":"Kein Firebase-Benutzer mit dieser E-Mail. Legen Sie zunächst einen in Firebase Console → Authentication → Users an.","firebaseAuthInvalidEmail":"Die Admin-E-Mail ist keine gültige E-Mail-Adresse.","firebaseInvalidApiKey":"Der Firebase-API-Schlüssel ist ungültig. Prüfen Sie den Wert in der Firebase Console.","firebaseNetwork":"Netzwerkfehler bei der Anmeldung bei Firebase. Prüfen Sie Ihre Verbindung.","firebaseTooManyRequests":"Zu viele Anmeldeversuche. Bitte versuchen Sie es später erneut oder setzen Sie das Passwort über Firebase Console zurück.","firebaseOperationNotAllowed":"Die Anmeldung per E-Mail/Passwort ist in diesem Firebase-Projekt nicht aktiviert. Öffnen Sie Firebase Console → Authentication → Sign-in method und aktivieren Sie den Email/Password-Anbieter.","firebaseUserDisabled":"Dieses Firebase-Benutzerkonto ist deaktiviert. Aktivieren Sie es über Firebase Console → Authentication → Users wieder.","wrongAdminEmail":"Das Firebase-Konto, mit dem Sie sich angemeldet haben, stimmt nicht mit der eingegebenen Admin-E-Mail überein. Bitte erneut versuchen.","rulesNotPinnedTitle":"Die Firestore-Regeln erkennen Sie noch nicht als Bootstrap-Admin.","rulesNotPinnedHint":"Öffnen Sie Firebase Console → Firestore → Rules und ersetzen Sie den Wert von `bootstrapAdminEmail()` durch: {{email}} — klicken Sie dann auf Veröffentlichen. Die Regelvorlage im README enthält einen Platzhalter `you@example.com`, der durch Ihre tatsächliche Admin-E-Mail ersetzt werden muss. Nachdem die aktualisierten Regeln veröffentlicht sind, klicken Sie hier erneut auf Absenden.","flexwegAuth":"Flexweg-API-Schlüssel abgelehnt. Prüfen Sie den Wert in Ihrem Flexweg-Konto → API.","flexwegNetwork":"Netzwerkfehler beim Kontakt mit Flexweg. Prüfen Sie die API-Basis-URL und Ihre Verbindung.","flexwegHttp":"Flexweg-API-Fehler ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore hat das Schreiben der Konfiguration abgelehnt.","firestoreRulesHint":"Öffnen Sie Firebase Console → Firestore → Regeln und stellen Sie sicher, dass die Bootstrap-Admin-E-Mail auf \'{{email}}\' gesetzt ist. Im README finden Sie eine kopierfertige Regelvorlage.","firestoreOther":"Firestore-Schreibvorgang fehlgeschlagen","uploadFailed":"config.js konnte nicht zu Flexweg hochgeladen werden","generic":"Etwas ist schiefgelaufen."},"docstore":{"contentTitle":"Content-Repository","contentIntro":"Hier werden Ihre Beiträge, Seiten und Einstellungen als Markdown- + JSON-Dateien gespeichert. Ein leeres Repository ist in Ordnung — das CMS legt die Dateien an.","provider":"Repository","localClone":"Lokaler Ordner (git-Klon)","localCloneHint":"Wählen Sie den Ordner Ihres Klons. Synchronisieren Sie ihn mit Ihrem gewohnten git-Client — das CMS liest und schreibt Dateien, es führt kein git aus.","contentDir":"Inhaltsordner im Repository","privateRepo":"Verwenden Sie ein privates Repository: Entwürfe werden dort gespeichert.","folderRequired":"Wählen Sie zuerst den Inhaltsordner.","checking":"Repository-Zugriff wird geprüft…","publishIntro":"Wohin die generierte Website veröffentlicht wird. Sie können dies später in den Einstellungen ändern.","existingSite":"Dieses Repository ist bereits eingerichtet — die Website wird weiterhin veröffentlicht nach: {{target}}. Sie können dies später in den Einstellungen ändern (eventuelle geheime Schlüssel müssen dort erneut eingegeben werden).","install":"Installieren","steps":{"config":"Konfiguration wird gespeichert…","content":"Inhalte werden geladen…","target":"Veröffentlichungsziel wird gespeichert…","testTarget":"Veröffentlichungsziel wird getestet…"},"doneTitle":"Alles bereit!","doneBody":"Die Konfiguration ist in diesem Browser gespeichert. Um anderen Redakteuren diese Einrichtung zu ersparen, laden Sie config.js herunter und ersetzen Sie die Datei im Admin-Ordner Ihres Hostings.","downloadConfig":"config.js herunterladen","open":"Admin öffnen","footer":"Die Inhalte bleiben in Ihrem Repository oder in diesem Browser; Zugriffstoken verlassen diesen Browser nie."},"data":{"title":"1. Wo speichern Sie Ihre Daten?","intro":"Ihre Beiträge, Seiten, Benutzer und Einstellungen — die eigenen Daten des Admins. Dies ist unabhängig davon, wo die öffentliche Website gehostet wird (nächster Schritt).","localNote":"Nichts zu konfigurieren: Die Inhalte werden in diesem Browser gespeichert. Exportieren Sie sie in den Einstellungen, um sie zu sichern oder später umzuziehen.","options":{"sqlite-file":{"title":"SQLite","hint":"Eine SQLite-Datenbank, gespeichert auf dem Hosting, das Sie im nächsten Schritt wählen (Flexweg, Ihr Server, S3, Git…). Ohne Benutzerkonten — oder der SQLite-Dienst von Flexweg mit Konten, wenn Sie bei Flexweg hosten."},"flexweg-sqlite":{"title":"SQLite (Flexweg-Dienst)","hint":"Eine SQLite-Datenbank, betrieben vom Flexweg-Dienst, mit integrierten Benutzerkonten. Erfordert ein Flexweg-Konto, unabhängig davon, wo die Website gehostet wird."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth in Ihrem Google-Projekt. Echtzeit, kostenloser Spark-Tarif."},"markdown-git":{"title":"Markdown-Dateien in Git","hint":"Beiträge als .md-Dateien in einem GitHub- / GitLab-Repository (oder einem lokalen Klon). Jeder Redakteur verwendet sein eigenes Token; jede Änderung ist ein Commit."},"local":{"title":"Dieser Browser","hint":"Ein Benutzer, keine Anmeldung, nichts einzurichten. Ideal für einen Admin, der auf Ihrem Computer läuft."}}},"hosting":{"title":"2. Wo wird die Website veröffentlicht?","intro":"Wohin die generierte statische Website (HTML, CSS, Bilder) bei jeder Veröffentlichung hochgeladen wird. Sie können dies später in den Einstellungen ändern.","existing":"Dieses Content-Repository veröffentlicht bereits auf das untenstehende Ziel. Behalten Sie es oder wählen Sie ein anderes."},"install":{"title":"3. Installation","intro":"Prüfen Sie die Zusammenfassung und installieren Sie dann.","data":"Daten","hosting":"Hosting","saveTarget":"Veröffentlichungsziel wird gespeichert…","noteConfigJs":"Die Admin-Konfiguration (config.js) wird nach Möglichkeit neben den Admin auf Flexweg hochgeladen; andernfalls wird Ihnen angeboten, sie herunterzuladen.","noteLocalConfig":"Die Konfiguration wird in diesem Browser gespeichert; Ihnen wird config.js zum Ablegen im Admin-Ordner angeboten, damit andere Redakteure diese Einrichtung überspringen."},"sqliteFile":{"security":"Keine Benutzerkonten: Wer dieses Admin öffnen kann, kann den Inhalt bearbeiten — schütze den Admin-Ordner auf Ebene deines Hostings. Die Datenbankdatei wird wie jede andere Datei ausgeliefert: Halte sie verschlüsselt oder speichere sie an einem separaten privaten Ort.","intro":"Wo die Datenbankdatei gespeichert wird. Dieser Admin liest und speichert sie über dieselben Konnektoren wie das Hosting.","path":"Pfad der Datenbankdatei","pathHint":"Wird beim ersten Speichern angelegt, falls sie noch nicht existiert. Bei einem Git-Repository ist jedes Speichern ein Commit — verwenden Sie besser ein Repository oder einen Branch, der keinen Website-Build auslöst.","existing":"bestehende Datenbank","new":"neue Datenbank","dataNote":"Hier ist nichts zu konfigurieren: Die Datenbank wird auf dem Hosting gespeichert, das Sie im nächsten Schritt wählen.","heading":"SQLite-Datenbank","flexwegService":"Den SQLite-Dienst von Flexweg verwenden","flexwegServiceHint":"Die Datenbank wird von Flexweg betrieben und bringt integrierte Benutzerkonten mit (E-Mail + Passwort). Andernfalls ist sie eine einfache Datei auf diesem Hosting, ohne Konten.","summaryFile":"Datei {{path}} auf diesem Hosting","summaryService":"SQLite-Dienst von Flexweg ({{path}})","encrypt":"Datenbank verschlüsseln","encryptHint":"Empfohlen bei öffentlichem Hosting: Ohne Passphrase ist die Datei unlesbar. Jeder neue Browser fragt einmal danach.","passphrase":"Passphrase","passphraseHint":"Speichere sie jetzt in deinem Passwort-Manager: Ohne sie kann niemand die Datenbank öffnen — auch du nicht.","copy":"Kopieren","copied":"Kopiert","generate":"Neu","passphraseTooShort":"Die Passphrase muss mindestens 12 Zeichen lang sein.","existingEncrypted":"An diesem Pfad gibt es bereits eine verschlüsselte Datenbank: Gib ihre Passphrase ein.","separate":"Datenbank an einem separaten privaten Ort speichern","separateHint":"Z. B. ein privater S3- / R2-Bucket oder ein privates Git-Repository: Die Datenbank wird dann nie von der öffentlichen Website ausgeliefert.","summaryEncrypted":"verschlüsselt","summaryLocation":"gespeichert in {{location}}","locationLabel":"Speicherort der Datenbank","gitBranchNote":"Die Datenbank liegt im Branch {{branch}} dieses Repositorys, der nie veröffentlicht wird: Speichern von Inhalten baut die Website nicht neu.","summaryBranch":"im Branch {{branch}}"},"adminHosting":{"deploying":"Admin wird auf die Website kopiert…","label":"Admin auch auf dieser Website hosten","hint":"Der Admin wird mit seiner config.js (ohne Geheimnisse) nach {{url}} kopiert — jeder Redakteur kann ihn dann dort öffnen. Jeder Redakteur meldet sich weiterhin mit seinem eigenen Zugang an.","folder":"Admin-Ordner","alreadyHere":"Dieser Admin läuft bereits von dieser Website aus: Seine config.js wird direkt aktualisiert.","doneBody":"Der Admin ist jetzt auf Ihrer Website. Aktivieren Sie bei GitHub Pages zuerst Pages für das Repository, falls noch nicht geschehen (Settings → Pages), und öffnen Sie ihn dann:","open":"Online-Admin öffnen","continueHere":"In diesem Admin fortfahren"}}'),Ere={actions:{upload:"Datei wird hochgeladen",delete:"Datei wird gelöscht",rename:"Datei wird umbenannt",get:"Datei wird gelesen",list:"Dateien werden aufgelistet",createFolder:"Ordner wird erstellt",renameFolder:"Ordner wird umbenannt",deleteFolder:"Ordner wird gelöscht",storageLimits:"Speichergrenzen werden abgerufen",commit:"Änderungen veröffentlichen"},errors:{configMissing:"Das Veröffentlichungsziel ist nicht konfiguriert. Richten Sie es vor dem Veröffentlichen in den Einstellungen ein.",network:"{{action}}: Netzwerkfehler oder CORS blockiert. Überprüfen Sie Ihre Verbindung.",auth:"{{action}}: Authentifizierung fehlgeschlagen. Prüfen Sie die Zugangsdaten des Veröffentlichungsziels in den Einstellungen.",notFound:"{{action}}: Ziel auf dem Veröffentlichungsziel nicht gefunden.",tooLarge:"{{action}}: Datei zu groß für das Veröffentlichungsziel.",rateLimited:"{{action}}: Zu viele Anfragen, bitte in Kürze erneut versuchen.",serverError:"{{action}}: Serverfehler des Veröffentlichungsziels ({{status}}). Bitte erneut versuchen.",generic:"{{action}} fehlgeschlagen ({{status}}){{detail}}.",unsupported:"{{action}}: wird vom Veröffentlichungsziel „{{connector}}“ nicht unterstützt.",unknownConnector:"Unbekanntes Veröffentlichungsziel „{{connector}}“. Prüfen Sie Einstellungen → Veröffentlichungsziel.",folderAccess:"Kein Zugriff auf den lokalen Ordner. Öffnen Sie Einstellungen → Veröffentlichungsziel und klicken Sie auf „Ordner neu verbinden“."}},_re={log:{rendering:"Seite wird gerendert…",uploading:"{{path}} wird hochgeladen…",deleting:"{{path}} wird gelöscht…",regenerating:"Listings werden neu generiert…",skipped:"{{path}} übersprungen (keine Änderungen)",done:"Veröffentlicht unter {{url}}",failed:"Fehlgeschlagen: {{error}}"}},Cre={errors:{notConnected:"Nicht mit dem Inhalts-Repository verbunden. Melden Sie sich erneut mit Ihrem Zugriffstoken an.",conflict:"Jemand anderes hat dieses Element inzwischen geändert. Seine Version wird jetzt angezeigt — wenden Sie Ihre Änderung erneut an.",sqliteUnsupported:"Das Ziel „{{connector}}“ kann keine Datenbankdatei speichern."}},Are={target:"Veröffentlichungsziel",settingsTitle:"Veröffentlichungsziel",settingsHelp:"Wohin die gerenderte Website beim Veröffentlichen hochgeladen wird. Zugangsdaten werden bei Ihrem Inhalts-Backend gespeichert (bzw. bei Git-Content-Repositorys in diesem Browser) und sind für alle Admins lesbar.",saved:"Veröffentlichungsziel gespeichert. Führen Sie Neu generieren → Alles aus, um die gesamte Website auf dem neuen Ziel zu veröffentlichen.",test:"Verbindung testen",testOk:"Verbindung OK",testFailed:"Verbindung fehlgeschlagen",names:{flexweg:"Flexweg","git-pages":"Git-Repository (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"S3-kompatibler Bucket (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Ihr eigener Server (PHP-Bridge)","browser-mirror":"Als ZIP herunterladen","local-folder":"Lokaler Ordner auf diesem Computer"},hints:{flexweg:"Upload über die Flexweg Files API.","git-pages":"Jede Veröffentlichung ist ein Commit im Repository; der Hoster baut die Website daraus neu.",s3:"Erfordert eine CORS-Regel auf dem Bucket, die den Origin dieses Admins zulässt, sowie Website-Hosting (oder ein CDN), um index.html-Dateien auszuliefern.","php-bridge":"Laden Sie external/bridges/php/flexweg-bridge.php auf Ihren Server hoch, legen Sie dessen API-Schlüssel fest und tragen Sie hier die URL ein.","browser-mirror":"Die Website wird in diesem Browser gespeichert; laden Sie das ZIP herunter und laden Sie es von Hand an beliebiger Stelle hoch.","local-folder":"Schreibt die Website direkt in einen Ordner (Chrome / Edge). Stellen Sie sie lokal bereit oder pushen Sie sie mit Ihren eigenen Tools."},fields:{flexweg:{apiKey:"API-Schlüssel",siteUrl:"Website-URL",apiBaseUrl:"API-Basis-URL"},"git-pages":{host:"Hosting",provider:"Git-Anbieter",owner:"Eigentümer (Benutzer oder Organisation)",repo:"Repository",project:"Projektpfad",branch:"Branch",dir:"Ordner im Repository",token:"Zugriffstoken",siteUrl:"Öffentliche Website-URL",apiBaseUrl:"API-URL (nur selbst gehostet)"},s3:{endpoint:"Endpoint",region:"Region",bucket:"Bucket",prefix:"Schlüsselpräfix (optional)",accessKeyId:"Access Key ID",secretAccessKey:"Geheimer Zugriffsschlüssel",siteUrl:"Öffentliche Website-URL",forcePathStyle:"Pfad-basierte URLs (MinIO, R2, die meisten kompatiblen Dienste)",publicRead:"Hochgeladene Dateien öffentlich machen (ACL public-read) — für Buckets, die nicht per Bucket-Policy öffentlich sind (OVHcloud, Scaleway…). Bei AWS-Buckets mit „Bucket owner enforced“ deaktiviert lassen."},"php-bridge":{apiBaseUrl:"Bridge-URL",apiKey:"API-Schlüssel der Bridge",siteUrl:"Öffentliche Website-URL"},"browser-mirror":{siteUrl:"Öffentliche Website-URL (optional)"},"local-folder":{siteUrl:"URL, unter der der Ordner bereitgestellt wird (optional)"}},help:{flexweg:{apiKey:"Wird in Ihrem Flexweg-Konto → API erzeugt."},"git-pages":{host:"Cloudflare Pages: Verbinden Sie das Projekt mit diesem Repository, ohne Build-Befehl und mit dem unten angegebenen Ausgabeordner. Funktioniert mit privaten Repositorys.",dir:'Leer lassen für das Stammverzeichnis des Repositorys. GitHub Pages: "" oder "docs". GitLab Pages: "public".',token:"Fine-grained Token für dieses Repository mit Contents: read & write (GitHub) — fügen Sie Pages: read & write hinzu, damit das CMS GitHub Pages aktivieren kann — oder ein Token mit dem Scope api (GitLab). Leer lassen, um das eigene Zugriffstoken jedes Redakteurs zu verwenden, wenn die Inhalte beim selben Anbieter liegen.",siteUrl:"z. B. https://user.github.io/repo — eine URL mit Unterordner ist in Ordnung, Links werden automatisch angepasst."},s3:{endpoint:"Für AWS leer lassen (wird aus der Region gebildet). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"Die Website-URL des Buckets oder Ihre CDN-Domain."},"php-bridge":{apiBaseUrl:"Die vollständige URL von flexweg-bridge.php auf Ihrem Server (HTTPS)."},"browser-mirror":{siteUrl:"Wohin Sie das ZIP hochladen werden — wird für absolute URLs verwendet (Sitemaps, RSS, Medien)."},"local-folder":{siteUrl:"z. B. http://localhost:8080, wenn ein lokaler Webserver den Ordner bereitstellt."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (mit dem Repository verbunden)","gitlab-pages":"GitLab Pages",other:"Andere (Netlify, Vercel, git pull auf dem Server…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Ordner wählen…",change:"Ordner ändern…",reconnect:"Ordner erneut verbinden",unsupported:"Dieser Browser kann nicht in lokale Ordner schreiben. Verwenden Sie Chrome oder Edge."},mirror:{download:"Website herunterladen (ZIP)",count:"{{count}} Dateien in diesem Browser"},adminHosting:{title:"Admin auf dieser Website",help:"Kopiert diesen Admin auf das Veröffentlichungsziel (Erstbereitstellung oder Aktualisierung nach einer neuen Version). Seine config.js enthält keine Geheimnisse.",deploy:"Admin bereitstellen / aktualisieren",deployed:"Admin bereitgestellt ({{count}} Dateien) — {{url}}"},pages:{enabled:"GitHub Pages für dieses Repository aktiviert — die Website ist in etwa einer Minute online.",enableHint:'Veröffentlichung erfolgreich. Um die Website online zu stellen, aktivieren Sie GitHub Pages für {{repo}}: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Oder geben Sie dem Token die Berechtigung "Pages: read and write", dann erledigt das CMS das für Sie.)'},siteUrl:{mismatch:"Die öffentliche URL der Website (Einstellungen → Website) ist {{site}}, aber dieses Ziel stellt die Website unter {{target}} bereit. Links, CSS und Sitemaps folgen der Website-URL — sie sind auf diesem Hosting falsch.",use:"{{url}} für die Website verwenden",updated:"Website-URL aktualisiert. Führen Sie Neu generieren → Alles aus, um die Seiten mit den neuen Links erneut zu veröffentlichen."}},Tre={heading:"Mit dem Content-Repository verbinden",tokenIntro:"Die Inhalte liegen im {{provider}}-Repository {{repo}}. Melden Sie sich mit Ihrem eigenen persönlichen Zugriffstoken an — Ihre Repository-Berechtigungen bestimmen Ihre Rolle (Schreibzugriff = Redakteur, Admin / Maintainer = Admin).",token:"Persönliches Zugriffstoken",tokenHelpGithub:"Fine-grained Token, nur Zugriff auf dieses Repository, Berechtigung Contents: Lesen und Schreiben.",tokenHelpGitlab:"Token mit dem api scope, Rolle Developer oder höher in diesem Projekt.",createToken:"Token erstellen",connect:"Verbinden",tokenStorage:"Das Token wird nur in diesem Browser gespeichert. Beim Abmelden wird es gelöscht.",failed:"Mit diesem Token kann nicht in das Repository geschrieben werden (ungültig, abgelaufen oder schreibgeschützt). Prüfen Sie seine Berechtigungen.",folderIntro:"Die Inhalte liegen in einem Ordner auf diesem Computer (in der Regel ein git-Klon, den Sie mit Ihrem eigenen git-Client synchronisieren). Gewähren Sie diesem Browser Zugriff darauf — Browser fragen nach jedem Neuladen erneut.",openFolder:"Inhaltsordner öffnen"},Ire={flexweg:{title:"Flexweg",short:"Flexweg-Hosting",hint:"Upload über die Flexweg Files API. API-Schlüssel aus Ihrem Flexweg-Konto."},"github-pages":{title:"GitHub Pages",short:"Kostenlos, aus einem GitHub-Repository",hint:"Jede Veröffentlichung ist ein Commit im Repository; GitHub Pages liefert es aus. Settings → Pages → Deploy from a branch. Öffentliche Repositories im kostenlosen Tarif."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Kostenlos, private Repositories möglich",hint:"Das CMS committet die Website in ein GitHub- / GitLab-Repository; verbinden Sie ein Cloudflare-Pages-Projekt damit (kein Build-Befehl, Ausgabeordner = der Ordner unten)."},"gitlab-pages":{title:"GitLab Pages",short:"Kostenlos, aus einem GitLab-Repository",hint:"Jede Veröffentlichung ist ein Commit; das CMS fügt eine minimale .gitlab-ci.yml hinzu, die den Ordner public/ veröffentlicht."},"git-other":{title:"Netlify, Vercel…",short:"Jeder Host, der ein Repository deployt",hint:"Das CMS committet die Website in ein Git-Repository; verbinden Sie Ihren Host (Netlify, Vercel, einen Server mit git pull…) mit diesem Repository."},s3:{title:"S3 / R2 / B2…",short:"Object-Storage-Bucket",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Erfordert eine CORS-Regel auf dem Bucket sowie Website-Hosting oder ein vorgeschaltetes CDN."},"own-server":{title:"Ihr eigener Server (FTP / SFTP)",short:"Shared Hosting, VPS…",hint:"Browser können kein FTP oder SFTP: Laden Sie die PHP-Bridge (external/bridges/php/flexweg-bridge.php) einmalig mit Ihrem FTP-Client hoch, legen Sie ihren API-Schlüssel fest und tragen Sie dann hier ihre URL ein. Funktioniert auf jedem PHP-Host."},"local-folder":{title:"Lokaler Ordner",short:"Auf diesem Computer",hint:"Schreibt die Website in einen Ordner dieses Computers (Chrome / Edge). Stellen Sie sie lokal bereit oder übertragen Sie sie mit Ihren eigenen Tools."},zip:{title:"Als ZIP herunterladen",short:"Manuell hochladen",hint:"Die Website wird in diesem Browser gespeichert; laden Sie in den Einstellungen ein ZIP herunter und laden Sie es beliebig hoch (Netlify Drop, FTP-Client…)."}},Nre={heading:"Mit der Datenbank verbinden",intro:"Dieser Admin speichert seine Inhalte in {{path}}. Geben Sie die Zugangsdaten für diesen Browser ein.",storage:"Die Zugangsdaten werden nur in diesem Browser gespeichert. Beim Abmelden werden sie vergessen.",passphrase:"Passphrase der Datenbank",passphraseHint:"Die Datenbank ist verschlüsselt. Gib die bei der Installation gewählte Passphrase ein (wird nur in diesem Browser gespeichert).",passphraseWrong:"Falsche Passphrase: Die Datenbank konnte nicht geöffnet werden.",passphraseMissing:"Gib die Passphrase der Datenbank ein."},Pre={common:ire,auth:are,nav:ore,dashboard:lre,posts:cre,pages:ure,taxonomies:dre,media:hre,themes:fre,plugins:pre,externalInstall:mre,externalLoader:gre,menus:bre,settings:yre,users:vre,firestoreSetup:xre,errors:wre,identity:kre,setup:Sre,flexweg:Ere,publish:_re,docstore:Cre,connectors:Are,gitAccess:Tre,hosting:Ire,sqliteAccess:Nre},Rre={save:"Guardar",saving:"Guardando…",saved:"Guardado",cancel:"Cancelar",delete:"Eliminar",deleting:"Eliminando…",edit:"Editar",create:"Crear",search:"Buscar",loading:"Cargando…",yes:"Sí",no:"No",confirm:"Confirmar",back:"Atrás",next:"Siguiente",previous:"Anterior",close:"Cerrar",all:"Todos",none:"Ninguno",actions:"Acciones",name:"Nombre",slug:"Slug",description:"Descripción",status:"Estado",createdAt:"Creado",updatedAt:"Actualizado",publishedAt:"Publicado",language:"Idioma",darkMode:"Modo oscuro",lightMode:"Modo claro",signOut:"Cerrar sesión",administrator:"Administrador",editor:"Editor",appName:"Flexweg CMS"},jre={signIn:"Iniciar sesión",signingIn:"Iniciando sesión…",email:"Correo electrónico",password:"Contraseña",emailPlaceholder:"tu@empresa.com",passwordPlaceholder:"••••••••",forgotPassword:"¿Olvidaste tu contraseña?",resetEmailSent:"Correo de restablecimiento de contraseña enviado a {{email}}.",enterEmailFirst:"Introduce primero tu correo arriba y luego haz clic en restablecer.",emailPasswordRequired:"El correo y la contraseña son obligatorios.",signInSubtitle:"Usa tu correo de trabajo y tu contraseña.",footer:"Las solicitudes de cuenta se gestionan a través de tu administrador.",errors:{invalidEmail:"Dirección de correo no válida.",invalidCredentials:"Correo o contraseña no válidos.",tooManyRequests:"Demasiados intentos. Inténtalo más tarde o restablece tu contraseña.",userDisabled:"Esta cuenta ha sido deshabilitada.",networkFailed:"Error de red. Comprueba tu conexión.",generic:"Error de autenticación."}},Mre={openMenu:"Abrir menú",closeMenu:"Cerrar menú",dashboard:"Panel",posts:"Entradas",pages:"Páginas",taxonomies:"Categorías y etiquetas",media:"Medios",themes:"Temas",themeSettings:"Ajustes del tema",plugins:"Plugins",menus:"Menús",users:"Usuarios",settings:"Ajustes"},Lre={title:"Panel",welcome:"Bienvenido de nuevo, {{email}}.",stats:{totalPosts:"Entradas",totalPages:"Páginas",online:"En línea",drafts:"Borradores"}},Dre={title:"Entradas",newPost:"Nueva entrada",noPosts:"Aún no hay entradas. Crea la primera para empezar.",noPostsInFilter:"Ninguna entrada coincide con el filtro actual.",search:{placeholder:"Buscar entradas…",clear:"Borrar búsqueda",noResults:"Ninguna entrada coincide con tu búsqueda."},pagination:{previous:"Anterior",next:"Siguiente",showing:"Mostrando {{from}}–{{to}} de {{total}}",pageOf:"Página {{page}} de {{total}}"},bulk:{selectedCount_one:"{{count}} seleccionada",selectedCount_other:"{{count}} seleccionadas",selectPage_one:"Seleccionar {{count}} en esta página",selectPage_other:"Seleccionar las {{count}} de esta página",deselectPage:"Deseleccionar página",allOnPageSelected_one:"{{count}} en esta página seleccionada.",allOnPageSelected_other:"Las {{count}} de esta página están seleccionadas.",selectAllMatching_one:"Seleccionar la entrada coincidente",selectAllMatching_other:"Seleccionar las {{count}} entradas coincidentes",allMatchingSelected_one:"La entrada coincidente está seleccionada.",allMatchingSelected_other:"Las {{count}} entradas coincidentes están seleccionadas.",selectOne:"Seleccionar «{{title}}»",publish:"Publicar ({{count}})",publishing:"Publicando…",publishedCount:"{{ok}} publicada(s), {{failed}} fallo(s).",unpublish:"Despublicar ({{count}})",unpublishing:"Despublicando…",unpublishedCount:"{{ok}} despublicada(s), {{failed}} fallo(s).",delete:"Eliminar",deleting:"Eliminando…",deletedCount:"{{ok}} eliminada(s), {{failed}} fallo(s).",confirmDelete_one:"¿Eliminar {{count}} entrada? Se despublica de Flexweg y no se puede deshacer.",confirmDelete_other:"¿Eliminar {{count}} entradas? Se despublican de Flexweg y no se puede deshacer.",noDraftSelected:"Ninguna entrada en borrador seleccionada.",noOnlineSelected:"Ninguna entrada en línea seleccionada.",clear:"Borrar selección"},filters:{all:"Todas",draft:"Borrador",online:"En línea"},fields:{title:"Título",slug:"Slug",excerpt:"Extracto",content:"Contenido",category:"Categoría",tags:"Etiquetas",heroImage:"Imagen destacada",seoTitle:"Título SEO",seoDescription:"Descripción SEO",createdAt:"Creado el",updatedAt:"Última actualización",publishedAt:"Publicado el"},edit:{newTitle:"Nueva entrada",editTitle:"Editar entrada",saved:"Guardado.",savedAndRepublished:"Guardado y republicado.",saveFailed:"Error al guardar.",saveAndRepublish:"Guardar y republicar",draftSaved:"Borrador guardado.",slugCollision:{post:'Esta URL ya la usa la entrada: "{{label}}".',page:'Esta URL ya la usa la página: "{{label}}".',category:'Esta URL ya la usa la categoría: "{{label}}".'},publish:"Publicar",unpublish:"Despublicar",publishing:"Publicando…",unpublishing:"Despublicando…",titlePlaceholder:"Añadir título",permalink:"Enlace permanente",slugFormatHint:"Solo minúsculas, ASCII, separadas por guiones.",slugAutoSuffixed:'Se añadió un sufijo porque "{{base}}" ya lo usa {{owner}}.',slugAutoSuffixedOwner:{post:'publicación: "{{label}}"',page:'página: "{{label}}"',category:'categoría: "{{label}}"'},saveBlocked:{titleRequired:"Añade un título antes de guardar.",slugRequired:"Se requieren un título y un slug de URL para guardar.",slugInvalid:"Formato de slug inválido (ASCII en minúsculas + guiones).",slugCollision:"Resuelve el conflicto de URL antes de guardar."},viewPublished:"Ver",confirmDelete:"¿Eliminar esta entrada?",inspector:{document:"Documento",block:"Bloque",blockEmpty:"Selecciona un bloque en el editor para ver sus opciones.",publishing:"Publicación",permalink:"Enlace permanente",categories:"Categorías y etiquetas",featured:"Imagen destacada",seo:"SEO",excerpt:"Extracto",dates:"Fechas"},blocks:{addBlock:"Añadir bloque",transform:"Transformar a",moveUp:"Mover arriba",moveDown:"Mover abajo",duplicate:"Duplicar",remove:"Eliminar bloque",paragraph:"Párrafo",heading2:"Título 2",heading3:"Título 3",bulletList:"Lista con viñetas",orderedList:"Lista numerada",blockquote:"Cita",codeBlock:"Código",image:"Imagen",horizontalRule:"Separador",categories:{text:"Texto",media:"Medios",layout:"Diseño",embed:"Incrustaciones",advanced:"Avanzado"},noSettings:"Este bloque no tiene ajustes.",noSelection:"Selecciona un bloque en el editor para ver sus opciones.",slash:{noResults:"Ningún bloque coincide."}}},status:{draft:"Borrador",online:"En línea"},preview:{title:"Vista previa",rendering:"Generando vista previa…",error:"Error en la vista previa: {{error}}",viewports:{mobile:"Móvil",tablet:"Tableta",desktop:"Escritorio"}}},Fre={title:"Páginas",newPage:"Nueva página",noPages:"Aún no hay páginas.",homeBadge:"Inicio",homeBadgeTooltip:"Se usa como página de inicio del sitio"},Ore={title:"Categorías y etiquetas",categories:"Categorías",tags:"Etiquetas",newCategory:"Nueva categoría",newTag:"Nueva etiqueta",noCategories:"Aún no hay categorías.",noTags:"Aún no hay etiquetas.",slugCollision:'Este slug ya lo usa "{{label}}".',seo:{button:"SEO",buttonTitle:"Editar metaetiquetas SEO",title:"Metaetiquetas SEO",subtitle:'Título y descripción personalizados para la página de archivo de "{{name}}".',metaTitle:"Meta título",metaTitleHint:"Se usa como <title> de la página. Por defecto: el nombre del término.",metaDescription:"Meta descripción",metaDescriptionHint:"Se usa como meta descripción de la página. Por defecto: la descripción del término."}},zre={title:"Biblioteca de medios",upload:"Subir",uploading:"Subiendo…",finalizing:"Finalizando…",uploadFailed:"Error al subir",retry:"Reintentar",noMedia:"Aún no hay medios.",alt:"Texto alternativo",caption:"Pie de foto",filename:"Nombre de archivo",size:"Tamaño",type:"Tipo"},Ure={title:"Temas",active:"Activo",activate:"Activar",installExternal:"Instalar tema",uninstallDisabledTitle:"Cambia a otro tema antes de desinstalar este.",syncAssets:"Sincronizar recursos del tema",regenerateSite:"Regenerar el sitio",regenerating:"Regenerando…",regenerate:{button:"Regenerar",running:"Ejecutando…",groupBuiltins:"Sitio",groupPlugins:"Plugins",home:"Solo página de inicio",homeHelp:"Regenera solo index.html — la opción más rápida.",allHtml:"Todas las páginas HTML",allHtmlHelp:"Cada entrada, página, archivo y listado — además de los snapshots menu / posts / authors JSON.",repair:"Reparar URLs",repairHelp:"Recalcula la URL canónica de cada publicación online y mueve los archivos que terminaron en la URL equivocada. Útil tras una importación realizada antes de que los términos se sincronizaran.",assets:"Recursos del tema",assetsHelp:"Sube el CSS y los scripts del tema activo a /theme-assets/.",everything:"Todo",everythingHelp:"Recursos del tema + todo HTML + cada salida de plugin. Opción más lenta.",noPluginTargets:"Sin regeneraciones de plugin — activa un plugin que soporte regenerar."},confirmSwitch:{title:"¿Cambiar a {{theme}}?",body:"Cambiar de tema requiere volver a subir los recursos del tema y regenerar cada página publicada para que el nuevo aspecto se propague en todas partes. Puede tardar un momento.",confirm:"Cambiar y regenerar",cancel:"Cancelar"}},Bre={title:"Plugins",enabled:"Activado",disabled:"Desactivado",enable:"Activar",disable:"Desactivar",configure:"Configurar",author:"autor",learnMore:"Más información",mustUseBadge:"Obligatorio",installExternal:"Instalar plugin",tabs:{regular:"Plugins",mustUse:"Obligatorios"}},$re={titlePlugin:"Instalar un plugin",titleTheme:"Instalar un tema",labelPlugin:"plugin",labelTheme:"tema",intro:"Suelta un archivo ZIP que contenga un bundle de {{label}} (manifest.json + bundle.js en la raíz del ZIP). El {{label}} se subirá a tu sitio Flexweg y se registrará tras una recarga. Volver a subir un ZIP con el mismo id de manifest actualiza la entrada existente en el sitio — no hace falta desinstalar.",zipField:"Archivo ZIP del bundle",install:"Instalar",installing:"Instalando…",installSuccess:"{{name}} instalado ({{count}} archivos subidos). Recargando…",upgradeSuccess:"{{name}} actualizado de v{{previousVersion}} a v{{newVersion}} ({{count}} archivos subidos). Recargando…",installedTitle:"Ya instalado",bundledDefaultsTitle:"Plugins/temas incluidos disponibles",bundledDefaultsHint:"{{count}} plugin/tema incluido está actualmente desinstalado. Restáuralos para recuperar lo que venía con esta versión del admin.",bundledDefaultsRestore:"Restaurar",bundledDefaultsRestored:"Restaurados {{plugins}} plugin(s) y {{themes}} tema(s). Recargando…",uninstall:"Desinstalar",uninstallSuccess:"{{id}} desinstalado. Recargando…",confirmUninstall:"¿Desinstalar {{id}}? Los archivos se eliminarán de Flexweg.",errors:{"no-manifest":"El ZIP no tiene manifest.json en la raíz.","invalid-manifest":"manifest.json no es válido (falta algún campo obligatorio o no es JSON válido).","incompatible-api":"El bundle se compiló contra una versión incompatible de la API runtime.","no-bundle":"El ZIP no contiene el archivo de entrada declarado en el manifest.","fetch-manifest":"No se pudo leer el external.json actual en Flexweg.","upload-failed":"Falló la subida — revisa tu clave API de Flexweg y tu conexión."}},Hre={someFailed:"{{count}} bundle(s) externo(s) no se pudieron cargar. Mira la consola del navegador."},Vre={title:"Menús",header:"Menú de cabecera",footer:"Menú de pie de página",label:"Etiqueta",saveAndPublish:"Guardar y generar",discard:"Descartar",saved:"Menús guardados y publicados.",saveFailed:"No se pudieron guardar los menús.",unsavedChanges:"Tienes cambios sin guardar."},qre={title:"Ajustes",tabs:{general:"General"},site:{title:"Sitio",siteTitle:"Título del sitio",siteDescription:"Descripción del sitio",siteLanguage:"Idioma del sitio",siteLanguageHelp:'Etiqueta BCP-47 (p. ej. en, fr-CA) inyectada en <html lang="…"> de cada página publicada. El prefijo se compara con los locales de traducción soportados para los textos de sitemap / RSS y las cadenas integradas en el tema; los locales no soportados recurren al inglés.',siteLanguageResolved:"Las traducciones usarán: {{label}}",baseUrl:"URL pública del sitio",postsPerPage:"Entradas por página",homeMode:"Contenido de la página de inicio",homeLatest:"Últimas entradas",homeStatic:"Página estática",homePage:"Página de inicio",discourageIndexing:"Disuadir a los motores de búsqueda de indexar este sitio",discourageIndexingHelp:"Si se activa, cada página publicada recibe una etiqueta meta noindex/nofollow y robots.txt bloquea a todos los rastreadores. Replica el comportamiento de WordPress — útil para sitios de staging o revisiones antes del lanzamiento. Los motores de búsqueda que respetan la directiva no indexarán el sitio.",discourageRegenerateHint:"Ajuste de indexación guardado. Haz clic en «Regenerar todo» en Temas para aplicar el cambio a todas las páginas publicadas y a robots.txt."},flexweg:{title:"API de Flexweg",apiKey:"Clave API",apiKeyHelp:"Generada desde tu cuenta Flexweg → API.",siteUrl:"URL del sitio",siteUrlHelp:"URL pública de tu sitio Flexweg sin barra final.",apiBaseUrl:"URL base de la API",storageHelpFirebase:"Almacenada en Firestore (config/flexweg). Lectura para cualquier miembro con sesión iniciada, escritura solo para administradores.",storageHelpSqlite:"Almacenada en la tabla SQLite local config. Lectura para cualquier miembro con sesión iniciada, escritura solo para administradores."},backend:{title:"Backend de datos",active:"Backend activo:",switchButton:"Cambiar de backend…",confirmTitle:"Se perderán todos los datos actuales.",confirmBody:"Cambiar borra la configuración del navegador y recarga el formulario de configuración. El nuevo backend empieza vacío — los datos del backend anterior siguen donde estaban (en Firestore o como un archivo .sqlite en Flexweg), pero el CMS no los leerá hasta que vuelvas a cambiar.",confirmYes:"Sí, cambiar de backend",downloadBackup:"Descargar una copia de seguridad del archivo .sqlite",downloadBackupHelp:"hazlo antes de cambiar de backend.",markdownGit:"Markdown — {{source}}",localFolder:"carpeta local",localBrowser:"Este navegador (local, un solo usuario)",sqliteFile:"Archivo SQLite — {{location}}"},performance:{title:"Rendimiento",help:"Cómo el admin carga entradas y páginas. El modo por defecto funciona en el plan gratuito de Firestore sin configuración; el modo paginado es para sitios muy grandes y requiere crear índices una vez.",mode:"Modo de carga",modeGlobal:"Estándar (sin configuración)",modePaginated:"Paginación del servidor (requiere índices de Firestore)",globalHelp:"Carga toda la colección de entradas en una suscripción en vivo. Orden, filtros y búsqueda se hacen en memoria. Recomendado para sitios con menos de ~5 000 entradas.",paginatedHelp:"Suscripciones paginadas por cursor, una página a la vez. Requiere índices compuestos de Firestore — ver README. Recomendado para sitios muy grandes.",savedReload:"Guardado. Recarga el admin para aplicar el nuevo modo."},editor:{title:"Editor",help:"Tipografía usada dentro del editor de entradas/páginas. Independiente del tema público.",fontFamily:"Familia tipográfica",bodySize:"Tamaño del cuerpo",h1Size:"Tamaño H1",h2Size:"Tamaño H2",h3Size:"Tamaño H3",sizeHelp:"Longitud CSS, p. ej. 16px o 1rem. Deja vacío para el valor por defecto.",reset:"Restablecer valores predeterminados"},profile:{title:"Perfil",adminLocale:"Idioma del admin",adminLocaleHelp:"Idioma usado por la interfaz de administración. Guardado en tu perfil.",firstName:"Nombre",lastName:"Apellido",headline:"Título",headlinePlaceholder:"p. ej. Periodista, Redactor jefe…",headlineHelp:"Se muestra públicamente bajo tu nombre en las tarjetas de autor y en tu página de archivo.",bio:"Biografía",bioPlaceholder:"Un párrafo corto que se muestra en tu página de autor y debajo de tus artículos.",bioHelp:"Visible en el sitio público en la barra lateral de autor y en la página de archivo del autor.",socials:"Perfiles sociales",socialsHelp:"Añade las URL de los perfiles que quieres mostrar en el sitio público y marca «Mostrar» para los que deben ser visibles. Las URL vacías se ignoran.",socialsShow:"Mostrar",socialsShowHelp:"Activa la visibilidad de esta red en el sitio público.",avatar:"Foto de perfil",avatarHelp:"Elige una imagen de tu biblioteca de medios. Las imágenes cuadradas se muestran mejor.",pickAvatar:"Elegir de medios",changeAvatar:"Cambiar foto",removeAvatar:"Eliminar",save:"Guardar perfil"},transfer:{title:"Mover o hacer copia de seguridad del contenido",help:"Exporta todo (entradas, páginas, categorías, metadatos de medios, perfiles, ajustes) en un único archivo JSON. En un backend Markdown o local puedes importar ese archivo conservando los ids — así se migra desde Firebase o SQLite. Los archivos de medios y las claves secretas no se incluyen.",export:"Exportar el contenido (JSON)",import:"Importar contenido…",modeMerge:"Combinar (sobrescribe los mismos ids)",modeReplace:"Reemplazar las colecciones importadas",replaceConfirm:"El modo Reemplazar elimina todos los elementos existentes de las colecciones presentes en el archivo antes de importar. ¿Continuar?",invalidFile:"Este archivo no es una exportación de contenido de Flexweg CMS.",imported:"Se han importado {{posts}} entradas/páginas, {{terms}} términos y {{media}} medios. Ejecuta Regenerar → Todo para publicarlos."},encryption:{title:"Cifrado de la base:",on:"activado",off:"desactivado",onHelp:"El archivo de la base es ilegible sin la frase de contraseña. Cambiarla vuelve a guardar el archivo con una nueva clave; los demás navegadores pedirán la nueva frase.",offHelp:"Cualquiera que pueda descargar el archivo de la base puede leerlo (un hosting estático lo sirve como cualquier página). Cífralo con una frase de contraseña.",enable:"Cifrar la base…",change:"Cambiar la frase de contraseña…",savedConfirm:"He guardado esta frase en mi gestor de contraseñas — sin ella no se puede abrir el contenido.",enableConfirm:"Cifrar ahora",changeConfirm:"Cambiar la frase",done:"Base guardada de nuevo con la nueva frase de contraseña."}},Wre={title:"Usuarios",noUsers:"Aún no hay usuarios.",role:"Rol",disabled:"Deshabilitado",editProfileTitle:"Editar perfil — {{email}}",profileSaved:"Perfil guardado.",descriptionFirebase:"Gestiona tu equipo. Las nuevas cuentas se crean en la Firebase Console y se replican aquí en el primer inicio de sesión.",descriptionSqlite:"Gestiona tu equipo. Usa el botón +Añadir usuario más abajo para crear cuentas directamente.",addUser:"Añadir usuario",addUserSuccess:"{{email}} añadido.",removeConfirmFirebase:"¿Eliminar la ficha de {{email}}? Se quita su perfil y rol del CMS. Para revocar el acceso, elimina además la cuenta en la Firebase Console.",removeConfirmSqlite:"¿Eliminar permanentemente a {{email}}? Se revoca su acceso Y se quitan su perfil y rol. Esta acción no se puede deshacer.",empty:{title:"Aún no hay miembros del equipo",descriptionFirebase:"Crea la primera cuenta en la Firebase Console y luego inicia sesión aquí una vez para registrar el perfil.",descriptionSqlite:"Pulsa +Añadir usuario arriba para invitar al primer miembro."},help:{title:"Cómo añadir un nuevo miembro al equipo",bootstrapLine:"El admin inicial (siempre con acceso total) es:",firebase:{step1:"Abre la Firebase Console → Authentication → Add user.",step2:"Pon un correo y una contraseña y envíalos al nuevo miembro.",step3:"Pídele que inicie sesión aquí una vez — su perfil aparece en la lista de arriba y puedes editar su rol y sus datos."},sqlite:{step1:"Pulsa el botón +Añadir usuario de arriba.",step2:"Introduce su correo y una contraseña temporal (8+ caracteres).",step3:"Comparte las credenciales de forma segura — podrá cambiar la contraseña desde su perfil una vez iniciada la sesión."},git:{step1:"Añade a la persona como colaboradora del repositorio de contenido (escritura = editor, admin / maintainer = admin).",step2:"La persona crea su propio token de acceso personal en GitHub / GitLab.",step3:"Abre el admin e inicia sesión con ese token — su perfil se crea aquí automáticamente."}},addUserModal:{title:"Añadir un nuevo miembro del equipo",intro:"Crea la cuenta directamente en la base de datos Flexweg SQLite Auth. El nuevo usuario tiene rol de editor por defecto; promociónalo desde la lista de abajo si necesita acceso de admin.",submit:"Crear usuario",submitting:"Creando…"},actions:{editProfile:"Editar perfil",promote:"Promover a administrador",demote:"Degradar a editor",disable:"Deshabilitar",enable:"Habilitar",delete:"Eliminar registro"},descriptionGit:"Los miembros del equipo son las personas con acceso de escritura al repositorio de contenido. Aparecen aquí tras su primer inicio de sesión; su rol sigue sus permisos en el repositorio.",descriptionLocal:"Este admin funciona en modo de un solo usuario: el contenido se guarda en este navegador y no hay cuentas.",descriptionSqliteFile:"Sin cuentas de usuario con este backend: cualquiera que pueda abrir el admin puede editar. Protege la carpeta del admin desde tu alojamiento. Los perfiles de autor de abajo son informativos."},Gre={title:"Configuración de Firestore necesaria",intro:"Las páginas de listado de entradas y páginas necesitan algunos índices compuestos de Firestore para consultar eficientemente. Deben crearse manualmente — Firebase reserva la creación de índices a los administradores del proyecto.",checking:"Verificando tus índices Firestore…",missingCount_one:"{{count}} índice falta:",missingCount_other:"{{count}} índices faltan:",openConsole:"Abrir Firebase Console para crear",noUrl:"No se pudo extraer la URL de autosugerencia — consulta el README para el comando gcloud.",howItWorks:"Cómo funciona",step1:"Haz clic en el enlace de cada índice faltante — Firebase Console se abre con la definición pre-rellenada.",step2:"Pulsa «Create» y espera 1–5 minutos a que el índice se construya (estado en la consola).",step3:"Vuelve aquí y pulsa Reintentar. Cuando ambas consultas tengan éxito, el admin se carga.",retry:"Reintentar",retrying:"Reintentando…",buildHint:"Los índices pueden tardar unos minutos en construirse tras la creación.",allReady:"Todos los índices están listos.",unexpectedTitle:"No se puede acceder a Firestore",unexpectedHint:"Verifica tu conexión y las reglas de Firestore. Si acabas de crear los índices, espera a que terminen y reintenta."},Kre={appError:"Error de la aplicación",loadAccountFailed:"No se pudo cargar tu cuenta",loadAccountHint:"Si el problema persiste, cierra sesión e inténtalo de nuevo.",accountDisabled:"Cuenta deshabilitada",accountDisabledMessage:"Tu acceso a este CMS ha sido deshabilitado. Contacta con tu administrador.",firebaseNotConfigured:"Firebase no está configurado",firebaseEnvMissing:`Faltan las siguientes variables de entorno:
|
|
3856
|
+
Kopieren Sie .env.example nach .env, tragen Sie Ihre Firebase-Projektdaten ein und starten Sie den Dev-Server neu.`,adminEmailNotConfigured:"Admin-E-Mail ist nicht konfiguriert",adminEmailMessage:"VITE_ADMIN_EMAIL fehlt in .env. Setzen Sie sie auf die E-Mail-Adresse des Bootstrap-Administrators.",consoleHint:"Überprüfen Sie die Browser-Konsole und Ihre .env-Konfiguration. Siehe README für Setup-Anweisungen."},kre={brandTitle:"AgentCMS",brandSubtitle:"Statischer Publisher",login:{heading:"Anmelden",intro:"Verwenden Sie die E-Mail-Adresse und das Passwort, die Ihr Administrator Ihnen mitgeteilt hat.",submit:"Anmelden",submitting:"Anmeldung läuft…"},fields:{name:"Anzeigename (optional)",namePlaceholder:"Erika Mustermann",email:"E-Mail",password:"Passwort",passwordHint:"Mindestens 8 Zeichen."},footer:"Neue Konten werden von einem Administrator über die Benutzerseite angelegt.",errors:{invalidEmail:"Bitte geben Sie eine gültige E-Mail-Adresse ein.",missingPassword:"Passwort ist erforderlich.",passwordTooShort:"Das Passwort muss mindestens 8 Zeichen lang sein."}},Sre=JSON.parse('{"title":"Willkommen bei AgentCMS","subtitle":"Erstkonfiguration","intro":"Geben Sie Ihre Firebase-Zugangsdaten, das Bootstrap-Administratorkonto und Ihren Flexweg-API-Schlüssel ein. Die Werte werden geprüft, in Ihrem Projekt gespeichert (Firestore + eine config.js-Datei auf Flexweg), und die Admin-Oberfläche lädt im normalen Anmeldeablauf neu. Sie machen das nur einmal.","introFirebase":"Schritt 1 — Firebase. Geben Sie Ihre Firebase-Projektdaten und das Bootstrap-Administratorkonto ein. Wir melden Sie an, prüfen die E-Mail und ob Ihre Firestore-Regeln diesen Admin pinnen, bevor wir zum Flexweg-Schritt weitergehen.","introFlexweg":"Schritt 2 — Flexweg. Geben Sie Ihren Flexweg-API-Schlüssel und die Site-URL ein. Wir testen die API, speichern die Konfiguration in Firestore, laden config.js auf Ihre Site hoch und synchronisieren die Theme-Assets.","continueToFlexweg":"Firebase prüfen und fortfahren","stepper":{"terms":"AGB","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Inhalte & Veröffentlichung","data":"Daten","hosting":"Hosting","install":"Installation"},"backend":{"title":"Daten-Backend wählen","intro":"Wählen Sie, wo das CMS Ihre Beiträge, Seiten, Benutzer und Einstellungen speichert. Sie können später über die Einstellungen wechseln (Daten werden nicht migriert).","sqliteTitle":"Flexweg SQLite (empfohlen)","sqliteHint":"Alle Daten verbleiben auf Ihrer Flexweg-Site als SQLite-Datei. Kein externer Dienst. Auth wird von der Flexweg SQLite-API bereitgestellt.","firebaseTitle":"Firebase","firebaseHint":"Verwenden Sie ein Firebase-Projekt für Firestore + Auth. Kostenlos im Spark-Plan. Echtzeit-Updates per onSnapshot.","continue":"Weiter","markdownGitTitle":"Markdown-Dateien in einem Git-Repository","markdownGitHint":"Beiträge als .md-Dateien auf GitHub / GitLab (oder in einem lokalen Klon). Jeder Redakteur meldet sich mit seinem eigenen Zugriffstoken an; jede Änderung ist ein Commit. Keine Datenbank, funktioniert mit mehreren Redakteuren und Rechnern.","localTitle":"Nur dieser Browser","localHint":"Ein Benutzer, keine Anmeldung, nichts einzurichten. Inhalte bleiben in diesem Browser (Export über die Einstellungen). Ideal für einen Admin, der auf Ihrem eigenen Computer läuft."},"sqlite":{"heading":"Verbinden Sie Ihre Flexweg-Site","intro":"Wir verwenden Ihren Flexweg-Master-API-Schlüssel EINMAL, um ein Token mit eingeschränktem Geltungsbereich für die SQLite-Datenbank zu erzeugen. Nach der Installation wird der Master-Schlüssel verworfen und nur das beschränkte Token (auf diese eine SQLite-Datei begrenzt) gespeichert.","apiKeyHint":"Flexweg-Master-API-Schlüssel. Wird nur zur Installation verwendet — danach nie gespeichert.","detectedFromUrl":"Aus URL erkannt","advanced":"Erweiterte Einstellungen (Site-URL, SQLite-Pfad…)","pathHint":"Wo die SQLite-Datei auf Ihrer Flexweg-Site liegt. Ordner werden automatisch erstellt.","adminHeading":"Administratorkonto","adminIntro":"Legen Sie den ersten Benutzer an — dieses Konto erhält automatisch Admin-Rechte. Weitere Mitglieder werden nach der Anmeldung über die Benutzerseite onboardet.","passwordHint":"Mindestens 8 Zeichen.","submit":"SQLite-Datenbank installieren"},"terms":{"title":"Nutzungsbedingungen","intro":"Bitte lesen und akzeptieren Sie die folgenden Bedingungen, bevor Sie AgentCMS verwenden. Sie sind in einfacher Sprache verfasst, um schnell lesbar zu sein.","section1":{"title":"1. Kostenloser Service","body":"AgentCMS wird Ihnen von Flexweg kostenlos zur Verfügung gestellt. Sie können es ohne Einschränkungen mit Ihrem Flexweg-Hosting nutzen — Flexweg wird Ihnen die Nutzung des CMS selbst niemals in Rechnung stellen. Die üblichen Gebühren Ihres Flexweg-Hosting-Plans und Ihres Firebase-Plans bleiben weiterhin anwendbar, jeweils auf dem entsprechenden Konto."},"section2":{"title":"2. Bereitstellung „wie besehen“, ohne Garantie","body":"Das CMS wird wie besehen bereitgestellt. Wir arbeiten daran, es stabil zu halten und im Laufe der Zeit zu verbessern, können jedoch nicht garantieren, dass es frei von Bugs, Mängeln oder Unterbrechungen ist. Verwenden Sie es mit derselben Vorsicht wie bei jedem Tool, das Sie nicht selbst geschrieben haben: Bewahren Sie Backups wichtiger Inhalte auf."},"section3":{"title":"3. Ihre Inhalte, Ihre Verantwortung","body":"Sie sind allein verantwortlich für die Inhalte, die Sie über das CMS veröffentlichen — Texte, Bilder, Videos, Formulare, Code-Einbettungen und alle anderen Medien. Sie müssen das anwendbare Recht in Ihrer Jurisdiktion (und in den von Ihnen anvisierten Jurisdiktionen) einhalten, ebenso wie Urheberrechte, Bild- und Persönlichkeitsrechte, Datenschutzbestimmungen sowie die Bedingungen jeglicher Drittanbieterdienste (z. B. eingebettete Schriften oder Videos). Flexweg ist nicht verantwortlich für die von den Nutzern des CMS veröffentlichten Inhalte."},"section4":{"title":"4. Ihr Firebase-Konto, Ihre Sicherheit","body":"Das CMS speichert seine Daten in Ihrem eigenen Firebase-Projekt. Sie sind für die Sicherheit dieses Projekts verantwortlich: Wählen Sie ein starkes Passwort für das Bootstrap-Administratorkonto, konfigurieren Sie die Firestore-Sicherheitsregeln wie dokumentiert, rotieren Sie Ihre API-Schlüssel bei Bedarf und prüfen Sie, wer Zugriff hat. Flexweg kann in keinem Fall für unbefugten Zugriff, Datenlecks, Hacks oder Verluste haftbar gemacht werden, die durch Fehlkonfiguration oder Kompromittierung Ihres Firebase-Kontos entstehen."},"section5":{"title":"5. Haftungsbeschränkung","body":"Flexweg kann nicht haftbar gemacht werden für Einnahmeverluste, Datenverluste, entgangene Geschäftsmöglichkeiten oder direkte oder indirekte Schäden, die aus der Nutzung, dem Missbrauch oder der Nichtverfügbarkeit des CMS entstehen. Soweit das anwendbare Recht eine Haftung von Flexweg vorschreibt, ist diese auf den Betrag beschränkt, der tatsächlich in den letzten 12 Monaten an Flexweg für das CMS gezahlt wurde — also null, da das CMS kostenlos ist."},"section6":{"title":"6. Ihre Daten bleiben bei Ihnen","body":"Inhalte, die Sie mit dem CMS erstellen, werden in Ihrem eigenen Firebase-Projekt (Texte, Einstellungen, Medienmetadaten) und auf Ihrem eigenen Flexweg-Hosting (veröffentlichtes HTML, Bilder, Theme-Assets) gespeichert. Das CMS selbst übermittelt Ihre Inhalte an keinen Drittanbieterdienst. Plugins oder Themes, die Sie aktivieren, können ihr eigenes Verhalten haben — prüfen Sie, was sie tun, bevor Sie sie aktivieren."},"section7":{"title":"7. Faire Nutzung","body":"Die Nutzung des CMS für rechtswidrige, betrügerische oder schädliche Aktivitäten oder auf eine Weise, die gegen die allgemeinen Nutzungsbedingungen von Flexweg verstößt, kann zur Sperrung Ihres Zugriffs auf das Flexweg-Hosting führen. Wir können diese CMS-Bedingungen auch im Laufe der Zeit aktualisieren; wesentliche Änderungen werden über das Admin-Panel oder per E-Mail kommuniziert."},"accept":"Ich habe die Nutzungsbedingungen gelesen und akzeptiere sie.","continue":"Weiter zur Konfiguration","back":"Zurück"},"sections":{"firebase":"Firebase","admin":"Bootstrap-Administrator","flexweg":"Flexweg-API"},"help":{"firebase":"Diese Werte finden Sie in Firebase Console → Projekteinstellungen → Allgemein → Ihre Apps → SDK-Setup und Konfiguration.","admin":"Verwenden Sie einen vorhandenen Benutzer aus Firebase Authentication. Wer sich mit dieser E-Mail anmeldet, wird als Administrator behandelt und umgeht die Benutzerdatensatz-Prüfung. Erstellen Sie den Benutzer bei Bedarf über Firebase Console → Authentication.","flexweg":"Erstellen Sie einen permanenten API-Schlüssel in Ihrem Flexweg-Konto → API. Die Site-URL ist die öffentliche Adresse Ihrer Flexweg-Site (z. B. https://ihre-site.flexweg.com).","flexwegApiKeyHint":"Ihren API-Schlüssel finden Sie in Ihren Flexweg-Kontoeinstellungen.","flexwegApiKeyLink":"Kontoeinstellungen öffnen"},"fields":{"apiKey":"API-Schlüssel","authDomain":"Auth-Domain","projectId":"Projekt-ID","storageBucket":"Storage-Bucket","messagingSenderId":"Messaging-Absender-ID","appId":"App-ID","adminEmail":"E-Mail","adminPassword":"Passwort","flexwegApiKey":"API-Schlüssel","flexwegSiteUrl":"Site-URL","flexwegApiBaseUrl":"API-Basis-URL","sqlitePath":"SQLite-Pfad"},"submit":"Speichern und fortfahren","submitting":"Konfiguration läuft…","success":"Setup abgeschlossen!","reloadingHint":"Die Admin-Oberfläche wird gleich neu geladen — bitte warten.","footer":"Diese Werte werden in Ihrem Projekt gespeichert (Firestore + Flexweg). Sie werden nirgendwo anders gesendet.","steps":{"signInFirebase":"Anmeldung bei Firebase…","testFlexweg":"Flexweg-API wird getestet…","writeFirestore":"Konfiguration wird gespeichert…","uploadConfig":"config.js wird zu Flexweg hochgeladen…","syncThemes":"Theme-Assets werden zu Flexweg synchronisiert…","sqliteInstall":"Beschränktes SQLite-Token wird erstellt…","sqliteRegisterAdmin":"Admin-Konto wird registriert…","sqliteSchema":"SQLite-Schema wird initialisiert…"},"stepsDone":{"sqliteInstall":"Beschränktes SQLite-Token ausgestellt","sqliteRegisterAdmin":"Admin registriert und angemeldet","sqliteSchema":"SQLite-Schema bereit"},"errors":{"missingFields":"Bitte füllen Sie alle Felder aus.","rootDeploymentTitle":"Die Admin-Oberfläche muss in einem Unterordner liegen, nicht im Stammverzeichnis der Site.","rootDeploymentHint":"Verschieben Sie die Admin-Dateien (index.html, config.js, runtime/, …) in einen Unterordner auf Flexweg — zum Beispiel /admin/ oder einen zufälligen Namen wie /erf34f654GH3/ aus Tarngründen. Laden Sie die Admin-Oberfläche dann von der URL des Unterordners neu und führen Sie das Setup erneut aus.","firebaseAuthGeneric":"Anmeldung bei Firebase fehlgeschlagen.","firebaseAuthInvalidCredential":"Firebase hat die Kombination aus E-Mail und Passwort abgelehnt.","firebaseAuthInvalidCredentialHint":"Neuere Firebase-Projekte aktivieren standardmäßig den Schutz vor E-Mail-Aufzählung, der denselben Fehler zurückgibt, egal ob das Passwort falsch ist, der Benutzer nicht existiert oder sich mit einem anderen Anbieter anmeldet. Zu prüfen:\\n• Geben Sie das Passwort erneut ein — kopieren/einfügen aus einem Passwortmanager, um Tippfehler auszuschließen. Mindestlänge sind 6 Zeichen.\\n• Öffnen Sie Firebase Console → Authentication → Users und bestätigen Sie, dass die E-Mail existiert. Prüfen Sie die Spalte „Providers“: Wird nur Google (oder ein anderer Anbieter) ohne „Email/Password“ angezeigt, setzen oder zurücksetzen Sie das Passwort über das Zeilenmenü (⋮ → Passwort zurücksetzen).\\n• Prüfen Sie, dass die Schreibweise der E-Mail exakt mit dem in Firebase gespeicherten Wert übereinstimmt.","firebaseAuthUserNotFound":"Kein Firebase-Benutzer mit dieser E-Mail. Legen Sie zunächst einen in Firebase Console → Authentication → Users an.","firebaseAuthInvalidEmail":"Die Admin-E-Mail ist keine gültige E-Mail-Adresse.","firebaseInvalidApiKey":"Der Firebase-API-Schlüssel ist ungültig. Prüfen Sie den Wert in der Firebase Console.","firebaseNetwork":"Netzwerkfehler bei der Anmeldung bei Firebase. Prüfen Sie Ihre Verbindung.","firebaseTooManyRequests":"Zu viele Anmeldeversuche. Bitte versuchen Sie es später erneut oder setzen Sie das Passwort über Firebase Console zurück.","firebaseOperationNotAllowed":"Die Anmeldung per E-Mail/Passwort ist in diesem Firebase-Projekt nicht aktiviert. Öffnen Sie Firebase Console → Authentication → Sign-in method und aktivieren Sie den Email/Password-Anbieter.","firebaseUserDisabled":"Dieses Firebase-Benutzerkonto ist deaktiviert. Aktivieren Sie es über Firebase Console → Authentication → Users wieder.","wrongAdminEmail":"Das Firebase-Konto, mit dem Sie sich angemeldet haben, stimmt nicht mit der eingegebenen Admin-E-Mail überein. Bitte erneut versuchen.","rulesNotPinnedTitle":"Die Firestore-Regeln erkennen Sie noch nicht als Bootstrap-Admin.","rulesNotPinnedHint":"Öffnen Sie Firebase Console → Firestore → Rules und ersetzen Sie den Wert von `bootstrapAdminEmail()` durch: {{email}} — klicken Sie dann auf Veröffentlichen. Die Regelvorlage im README enthält einen Platzhalter `you@example.com`, der durch Ihre tatsächliche Admin-E-Mail ersetzt werden muss. Nachdem die aktualisierten Regeln veröffentlicht sind, klicken Sie hier erneut auf Absenden.","flexwegAuth":"Flexweg-API-Schlüssel abgelehnt. Prüfen Sie den Wert in Ihrem Flexweg-Konto → API.","flexwegNetwork":"Netzwerkfehler beim Kontakt mit Flexweg. Prüfen Sie die API-Basis-URL und Ihre Verbindung.","flexwegHttp":"Flexweg-API-Fehler ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore hat das Schreiben der Konfiguration abgelehnt.","firestoreRulesHint":"Öffnen Sie Firebase Console → Firestore → Regeln und stellen Sie sicher, dass die Bootstrap-Admin-E-Mail auf \'{{email}}\' gesetzt ist. Im README finden Sie eine kopierfertige Regelvorlage.","firestoreOther":"Firestore-Schreibvorgang fehlgeschlagen","uploadFailed":"config.js konnte nicht zu Flexweg hochgeladen werden","generic":"Etwas ist schiefgelaufen."},"docstore":{"contentTitle":"Content-Repository","contentIntro":"Hier werden Ihre Beiträge, Seiten und Einstellungen als Markdown- + JSON-Dateien gespeichert. Ein leeres Repository ist in Ordnung — das CMS legt die Dateien an.","provider":"Repository","localClone":"Lokaler Ordner (git-Klon)","localCloneHint":"Wählen Sie den Ordner Ihres Klons. Synchronisieren Sie ihn mit Ihrem gewohnten git-Client — das CMS liest und schreibt Dateien, es führt kein git aus.","contentDir":"Inhaltsordner im Repository","privateRepo":"Verwenden Sie ein privates Repository: Entwürfe werden dort gespeichert.","folderRequired":"Wählen Sie zuerst den Inhaltsordner.","checking":"Repository-Zugriff wird geprüft…","publishIntro":"Wohin die generierte Website veröffentlicht wird. Sie können dies später in den Einstellungen ändern.","existingSite":"Dieses Repository ist bereits eingerichtet — die Website wird weiterhin veröffentlicht nach: {{target}}. Sie können dies später in den Einstellungen ändern (eventuelle geheime Schlüssel müssen dort erneut eingegeben werden).","install":"Installieren","steps":{"config":"Konfiguration wird gespeichert…","content":"Inhalte werden geladen…","target":"Veröffentlichungsziel wird gespeichert…","testTarget":"Veröffentlichungsziel wird getestet…"},"doneTitle":"Alles bereit!","doneBody":"Die Konfiguration ist in diesem Browser gespeichert. Um anderen Redakteuren diese Einrichtung zu ersparen, laden Sie config.js herunter und ersetzen Sie die Datei im Admin-Ordner Ihres Hostings.","downloadConfig":"config.js herunterladen","open":"Admin öffnen","footer":"Die Inhalte bleiben in Ihrem Repository oder in diesem Browser; Zugriffstoken verlassen diesen Browser nie."},"data":{"title":"1. Wo speichern Sie Ihre Daten?","intro":"Ihre Beiträge, Seiten, Benutzer und Einstellungen — die eigenen Daten des Admins. Dies ist unabhängig davon, wo die öffentliche Website gehostet wird (nächster Schritt).","localNote":"Nichts zu konfigurieren: Die Inhalte werden in diesem Browser gespeichert. Exportieren Sie sie in den Einstellungen, um sie zu sichern oder später umzuziehen.","options":{"sqlite-file":{"title":"SQLite","hint":"Eine SQLite-Datenbank, gespeichert auf dem Hosting, das Sie im nächsten Schritt wählen (Flexweg, Ihr Server, S3, Git…). Ohne Benutzerkonten — oder der SQLite-Dienst von Flexweg mit Konten, wenn Sie bei Flexweg hosten."},"flexweg-sqlite":{"title":"SQLite (Flexweg-Dienst)","hint":"Eine SQLite-Datenbank, betrieben vom Flexweg-Dienst, mit integrierten Benutzerkonten. Erfordert ein Flexweg-Konto, unabhängig davon, wo die Website gehostet wird."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth in Ihrem Google-Projekt. Echtzeit, kostenloser Spark-Tarif."},"markdown-git":{"title":"Markdown-Dateien in Git","hint":"Beiträge als .md-Dateien in einem GitHub- / GitLab-Repository (oder einem lokalen Klon). Jeder Redakteur verwendet sein eigenes Token; jede Änderung ist ein Commit."},"local":{"title":"Dieser Browser","hint":"Ein Benutzer, keine Anmeldung, nichts einzurichten. Ideal für einen Admin, der auf Ihrem Computer läuft."}}},"hosting":{"title":"2. Wo wird die Website veröffentlicht?","intro":"Wohin die generierte statische Website (HTML, CSS, Bilder) bei jeder Veröffentlichung hochgeladen wird. Sie können dies später in den Einstellungen ändern.","existing":"Dieses Content-Repository veröffentlicht bereits auf das untenstehende Ziel. Behalten Sie es oder wählen Sie ein anderes."},"install":{"title":"3. Installation","intro":"Prüfen Sie die Zusammenfassung und installieren Sie dann.","data":"Daten","hosting":"Hosting","saveTarget":"Veröffentlichungsziel wird gespeichert…","noteConfigJs":"Die Admin-Konfiguration (config.js) wird nach Möglichkeit neben den Admin auf Flexweg hochgeladen; andernfalls wird Ihnen angeboten, sie herunterzuladen.","noteLocalConfig":"Die Konfiguration wird in diesem Browser gespeichert; Ihnen wird config.js zum Ablegen im Admin-Ordner angeboten, damit andere Redakteure diese Einrichtung überspringen."},"sqliteFile":{"security":"Keine Benutzerkonten: Wer dieses Admin öffnen kann, kann den Inhalt bearbeiten — schütze den Admin-Ordner auf Ebene deines Hostings. Die Datenbankdatei wird wie jede andere Datei ausgeliefert: Halte sie verschlüsselt oder speichere sie an einem separaten privaten Ort.","intro":"Wo die Datenbankdatei gespeichert wird. Dieser Admin liest und speichert sie über dieselben Konnektoren wie das Hosting.","path":"Pfad der Datenbankdatei","pathHint":"Wird beim ersten Speichern angelegt, falls sie noch nicht existiert. Bei einem Git-Repository ist jedes Speichern ein Commit — verwenden Sie besser ein Repository oder einen Branch, der keinen Website-Build auslöst.","existing":"bestehende Datenbank","new":"neue Datenbank","dataNote":"Hier ist nichts zu konfigurieren: Die Datenbank wird auf dem Hosting gespeichert, das Sie im nächsten Schritt wählen.","heading":"SQLite-Datenbank","flexwegService":"Den SQLite-Dienst von Flexweg verwenden","flexwegServiceHint":"Die Datenbank wird von Flexweg betrieben und bringt integrierte Benutzerkonten mit (E-Mail + Passwort). Andernfalls ist sie eine einfache Datei auf diesem Hosting, ohne Konten.","summaryFile":"Datei {{path}} auf diesem Hosting","summaryService":"SQLite-Dienst von Flexweg ({{path}})","encrypt":"Datenbank verschlüsseln","encryptHint":"Empfohlen bei öffentlichem Hosting: Ohne Passphrase ist die Datei unlesbar. Jeder neue Browser fragt einmal danach.","passphrase":"Passphrase","passphraseHint":"Speichere sie jetzt in deinem Passwort-Manager: Ohne sie kann niemand die Datenbank öffnen — auch du nicht.","copy":"Kopieren","copied":"Kopiert","generate":"Neu","passphraseTooShort":"Die Passphrase muss mindestens 12 Zeichen lang sein.","existingEncrypted":"An diesem Pfad gibt es bereits eine verschlüsselte Datenbank: Gib ihre Passphrase ein.","separate":"Datenbank an einem separaten privaten Ort speichern","separateHint":"Z. B. ein privater S3- / R2-Bucket oder ein privates Git-Repository: Die Datenbank wird dann nie von der öffentlichen Website ausgeliefert.","summaryEncrypted":"verschlüsselt","summaryLocation":"gespeichert in {{location}}","locationLabel":"Speicherort der Datenbank","gitBranchNote":"Die Datenbank liegt im Branch {{branch}} dieses Repositorys, der nie veröffentlicht wird: Speichern von Inhalten baut die Website nicht neu.","summaryBranch":"im Branch {{branch}}"},"adminHosting":{"deploying":"Admin wird auf die Website kopiert…","label":"Admin auch auf dieser Website hosten","hint":"Der Admin wird mit seiner config.js (ohne Geheimnisse) nach {{url}} kopiert — jeder Redakteur kann ihn dann dort öffnen. Jeder Redakteur meldet sich weiterhin mit seinem eigenen Zugang an.","folder":"Admin-Ordner","alreadyHere":"Dieser Admin läuft bereits von dieser Website aus: Seine config.js wird direkt aktualisiert.","doneBody":"Der Admin ist jetzt auf Ihrer Website. Aktivieren Sie bei GitHub Pages zuerst Pages für das Repository, falls noch nicht geschehen (Settings → Pages), und öffnen Sie ihn dann:","open":"Online-Admin öffnen","continueHere":"In diesem Admin fortfahren"}}'),Ere={actions:{upload:"Datei wird hochgeladen",delete:"Datei wird gelöscht",rename:"Datei wird umbenannt",get:"Datei wird gelesen",list:"Dateien werden aufgelistet",createFolder:"Ordner wird erstellt",renameFolder:"Ordner wird umbenannt",deleteFolder:"Ordner wird gelöscht",storageLimits:"Speichergrenzen werden abgerufen",commit:"Änderungen veröffentlichen"},errors:{configMissing:"Das Veröffentlichungsziel ist nicht konfiguriert. Richten Sie es vor dem Veröffentlichen in den Einstellungen ein.",network:"{{action}}: Netzwerkfehler oder CORS blockiert. Überprüfen Sie Ihre Verbindung.",auth:"{{action}}: Authentifizierung fehlgeschlagen. Prüfen Sie die Zugangsdaten des Veröffentlichungsziels in den Einstellungen.",notFound:"{{action}}: Ziel auf dem Veröffentlichungsziel nicht gefunden.",tooLarge:"{{action}}: Datei zu groß für das Veröffentlichungsziel.",rateLimited:"{{action}}: Zu viele Anfragen, bitte in Kürze erneut versuchen.",serverError:"{{action}}: Serverfehler des Veröffentlichungsziels ({{status}}). Bitte erneut versuchen.",generic:"{{action}} fehlgeschlagen ({{status}}){{detail}}.",unsupported:"{{action}}: wird vom Veröffentlichungsziel „{{connector}}“ nicht unterstützt.",unknownConnector:"Unbekanntes Veröffentlichungsziel „{{connector}}“. Prüfen Sie Einstellungen → Veröffentlichungsziel.",folderAccess:"Kein Zugriff auf den lokalen Ordner. Öffnen Sie Einstellungen → Veröffentlichungsziel und klicken Sie auf „Ordner neu verbinden“."}},_re={log:{rendering:"Seite wird gerendert…",uploading:"{{path}} wird hochgeladen…",deleting:"{{path}} wird gelöscht…",regenerating:"Listings werden neu generiert…",skipped:"{{path}} übersprungen (keine Änderungen)",done:"Veröffentlicht unter {{url}}",failed:"Fehlgeschlagen: {{error}}"}},Cre={errors:{notConnected:"Nicht mit dem Inhalts-Repository verbunden. Melden Sie sich erneut mit Ihrem Zugriffstoken an.",conflict:"Jemand anderes hat dieses Element inzwischen geändert. Seine Version wird jetzt angezeigt — wenden Sie Ihre Änderung erneut an.",sqliteUnsupported:"Das Ziel „{{connector}}“ kann keine Datenbankdatei speichern."}},Are={target:"Veröffentlichungsziel",settingsTitle:"Veröffentlichungsziel",settingsHelp:"Wohin die gerenderte Website beim Veröffentlichen hochgeladen wird. Zugangsdaten werden bei Ihrem Inhalts-Backend gespeichert (bzw. bei Git-Content-Repositorys in diesem Browser) und sind für alle Admins lesbar.",saved:"Veröffentlichungsziel gespeichert. Führen Sie Neu generieren → Alles aus, um die gesamte Website auf dem neuen Ziel zu veröffentlichen.",test:"Verbindung testen",testOk:"Verbindung OK",testFailed:"Verbindung fehlgeschlagen",names:{flexweg:"Flexweg","git-pages":"Git-Repository (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"S3-kompatibler Bucket (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Ihr eigener Server (PHP-Bridge)","browser-mirror":"Als ZIP herunterladen","local-folder":"Lokaler Ordner auf diesem Computer"},hints:{flexweg:"Upload über die Flexweg Files API.","git-pages":"Jede Veröffentlichung ist ein Commit im Repository; der Hoster baut die Website daraus neu.",s3:"Erfordert eine CORS-Regel auf dem Bucket, die den Origin dieses Admins zulässt, sowie Website-Hosting (oder ein CDN), um index.html-Dateien auszuliefern.","php-bridge":"Laden Sie external/bridges/php/flexweg-bridge.php auf Ihren Server hoch, legen Sie dessen API-Schlüssel fest und tragen Sie hier die URL ein.","browser-mirror":"Die Website wird in diesem Browser gespeichert; laden Sie das ZIP herunter und laden Sie es von Hand an beliebiger Stelle hoch.","local-folder":"Schreibt die Website direkt in einen Ordner (Chrome / Edge). Stellen Sie sie lokal bereit oder pushen Sie sie mit Ihren eigenen Tools."},fields:{flexweg:{apiKey:"API-Schlüssel",siteUrl:"Website-URL",apiBaseUrl:"API-Basis-URL"},"git-pages":{host:"Hosting",provider:"Git-Anbieter",owner:"Eigentümer (Benutzer oder Organisation)",repo:"Repository",project:"Projektpfad",branch:"Branch",dir:"Ordner im Repository",token:"Zugriffstoken",siteUrl:"Öffentliche Website-URL",apiBaseUrl:"API-URL (nur selbst gehostet)"},s3:{endpoint:"Endpoint",region:"Region",bucket:"Bucket",prefix:"Schlüsselpräfix (optional)",accessKeyId:"Access Key ID",secretAccessKey:"Geheimer Zugriffsschlüssel",siteUrl:"Öffentliche Website-URL",forcePathStyle:"Pfad-basierte URLs (MinIO, R2, die meisten kompatiblen Dienste)",publicRead:"Hochgeladene Dateien öffentlich machen (ACL public-read) — für Buckets, die nicht per Bucket-Policy öffentlich sind (OVHcloud, Scaleway…). Bei AWS-Buckets mit „Bucket owner enforced“ deaktiviert lassen."},"php-bridge":{apiBaseUrl:"Bridge-URL",apiKey:"API-Schlüssel der Bridge",siteUrl:"Öffentliche Website-URL"},"browser-mirror":{siteUrl:"Öffentliche Website-URL (optional)"},"local-folder":{siteUrl:"URL, unter der der Ordner bereitgestellt wird (optional)"}},help:{flexweg:{apiKey:"Wird in Ihrem Flexweg-Konto → API erzeugt."},"git-pages":{host:"Cloudflare Pages: Verbinden Sie das Projekt mit diesem Repository, ohne Build-Befehl und mit dem unten angegebenen Ausgabeordner. Funktioniert mit privaten Repositorys.",dir:'Leer lassen für das Stammverzeichnis des Repositorys. GitHub Pages: "" oder "docs". GitLab Pages: "public".',token:"Fine-grained Token für dieses Repository mit Contents: read & write (GitHub) — fügen Sie Pages: read & write hinzu, damit das CMS GitHub Pages aktivieren kann — oder ein Token mit dem Scope api (GitLab). Leer lassen, um das eigene Zugriffstoken jedes Redakteurs zu verwenden, wenn die Inhalte beim selben Anbieter liegen.",siteUrl:"z. B. https://user.github.io/repo — eine URL mit Unterordner ist in Ordnung, Links werden automatisch angepasst."},s3:{endpoint:"Für AWS leer lassen (wird aus der Region gebildet). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"Die Website-URL des Buckets oder Ihre CDN-Domain."},"php-bridge":{apiBaseUrl:"Die vollständige URL von flexweg-bridge.php auf Ihrem Server (HTTPS)."},"browser-mirror":{siteUrl:"Wohin Sie das ZIP hochladen werden — wird für absolute URLs verwendet (Sitemaps, RSS, Medien)."},"local-folder":{siteUrl:"z. B. http://localhost:8080, wenn ein lokaler Webserver den Ordner bereitstellt."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (mit dem Repository verbunden)","gitlab-pages":"GitLab Pages",other:"Andere (Netlify, Vercel, git pull auf dem Server…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Ordner wählen…",change:"Ordner ändern…",reconnect:"Ordner erneut verbinden",unsupported:"Dieser Browser kann nicht in lokale Ordner schreiben. Verwenden Sie Chrome oder Edge."},mirror:{download:"Website herunterladen (ZIP)",count:"{{count}} Dateien in diesem Browser"},adminHosting:{title:"Admin auf dieser Website",help:"Kopiert diesen Admin auf das Veröffentlichungsziel (Erstbereitstellung oder Aktualisierung nach einer neuen Version). Seine config.js enthält keine Geheimnisse.",deploy:"Admin bereitstellen / aktualisieren",deployed:"Admin bereitgestellt ({{count}} Dateien) — {{url}}"},pages:{enabled:"GitHub Pages für dieses Repository aktiviert — die Website ist in etwa einer Minute online.",enableHint:'Veröffentlichung erfolgreich. Um die Website online zu stellen, aktivieren Sie GitHub Pages für {{repo}}: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Oder geben Sie dem Token die Berechtigung "Pages: read and write", dann erledigt das CMS das für Sie.)'},siteUrl:{mismatch:"Die öffentliche URL der Website (Einstellungen → Website) ist {{site}}, aber dieses Ziel stellt die Website unter {{target}} bereit. Links, CSS und Sitemaps folgen der Website-URL — sie sind auf diesem Hosting falsch.",use:"{{url}} für die Website verwenden",updated:"Website-URL aktualisiert. Führen Sie Neu generieren → Alles aus, um die Seiten mit den neuen Links erneut zu veröffentlichen."}},Tre={heading:"Mit dem Content-Repository verbinden",tokenIntro:"Die Inhalte liegen im {{provider}}-Repository {{repo}}. Melden Sie sich mit Ihrem eigenen persönlichen Zugriffstoken an — Ihre Repository-Berechtigungen bestimmen Ihre Rolle (Schreibzugriff = Redakteur, Admin / Maintainer = Admin).",token:"Persönliches Zugriffstoken",tokenHelpGithub:"Fine-grained Token, nur Zugriff auf dieses Repository, Berechtigung Contents: Lesen und Schreiben.",tokenHelpGitlab:"Token mit dem api scope, Rolle Developer oder höher in diesem Projekt.",createToken:"Token erstellen",connect:"Verbinden",tokenStorage:"Das Token wird nur in diesem Browser gespeichert. Beim Abmelden wird es gelöscht.",failed:"Mit diesem Token kann nicht in das Repository geschrieben werden (ungültig, abgelaufen oder schreibgeschützt). Prüfen Sie seine Berechtigungen.",folderIntro:"Die Inhalte liegen in einem Ordner auf diesem Computer (in der Regel ein git-Klon, den Sie mit Ihrem eigenen git-Client synchronisieren). Gewähren Sie diesem Browser Zugriff darauf — Browser fragen nach jedem Neuladen erneut.",openFolder:"Inhaltsordner öffnen"},Ire={flexweg:{title:"Flexweg",short:"Flexweg-Hosting",hint:"Upload über die Flexweg Files API. API-Schlüssel aus Ihrem Flexweg-Konto."},"github-pages":{title:"GitHub Pages",short:"Kostenlos, aus einem GitHub-Repository",hint:"Jede Veröffentlichung ist ein Commit im Repository; GitHub Pages liefert es aus. Settings → Pages → Deploy from a branch. Öffentliche Repositories im kostenlosen Tarif."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Kostenlos, private Repositories möglich",hint:"Das CMS committet die Website in ein GitHub- / GitLab-Repository; verbinden Sie ein Cloudflare-Pages-Projekt damit (kein Build-Befehl, Ausgabeordner = der Ordner unten)."},"gitlab-pages":{title:"GitLab Pages",short:"Kostenlos, aus einem GitLab-Repository",hint:"Jede Veröffentlichung ist ein Commit; das CMS fügt eine minimale .gitlab-ci.yml hinzu, die den Ordner public/ veröffentlicht."},"git-other":{title:"Netlify, Vercel…",short:"Jeder Host, der ein Repository deployt",hint:"Das CMS committet die Website in ein Git-Repository; verbinden Sie Ihren Host (Netlify, Vercel, einen Server mit git pull…) mit diesem Repository."},s3:{title:"S3 / R2 / B2…",short:"Object-Storage-Bucket",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Erfordert eine CORS-Regel auf dem Bucket sowie Website-Hosting oder ein vorgeschaltetes CDN."},"own-server":{title:"Ihr eigener Server (FTP / SFTP)",short:"Shared Hosting, VPS…",hint:"Browser können kein FTP oder SFTP: Laden Sie die PHP-Bridge (external/bridges/php/flexweg-bridge.php) einmalig mit Ihrem FTP-Client hoch, legen Sie ihren API-Schlüssel fest und tragen Sie dann hier ihre URL ein. Funktioniert auf jedem PHP-Host."},"local-folder":{title:"Lokaler Ordner",short:"Auf diesem Computer",hint:"Schreibt die Website in einen Ordner dieses Computers (Chrome / Edge). Stellen Sie sie lokal bereit oder übertragen Sie sie mit Ihren eigenen Tools."},zip:{title:"Als ZIP herunterladen",short:"Manuell hochladen",hint:"Die Website wird in diesem Browser gespeichert; laden Sie in den Einstellungen ein ZIP herunter und laden Sie es beliebig hoch (Netlify Drop, FTP-Client…)."}},Nre={heading:"Mit der Datenbank verbinden",intro:"Dieser Admin speichert seine Inhalte in {{path}}. Geben Sie die Zugangsdaten für diesen Browser ein.",storage:"Die Zugangsdaten werden nur in diesem Browser gespeichert. Beim Abmelden werden sie vergessen.",passphrase:"Passphrase der Datenbank",passphraseHint:"Die Datenbank ist verschlüsselt. Gib die bei der Installation gewählte Passphrase ein (wird nur in diesem Browser gespeichert).",passphraseWrong:"Falsche Passphrase: Die Datenbank konnte nicht geöffnet werden.",passphraseMissing:"Gib die Passphrase der Datenbank ein."},Pre={common:ire,auth:are,nav:ore,dashboard:lre,posts:cre,pages:ure,taxonomies:dre,media:hre,themes:fre,plugins:pre,externalInstall:mre,externalLoader:gre,menus:bre,settings:yre,users:vre,firestoreSetup:xre,errors:wre,identity:kre,setup:Sre,flexweg:Ere,publish:_re,docstore:Cre,connectors:Are,gitAccess:Tre,hosting:Ire,sqliteAccess:Nre},Rre={save:"Guardar",saving:"Guardando…",saved:"Guardado",cancel:"Cancelar",delete:"Eliminar",deleting:"Eliminando…",edit:"Editar",create:"Crear",search:"Buscar",loading:"Cargando…",yes:"Sí",no:"No",confirm:"Confirmar",back:"Atrás",next:"Siguiente",previous:"Anterior",close:"Cerrar",all:"Todos",none:"Ninguno",actions:"Acciones",name:"Nombre",slug:"Slug",description:"Descripción",status:"Estado",createdAt:"Creado",updatedAt:"Actualizado",publishedAt:"Publicado",language:"Idioma",darkMode:"Modo oscuro",lightMode:"Modo claro",signOut:"Cerrar sesión",administrator:"Administrador",editor:"Editor",appName:"AgentCMS"},jre={signIn:"Iniciar sesión",signingIn:"Iniciando sesión…",email:"Correo electrónico",password:"Contraseña",emailPlaceholder:"tu@empresa.com",passwordPlaceholder:"••••••••",forgotPassword:"¿Olvidaste tu contraseña?",resetEmailSent:"Correo de restablecimiento de contraseña enviado a {{email}}.",enterEmailFirst:"Introduce primero tu correo arriba y luego haz clic en restablecer.",emailPasswordRequired:"El correo y la contraseña son obligatorios.",signInSubtitle:"Usa tu correo de trabajo y tu contraseña.",footer:"Las solicitudes de cuenta se gestionan a través de tu administrador.",errors:{invalidEmail:"Dirección de correo no válida.",invalidCredentials:"Correo o contraseña no válidos.",tooManyRequests:"Demasiados intentos. Inténtalo más tarde o restablece tu contraseña.",userDisabled:"Esta cuenta ha sido deshabilitada.",networkFailed:"Error de red. Comprueba tu conexión.",generic:"Error de autenticación."}},Mre={openMenu:"Abrir menú",closeMenu:"Cerrar menú",dashboard:"Panel",posts:"Entradas",pages:"Páginas",taxonomies:"Categorías y etiquetas",media:"Medios",themes:"Temas",themeSettings:"Ajustes del tema",plugins:"Plugins",menus:"Menús",users:"Usuarios",settings:"Ajustes"},Lre={title:"Panel",welcome:"Bienvenido de nuevo, {{email}}.",stats:{totalPosts:"Entradas",totalPages:"Páginas",online:"En línea",drafts:"Borradores"}},Dre={title:"Entradas",newPost:"Nueva entrada",noPosts:"Aún no hay entradas. Crea la primera para empezar.",noPostsInFilter:"Ninguna entrada coincide con el filtro actual.",search:{placeholder:"Buscar entradas…",clear:"Borrar búsqueda",noResults:"Ninguna entrada coincide con tu búsqueda."},pagination:{previous:"Anterior",next:"Siguiente",showing:"Mostrando {{from}}–{{to}} de {{total}}",pageOf:"Página {{page}} de {{total}}"},bulk:{selectedCount_one:"{{count}} seleccionada",selectedCount_other:"{{count}} seleccionadas",selectPage_one:"Seleccionar {{count}} en esta página",selectPage_other:"Seleccionar las {{count}} de esta página",deselectPage:"Deseleccionar página",allOnPageSelected_one:"{{count}} en esta página seleccionada.",allOnPageSelected_other:"Las {{count}} de esta página están seleccionadas.",selectAllMatching_one:"Seleccionar la entrada coincidente",selectAllMatching_other:"Seleccionar las {{count}} entradas coincidentes",allMatchingSelected_one:"La entrada coincidente está seleccionada.",allMatchingSelected_other:"Las {{count}} entradas coincidentes están seleccionadas.",selectOne:"Seleccionar «{{title}}»",publish:"Publicar ({{count}})",publishing:"Publicando…",publishedCount:"{{ok}} publicada(s), {{failed}} fallo(s).",unpublish:"Despublicar ({{count}})",unpublishing:"Despublicando…",unpublishedCount:"{{ok}} despublicada(s), {{failed}} fallo(s).",delete:"Eliminar",deleting:"Eliminando…",deletedCount:"{{ok}} eliminada(s), {{failed}} fallo(s).",confirmDelete_one:"¿Eliminar {{count}} entrada? Se despublica de Flexweg y no se puede deshacer.",confirmDelete_other:"¿Eliminar {{count}} entradas? Se despublican de Flexweg y no se puede deshacer.",noDraftSelected:"Ninguna entrada en borrador seleccionada.",noOnlineSelected:"Ninguna entrada en línea seleccionada.",clear:"Borrar selección"},filters:{all:"Todas",draft:"Borrador",online:"En línea"},fields:{title:"Título",slug:"Slug",excerpt:"Extracto",content:"Contenido",category:"Categoría",tags:"Etiquetas",heroImage:"Imagen destacada",seoTitle:"Título SEO",seoDescription:"Descripción SEO",createdAt:"Creado el",updatedAt:"Última actualización",publishedAt:"Publicado el"},edit:{newTitle:"Nueva entrada",editTitle:"Editar entrada",saved:"Guardado.",savedAndRepublished:"Guardado y republicado.",saveFailed:"Error al guardar.",saveAndRepublish:"Guardar y republicar",draftSaved:"Borrador guardado.",slugCollision:{post:'Esta URL ya la usa la entrada: "{{label}}".',page:'Esta URL ya la usa la página: "{{label}}".',category:'Esta URL ya la usa la categoría: "{{label}}".'},publish:"Publicar",unpublish:"Despublicar",publishing:"Publicando…",unpublishing:"Despublicando…",titlePlaceholder:"Añadir título",permalink:"Enlace permanente",slugFormatHint:"Solo minúsculas, ASCII, separadas por guiones.",slugAutoSuffixed:'Se añadió un sufijo porque "{{base}}" ya lo usa {{owner}}.',slugAutoSuffixedOwner:{post:'publicación: "{{label}}"',page:'página: "{{label}}"',category:'categoría: "{{label}}"'},saveBlocked:{titleRequired:"Añade un título antes de guardar.",slugRequired:"Se requieren un título y un slug de URL para guardar.",slugInvalid:"Formato de slug inválido (ASCII en minúsculas + guiones).",slugCollision:"Resuelve el conflicto de URL antes de guardar."},viewPublished:"Ver",confirmDelete:"¿Eliminar esta entrada?",inspector:{document:"Documento",block:"Bloque",blockEmpty:"Selecciona un bloque en el editor para ver sus opciones.",publishing:"Publicación",permalink:"Enlace permanente",categories:"Categorías y etiquetas",featured:"Imagen destacada",seo:"SEO",excerpt:"Extracto",dates:"Fechas"},blocks:{addBlock:"Añadir bloque",transform:"Transformar a",moveUp:"Mover arriba",moveDown:"Mover abajo",duplicate:"Duplicar",remove:"Eliminar bloque",paragraph:"Párrafo",heading2:"Título 2",heading3:"Título 3",bulletList:"Lista con viñetas",orderedList:"Lista numerada",blockquote:"Cita",codeBlock:"Código",image:"Imagen",horizontalRule:"Separador",categories:{text:"Texto",media:"Medios",layout:"Diseño",embed:"Incrustaciones",advanced:"Avanzado"},noSettings:"Este bloque no tiene ajustes.",noSelection:"Selecciona un bloque en el editor para ver sus opciones.",slash:{noResults:"Ningún bloque coincide."}}},status:{draft:"Borrador",online:"En línea"},preview:{title:"Vista previa",rendering:"Generando vista previa…",error:"Error en la vista previa: {{error}}",viewports:{mobile:"Móvil",tablet:"Tableta",desktop:"Escritorio"}}},Fre={title:"Páginas",newPage:"Nueva página",noPages:"Aún no hay páginas.",homeBadge:"Inicio",homeBadgeTooltip:"Se usa como página de inicio del sitio"},Ore={title:"Categorías y etiquetas",categories:"Categorías",tags:"Etiquetas",newCategory:"Nueva categoría",newTag:"Nueva etiqueta",noCategories:"Aún no hay categorías.",noTags:"Aún no hay etiquetas.",slugCollision:'Este slug ya lo usa "{{label}}".',seo:{button:"SEO",buttonTitle:"Editar metaetiquetas SEO",title:"Metaetiquetas SEO",subtitle:'Título y descripción personalizados para la página de archivo de "{{name}}".',metaTitle:"Meta título",metaTitleHint:"Se usa como <title> de la página. Por defecto: el nombre del término.",metaDescription:"Meta descripción",metaDescriptionHint:"Se usa como meta descripción de la página. Por defecto: la descripción del término."}},zre={title:"Biblioteca de medios",upload:"Subir",uploading:"Subiendo…",finalizing:"Finalizando…",uploadFailed:"Error al subir",retry:"Reintentar",noMedia:"Aún no hay medios.",alt:"Texto alternativo",caption:"Pie de foto",filename:"Nombre de archivo",size:"Tamaño",type:"Tipo"},Ure={title:"Temas",active:"Activo",activate:"Activar",installExternal:"Instalar tema",uninstallDisabledTitle:"Cambia a otro tema antes de desinstalar este.",syncAssets:"Sincronizar recursos del tema",regenerateSite:"Regenerar el sitio",regenerating:"Regenerando…",regenerate:{button:"Regenerar",running:"Ejecutando…",groupBuiltins:"Sitio",groupPlugins:"Plugins",home:"Solo página de inicio",homeHelp:"Regenera solo index.html — la opción más rápida.",allHtml:"Todas las páginas HTML",allHtmlHelp:"Cada entrada, página, archivo y listado — además de los snapshots menu / posts / authors JSON.",repair:"Reparar URLs",repairHelp:"Recalcula la URL canónica de cada publicación online y mueve los archivos que terminaron en la URL equivocada. Útil tras una importación realizada antes de que los términos se sincronizaran.",assets:"Recursos del tema",assetsHelp:"Sube el CSS y los scripts del tema activo a /theme-assets/.",everything:"Todo",everythingHelp:"Recursos del tema + todo HTML + cada salida de plugin. Opción más lenta.",noPluginTargets:"Sin regeneraciones de plugin — activa un plugin que soporte regenerar."},confirmSwitch:{title:"¿Cambiar a {{theme}}?",body:"Cambiar de tema requiere volver a subir los recursos del tema y regenerar cada página publicada para que el nuevo aspecto se propague en todas partes. Puede tardar un momento.",confirm:"Cambiar y regenerar",cancel:"Cancelar"}},Bre={title:"Plugins",enabled:"Activado",disabled:"Desactivado",enable:"Activar",disable:"Desactivar",configure:"Configurar",author:"autor",learnMore:"Más información",mustUseBadge:"Obligatorio",installExternal:"Instalar plugin",tabs:{regular:"Plugins",mustUse:"Obligatorios"}},$re={titlePlugin:"Instalar un plugin",titleTheme:"Instalar un tema",labelPlugin:"plugin",labelTheme:"tema",intro:"Suelta un archivo ZIP que contenga un bundle de {{label}} (manifest.json + bundle.js en la raíz del ZIP). El {{label}} se subirá a tu sitio Flexweg y se registrará tras una recarga. Volver a subir un ZIP con el mismo id de manifest actualiza la entrada existente en el sitio — no hace falta desinstalar.",zipField:"Archivo ZIP del bundle",install:"Instalar",installing:"Instalando…",installSuccess:"{{name}} instalado ({{count}} archivos subidos). Recargando…",upgradeSuccess:"{{name}} actualizado de v{{previousVersion}} a v{{newVersion}} ({{count}} archivos subidos). Recargando…",installedTitle:"Ya instalado",bundledDefaultsTitle:"Plugins/temas incluidos disponibles",bundledDefaultsHint:"{{count}} plugin/tema incluido está actualmente desinstalado. Restáuralos para recuperar lo que venía con esta versión del admin.",bundledDefaultsRestore:"Restaurar",bundledDefaultsRestored:"Restaurados {{plugins}} plugin(s) y {{themes}} tema(s). Recargando…",uninstall:"Desinstalar",uninstallSuccess:"{{id}} desinstalado. Recargando…",confirmUninstall:"¿Desinstalar {{id}}? Los archivos se eliminarán de Flexweg.",errors:{"no-manifest":"El ZIP no tiene manifest.json en la raíz.","invalid-manifest":"manifest.json no es válido (falta algún campo obligatorio o no es JSON válido).","incompatible-api":"El bundle se compiló contra una versión incompatible de la API runtime.","no-bundle":"El ZIP no contiene el archivo de entrada declarado en el manifest.","fetch-manifest":"No se pudo leer el external.json actual en Flexweg.","upload-failed":"Falló la subida — revisa tu clave API de Flexweg y tu conexión."}},Hre={someFailed:"{{count}} bundle(s) externo(s) no se pudieron cargar. Mira la consola del navegador."},Vre={title:"Menús",header:"Menú de cabecera",footer:"Menú de pie de página",label:"Etiqueta",saveAndPublish:"Guardar y generar",discard:"Descartar",saved:"Menús guardados y publicados.",saveFailed:"No se pudieron guardar los menús.",unsavedChanges:"Tienes cambios sin guardar."},qre={title:"Ajustes",tabs:{general:"General"},site:{title:"Sitio",siteTitle:"Título del sitio",siteDescription:"Descripción del sitio",siteLanguage:"Idioma del sitio",siteLanguageHelp:'Etiqueta BCP-47 (p. ej. en, fr-CA) inyectada en <html lang="…"> de cada página publicada. El prefijo se compara con los locales de traducción soportados para los textos de sitemap / RSS y las cadenas integradas en el tema; los locales no soportados recurren al inglés.',siteLanguageResolved:"Las traducciones usarán: {{label}}",baseUrl:"URL pública del sitio",postsPerPage:"Entradas por página",homeMode:"Contenido de la página de inicio",homeLatest:"Últimas entradas",homeStatic:"Página estática",homePage:"Página de inicio",discourageIndexing:"Disuadir a los motores de búsqueda de indexar este sitio",discourageIndexingHelp:"Si se activa, cada página publicada recibe una etiqueta meta noindex/nofollow y robots.txt bloquea a todos los rastreadores. Replica el comportamiento de WordPress — útil para sitios de staging o revisiones antes del lanzamiento. Los motores de búsqueda que respetan la directiva no indexarán el sitio.",discourageRegenerateHint:"Ajuste de indexación guardado. Haz clic en «Regenerar todo» en Temas para aplicar el cambio a todas las páginas publicadas y a robots.txt."},flexweg:{title:"API de Flexweg",apiKey:"Clave API",apiKeyHelp:"Generada desde tu cuenta Flexweg → API.",siteUrl:"URL del sitio",siteUrlHelp:"URL pública de tu sitio Flexweg sin barra final.",apiBaseUrl:"URL base de la API",storageHelpFirebase:"Almacenada en Firestore (config/flexweg). Lectura para cualquier miembro con sesión iniciada, escritura solo para administradores.",storageHelpSqlite:"Almacenada en la tabla SQLite local config. Lectura para cualquier miembro con sesión iniciada, escritura solo para administradores."},backend:{title:"Backend de datos",active:"Backend activo:",switchButton:"Cambiar de backend…",confirmTitle:"Se perderán todos los datos actuales.",confirmBody:"Cambiar borra la configuración del navegador y recarga el formulario de configuración. El nuevo backend empieza vacío — los datos del backend anterior siguen donde estaban (en Firestore o como un archivo .sqlite en Flexweg), pero el CMS no los leerá hasta que vuelvas a cambiar.",confirmYes:"Sí, cambiar de backend",downloadBackup:"Descargar una copia de seguridad del archivo .sqlite",downloadBackupHelp:"hazlo antes de cambiar de backend.",markdownGit:"Markdown — {{source}}",localFolder:"carpeta local",localBrowser:"Este navegador (local, un solo usuario)",sqliteFile:"Archivo SQLite — {{location}}"},performance:{title:"Rendimiento",help:"Cómo el admin carga entradas y páginas. El modo por defecto funciona en el plan gratuito de Firestore sin configuración; el modo paginado es para sitios muy grandes y requiere crear índices una vez.",mode:"Modo de carga",modeGlobal:"Estándar (sin configuración)",modePaginated:"Paginación del servidor (requiere índices de Firestore)",globalHelp:"Carga toda la colección de entradas en una suscripción en vivo. Orden, filtros y búsqueda se hacen en memoria. Recomendado para sitios con menos de ~5 000 entradas.",paginatedHelp:"Suscripciones paginadas por cursor, una página a la vez. Requiere índices compuestos de Firestore — ver README. Recomendado para sitios muy grandes.",savedReload:"Guardado. Recarga el admin para aplicar el nuevo modo."},editor:{title:"Editor",help:"Tipografía usada dentro del editor de entradas/páginas. Independiente del tema público.",fontFamily:"Familia tipográfica",bodySize:"Tamaño del cuerpo",h1Size:"Tamaño H1",h2Size:"Tamaño H2",h3Size:"Tamaño H3",sizeHelp:"Longitud CSS, p. ej. 16px o 1rem. Deja vacío para el valor por defecto.",reset:"Restablecer valores predeterminados"},profile:{title:"Perfil",adminLocale:"Idioma del admin",adminLocaleHelp:"Idioma usado por la interfaz de administración. Guardado en tu perfil.",firstName:"Nombre",lastName:"Apellido",headline:"Título",headlinePlaceholder:"p. ej. Periodista, Redactor jefe…",headlineHelp:"Se muestra públicamente bajo tu nombre en las tarjetas de autor y en tu página de archivo.",bio:"Biografía",bioPlaceholder:"Un párrafo corto que se muestra en tu página de autor y debajo de tus artículos.",bioHelp:"Visible en el sitio público en la barra lateral de autor y en la página de archivo del autor.",socials:"Perfiles sociales",socialsHelp:"Añade las URL de los perfiles que quieres mostrar en el sitio público y marca «Mostrar» para los que deben ser visibles. Las URL vacías se ignoran.",socialsShow:"Mostrar",socialsShowHelp:"Activa la visibilidad de esta red en el sitio público.",avatar:"Foto de perfil",avatarHelp:"Elige una imagen de tu biblioteca de medios. Las imágenes cuadradas se muestran mejor.",pickAvatar:"Elegir de medios",changeAvatar:"Cambiar foto",removeAvatar:"Eliminar",save:"Guardar perfil"},transfer:{title:"Mover o hacer copia de seguridad del contenido",help:"Exporta todo (entradas, páginas, categorías, metadatos de medios, perfiles, ajustes) en un único archivo JSON. En un backend Markdown o local puedes importar ese archivo conservando los ids — así se migra desde Firebase o SQLite. Los archivos de medios y las claves secretas no se incluyen.",export:"Exportar el contenido (JSON)",import:"Importar contenido…",modeMerge:"Combinar (sobrescribe los mismos ids)",modeReplace:"Reemplazar las colecciones importadas",replaceConfirm:"El modo Reemplazar elimina todos los elementos existentes de las colecciones presentes en el archivo antes de importar. ¿Continuar?",invalidFile:"Este archivo no es una exportación de contenido de AgentCMS.",imported:"Se han importado {{posts}} entradas/páginas, {{terms}} términos y {{media}} medios. Ejecuta Regenerar → Todo para publicarlos."},encryption:{title:"Cifrado de la base:",on:"activado",off:"desactivado",onHelp:"El archivo de la base es ilegible sin la frase de contraseña. Cambiarla vuelve a guardar el archivo con una nueva clave; los demás navegadores pedirán la nueva frase.",offHelp:"Cualquiera que pueda descargar el archivo de la base puede leerlo (un hosting estático lo sirve como cualquier página). Cífralo con una frase de contraseña.",enable:"Cifrar la base…",change:"Cambiar la frase de contraseña…",savedConfirm:"He guardado esta frase en mi gestor de contraseñas — sin ella no se puede abrir el contenido.",enableConfirm:"Cifrar ahora",changeConfirm:"Cambiar la frase",done:"Base guardada de nuevo con la nueva frase de contraseña."}},Wre={title:"Usuarios",noUsers:"Aún no hay usuarios.",role:"Rol",disabled:"Deshabilitado",editProfileTitle:"Editar perfil — {{email}}",profileSaved:"Perfil guardado.",descriptionFirebase:"Gestiona tu equipo. Las nuevas cuentas se crean en la Firebase Console y se replican aquí en el primer inicio de sesión.",descriptionSqlite:"Gestiona tu equipo. Usa el botón +Añadir usuario más abajo para crear cuentas directamente.",addUser:"Añadir usuario",addUserSuccess:"{{email}} añadido.",removeConfirmFirebase:"¿Eliminar la ficha de {{email}}? Se quita su perfil y rol del CMS. Para revocar el acceso, elimina además la cuenta en la Firebase Console.",removeConfirmSqlite:"¿Eliminar permanentemente a {{email}}? Se revoca su acceso Y se quitan su perfil y rol. Esta acción no se puede deshacer.",empty:{title:"Aún no hay miembros del equipo",descriptionFirebase:"Crea la primera cuenta en la Firebase Console y luego inicia sesión aquí una vez para registrar el perfil.",descriptionSqlite:"Pulsa +Añadir usuario arriba para invitar al primer miembro."},help:{title:"Cómo añadir un nuevo miembro al equipo",bootstrapLine:"El admin inicial (siempre con acceso total) es:",firebase:{step1:"Abre la Firebase Console → Authentication → Add user.",step2:"Pon un correo y una contraseña y envíalos al nuevo miembro.",step3:"Pídele que inicie sesión aquí una vez — su perfil aparece en la lista de arriba y puedes editar su rol y sus datos."},sqlite:{step1:"Pulsa el botón +Añadir usuario de arriba.",step2:"Introduce su correo y una contraseña temporal (8+ caracteres).",step3:"Comparte las credenciales de forma segura — podrá cambiar la contraseña desde su perfil una vez iniciada la sesión."},git:{step1:"Añade a la persona como colaboradora del repositorio de contenido (escritura = editor, admin / maintainer = admin).",step2:"La persona crea su propio token de acceso personal en GitHub / GitLab.",step3:"Abre el admin e inicia sesión con ese token — su perfil se crea aquí automáticamente."}},addUserModal:{title:"Añadir un nuevo miembro del equipo",intro:"Crea la cuenta directamente en la base de datos Flexweg SQLite Auth. El nuevo usuario tiene rol de editor por defecto; promociónalo desde la lista de abajo si necesita acceso de admin.",submit:"Crear usuario",submitting:"Creando…"},actions:{editProfile:"Editar perfil",promote:"Promover a administrador",demote:"Degradar a editor",disable:"Deshabilitar",enable:"Habilitar",delete:"Eliminar registro"},descriptionGit:"Los miembros del equipo son las personas con acceso de escritura al repositorio de contenido. Aparecen aquí tras su primer inicio de sesión; su rol sigue sus permisos en el repositorio.",descriptionLocal:"Este admin funciona en modo de un solo usuario: el contenido se guarda en este navegador y no hay cuentas.",descriptionSqliteFile:"Sin cuentas de usuario con este backend: cualquiera que pueda abrir el admin puede editar. Protege la carpeta del admin desde tu alojamiento. Los perfiles de autor de abajo son informativos."},Gre={title:"Configuración de Firestore necesaria",intro:"Las páginas de listado de entradas y páginas necesitan algunos índices compuestos de Firestore para consultar eficientemente. Deben crearse manualmente — Firebase reserva la creación de índices a los administradores del proyecto.",checking:"Verificando tus índices Firestore…",missingCount_one:"{{count}} índice falta:",missingCount_other:"{{count}} índices faltan:",openConsole:"Abrir Firebase Console para crear",noUrl:"No se pudo extraer la URL de autosugerencia — consulta el README para el comando gcloud.",howItWorks:"Cómo funciona",step1:"Haz clic en el enlace de cada índice faltante — Firebase Console se abre con la definición pre-rellenada.",step2:"Pulsa «Create» y espera 1–5 minutos a que el índice se construya (estado en la consola).",step3:"Vuelve aquí y pulsa Reintentar. Cuando ambas consultas tengan éxito, el admin se carga.",retry:"Reintentar",retrying:"Reintentando…",buildHint:"Los índices pueden tardar unos minutos en construirse tras la creación.",allReady:"Todos los índices están listos.",unexpectedTitle:"No se puede acceder a Firestore",unexpectedHint:"Verifica tu conexión y las reglas de Firestore. Si acabas de crear los índices, espera a que terminen y reintenta."},Kre={appError:"Error de la aplicación",loadAccountFailed:"No se pudo cargar tu cuenta",loadAccountHint:"Si el problema persiste, cierra sesión e inténtalo de nuevo.",accountDisabled:"Cuenta deshabilitada",accountDisabledMessage:"Tu acceso a este CMS ha sido deshabilitado. Contacta con tu administrador.",firebaseNotConfigured:"Firebase no está configurado",firebaseEnvMissing:`Faltan las siguientes variables de entorno:
|
|
3857
3857
|
{{vars}}
|
|
3858
3858
|
|
|
3859
|
-
Copia .env.example a .env, rellena las credenciales de tu proyecto Firebase y reinicia el servidor de desarrollo.`,adminEmailNotConfigured:"El correo del admin no está configurado",adminEmailMessage:"Falta VITE_ADMIN_EMAIL en .env. Establécelo con el correo del administrador inicial.",consoleHint:"Revisa la consola del navegador y tu configuración .env. Consulta el README para las instrucciones de configuración."},Jre={brandTitle:"Flexweg CMS",brandSubtitle:"Publicación estática",login:{heading:"Iniciar sesión",intro:"Usa el correo y la contraseña que te ha facilitado tu administrador.",submit:"Iniciar sesión",submitting:"Iniciando sesión…"},fields:{name:"Nombre a mostrar (opcional)",namePlaceholder:"Juan Pérez",email:"Correo electrónico",password:"Contraseña",passwordHint:"Al menos 8 caracteres."},footer:"Las nuevas cuentas las crea un administrador desde la página Usuarios.",errors:{invalidEmail:"Introduce una dirección de correo válida.",missingPassword:"La contraseña es obligatoria.",passwordTooShort:"La contraseña debe tener al menos 8 caracteres."}},Qre=JSON.parse('{"title":"Bienvenido a Flexweg CMS","subtitle":"Configuración inicial","intro":"Introduce tus credenciales de Firebase, la cuenta del administrador inicial y tu clave API de Flexweg. Los valores se validan, se guardan en tu proyecto (Firestore + un archivo config.js en Flexweg) y el admin recarga al flujo de inicio de sesión normal. Solo tienes que hacerlo una vez.","introFirebase":"Paso 1 — Firebase. Introduce las credenciales de tu proyecto Firebase y la cuenta de administrador bootstrap. Iniciamos sesión, verificamos el correo y comprobamos que tus reglas de Firestore reconozcan a este admin antes de pasar al paso Flexweg.","introFlexweg":"Paso 2 — Flexweg. Introduce tu clave API Flexweg y la URL del sitio. Probamos la API, guardamos la configuración en Firestore, subimos config.js a tu sitio y sincronizamos los activos del tema.","continueToFlexweg":"Validar Firebase y continuar","stepper":{"terms":"Condiciones","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Contenido y publicación","data":"Datos","hosting":"Hosting","install":"Instalación"},"backend":{"title":"Elige un backend de datos","intro":"Elige dónde el CMS guardará tus posts, páginas, usuarios y ajustes. Puedes cambiarlo luego desde Ajustes (los datos no se migran).","sqliteTitle":"Flexweg SQLite (recomendado)","sqliteHint":"Todos los datos se quedan en tu sitio Flexweg como un archivo SQLite. Sin servicio externo. La auth la proporciona la API SQLite de Flexweg.","firebaseTitle":"Firebase","firebaseHint":"Usa un proyecto Firebase para Firestore + Auth. Gratis con el plan Spark. Actualizaciones en tiempo real vía onSnapshot.","continue":"Continuar","markdownGitTitle":"Archivos Markdown en un repositorio Git","markdownGitHint":"Entradas como archivos .md en GitHub / GitLab (o un clon local). Cada editor inicia sesión con su propio token de acceso; cada cambio es un commit. Sin base de datos, funciona con varios editores y equipos.","localTitle":"Solo este navegador","localHint":"Un solo usuario, sin inicio de sesión, nada que configurar. El contenido se queda en este navegador (expórtalo desde Ajustes). Ideal para un admin que se ejecuta en tu propio ordenador."},"sqlite":{"heading":"Conecta tu sitio Flexweg","intro":"Usaremos tu clave API maestra de Flexweg UNA SOLA VEZ para crear un token con alcance limitado para la base de datos SQLite. Tras la instalación, la clave maestra se descarta y solo se almacena el token con alcance (limitado a este único archivo SQLite).","apiKeyHint":"Clave API maestra de Flexweg. Se usa solo para instalar — nunca se almacena después.","detectedFromUrl":"Detectado desde la URL","advanced":"Ajustes avanzados (URL del sitio, ruta SQLite…)","pathHint":"Dónde vive el archivo SQLite en tu sitio Flexweg. Las carpetas se crean automáticamente.","adminHeading":"Cuenta de administrador","adminIntro":"Crea el primer usuario — esta cuenta obtiene derechos de admin automáticamente. Los miembros siguientes se incorporan desde la página Usuarios una vez con sesión iniciada.","passwordHint":"Al menos 8 caracteres.","submit":"Instalar base de datos SQLite"},"terms":{"title":"Condiciones de uso","intro":"Por favor, lee y acepta las condiciones a continuación antes de utilizar Flexweg CMS. Están redactadas en lenguaje sencillo para que se lean rápido.","section1":{"title":"1. Servicio gratuito","body":"Flexweg CMS es una herramienta que Flexweg pone a tu disposición de forma gratuita. Puedes usarla sin límite con tu hosting Flexweg — Flexweg nunca te facturará por usar el CMS en sí. Las tarifas habituales de tu plan de hosting Flexweg y de tu plan Firebase siguen aplicándose, cada una en la cuenta correspondiente."},"section2":{"title":"2. Servicio «tal cual», sin garantía","body":"El CMS se proporciona tal cual. Trabajamos para mantenerlo estable y mejorarlo con el tiempo, pero no podemos garantizar que esté libre de errores, defectos o interrupciones. Úsalo con la misma precaución que cualquier herramienta que no hayas escrito tú mismo: mantén copias de seguridad de los contenidos importantes."},"section3":{"title":"3. Tus contenidos, tu responsabilidad","body":"Eres el único responsable de los contenidos que publicas a través del CMS — textos, imágenes, vídeos, formularios, integraciones de código y cualquier otro medio. Debes respetar la legislación aplicable en tu jurisdicción (y en las que te dirijas), los derechos de autor, los derechos de imagen y de personalidad, las normas de protección de datos personales y las condiciones de cualquier servicio de terceros que utilices (fuentes embebidas, vídeos, etc.). Flexweg no es responsable de los contenidos publicados por los usuarios del CMS."},"section4":{"title":"4. Tu cuenta de Firebase, tu seguridad","body":"El CMS almacena sus datos en tu propio proyecto Firebase. Eres responsable de la seguridad de ese proyecto: elige una contraseña robusta para la cuenta de administrador inicial, configura las reglas de seguridad de Firestore como se documenta, rota tus claves API cuando sea necesario y revisa quién tiene acceso. Flexweg no podrá en ningún caso ser responsabilizado por accesos no autorizados, fugas de datos, hackeos o pérdidas derivadas de una mala configuración o de un compromiso de tu cuenta Firebase."},"section5":{"title":"5. Limitación de responsabilidad","body":"Flexweg no podrá ser responsabilizado por ninguna pérdida de ingresos, pérdida de datos, pérdida de oportunidad comercial ni por ningún daño directo o indirecto derivado del uso, mal uso o falta de disponibilidad del CMS. Cuando la legislación aplicable obligue a Flexweg a asumir alguna responsabilidad, ésta se limita al importe efectivamente pagado a Flexweg por el CMS durante los últimos 12 meses — es decir, cero, ya que el CMS es gratuito."},"section6":{"title":"6. Tus datos siguen siendo tuyos","body":"Los contenidos que creas con el CMS se almacenan en tu propio proyecto Firebase (textos, ajustes, metadatos de los medios) y en tu propio hosting Flexweg (HTML publicado, imágenes, assets de tema). El CMS en sí no transmite tus contenidos a ningún servicio de terceros. Los plugins o temas que decidas activar pueden tener su propio comportamiento — revisa lo que hacen antes de activarlos."},"section7":{"title":"7. Uso correcto","body":"El uso del CMS para actividades ilegales, fraudulentas o nocivas, o de manera contraria a las condiciones generales de uso de Flexweg, puede provocar la suspensión de tu acceso al hosting Flexweg. También podemos actualizar estas condiciones del CMS con el tiempo; los cambios significativos se comunicarán a través del admin o por email."},"accept":"He leído y acepto las Condiciones de uso.","continue":"Continuar a la configuración","back":"Volver"},"sections":{"firebase":"Firebase","admin":"Administrador inicial","flexweg":"API de Flexweg"},"help":{"firebase":"Encuentra estos valores en Firebase Console → Configuración del proyecto → General → Tus apps → Configuración del SDK.","admin":"Usa un usuario existente de Firebase Authentication. Cualquiera que inicie sesión con este correo es tratado como administrador y se salta la comprobación del registro de usuario. Crea el usuario en Firebase Console → Authentication si aún no existe.","flexweg":"Genera una clave API permanente en tu cuenta Flexweg → API. La URL del sitio es la dirección pública de tu sitio Flexweg (p. ej. https://tu-sitio.flexweg.com).","flexwegApiKeyHint":"Obtén tu clave API desde la configuración de tu cuenta Flexweg.","flexwegApiKeyLink":"Abrir configuración de la cuenta"},"fields":{"apiKey":"Clave API","authDomain":"Dominio de autenticación","projectId":"ID del proyecto","storageBucket":"Bucket de almacenamiento","messagingSenderId":"ID de remitente de mensajería","appId":"ID de la app","adminEmail":"Correo","adminPassword":"Contraseña","flexwegApiKey":"Clave API","flexwegSiteUrl":"URL del sitio","flexwegApiBaseUrl":"URL base de la API","sqlitePath":"Ruta SQLite"},"submit":"Guardar y continuar","submitting":"Configurando…","success":"¡Configuración completada!","reloadingHint":"Se recargará el admin en un momento — espera un instante.","footer":"Estos valores se guardan en tu proyecto (Firestore + Flexweg). No se envían a ningún otro sitio.","steps":{"signInFirebase":"Iniciando sesión en Firebase…","testFlexweg":"Probando la API de Flexweg…","writeFirestore":"Guardando configuración…","uploadConfig":"Subiendo config.js a Flexweg…","syncThemes":"Sincronizando assets de tema con Flexweg…","sqliteInstall":"Creando token SQLite con alcance limitado…","sqliteRegisterAdmin":"Registrando la cuenta de admin…","sqliteSchema":"Inicializando el esquema SQLite…"},"stepsDone":{"sqliteInstall":"Token SQLite con alcance limitado emitido","sqliteRegisterAdmin":"Admin registrado y con sesión iniciada","sqliteSchema":"Esquema SQLite listo"},"errors":{"missingFields":"Por favor, rellena todos los campos.","rootDeploymentTitle":"El admin debe estar en una subcarpeta, no en la raíz del sitio.","rootDeploymentHint":"Mueve los archivos del admin (index.html, config.js, runtime/, …) a una subcarpeta en Flexweg — por ejemplo /admin/ o un nombre aleatorio como /erf34f654GH3/ para mayor discreción. Luego recarga el admin desde la URL de la subcarpeta y vuelve a ejecutar la configuración.","firebaseAuthGeneric":"No se pudo iniciar sesión en Firebase.","firebaseAuthInvalidCredential":"Firebase rechazó la combinación de correo y contraseña.","firebaseAuthInvalidCredentialHint":"Los proyectos de Firebase recientes activan por defecto la protección contra enumeración de correos, que devuelve el mismo error tanto si la contraseña es incorrecta, como si el usuario no existe o inicia sesión con otro proveedor. A comprobar:\\n• Vuelve a introducir la contraseña — copia y pega desde un gestor de contraseñas para descartar erratas. La longitud mínima es 6 caracteres.\\n• Abre Firebase Console → Authentication → Users y confirma que el correo existe. Revisa la columna «Providers»: si solo muestra Google (u otro proveedor) sin «Email/Password», establece o restablece la contraseña desde el menú de la fila (⋮ → Restablecer contraseña).\\n• Verifica que el correo coincida exactamente con lo que está almacenado en Firebase.","firebaseAuthUserNotFound":"No existe un usuario de Firebase con este correo. Créalo primero en Firebase Console → Authentication → Users.","firebaseAuthInvalidEmail":"El correo del administrador no es una dirección válida.","firebaseInvalidApiKey":"La clave API de Firebase no es válida. Verifica el valor en Firebase Console.","firebaseNetwork":"Error de red al iniciar sesión en Firebase. Verifica tu conexión.","firebaseTooManyRequests":"Demasiados intentos de inicio de sesión. Inténtalo más tarde o restablece la contraseña desde Firebase Console.","firebaseOperationNotAllowed":"El inicio de sesión con correo/contraseña no está activado en este proyecto Firebase. Abre Firebase Console → Authentication → Sign-in method y habilita el proveedor Email/Password.","firebaseUserDisabled":"Esta cuenta de usuario de Firebase está deshabilitada. Vuelve a habilitarla desde Firebase Console → Authentication → Users.","wrongAdminEmail":"La cuenta de Firebase con la que iniciaste sesión no coincide con el correo de admin que has escrito. Inténtalo de nuevo.","rulesNotPinnedTitle":"Las reglas de Firestore aún no te reconocen como admin bootstrap.","rulesNotPinnedHint":"Abre Firebase Console → Firestore → Reglas y sustituye el valor de `bootstrapAdminEmail()` por: {{email}} — luego haz clic en Publicar. La plantilla de reglas del README incluye un marcador `you@example.com` que debe sustituirse por tu correo de admin real. Una vez publicadas las nuevas reglas, vuelve a hacer clic en Enviar aquí.","flexwegAuth":"Clave API de Flexweg rechazada. Verifica el valor en tu cuenta Flexweg → API.","flexwegNetwork":"Error de red al contactar con Flexweg. Verifica la URL base de la API y tu conexión.","flexwegHttp":"Error de la API de Flexweg ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore rechazó la escritura de la configuración.","firestoreRulesHint":"Abre Firebase Console → Firestore → Reglas y comprueba que el correo de admin de bootstrap está fijado en \'{{email}}\'. El README incluye una plantilla de reglas lista para copiar.","firestoreOther":"Falló la escritura en Firestore","uploadFailed":"No se pudo subir config.js a Flexweg","generic":"Algo salió mal."},"docstore":{"contentTitle":"Repositorio de contenido","contentIntro":"Donde se guardan tus entradas, páginas y ajustes como archivos Markdown + JSON. Un repositorio vacío sirve — el CMS crea los archivos.","provider":"Repositorio","localClone":"Carpeta local (clon git)","localCloneHint":"Elige la carpeta de tu clon. Sincronízala con tu cliente git habitual — el CMS lee y escribe archivos, no ejecuta git.","contentDir":"Carpeta de contenido en el repositorio","privateRepo":"Usa un repositorio privado: los borradores se guardan allí.","folderRequired":"Elige primero la carpeta de contenido.","checking":"Comprobando el acceso al repositorio…","publishIntro":"Dónde se publica el sitio generado. Puedes cambiarlo más tarde en Ajustes.","existingSite":"Este repositorio ya está configurado — el sitio se sigue publicando en: {{target}}. Puedes cambiarlo más tarde en Ajustes (las claves secretas, si las hay, deben volver a introducirse allí).","install":"Instalar","steps":{"config":"Guardando la configuración…","content":"Cargando el contenido…","target":"Guardando el destino de publicación…","testTarget":"Probando el destino de publicación…"},"doneTitle":"¡Todo listo!","doneBody":"La configuración se ha guardado en este navegador. Para ahorrar este paso a otros editores, descarga config.js y reemplaza el de la carpeta admin de tu alojamiento.","downloadConfig":"Descargar config.js","open":"Abrir el admin","footer":"El contenido se queda en tu repositorio o en este navegador; los tokens de acceso nunca salen de este navegador."},"data":{"title":"1. ¿Dónde guardas tus datos?","intro":"Tus entradas, páginas, usuarios y ajustes — los datos propios del admin. Es independiente de dónde se aloja el sitio público (siguiente paso).","localNote":"Nada que configurar: el contenido se guarda en este navegador. Expórtalo desde Ajustes para hacer una copia de seguridad o moverlo más tarde.","options":{"sqlite-file":{"title":"SQLite","hint":"Una base de datos SQLite guardada en el alojamiento que elijas en el siguiente paso (Flexweg, tu servidor, S3, Git…). Sin cuentas de usuario — o el servicio SQLite de Flexweg, con cuentas, si alojas en Flexweg."},"flexweg-sqlite":{"title":"SQLite (servicio Flexweg)","hint":"Una base de datos SQLite gestionada por el servicio de Flexweg, con cuentas de usuario integradas. Necesita una cuenta de Flexweg, esté donde esté alojado el sitio."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth en tu proyecto de Google. Tiempo real, plan Spark gratuito."},"markdown-git":{"title":"Archivos Markdown en Git","hint":"Entradas como archivos .md en un repositorio GitHub / GitLab (o un clon local). Cada editor usa su propio token; cada cambio es un commit."},"local":{"title":"Este navegador","hint":"Un solo usuario, sin inicio de sesión, nada que configurar. Ideal para un admin que se ejecuta en tu ordenador."}}},"hosting":{"title":"2. ¿Dónde se publica el sitio?","intro":"Dónde se sube el sitio estático generado (HTML, CSS, imágenes) cada vez que publicas. Puedes cambiarlo más tarde en Ajustes.","existing":"Este repositorio de contenido ya publica en el destino de abajo. Mantenlo o elige otro."},"install":{"title":"3. Instalación","intro":"Revisa el resumen y luego instala.","data":"Datos","hosting":"Hosting","saveTarget":"Guardando el destino de publicación…","noteConfigJs":"La configuración del admin (config.js) se sube junto al admin en Flexweg cuando es posible; si no, se te ofrecerá descargarla.","noteLocalConfig":"La configuración se guarda en este navegador; se te ofrecerá config.js para ponerlo en la carpeta del admin y que otros editores se salten esta configuración."},"sqliteFile":{"security":"Sin cuentas de usuario: cualquiera que pueda abrir este admin puede editar el contenido — protege la carpeta del admin en tu hosting. El archivo de la base se sirve como cualquier otro archivo: mantenlo cifrado o guárdalo en una ubicación privada aparte.","intro":"Dónde se guarda el archivo de base de datos. Este admin lo lee y lo guarda a través de los mismos conectores que el alojamiento.","path":"Ruta del archivo de base de datos","pathHint":"Se crea al guardar por primera vez si aún no existe. Con un repositorio Git, cada guardado es un commit — mejor usa un repositorio o una rama que no lance un build del sitio.","existing":"base de datos existente","new":"nueva base de datos","dataNote":"Nada que configurar aquí: la base de datos se guardará en el alojamiento que elijas en el siguiente paso.","heading":"Base de datos SQLite","flexwegService":"Usar el servicio SQLite de Flexweg","flexwegServiceHint":"La base de datos la gestiona Flexweg e incluye cuentas de usuario integradas (correo + contraseña). Si no, es un simple archivo en este alojamiento, sin cuentas.","summaryFile":"Archivo {{path}} en este alojamiento","summaryService":"Servicio SQLite de Flexweg ({{path}})","encrypt":"Cifrar la base","encryptHint":"Recomendado en un hosting público: el archivo es ilegible sin la frase de contraseña. Cada navegador nuevo la pide una vez.","passphrase":"Frase de contraseña","passphraseHint":"Guárdala ahora en tu gestor de contraseñas: sin ella nadie puede abrir la base, ni siquiera tú.","copy":"Copiar","copied":"Copiada","generate":"Nueva","passphraseTooShort":"La frase de contraseña debe tener al menos 12 caracteres.","existingEncrypted":"Ya existe una base cifrada en esta ruta: introduce su frase de contraseña.","separate":"Guardar la base en una ubicación privada aparte","separateHint":"P. ej. un bucket S3 / R2 privado o un repositorio Git privado: la base nunca la sirve el sitio público.","summaryEncrypted":"cifrada","summaryLocation":"guardada en {{location}}","locationLabel":"Ubicación de la base","gitBranchNote":"La base se guarda en la rama {{branch}} de este repositorio, que nunca se publica: guardar contenido no vuelve a generar el sitio.","summaryBranch":"en la rama {{branch}}"},"adminHosting":{"deploying":"Copiando el admin al sitio…","label":"Alojar también el admin en este sitio","hint":"El admin se copia en {{url}} con su config.js (sin secretos dentro) — así cada editor puede abrirlo allí. Cada editor sigue iniciando sesión con su propio acceso.","folder":"Carpeta del admin","alreadyHere":"Este admin ya se ejecuta desde este sitio: su config.js se actualizará en su lugar.","doneBody":"El admin ya está en tu sitio. En GitHub Pages, activa primero Pages para el repositorio si aún no lo has hecho (Settings → Pages) y luego ábrelo:","open":"Abrir el admin en línea","continueHere":"Continuar en este admin"}}'),Xre={actions:{upload:"Subiendo archivo",delete:"Eliminando archivo",rename:"Renombrando archivo",get:"Leyendo archivo",list:"Listando archivos",createFolder:"Creando carpeta",renameFolder:"Renombrando carpeta",deleteFolder:"Eliminando carpeta",storageLimits:"Leyendo límites de almacenamiento",commit:"Publicando cambios"},errors:{configMissing:"El destino de publicación no está configurado. Configúralo en Ajustes antes de publicar.",network:"{{action}}: error de red o CORS bloqueado. Comprueba tu conexión.",auth:"{{action}}: falló la autenticación. Revisa las credenciales del destino de publicación en Ajustes.",notFound:"{{action}}: no se encontró en el destino de publicación.",tooLarge:"{{action}}: archivo demasiado grande para el destino de publicación.",rateLimited:"{{action}}: demasiadas peticiones, vuelve a intentarlo en un momento.",serverError:"{{action}}: error del servidor del destino de publicación ({{status}}). Inténtalo de nuevo.",generic:"{{action}} falló ({{status}}){{detail}}.",unsupported:"{{action}}: no compatible con el destino de publicación «{{connector}}».",unknownConnector:"Destino de publicación desconocido «{{connector}}». Revisa Ajustes → Destino de publicación.",folderAccess:"Sin acceso a la carpeta local. Abre Ajustes → Destino de publicación y pulsa «Reconectar carpeta»."}},Zre={log:{rendering:"Generando página…",uploading:"Subiendo {{path}}…",deleting:"Eliminando {{path}}…",regenerating:"Regenerando listados…",skipped:"Omitido {{path}} (sin cambios)",done:"Publicado en {{url}}",failed:"Falló: {{error}}"}},Yre={errors:{notConnected:"No conectado al repositorio de contenido. Vuelve a iniciar sesión con tu token de acceso.",conflict:"Otra persona modificó este elemento mientras tanto. Ahora se muestra su versión: vuelve a aplicar tu cambio.",sqliteUnsupported:"El destino «{{connector}}» no puede guardar un archivo de base de datos."}},ese={target:"Destino de publicación",settingsTitle:"Destino de publicación",settingsHelp:"Dónde se sube el sitio renderizado al publicar. Las credenciales se guardan con tu backend de contenido (o en este navegador para los repositorios Git de contenido) y todos los admins pueden leerlas.",saved:"Destino de publicación guardado. Ejecuta Regenerar → Todo para publicar el sitio completo en el nuevo destino.",test:"Probar la conexión",testOk:"Conexión OK",testFailed:"Error de conexión",names:{flexweg:"Flexweg","git-pages":"Repositorio Git (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"Bucket compatible con S3 (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Tu propio servidor (bridge PHP)","browser-mirror":"Descargar como ZIP","local-folder":"Carpeta local en este ordenador"},hints:{flexweg:"Subida a través de la API Files de Flexweg.","git-pages":"Cada publicación es un commit en el repositorio; el alojamiento reconstruye el sitio a partir de él.",s3:"Requiere una regla CORS en el bucket que permita el origen de este admin, y alojamiento web (o una CDN) para servir los archivos index.html.","php-bridge":"Sube external/bridges/php/flexweg-bridge.php a tu servidor, define su clave de API y luego introduce su URL aquí.","browser-mirror":"El sitio se guarda en este navegador; descarga el ZIP y súbelo a mano donde quieras.","local-folder":"Escribe el sitio directamente en una carpeta (Chrome / Edge). Sírvelo en local o súbelo con tus propias herramientas."},fields:{flexweg:{apiKey:"Clave de API",siteUrl:"URL del sitio",apiBaseUrl:"URL base de la API"},"git-pages":{host:"Alojamiento",provider:"Proveedor Git",owner:"Propietario (usuario u organización)",repo:"Repositorio",project:"Ruta del proyecto",branch:"Rama",dir:"Carpeta en el repositorio",token:"Token de acceso",siteUrl:"URL pública del sitio",apiBaseUrl:"URL de la API (solo autoalojado)"},s3:{endpoint:"Endpoint",region:"Región",bucket:"Bucket",prefix:"Prefijo de claves (opcional)",accessKeyId:"ID de clave de acceso",secretAccessKey:"Clave de acceso secreta",siteUrl:"URL pública del sitio",forcePathStyle:"URLs de tipo ruta (MinIO, R2, la mayoría de compatibles)",publicRead:"Hacer públicos los archivos subidos (ACL public-read) — para buckets que no son públicos mediante una política (OVHcloud, Scaleway…). Déjalo desactivado en buckets de AWS con «bucket owner enforced»."},"php-bridge":{apiBaseUrl:"URL del bridge",apiKey:"Clave de API del bridge",siteUrl:"URL pública del sitio"},"browser-mirror":{siteUrl:"URL pública del sitio (opcional)"},"local-folder":{siteUrl:"URL en la que se sirve la carpeta (opcional)"}},help:{flexweg:{apiKey:"Se genera desde tu cuenta de Flexweg → API."},"git-pages":{host:"Cloudflare Pages: conecta el proyecto a este repositorio sin comando de build y con la carpeta de salida de abajo. Funciona con repositorios privados.",dir:'Déjalo vacío para la raíz del repositorio. GitHub Pages: "" o "docs". GitLab Pages: "public".',token:"Token fine-grained sobre este repositorio con Contents: read & write (GitHub) — añade Pages: read & write para que el CMS pueda activar GitHub Pages — o un token con el scope api (GitLab). Déjalo vacío para usar el token de acceso de cada editor cuando el contenido está en el mismo proveedor.",siteUrl:"p. ej. https://user.github.io/repo — una URL con subcarpeta sirve, los enlaces se ajustan automáticamente."},s3:{endpoint:"Déjalo vacío para AWS (se deduce de la región). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"La URL de sitio web del bucket o tu dominio de CDN."},"php-bridge":{apiBaseUrl:"La URL completa de flexweg-bridge.php en tu servidor (HTTPS)."},"browser-mirror":{siteUrl:"Donde subirás el ZIP — se usa para las URLs absolutas (sitemaps, RSS, medios)."},"local-folder":{siteUrl:"p. ej. http://localhost:8080 cuando un servidor web local sirve la carpeta."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (conectado al repositorio)","gitlab-pages":"GitLab Pages",other:"Otro (Netlify, Vercel, git pull en el servidor…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Elegir carpeta…",change:"Cambiar de carpeta…",reconnect:"Volver a conectar la carpeta",unsupported:"Este navegador no puede escribir en carpetas locales. Usa Chrome o Edge."},mirror:{download:"Descargar el sitio (ZIP)",count:"{{count}} archivos en este navegador"},adminHosting:{title:"Admin en este sitio",help:"Copia este admin en el destino de publicación (primer despliegue, o actualización tras una nueva versión). Su config.js no contiene secretos.",deploy:"Desplegar / actualizar el admin",deployed:"Admin desplegado ({{count}} archivos) — {{url}}"},pages:{enabled:"GitHub Pages activado para este repositorio — el sitio estará en línea en un minuto aproximadamente.",enableHint:'Publicación completada. Para poner el sitio en línea, activa GitHub Pages para {{repo}}: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (O da al token el permiso "Pages: read and write" y el CMS lo hará por ti.)'},siteUrl:{mismatch:"La URL pública del sitio (Ajustes → Sitio) es {{site}}, pero este destino sirve el sitio en {{target}}. Los enlaces, el CSS y los sitemaps siguen la URL del sitio: serán incorrectos en este alojamiento.",use:"Usar {{url}} para el sitio",updated:"URL del sitio actualizada. Ejecuta Regenerar → Todo para volver a publicar las páginas con los nuevos enlaces."}},tse={heading:"Conectar con el repositorio de contenido",tokenIntro:"El contenido se guarda en el repositorio {{provider}} {{repo}}. Inicia sesión con tu propio token de acceso personal — tus permisos en el repositorio deciden tu rol (escritura = editor, admin / maintainer = admin).",token:"Token de acceso personal",tokenHelpGithub:"Token fine-grained, con acceso solo a este repositorio, permiso Contents: lectura y escritura.",tokenHelpGitlab:"Token con el api scope, rol Developer o superior en este proyecto.",createToken:"Crear un token",connect:"Conectar",tokenStorage:"El token se guarda solo en este navegador. Al cerrar sesión se olvida.",failed:"Este token no puede escribir en el repositorio (no válido, caducado o de solo lectura). Comprueba sus permisos.",folderIntro:"El contenido se guarda en una carpeta de este ordenador (normalmente un clon git que sincronizas con tu propio cliente git). Concede acceso a este navegador — los navegadores vuelven a pedirlo tras cada recarga.",openFolder:"Abrir la carpeta de contenido"},nse={flexweg:{title:"Flexweg",short:"Hosting Flexweg",hint:"Sube a través de la Flexweg Files API. Clave API de tu cuenta Flexweg."},"github-pages":{title:"GitHub Pages",short:"Gratis, desde un repositorio GitHub",hint:"Cada publicación es un commit en el repositorio; GitHub Pages lo sirve. Settings → Pages → Deploy from a branch. Repositorios públicos en el plan gratuito."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Gratis, admite repositorios privados",hint:"El CMS hace commit del sitio en un repositorio GitHub / GitLab; conecta un proyecto de Cloudflare Pages a él (sin comando de build, carpeta de salida = la carpeta de abajo)."},"gitlab-pages":{title:"GitLab Pages",short:"Gratis, desde un repositorio GitLab",hint:"Cada publicación es un commit; el CMS añade un .gitlab-ci.yml mínimo que publica la carpeta public/."},"git-other":{title:"Netlify, Vercel…",short:"Cualquier host que despliegue un repositorio",hint:"El CMS hace commit del sitio en un repositorio Git; conecta tu host (Netlify, Vercel, un servidor que ejecuta git pull…) a ese repositorio."},s3:{title:"S3 / R2 / B2…",short:"Bucket de almacenamiento de objetos",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Requiere una regla CORS en el bucket y alojamiento web o un CDN delante."},"own-server":{title:"Tu propio servidor (FTP / SFTP)",short:"Hosting compartido, VPS…",hint:"Los navegadores no hablan FTP ni SFTP: sube una vez el puente PHP (external/bridges/php/flexweg-bridge.php) con tu cliente FTP, define su clave API y luego introduce su URL aquí. Funciona en cualquier host PHP."},"local-folder":{title:"Carpeta local",short:"En este ordenador",hint:"Escribe el sitio en una carpeta de este ordenador (Chrome / Edge). Sírvelo localmente o súbelo con tus propias herramientas."},zip:{title:"Descargar como ZIP",short:"Súbelo a mano",hint:"El sitio se guarda en este navegador; descarga un ZIP desde Ajustes y súbelo donde quieras (Netlify Drop, cliente FTP…)."}},rse={heading:"Conectarse a la base de datos",intro:"Este admin guarda su contenido en {{path}}. Introduce las credenciales de acceso para este navegador.",storage:"Las credenciales solo se guardan en este navegador. Al cerrar sesión se olvidan.",passphrase:"Frase de contraseña de la base",passphraseHint:"La base está cifrada. Introduce la frase de contraseña elegida en la instalación (se guarda solo en este navegador).",passphraseWrong:"Frase de contraseña incorrecta: no se pudo abrir la base.",passphraseMissing:"Introduce la frase de contraseña de la base."},sse={common:Rre,auth:jre,nav:Mre,dashboard:Lre,posts:Dre,pages:Fre,taxonomies:Ore,media:zre,themes:Ure,plugins:Bre,externalInstall:$re,externalLoader:Hre,menus:Vre,settings:qre,users:Wre,firestoreSetup:Gre,errors:Kre,identity:Jre,setup:Qre,flexweg:Xre,publish:Zre,docstore:Yre,connectors:ese,gitAccess:tse,hosting:nse,sqliteAccess:rse},ise={save:"Opslaan",saving:"Opslaan…",saved:"Opgeslagen",cancel:"Annuleren",delete:"Verwijderen",deleting:"Verwijderen…",edit:"Bewerken",create:"Aanmaken",search:"Zoeken",loading:"Laden…",yes:"Ja",no:"Nee",confirm:"Bevestigen",back:"Terug",next:"Volgende",previous:"Vorige",close:"Sluiten",all:"Alle",none:"Geen",actions:"Acties",name:"Naam",slug:"Slug",description:"Beschrijving",status:"Status",createdAt:"Aangemaakt",updatedAt:"Bijgewerkt",publishedAt:"Gepubliceerd",language:"Taal",darkMode:"Donkere modus",lightMode:"Lichte modus",signOut:"Uitloggen",administrator:"Beheerder",editor:"Redacteur",appName:"Flexweg CMS"},ase={signIn:"Inloggen",signingIn:"Inloggen…",email:"E-mail",password:"Wachtwoord",emailPlaceholder:"u@bedrijf.com",passwordPlaceholder:"••••••••",forgotPassword:"Wachtwoord vergeten?",resetEmailSent:"E-mail om wachtwoord opnieuw in te stellen verzonden naar {{email}}.",enterEmailFirst:"Voer eerst uw e-mail hierboven in en klik dan op resetten.",emailPasswordRequired:"E-mail en wachtwoord zijn vereist.",signInSubtitle:"Gebruik uw werk-e-mail en wachtwoord.",footer:"Accountaanvragen verlopen via uw beheerder.",errors:{invalidEmail:"Ongeldig e-mailadres.",invalidCredentials:"Ongeldig e-mailadres of wachtwoord.",tooManyRequests:"Te veel pogingen. Probeer later opnieuw of stel uw wachtwoord opnieuw in.",userDisabled:"Dit account is uitgeschakeld.",networkFailed:"Netwerkfout. Controleer uw verbinding.",generic:"Authenticatie mislukt."}},ose={openMenu:"Menu openen",closeMenu:"Menu sluiten",dashboard:"Dashboard",posts:"Berichten",pages:"Pagina's",taxonomies:"Categorieën & Tags",media:"Media",themes:"Thema's",themeSettings:"Thema-instellingen",plugins:"Plugins",menus:"Menu's",users:"Gebruikers",settings:"Instellingen"},lse={title:"Dashboard",welcome:"Welkom terug, {{email}}.",stats:{totalPosts:"Berichten",totalPages:"Pagina's",online:"Online",drafts:"Concepten"}},cse={title:"Berichten",newPost:"Nieuw bericht",noPosts:"Nog geen berichten. Maak uw eerste bericht om te beginnen.",noPostsInFilter:"Geen berichten passen bij het huidige filter.",search:{placeholder:"Berichten zoeken…",clear:"Zoekopdracht wissen",noResults:"Geen berichten komen overeen met uw zoekopdracht."},pagination:{previous:"Vorige",next:"Volgende",showing:"{{from}}–{{to}} van {{total}} weergegeven",pageOf:"Pagina {{page}} van {{total}}"},bulk:{selectedCount_one:"{{count}} geselecteerd",selectedCount_other:"{{count}} geselecteerd",selectPage_one:"{{count}} op deze pagina selecteren",selectPage_other:"Alle {{count}} op deze pagina selecteren",deselectPage:"Pagina deselecteren",allOnPageSelected_one:"{{count}} op deze pagina geselecteerd.",allOnPageSelected_other:"Alle {{count}} op deze pagina geselecteerd.",selectAllMatching_one:"Het overeenkomende bericht selecteren",selectAllMatching_other:"Alle {{count}} overeenkomende berichten selecteren",allMatchingSelected_one:"Het overeenkomende bericht is geselecteerd.",allMatchingSelected_other:"Alle {{count}} overeenkomende berichten zijn geselecteerd.",selectOne:'"{{title}}" selecteren',publish:"Publiceren ({{count}})",publishing:"Publiceren…",publishedCount:"{{ok}} gepubliceerd, {{failed}} mislukt.",unpublish:"Depubliceren ({{count}})",unpublishing:"Depubliceren…",unpublishedCount:"{{ok}} gedepubliceerd, {{failed}} mislukt.",delete:"Verwijderen",deleting:"Verwijderen…",deletedCount:"{{ok}} verwijderd, {{failed}} mislukt.",confirmDelete_one:"{{count}} bericht verwijderen? Dit depubliceert van Flexweg en kan niet ongedaan worden gemaakt.",confirmDelete_other:"{{count}} berichten verwijderen? Dit depubliceert van Flexweg en kan niet ongedaan worden gemaakt.",noDraftSelected:"Geen conceptberichten geselecteerd.",noOnlineSelected:"Geen online berichten geselecteerd.",clear:"Selectie wissen"},filters:{all:"Alle",draft:"Concept",online:"Online"},fields:{title:"Titel",slug:"Slug",excerpt:"Samenvatting",content:"Inhoud",category:"Categorie",tags:"Tags",heroImage:"Uitgelichte afbeelding",seoTitle:"SEO-titel",seoDescription:"SEO-beschrijving",createdAt:"Aangemaakt op",updatedAt:"Laatst bijgewerkt",publishedAt:"Gepubliceerd op"},edit:{newTitle:"Nieuw bericht",editTitle:"Bericht bewerken",saved:"Opgeslagen.",savedAndRepublished:"Opgeslagen en opnieuw gepubliceerd.",saveFailed:"Opslaan mislukt.",saveAndRepublish:"Opslaan en opnieuw publiceren",draftSaved:"Concept opgeslagen.",slugCollision:{post:'Deze URL wordt al gebruikt door bericht: "{{label}}".',page:'Deze URL wordt al gebruikt door pagina: "{{label}}".',category:'Deze URL wordt al gebruikt door categorie: "{{label}}".'},publish:"Publiceren",unpublish:"Depubliceren",publishing:"Publiceren…",unpublishing:"Depubliceren…",titlePlaceholder:"Titel toevoegen",permalink:"Permalink",slugFormatHint:"Alleen kleine letters, ASCII, gescheiden door streepjes.",slugAutoSuffixed:'Suffix toegevoegd omdat "{{base}}" al wordt gebruikt door {{owner}}.',slugAutoSuffixedOwner:{post:'bericht: "{{label}}"',page:'pagina: "{{label}}"',category:'categorie: "{{label}}"'},saveBlocked:{titleRequired:"Voeg een titel toe voordat u opslaat.",slugRequired:"Een titel en URL-slug zijn vereist om op te slaan.",slugInvalid:"Ongeldig slug-formaat (ASCII in kleine letters + streepjes).",slugCollision:"Los het URL-conflict op voordat u opslaat."},viewPublished:"Bekijken",confirmDelete:"Dit item verwijderen?",inspector:{document:"Document",block:"Blok",blockEmpty:"Selecteer een blok in de editor om de opties te zien.",publishing:"Publicatie",permalink:"Permalink",categories:"Categorieën & tags",featured:"Uitgelichte afbeelding",seo:"SEO",excerpt:"Samenvatting",dates:"Datums"},blocks:{addBlock:"Blok toevoegen",transform:"Omzetten naar",moveUp:"Omhoog verplaatsen",moveDown:"Omlaag verplaatsen",duplicate:"Dupliceren",remove:"Blok verwijderen",paragraph:"Paragraaf",heading2:"Kop 2",heading3:"Kop 3",bulletList:"Opsomming",orderedList:"Genummerde lijst",blockquote:"Citaat",codeBlock:"Code",image:"Afbeelding",horizontalRule:"Scheiding",categories:{text:"Tekst",media:"Media",layout:"Lay-out",embed:"Insluitingen",advanced:"Geavanceerd"},noSettings:"Dit blok heeft geen instellingen.",noSelection:"Selecteer een blok in de editor om de opties te zien.",slash:{noResults:"Geen overeenkomend blok."}}},status:{draft:"Concept",online:"Online"},preview:{title:"Voorbeeld",rendering:"Voorbeeld renderen…",error:"Voorbeeld mislukt: {{error}}",viewports:{mobile:"Mobiel",tablet:"Tablet",desktop:"Desktop"}}},use={title:"Pagina's",newPage:"Nieuwe pagina",noPages:"Nog geen pagina's.",homeBadge:"Startpagina",homeBadgeTooltip:"Wordt gebruikt als startpagina van de site"},dse={title:"Categorieën & Tags",categories:"Categorieën",tags:"Tags",newCategory:"Nieuwe categorie",newTag:"Nieuwe tag",noCategories:"Nog geen categorieën.",noTags:"Nog geen tags.",slugCollision:'Deze slug wordt al gebruikt door "{{label}}".',seo:{button:"SEO",buttonTitle:"SEO-metatags bewerken",title:"SEO-metatags",subtitle:'Aangepaste titel en beschrijving voor de archiefpagina van "{{name}}".',metaTitle:"Metatitel",metaTitleHint:"Gebruikt als <title> van de pagina. Standaard: de naam van de term.",metaDescription:"Metabeschrijving",metaDescriptionHint:"Gebruikt als metabeschrijving van de pagina. Standaard: de beschrijving van de term."}},hse={title:"Mediabibliotheek",upload:"Uploaden",uploading:"Uploaden…",finalizing:"Afronden…",uploadFailed:"Upload mislukt",retry:"Opnieuw proberen",noMedia:"Nog geen media.",alt:"Alt-tekst",caption:"Bijschrift",filename:"Bestandsnaam",size:"Grootte",type:"Type"},fse={title:"Thema's",active:"Actief",activate:"Activeren",installExternal:"Thema installeren",uninstallDisabledTitle:"Schakel naar een ander thema voordat u dit deïnstalleert.",syncAssets:"Thema-bestanden synchroniseren",regenerateSite:"Site opnieuw genereren",regenerating:"Opnieuw genereren…",regenerate:{button:"Opnieuw genereren",running:"Bezig…",groupBuiltins:"Site",groupPlugins:"Plugins",home:"Alleen homepage",homeHelp:"Genereert alleen index.html opnieuw — snelste optie.",allHtml:"Alle HTML-pagina's",allHtmlHelp:"Elke post, pagina, archief en lijst — plus menu / posts / authors JSON-snapshots.",repair:"URL's herstellen",repairHelp:"Berekent de canonieke URL van elke online post opnieuw en verplaatst bestanden die op de verkeerde URL terechtkwamen. Handig na een import die liep voordat de termen gesynchroniseerd waren.",assets:"Thema-bestanden",assetsHelp:"Uploadt CSS + bijbehorende scripts van het actieve thema naar /theme-assets/.",everything:"Alles",everythingHelp:"Thema-bestanden + alle HTML + elke plugin-uitvoer. Langzaamste optie.",noPluginTargets:"Geen plugin-regeneraties — activeer een plugin die regenereren ondersteunt."},confirmSwitch:{title:"Overschakelen naar {{theme}}?",body:"Wisselen van thema vereist het opnieuw uploaden van de thema-bestanden en het regenereren van elke gepubliceerde pagina zodat het nieuwe uiterlijk overal doorwerkt. Dit kan even duren.",confirm:"Overschakelen en regenereren",cancel:"Annuleren"}},pse={title:"Plugins",enabled:"Ingeschakeld",disabled:"Uitgeschakeld",enable:"Inschakelen",disable:"Uitschakelen",configure:"Configureren",author:"auteur",learnMore:"Meer info",mustUseBadge:"Verplicht",installExternal:"Plugin installeren",tabs:{regular:"Plugins",mustUse:"Verplichte plugins"}},mse={titlePlugin:"Een plugin installeren",titleTheme:"Een thema installeren",labelPlugin:"plugin",labelTheme:"thema",intro:"Sleep een ZIP-bestand met een {{label}}-bundle (manifest.json + bundle.js in de root van de ZIP) hierheen. De {{label}} wordt naar uw Flexweg-site geüpload en na een herlaad geregistreerd. Een ZIP met dezelfde manifest-id opnieuw uploaden werkt het bestaande item ter plaatse bij — geen deïnstallatie nodig.",zipField:"Bundle-ZIP-bestand",install:"Installeren",installing:"Bezig met installeren…",installSuccess:"{{name}} geïnstalleerd ({{count}} bestanden geüpload). Herladen…",upgradeSuccess:"{{name}} bijgewerkt van v{{previousVersion}} naar v{{newVersion}} ({{count}} bestanden geüpload). Herladen…",installedTitle:"Al geïnstalleerd",bundledDefaultsTitle:"Meegeleverde standaards beschikbaar",bundledDefaultsHint:"{{count}} meegeleverde plugin/thema is momenteel gedeïnstalleerd. Herstel ze om terug te krijgen wat met deze admin-versie werd meegeleverd.",bundledDefaultsRestore:"Herstellen",bundledDefaultsRestored:"{{plugins}} plugin(s) en {{themes}} thema('s) hersteld. Herladen…",uninstall:"Deïnstalleren",uninstallSuccess:"{{id}} gedeïnstalleerd. Herladen…",confirmUninstall:"{{id}} deïnstalleren? Bestanden worden verwijderd van Flexweg.",errors:{"no-manifest":"ZIP mist manifest.json in de root.","invalid-manifest":"manifest.json is ongeldig (verplichte velden ontbreken of het is geen geldig JSON).","incompatible-api":"De bundle is gebouwd tegen een incompatibele runtime-API-versie.","no-bundle":"De ZIP bevat niet het in het manifest opgegeven entry-bestand.","fetch-manifest":"Kon de huidige external.json op Flexweg niet lezen.","upload-failed":"Upload mislukt — controleer uw Flexweg-API-sleutel en uw verbinding."}},gse={someFailed:"{{count}} externe bundle(s) konden niet worden geladen. Bekijk de browserconsole."},bse={title:"Menu's",header:"Hoofdmenu",footer:"Voettekstmenu",label:"Label",saveAndPublish:"Opslaan & genereren",discard:"Negeren",saved:"Menu's opgeslagen en gepubliceerd.",saveFailed:"Kon menu's niet opslaan.",unsavedChanges:"U heeft niet-opgeslagen wijzigingen."},yse={title:"Instellingen",tabs:{general:"Algemeen"},site:{title:"Site",siteTitle:"Sitetitel",siteDescription:"Sitebeschrijving",siteLanguage:"Sitetaal",siteLanguageHelp:'BCP-47-tag (bv. en, fr-CA) die op elke gepubliceerde pagina in <html lang="…"> wordt geplaatst. Het voorvoegsel wordt vergeleken met de ondersteunde vertaallocales voor sitemap-/RSS-labels en in het thema ingebakken teksten; niet-ondersteunde locales vallen terug op Engels.',siteLanguageResolved:"Vertalingen gebruiken: {{label}}",baseUrl:"Publieke site-URL",postsPerPage:"Berichten per pagina",homeMode:"Inhoud startpagina",homeLatest:"Laatste berichten",homeStatic:"Statische pagina",homePage:"Startpagina",discourageIndexing:"Zoekmachines ontmoedigen deze site te indexeren",discourageIndexingHelp:"Indien ingeschakeld krijgt elke gepubliceerde pagina een noindex/nofollow-metatag en blokkeert robots.txt alle crawlers. Volgt het gedrag van WordPress — handig voor stagingsites of controles vóór de lancering. Zoekmachines die de instructie respecteren, indexeren de site niet.",discourageRegenerateHint:"Indexeringsinstelling opgeslagen. Klik in Thema's op 'Alles opnieuw genereren' om de wijziging toe te passen op alle gepubliceerde pagina's en robots.txt."},flexweg:{title:"Flexweg-API",apiKey:"API-sleutel",apiKeyHelp:"Aangemaakt vanuit uw Flexweg-account → API.",siteUrl:"Site-URL",siteUrlHelp:"Publieke URL van uw Flexweg-site zonder slash op het einde.",apiBaseUrl:"API-basis-URL",storageHelpFirebase:"Opgeslagen in Firestore (config/flexweg). Te lezen door elk ingelogd teamlid, alleen door beheerders te schrijven.",storageHelpSqlite:"Opgeslagen in de lokale SQLite-tabel config. Te lezen door elk ingelogd teamlid, alleen door beheerders te schrijven."},backend:{title:"Data-backend",active:"Actief backend:",switchButton:"Backend wisselen…",confirmTitle:"Alle huidige data gaat verloren.",confirmBody:"Wisselen wist de configuratie in de browser en herlaadt het instelformulier. Het nieuwe backend start leeg — de data van het vorige backend blijft staan (in Firestore of als .sqlite-bestand op Flexweg), maar het CMS leest het pas weer wanneer u terug wisselt.",confirmYes:"Ja, backend wisselen",downloadBackup:"Download een back-up van het .sqlite-bestand",downloadBackupHelp:"doe dit voordat u van backend wisselt.",markdownGit:"Markdown — {{source}}",localFolder:"lokale map",localBrowser:"Deze browser (lokaal, één gebruiker)",sqliteFile:"SQLite-bestand — {{location}}"},performance:{title:"Prestaties",help:"Hoe de admin berichten en pagina's laadt. De standaardmodus werkt op het gratis Firestore-plan zonder setup; de gepagineerde modus is voor zeer grote sites en vereist eenmalige index-setup.",mode:"Laadmodus",modeGlobal:"Standaard (geen setup nodig)",modePaginated:"Server-side gepagineerd (Firestore-indexen vereist)",globalHelp:"Laadt de hele berichten-collectie in één live abonnement. Sorteren, filteren en zoeken gebeurt in het geheugen. Aanbevolen voor sites met minder dan ~5 000 berichten.",paginatedHelp:"Cursor-gepagineerde abonnementen, één pagina per keer. Vereist Firestore-composite-indexen — zie README. Aanbevolen voor zeer grote sites.",savedReload:"Opgeslagen. Herlaad de admin om de nieuwe modus toe te passen."},editor:{title:"Editor",help:"Typografie binnen de bericht-/pagina-editor. Onafhankelijk van het publieke thema.",fontFamily:"Lettertypefamilie",bodySize:"Tekstgrootte",h1Size:"H1-grootte",h2Size:"H2-grootte",h3Size:"H3-grootte",sizeHelp:"CSS-lengte, bijv. 16px of 1rem. Laat leeg voor standaard.",reset:"Terugzetten naar standaard"},profile:{title:"Profiel",adminLocale:"Admin-taal",adminLocaleHelp:"Taal die wordt gebruikt door de adminschermen. Opgeslagen in uw profiel.",firstName:"Voornaam",lastName:"Achternaam",headline:"Titel",headlinePlaceholder:"bv. Journalist, Hoofdredacteur…",headlineHelp:"Wordt openbaar onder uw naam getoond in auteurkaarten en op uw archiefpagina.",bio:"Biografie",bioPlaceholder:"Een korte alinea die op uw auteurspagina en onder uw artikelen verschijnt.",bioHelp:"Zichtbaar op de publieke site in de auteur-zijbalk en op de auteursarchiefpagina.",socials:"Sociale profielen",socialsHelp:`Voeg de URL's toe van de profielen die u op de publieke site wilt tonen en vink "Tonen" aan voor de zichtbare. Lege URL's worden genegeerd.`,socialsShow:"Tonen",socialsShowHelp:"Schakelt de zichtbaarheid van dit netwerk op de publieke site om.",avatar:"Profielfoto",avatarHelp:"Kies een afbeelding uit uw mediabibliotheek. Vierkante afbeeldingen werken het best.",pickAvatar:"Kies uit media",changeAvatar:"Foto wijzigen",removeAvatar:"Verwijderen",save:"Profiel opslaan"},transfer:{title:"Content verplaatsen of back-uppen",help:"Exporteer alles (posts, pagina's, categorieën, metadata van media, profielen, instellingen) als één JSON-bestand. Op een Markdown- of lokaal backend kunt u zo'n bestand importeren met behoud van de id's — zo migreert u vanaf Firebase of SQLite. Mediabestanden en geheime sleutels worden niet meegenomen.",export:"Content exporteren (JSON)",import:"Content importeren…",modeMerge:"Samenvoegen (zelfde id's overschrijven)",modeReplace:"Geïmporteerde collecties vervangen",replaceConfirm:"De modus Vervangen verwijdert vóór het importeren alle bestaande items van de collecties die in het bestand staan. Doorgaan?",invalidFile:"Dit bestand is geen contentexport van Flexweg CMS.",imported:"{{posts}} posts/pagina's, {{terms}} termen en {{media}} media geïmporteerd. Voer Opnieuw genereren → Alles uit om ze te publiceren."},encryption:{title:"Databaseversleuteling:",on:"aan",off:"uit",onHelp:"Het databasebestand is onleesbaar zonder de wachtzin. Wijzigen slaat het bestand opnieuw op met een nieuwe sleutel; andere browsers vragen om de nieuwe wachtzin.",offHelp:"Het databasebestand is leesbaar voor iedereen die het kan downloaden (statische hosting serveert het als elke pagina). Versleutel het met een wachtzin.",enable:"Database versleutelen…",change:"Wachtzin wijzigen…",savedConfirm:"Ik heb deze wachtzin in mijn wachtwoordmanager bewaard — zonder kan de inhoud niet worden geopend.",enableConfirm:"Nu versleutelen",changeConfirm:"Wachtzin wijzigen",done:"Database opnieuw opgeslagen met de nieuwe wachtzin."}},vse={title:"Gebruikers",noUsers:"Nog geen gebruikers.",role:"Rol",disabled:"Uitgeschakeld",editProfileTitle:"Profiel bewerken — {{email}}",profileSaved:"Profiel opgeslagen.",descriptionFirebase:"Beheer uw team. Nieuwe accounts worden aangemaakt in de Firebase Console en hier gespiegeld bij de eerste keer inloggen.",descriptionSqlite:"Beheer uw team. Gebruik de knop +Gebruiker toevoegen hieronder om accounts direct aan te maken.",addUser:"Gebruiker toevoegen",addUserSuccess:"{{email}} toegevoegd.",removeConfirmFirebase:"Het record van {{email}} verwijderen? Hiermee verwijdert u hun profiel en rol uit het CMS. Om hun login-toegang in te trekken, verwijdert u het account ook in de Firebase Console.",removeConfirmSqlite:"{{email}} definitief verwijderen? Dit trekt hun login-toegang in EN verwijdert hun profiel en rol. Dit kan niet ongedaan worden gemaakt.",empty:{title:"Nog geen teamleden",descriptionFirebase:"Maak het eerste account aan in de Firebase Console en log hier daarna één keer in om het profiel te registreren.",descriptionSqlite:"Klik op +Gebruiker toevoegen hierboven om het eerste teamlid uit te nodigen."},help:{title:"Hoe u een nieuw teamlid toevoegt",bootstrapLine:"De bootstrap-admin (altijd volledige toegang) is:",firebase:{step1:"Open de Firebase Console → Authentication → Add user.",step2:"Stel een e-mail en wachtwoord in en stuur ze naar het nieuwe teamlid.",step3:"Vraag hen om hier één keer in te loggen — hun profiel verschijnt in de lijst hierboven en u kunt hun rol en gegevens bewerken."},sqlite:{step1:"Klik op de knop +Gebruiker toevoegen hierboven.",step2:"Voer hun e-mail en een tijdelijk wachtwoord (8+ tekens) in.",step3:"Deel de inloggegevens veilig — ze kunnen het wachtwoord vanuit hun profiel wijzigen zodra ze zijn ingelogd."},git:{step1:"Voeg de persoon toe als collaborator van de content-repository (schrijftoegang = redacteur, admin / maintainer = admin).",step2:"Diegene maakt een eigen persoonlijk toegangstoken aan op GitHub / GitLab.",step3:"Diegene opent de admin en logt in met dat token — het profiel wordt hier automatisch aangemaakt."}},addUserModal:{title:"Een nieuw teamlid toevoegen",intro:"Maakt het account direct aan in de Flexweg SQLite Auth-database. De nieuwe gebruiker krijgt standaard de rol editor; promoveer hem of haar via de lijst hieronder als adminrechten nodig zijn.",submit:"Gebruiker aanmaken",submitting:"Aanmaken…"},actions:{editProfile:"Profiel bewerken",promote:"Promoveren tot beheerder",demote:"Degraderen tot redacteur",disable:"Uitschakelen",enable:"Inschakelen",delete:"Record verwijderen"},descriptionGit:"Teamleden zijn de personen met schrijftoegang tot de content-repository. Ze verschijnen hier na hun eerste login; hun rol volgt hun rechten op de repository.",descriptionLocal:"Deze admin draait in modus voor één gebruiker: content wordt in deze browser opgeslagen en er zijn geen accounts.",descriptionSqliteFile:"Geen gebruikersaccounts met dit backend: iedereen die de admin kan openen, kan bewerken. Beveilig de admin-map op het niveau van uw hosting. De auteursprofielen hieronder zijn ter informatie."},xse={title:"Firestore-setup vereist",intro:"De berichten- en pagina-overzichtspagina's hebben enkele Firestore composite indexes nodig om efficiënt te queryen. Die moeten handmatig worden aangemaakt — Firebase reserveert het aanmaken van indexes voor projectbeheerders.",checking:"Uw Firestore-indexes controleren…",missingCount_one:"{{count}} index ontbreekt:",missingCount_other:"{{count}} indexes ontbreken:",openConsole:"Firebase Console openen om aan te maken",noUrl:"Auto-suggestie-URL niet extraheerbaar — zie README voor het gcloud-commando.",howItWorks:"Hoe het werkt",step1:"Klik op de link voor elke ontbrekende index — Firebase Console opent met de definitie vooraf ingevuld.",step2:'Klik op "Create" en wacht 1–5 minuten tot de index is opgebouwd (status in de console).',step3:"Kom terug en klik op Opnieuw proberen. Zodra beide queries slagen, laadt de admin.",retry:"Opnieuw proberen",retrying:"Opnieuw proberen…",buildHint:"Het opbouwen van een index kan na aanmaak een paar minuten duren.",allReady:"Alle indexes klaar.",unexpectedTitle:"Firestore niet bereikbaar",unexpectedHint:"Controleer uw verbinding en Firestore-regels. Als u net de indexes hebt aangemaakt, wacht tot ze klaar zijn en probeer opnieuw."},wse={appError:"Toepassingsfout",loadAccountFailed:"Kon uw account niet laden",loadAccountHint:"Als het probleem aanhoudt, log uit en probeer opnieuw.",accountDisabled:"Account uitgeschakeld",accountDisabledMessage:"Uw toegang tot deze CMS is uitgeschakeld. Neem contact op met uw beheerder.",firebaseNotConfigured:"Firebase is niet geconfigureerd",firebaseEnvMissing:`De volgende omgevingsvariabelen ontbreken:
|
|
3859
|
+
Copia .env.example a .env, rellena las credenciales de tu proyecto Firebase y reinicia el servidor de desarrollo.`,adminEmailNotConfigured:"El correo del admin no está configurado",adminEmailMessage:"Falta VITE_ADMIN_EMAIL en .env. Establécelo con el correo del administrador inicial.",consoleHint:"Revisa la consola del navegador y tu configuración .env. Consulta el README para las instrucciones de configuración."},Jre={brandTitle:"AgentCMS",brandSubtitle:"Publicación estática",login:{heading:"Iniciar sesión",intro:"Usa el correo y la contraseña que te ha facilitado tu administrador.",submit:"Iniciar sesión",submitting:"Iniciando sesión…"},fields:{name:"Nombre a mostrar (opcional)",namePlaceholder:"Juan Pérez",email:"Correo electrónico",password:"Contraseña",passwordHint:"Al menos 8 caracteres."},footer:"Las nuevas cuentas las crea un administrador desde la página Usuarios.",errors:{invalidEmail:"Introduce una dirección de correo válida.",missingPassword:"La contraseña es obligatoria.",passwordTooShort:"La contraseña debe tener al menos 8 caracteres."}},Qre=JSON.parse('{"title":"Bienvenido a AgentCMS","subtitle":"Configuración inicial","intro":"Introduce tus credenciales de Firebase, la cuenta del administrador inicial y tu clave API de Flexweg. Los valores se validan, se guardan en tu proyecto (Firestore + un archivo config.js en Flexweg) y el admin recarga al flujo de inicio de sesión normal. Solo tienes que hacerlo una vez.","introFirebase":"Paso 1 — Firebase. Introduce las credenciales de tu proyecto Firebase y la cuenta de administrador bootstrap. Iniciamos sesión, verificamos el correo y comprobamos que tus reglas de Firestore reconozcan a este admin antes de pasar al paso Flexweg.","introFlexweg":"Paso 2 — Flexweg. Introduce tu clave API Flexweg y la URL del sitio. Probamos la API, guardamos la configuración en Firestore, subimos config.js a tu sitio y sincronizamos los activos del tema.","continueToFlexweg":"Validar Firebase y continuar","stepper":{"terms":"Condiciones","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Contenido y publicación","data":"Datos","hosting":"Hosting","install":"Instalación"},"backend":{"title":"Elige un backend de datos","intro":"Elige dónde el CMS guardará tus posts, páginas, usuarios y ajustes. Puedes cambiarlo luego desde Ajustes (los datos no se migran).","sqliteTitle":"Flexweg SQLite (recomendado)","sqliteHint":"Todos los datos se quedan en tu sitio Flexweg como un archivo SQLite. Sin servicio externo. La auth la proporciona la API SQLite de Flexweg.","firebaseTitle":"Firebase","firebaseHint":"Usa un proyecto Firebase para Firestore + Auth. Gratis con el plan Spark. Actualizaciones en tiempo real vía onSnapshot.","continue":"Continuar","markdownGitTitle":"Archivos Markdown en un repositorio Git","markdownGitHint":"Entradas como archivos .md en GitHub / GitLab (o un clon local). Cada editor inicia sesión con su propio token de acceso; cada cambio es un commit. Sin base de datos, funciona con varios editores y equipos.","localTitle":"Solo este navegador","localHint":"Un solo usuario, sin inicio de sesión, nada que configurar. El contenido se queda en este navegador (expórtalo desde Ajustes). Ideal para un admin que se ejecuta en tu propio ordenador."},"sqlite":{"heading":"Conecta tu sitio Flexweg","intro":"Usaremos tu clave API maestra de Flexweg UNA SOLA VEZ para crear un token con alcance limitado para la base de datos SQLite. Tras la instalación, la clave maestra se descarta y solo se almacena el token con alcance (limitado a este único archivo SQLite).","apiKeyHint":"Clave API maestra de Flexweg. Se usa solo para instalar — nunca se almacena después.","detectedFromUrl":"Detectado desde la URL","advanced":"Ajustes avanzados (URL del sitio, ruta SQLite…)","pathHint":"Dónde vive el archivo SQLite en tu sitio Flexweg. Las carpetas se crean automáticamente.","adminHeading":"Cuenta de administrador","adminIntro":"Crea el primer usuario — esta cuenta obtiene derechos de admin automáticamente. Los miembros siguientes se incorporan desde la página Usuarios una vez con sesión iniciada.","passwordHint":"Al menos 8 caracteres.","submit":"Instalar base de datos SQLite"},"terms":{"title":"Condiciones de uso","intro":"Por favor, lee y acepta las condiciones a continuación antes de utilizar AgentCMS. Están redactadas en lenguaje sencillo para que se lean rápido.","section1":{"title":"1. Servicio gratuito","body":"AgentCMS es una herramienta que Flexweg pone a tu disposición de forma gratuita. Puedes usarla sin límite con tu hosting Flexweg — Flexweg nunca te facturará por usar el CMS en sí. Las tarifas habituales de tu plan de hosting Flexweg y de tu plan Firebase siguen aplicándose, cada una en la cuenta correspondiente."},"section2":{"title":"2. Servicio «tal cual», sin garantía","body":"El CMS se proporciona tal cual. Trabajamos para mantenerlo estable y mejorarlo con el tiempo, pero no podemos garantizar que esté libre de errores, defectos o interrupciones. Úsalo con la misma precaución que cualquier herramienta que no hayas escrito tú mismo: mantén copias de seguridad de los contenidos importantes."},"section3":{"title":"3. Tus contenidos, tu responsabilidad","body":"Eres el único responsable de los contenidos que publicas a través del CMS — textos, imágenes, vídeos, formularios, integraciones de código y cualquier otro medio. Debes respetar la legislación aplicable en tu jurisdicción (y en las que te dirijas), los derechos de autor, los derechos de imagen y de personalidad, las normas de protección de datos personales y las condiciones de cualquier servicio de terceros que utilices (fuentes embebidas, vídeos, etc.). Flexweg no es responsable de los contenidos publicados por los usuarios del CMS."},"section4":{"title":"4. Tu cuenta de Firebase, tu seguridad","body":"El CMS almacena sus datos en tu propio proyecto Firebase. Eres responsable de la seguridad de ese proyecto: elige una contraseña robusta para la cuenta de administrador inicial, configura las reglas de seguridad de Firestore como se documenta, rota tus claves API cuando sea necesario y revisa quién tiene acceso. Flexweg no podrá en ningún caso ser responsabilizado por accesos no autorizados, fugas de datos, hackeos o pérdidas derivadas de una mala configuración o de un compromiso de tu cuenta Firebase."},"section5":{"title":"5. Limitación de responsabilidad","body":"Flexweg no podrá ser responsabilizado por ninguna pérdida de ingresos, pérdida de datos, pérdida de oportunidad comercial ni por ningún daño directo o indirecto derivado del uso, mal uso o falta de disponibilidad del CMS. Cuando la legislación aplicable obligue a Flexweg a asumir alguna responsabilidad, ésta se limita al importe efectivamente pagado a Flexweg por el CMS durante los últimos 12 meses — es decir, cero, ya que el CMS es gratuito."},"section6":{"title":"6. Tus datos siguen siendo tuyos","body":"Los contenidos que creas con el CMS se almacenan en tu propio proyecto Firebase (textos, ajustes, metadatos de los medios) y en tu propio hosting Flexweg (HTML publicado, imágenes, assets de tema). El CMS en sí no transmite tus contenidos a ningún servicio de terceros. Los plugins o temas que decidas activar pueden tener su propio comportamiento — revisa lo que hacen antes de activarlos."},"section7":{"title":"7. Uso correcto","body":"El uso del CMS para actividades ilegales, fraudulentas o nocivas, o de manera contraria a las condiciones generales de uso de Flexweg, puede provocar la suspensión de tu acceso al hosting Flexweg. También podemos actualizar estas condiciones del CMS con el tiempo; los cambios significativos se comunicarán a través del admin o por email."},"accept":"He leído y acepto las Condiciones de uso.","continue":"Continuar a la configuración","back":"Volver"},"sections":{"firebase":"Firebase","admin":"Administrador inicial","flexweg":"API de Flexweg"},"help":{"firebase":"Encuentra estos valores en Firebase Console → Configuración del proyecto → General → Tus apps → Configuración del SDK.","admin":"Usa un usuario existente de Firebase Authentication. Cualquiera que inicie sesión con este correo es tratado como administrador y se salta la comprobación del registro de usuario. Crea el usuario en Firebase Console → Authentication si aún no existe.","flexweg":"Genera una clave API permanente en tu cuenta Flexweg → API. La URL del sitio es la dirección pública de tu sitio Flexweg (p. ej. https://tu-sitio.flexweg.com).","flexwegApiKeyHint":"Obtén tu clave API desde la configuración de tu cuenta Flexweg.","flexwegApiKeyLink":"Abrir configuración de la cuenta"},"fields":{"apiKey":"Clave API","authDomain":"Dominio de autenticación","projectId":"ID del proyecto","storageBucket":"Bucket de almacenamiento","messagingSenderId":"ID de remitente de mensajería","appId":"ID de la app","adminEmail":"Correo","adminPassword":"Contraseña","flexwegApiKey":"Clave API","flexwegSiteUrl":"URL del sitio","flexwegApiBaseUrl":"URL base de la API","sqlitePath":"Ruta SQLite"},"submit":"Guardar y continuar","submitting":"Configurando…","success":"¡Configuración completada!","reloadingHint":"Se recargará el admin en un momento — espera un instante.","footer":"Estos valores se guardan en tu proyecto (Firestore + Flexweg). No se envían a ningún otro sitio.","steps":{"signInFirebase":"Iniciando sesión en Firebase…","testFlexweg":"Probando la API de Flexweg…","writeFirestore":"Guardando configuración…","uploadConfig":"Subiendo config.js a Flexweg…","syncThemes":"Sincronizando assets de tema con Flexweg…","sqliteInstall":"Creando token SQLite con alcance limitado…","sqliteRegisterAdmin":"Registrando la cuenta de admin…","sqliteSchema":"Inicializando el esquema SQLite…"},"stepsDone":{"sqliteInstall":"Token SQLite con alcance limitado emitido","sqliteRegisterAdmin":"Admin registrado y con sesión iniciada","sqliteSchema":"Esquema SQLite listo"},"errors":{"missingFields":"Por favor, rellena todos los campos.","rootDeploymentTitle":"El admin debe estar en una subcarpeta, no en la raíz del sitio.","rootDeploymentHint":"Mueve los archivos del admin (index.html, config.js, runtime/, …) a una subcarpeta en Flexweg — por ejemplo /admin/ o un nombre aleatorio como /erf34f654GH3/ para mayor discreción. Luego recarga el admin desde la URL de la subcarpeta y vuelve a ejecutar la configuración.","firebaseAuthGeneric":"No se pudo iniciar sesión en Firebase.","firebaseAuthInvalidCredential":"Firebase rechazó la combinación de correo y contraseña.","firebaseAuthInvalidCredentialHint":"Los proyectos de Firebase recientes activan por defecto la protección contra enumeración de correos, que devuelve el mismo error tanto si la contraseña es incorrecta, como si el usuario no existe o inicia sesión con otro proveedor. A comprobar:\\n• Vuelve a introducir la contraseña — copia y pega desde un gestor de contraseñas para descartar erratas. La longitud mínima es 6 caracteres.\\n• Abre Firebase Console → Authentication → Users y confirma que el correo existe. Revisa la columna «Providers»: si solo muestra Google (u otro proveedor) sin «Email/Password», establece o restablece la contraseña desde el menú de la fila (⋮ → Restablecer contraseña).\\n• Verifica que el correo coincida exactamente con lo que está almacenado en Firebase.","firebaseAuthUserNotFound":"No existe un usuario de Firebase con este correo. Créalo primero en Firebase Console → Authentication → Users.","firebaseAuthInvalidEmail":"El correo del administrador no es una dirección válida.","firebaseInvalidApiKey":"La clave API de Firebase no es válida. Verifica el valor en Firebase Console.","firebaseNetwork":"Error de red al iniciar sesión en Firebase. Verifica tu conexión.","firebaseTooManyRequests":"Demasiados intentos de inicio de sesión. Inténtalo más tarde o restablece la contraseña desde Firebase Console.","firebaseOperationNotAllowed":"El inicio de sesión con correo/contraseña no está activado en este proyecto Firebase. Abre Firebase Console → Authentication → Sign-in method y habilita el proveedor Email/Password.","firebaseUserDisabled":"Esta cuenta de usuario de Firebase está deshabilitada. Vuelve a habilitarla desde Firebase Console → Authentication → Users.","wrongAdminEmail":"La cuenta de Firebase con la que iniciaste sesión no coincide con el correo de admin que has escrito. Inténtalo de nuevo.","rulesNotPinnedTitle":"Las reglas de Firestore aún no te reconocen como admin bootstrap.","rulesNotPinnedHint":"Abre Firebase Console → Firestore → Reglas y sustituye el valor de `bootstrapAdminEmail()` por: {{email}} — luego haz clic en Publicar. La plantilla de reglas del README incluye un marcador `you@example.com` que debe sustituirse por tu correo de admin real. Una vez publicadas las nuevas reglas, vuelve a hacer clic en Enviar aquí.","flexwegAuth":"Clave API de Flexweg rechazada. Verifica el valor en tu cuenta Flexweg → API.","flexwegNetwork":"Error de red al contactar con Flexweg. Verifica la URL base de la API y tu conexión.","flexwegHttp":"Error de la API de Flexweg ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore rechazó la escritura de la configuración.","firestoreRulesHint":"Abre Firebase Console → Firestore → Reglas y comprueba que el correo de admin de bootstrap está fijado en \'{{email}}\'. El README incluye una plantilla de reglas lista para copiar.","firestoreOther":"Falló la escritura en Firestore","uploadFailed":"No se pudo subir config.js a Flexweg","generic":"Algo salió mal."},"docstore":{"contentTitle":"Repositorio de contenido","contentIntro":"Donde se guardan tus entradas, páginas y ajustes como archivos Markdown + JSON. Un repositorio vacío sirve — el CMS crea los archivos.","provider":"Repositorio","localClone":"Carpeta local (clon git)","localCloneHint":"Elige la carpeta de tu clon. Sincronízala con tu cliente git habitual — el CMS lee y escribe archivos, no ejecuta git.","contentDir":"Carpeta de contenido en el repositorio","privateRepo":"Usa un repositorio privado: los borradores se guardan allí.","folderRequired":"Elige primero la carpeta de contenido.","checking":"Comprobando el acceso al repositorio…","publishIntro":"Dónde se publica el sitio generado. Puedes cambiarlo más tarde en Ajustes.","existingSite":"Este repositorio ya está configurado — el sitio se sigue publicando en: {{target}}. Puedes cambiarlo más tarde en Ajustes (las claves secretas, si las hay, deben volver a introducirse allí).","install":"Instalar","steps":{"config":"Guardando la configuración…","content":"Cargando el contenido…","target":"Guardando el destino de publicación…","testTarget":"Probando el destino de publicación…"},"doneTitle":"¡Todo listo!","doneBody":"La configuración se ha guardado en este navegador. Para ahorrar este paso a otros editores, descarga config.js y reemplaza el de la carpeta admin de tu alojamiento.","downloadConfig":"Descargar config.js","open":"Abrir el admin","footer":"El contenido se queda en tu repositorio o en este navegador; los tokens de acceso nunca salen de este navegador."},"data":{"title":"1. ¿Dónde guardas tus datos?","intro":"Tus entradas, páginas, usuarios y ajustes — los datos propios del admin. Es independiente de dónde se aloja el sitio público (siguiente paso).","localNote":"Nada que configurar: el contenido se guarda en este navegador. Expórtalo desde Ajustes para hacer una copia de seguridad o moverlo más tarde.","options":{"sqlite-file":{"title":"SQLite","hint":"Una base de datos SQLite guardada en el alojamiento que elijas en el siguiente paso (Flexweg, tu servidor, S3, Git…). Sin cuentas de usuario — o el servicio SQLite de Flexweg, con cuentas, si alojas en Flexweg."},"flexweg-sqlite":{"title":"SQLite (servicio Flexweg)","hint":"Una base de datos SQLite gestionada por el servicio de Flexweg, con cuentas de usuario integradas. Necesita una cuenta de Flexweg, esté donde esté alojado el sitio."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth en tu proyecto de Google. Tiempo real, plan Spark gratuito."},"markdown-git":{"title":"Archivos Markdown en Git","hint":"Entradas como archivos .md en un repositorio GitHub / GitLab (o un clon local). Cada editor usa su propio token; cada cambio es un commit."},"local":{"title":"Este navegador","hint":"Un solo usuario, sin inicio de sesión, nada que configurar. Ideal para un admin que se ejecuta en tu ordenador."}}},"hosting":{"title":"2. ¿Dónde se publica el sitio?","intro":"Dónde se sube el sitio estático generado (HTML, CSS, imágenes) cada vez que publicas. Puedes cambiarlo más tarde en Ajustes.","existing":"Este repositorio de contenido ya publica en el destino de abajo. Mantenlo o elige otro."},"install":{"title":"3. Instalación","intro":"Revisa el resumen y luego instala.","data":"Datos","hosting":"Hosting","saveTarget":"Guardando el destino de publicación…","noteConfigJs":"La configuración del admin (config.js) se sube junto al admin en Flexweg cuando es posible; si no, se te ofrecerá descargarla.","noteLocalConfig":"La configuración se guarda en este navegador; se te ofrecerá config.js para ponerlo en la carpeta del admin y que otros editores se salten esta configuración."},"sqliteFile":{"security":"Sin cuentas de usuario: cualquiera que pueda abrir este admin puede editar el contenido — protege la carpeta del admin en tu hosting. El archivo de la base se sirve como cualquier otro archivo: mantenlo cifrado o guárdalo en una ubicación privada aparte.","intro":"Dónde se guarda el archivo de base de datos. Este admin lo lee y lo guarda a través de los mismos conectores que el alojamiento.","path":"Ruta del archivo de base de datos","pathHint":"Se crea al guardar por primera vez si aún no existe. Con un repositorio Git, cada guardado es un commit — mejor usa un repositorio o una rama que no lance un build del sitio.","existing":"base de datos existente","new":"nueva base de datos","dataNote":"Nada que configurar aquí: la base de datos se guardará en el alojamiento que elijas en el siguiente paso.","heading":"Base de datos SQLite","flexwegService":"Usar el servicio SQLite de Flexweg","flexwegServiceHint":"La base de datos la gestiona Flexweg e incluye cuentas de usuario integradas (correo + contraseña). Si no, es un simple archivo en este alojamiento, sin cuentas.","summaryFile":"Archivo {{path}} en este alojamiento","summaryService":"Servicio SQLite de Flexweg ({{path}})","encrypt":"Cifrar la base","encryptHint":"Recomendado en un hosting público: el archivo es ilegible sin la frase de contraseña. Cada navegador nuevo la pide una vez.","passphrase":"Frase de contraseña","passphraseHint":"Guárdala ahora en tu gestor de contraseñas: sin ella nadie puede abrir la base, ni siquiera tú.","copy":"Copiar","copied":"Copiada","generate":"Nueva","passphraseTooShort":"La frase de contraseña debe tener al menos 12 caracteres.","existingEncrypted":"Ya existe una base cifrada en esta ruta: introduce su frase de contraseña.","separate":"Guardar la base en una ubicación privada aparte","separateHint":"P. ej. un bucket S3 / R2 privado o un repositorio Git privado: la base nunca la sirve el sitio público.","summaryEncrypted":"cifrada","summaryLocation":"guardada en {{location}}","locationLabel":"Ubicación de la base","gitBranchNote":"La base se guarda en la rama {{branch}} de este repositorio, que nunca se publica: guardar contenido no vuelve a generar el sitio.","summaryBranch":"en la rama {{branch}}"},"adminHosting":{"deploying":"Copiando el admin al sitio…","label":"Alojar también el admin en este sitio","hint":"El admin se copia en {{url}} con su config.js (sin secretos dentro) — así cada editor puede abrirlo allí. Cada editor sigue iniciando sesión con su propio acceso.","folder":"Carpeta del admin","alreadyHere":"Este admin ya se ejecuta desde este sitio: su config.js se actualizará en su lugar.","doneBody":"El admin ya está en tu sitio. En GitHub Pages, activa primero Pages para el repositorio si aún no lo has hecho (Settings → Pages) y luego ábrelo:","open":"Abrir el admin en línea","continueHere":"Continuar en este admin"}}'),Xre={actions:{upload:"Subiendo archivo",delete:"Eliminando archivo",rename:"Renombrando archivo",get:"Leyendo archivo",list:"Listando archivos",createFolder:"Creando carpeta",renameFolder:"Renombrando carpeta",deleteFolder:"Eliminando carpeta",storageLimits:"Leyendo límites de almacenamiento",commit:"Publicando cambios"},errors:{configMissing:"El destino de publicación no está configurado. Configúralo en Ajustes antes de publicar.",network:"{{action}}: error de red o CORS bloqueado. Comprueba tu conexión.",auth:"{{action}}: falló la autenticación. Revisa las credenciales del destino de publicación en Ajustes.",notFound:"{{action}}: no se encontró en el destino de publicación.",tooLarge:"{{action}}: archivo demasiado grande para el destino de publicación.",rateLimited:"{{action}}: demasiadas peticiones, vuelve a intentarlo en un momento.",serverError:"{{action}}: error del servidor del destino de publicación ({{status}}). Inténtalo de nuevo.",generic:"{{action}} falló ({{status}}){{detail}}.",unsupported:"{{action}}: no compatible con el destino de publicación «{{connector}}».",unknownConnector:"Destino de publicación desconocido «{{connector}}». Revisa Ajustes → Destino de publicación.",folderAccess:"Sin acceso a la carpeta local. Abre Ajustes → Destino de publicación y pulsa «Reconectar carpeta»."}},Zre={log:{rendering:"Generando página…",uploading:"Subiendo {{path}}…",deleting:"Eliminando {{path}}…",regenerating:"Regenerando listados…",skipped:"Omitido {{path}} (sin cambios)",done:"Publicado en {{url}}",failed:"Falló: {{error}}"}},Yre={errors:{notConnected:"No conectado al repositorio de contenido. Vuelve a iniciar sesión con tu token de acceso.",conflict:"Otra persona modificó este elemento mientras tanto. Ahora se muestra su versión: vuelve a aplicar tu cambio.",sqliteUnsupported:"El destino «{{connector}}» no puede guardar un archivo de base de datos."}},ese={target:"Destino de publicación",settingsTitle:"Destino de publicación",settingsHelp:"Dónde se sube el sitio renderizado al publicar. Las credenciales se guardan con tu backend de contenido (o en este navegador para los repositorios Git de contenido) y todos los admins pueden leerlas.",saved:"Destino de publicación guardado. Ejecuta Regenerar → Todo para publicar el sitio completo en el nuevo destino.",test:"Probar la conexión",testOk:"Conexión OK",testFailed:"Error de conexión",names:{flexweg:"Flexweg","git-pages":"Repositorio Git (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"Bucket compatible con S3 (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Tu propio servidor (bridge PHP)","browser-mirror":"Descargar como ZIP","local-folder":"Carpeta local en este ordenador"},hints:{flexweg:"Subida a través de la API Files de Flexweg.","git-pages":"Cada publicación es un commit en el repositorio; el alojamiento reconstruye el sitio a partir de él.",s3:"Requiere una regla CORS en el bucket que permita el origen de este admin, y alojamiento web (o una CDN) para servir los archivos index.html.","php-bridge":"Sube external/bridges/php/flexweg-bridge.php a tu servidor, define su clave de API y luego introduce su URL aquí.","browser-mirror":"El sitio se guarda en este navegador; descarga el ZIP y súbelo a mano donde quieras.","local-folder":"Escribe el sitio directamente en una carpeta (Chrome / Edge). Sírvelo en local o súbelo con tus propias herramientas."},fields:{flexweg:{apiKey:"Clave de API",siteUrl:"URL del sitio",apiBaseUrl:"URL base de la API"},"git-pages":{host:"Alojamiento",provider:"Proveedor Git",owner:"Propietario (usuario u organización)",repo:"Repositorio",project:"Ruta del proyecto",branch:"Rama",dir:"Carpeta en el repositorio",token:"Token de acceso",siteUrl:"URL pública del sitio",apiBaseUrl:"URL de la API (solo autoalojado)"},s3:{endpoint:"Endpoint",region:"Región",bucket:"Bucket",prefix:"Prefijo de claves (opcional)",accessKeyId:"ID de clave de acceso",secretAccessKey:"Clave de acceso secreta",siteUrl:"URL pública del sitio",forcePathStyle:"URLs de tipo ruta (MinIO, R2, la mayoría de compatibles)",publicRead:"Hacer públicos los archivos subidos (ACL public-read) — para buckets que no son públicos mediante una política (OVHcloud, Scaleway…). Déjalo desactivado en buckets de AWS con «bucket owner enforced»."},"php-bridge":{apiBaseUrl:"URL del bridge",apiKey:"Clave de API del bridge",siteUrl:"URL pública del sitio"},"browser-mirror":{siteUrl:"URL pública del sitio (opcional)"},"local-folder":{siteUrl:"URL en la que se sirve la carpeta (opcional)"}},help:{flexweg:{apiKey:"Se genera desde tu cuenta de Flexweg → API."},"git-pages":{host:"Cloudflare Pages: conecta el proyecto a este repositorio sin comando de build y con la carpeta de salida de abajo. Funciona con repositorios privados.",dir:'Déjalo vacío para la raíz del repositorio. GitHub Pages: "" o "docs". GitLab Pages: "public".',token:"Token fine-grained sobre este repositorio con Contents: read & write (GitHub) — añade Pages: read & write para que el CMS pueda activar GitHub Pages — o un token con el scope api (GitLab). Déjalo vacío para usar el token de acceso de cada editor cuando el contenido está en el mismo proveedor.",siteUrl:"p. ej. https://user.github.io/repo — una URL con subcarpeta sirve, los enlaces se ajustan automáticamente."},s3:{endpoint:"Déjalo vacío para AWS (se deduce de la región). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"La URL de sitio web del bucket o tu dominio de CDN."},"php-bridge":{apiBaseUrl:"La URL completa de flexweg-bridge.php en tu servidor (HTTPS)."},"browser-mirror":{siteUrl:"Donde subirás el ZIP — se usa para las URLs absolutas (sitemaps, RSS, medios)."},"local-folder":{siteUrl:"p. ej. http://localhost:8080 cuando un servidor web local sirve la carpeta."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (conectado al repositorio)","gitlab-pages":"GitLab Pages",other:"Otro (Netlify, Vercel, git pull en el servidor…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Elegir carpeta…",change:"Cambiar de carpeta…",reconnect:"Volver a conectar la carpeta",unsupported:"Este navegador no puede escribir en carpetas locales. Usa Chrome o Edge."},mirror:{download:"Descargar el sitio (ZIP)",count:"{{count}} archivos en este navegador"},adminHosting:{title:"Admin en este sitio",help:"Copia este admin en el destino de publicación (primer despliegue, o actualización tras una nueva versión). Su config.js no contiene secretos.",deploy:"Desplegar / actualizar el admin",deployed:"Admin desplegado ({{count}} archivos) — {{url}}"},pages:{enabled:"GitHub Pages activado para este repositorio — el sitio estará en línea en un minuto aproximadamente.",enableHint:'Publicación completada. Para poner el sitio en línea, activa GitHub Pages para {{repo}}: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (O da al token el permiso "Pages: read and write" y el CMS lo hará por ti.)'},siteUrl:{mismatch:"La URL pública del sitio (Ajustes → Sitio) es {{site}}, pero este destino sirve el sitio en {{target}}. Los enlaces, el CSS y los sitemaps siguen la URL del sitio: serán incorrectos en este alojamiento.",use:"Usar {{url}} para el sitio",updated:"URL del sitio actualizada. Ejecuta Regenerar → Todo para volver a publicar las páginas con los nuevos enlaces."}},tse={heading:"Conectar con el repositorio de contenido",tokenIntro:"El contenido se guarda en el repositorio {{provider}} {{repo}}. Inicia sesión con tu propio token de acceso personal — tus permisos en el repositorio deciden tu rol (escritura = editor, admin / maintainer = admin).",token:"Token de acceso personal",tokenHelpGithub:"Token fine-grained, con acceso solo a este repositorio, permiso Contents: lectura y escritura.",tokenHelpGitlab:"Token con el api scope, rol Developer o superior en este proyecto.",createToken:"Crear un token",connect:"Conectar",tokenStorage:"El token se guarda solo en este navegador. Al cerrar sesión se olvida.",failed:"Este token no puede escribir en el repositorio (no válido, caducado o de solo lectura). Comprueba sus permisos.",folderIntro:"El contenido se guarda en una carpeta de este ordenador (normalmente un clon git que sincronizas con tu propio cliente git). Concede acceso a este navegador — los navegadores vuelven a pedirlo tras cada recarga.",openFolder:"Abrir la carpeta de contenido"},nse={flexweg:{title:"Flexweg",short:"Hosting Flexweg",hint:"Sube a través de la Flexweg Files API. Clave API de tu cuenta Flexweg."},"github-pages":{title:"GitHub Pages",short:"Gratis, desde un repositorio GitHub",hint:"Cada publicación es un commit en el repositorio; GitHub Pages lo sirve. Settings → Pages → Deploy from a branch. Repositorios públicos en el plan gratuito."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Gratis, admite repositorios privados",hint:"El CMS hace commit del sitio en un repositorio GitHub / GitLab; conecta un proyecto de Cloudflare Pages a él (sin comando de build, carpeta de salida = la carpeta de abajo)."},"gitlab-pages":{title:"GitLab Pages",short:"Gratis, desde un repositorio GitLab",hint:"Cada publicación es un commit; el CMS añade un .gitlab-ci.yml mínimo que publica la carpeta public/."},"git-other":{title:"Netlify, Vercel…",short:"Cualquier host que despliegue un repositorio",hint:"El CMS hace commit del sitio en un repositorio Git; conecta tu host (Netlify, Vercel, un servidor que ejecuta git pull…) a ese repositorio."},s3:{title:"S3 / R2 / B2…",short:"Bucket de almacenamiento de objetos",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Requiere una regla CORS en el bucket y alojamiento web o un CDN delante."},"own-server":{title:"Tu propio servidor (FTP / SFTP)",short:"Hosting compartido, VPS…",hint:"Los navegadores no hablan FTP ni SFTP: sube una vez el puente PHP (external/bridges/php/flexweg-bridge.php) con tu cliente FTP, define su clave API y luego introduce su URL aquí. Funciona en cualquier host PHP."},"local-folder":{title:"Carpeta local",short:"En este ordenador",hint:"Escribe el sitio en una carpeta de este ordenador (Chrome / Edge). Sírvelo localmente o súbelo con tus propias herramientas."},zip:{title:"Descargar como ZIP",short:"Súbelo a mano",hint:"El sitio se guarda en este navegador; descarga un ZIP desde Ajustes y súbelo donde quieras (Netlify Drop, cliente FTP…)."}},rse={heading:"Conectarse a la base de datos",intro:"Este admin guarda su contenido en {{path}}. Introduce las credenciales de acceso para este navegador.",storage:"Las credenciales solo se guardan en este navegador. Al cerrar sesión se olvidan.",passphrase:"Frase de contraseña de la base",passphraseHint:"La base está cifrada. Introduce la frase de contraseña elegida en la instalación (se guarda solo en este navegador).",passphraseWrong:"Frase de contraseña incorrecta: no se pudo abrir la base.",passphraseMissing:"Introduce la frase de contraseña de la base."},sse={common:Rre,auth:jre,nav:Mre,dashboard:Lre,posts:Dre,pages:Fre,taxonomies:Ore,media:zre,themes:Ure,plugins:Bre,externalInstall:$re,externalLoader:Hre,menus:Vre,settings:qre,users:Wre,firestoreSetup:Gre,errors:Kre,identity:Jre,setup:Qre,flexweg:Xre,publish:Zre,docstore:Yre,connectors:ese,gitAccess:tse,hosting:nse,sqliteAccess:rse},ise={save:"Opslaan",saving:"Opslaan…",saved:"Opgeslagen",cancel:"Annuleren",delete:"Verwijderen",deleting:"Verwijderen…",edit:"Bewerken",create:"Aanmaken",search:"Zoeken",loading:"Laden…",yes:"Ja",no:"Nee",confirm:"Bevestigen",back:"Terug",next:"Volgende",previous:"Vorige",close:"Sluiten",all:"Alle",none:"Geen",actions:"Acties",name:"Naam",slug:"Slug",description:"Beschrijving",status:"Status",createdAt:"Aangemaakt",updatedAt:"Bijgewerkt",publishedAt:"Gepubliceerd",language:"Taal",darkMode:"Donkere modus",lightMode:"Lichte modus",signOut:"Uitloggen",administrator:"Beheerder",editor:"Redacteur",appName:"AgentCMS"},ase={signIn:"Inloggen",signingIn:"Inloggen…",email:"E-mail",password:"Wachtwoord",emailPlaceholder:"u@bedrijf.com",passwordPlaceholder:"••••••••",forgotPassword:"Wachtwoord vergeten?",resetEmailSent:"E-mail om wachtwoord opnieuw in te stellen verzonden naar {{email}}.",enterEmailFirst:"Voer eerst uw e-mail hierboven in en klik dan op resetten.",emailPasswordRequired:"E-mail en wachtwoord zijn vereist.",signInSubtitle:"Gebruik uw werk-e-mail en wachtwoord.",footer:"Accountaanvragen verlopen via uw beheerder.",errors:{invalidEmail:"Ongeldig e-mailadres.",invalidCredentials:"Ongeldig e-mailadres of wachtwoord.",tooManyRequests:"Te veel pogingen. Probeer later opnieuw of stel uw wachtwoord opnieuw in.",userDisabled:"Dit account is uitgeschakeld.",networkFailed:"Netwerkfout. Controleer uw verbinding.",generic:"Authenticatie mislukt."}},ose={openMenu:"Menu openen",closeMenu:"Menu sluiten",dashboard:"Dashboard",posts:"Berichten",pages:"Pagina's",taxonomies:"Categorieën & Tags",media:"Media",themes:"Thema's",themeSettings:"Thema-instellingen",plugins:"Plugins",menus:"Menu's",users:"Gebruikers",settings:"Instellingen"},lse={title:"Dashboard",welcome:"Welkom terug, {{email}}.",stats:{totalPosts:"Berichten",totalPages:"Pagina's",online:"Online",drafts:"Concepten"}},cse={title:"Berichten",newPost:"Nieuw bericht",noPosts:"Nog geen berichten. Maak uw eerste bericht om te beginnen.",noPostsInFilter:"Geen berichten passen bij het huidige filter.",search:{placeholder:"Berichten zoeken…",clear:"Zoekopdracht wissen",noResults:"Geen berichten komen overeen met uw zoekopdracht."},pagination:{previous:"Vorige",next:"Volgende",showing:"{{from}}–{{to}} van {{total}} weergegeven",pageOf:"Pagina {{page}} van {{total}}"},bulk:{selectedCount_one:"{{count}} geselecteerd",selectedCount_other:"{{count}} geselecteerd",selectPage_one:"{{count}} op deze pagina selecteren",selectPage_other:"Alle {{count}} op deze pagina selecteren",deselectPage:"Pagina deselecteren",allOnPageSelected_one:"{{count}} op deze pagina geselecteerd.",allOnPageSelected_other:"Alle {{count}} op deze pagina geselecteerd.",selectAllMatching_one:"Het overeenkomende bericht selecteren",selectAllMatching_other:"Alle {{count}} overeenkomende berichten selecteren",allMatchingSelected_one:"Het overeenkomende bericht is geselecteerd.",allMatchingSelected_other:"Alle {{count}} overeenkomende berichten zijn geselecteerd.",selectOne:'"{{title}}" selecteren',publish:"Publiceren ({{count}})",publishing:"Publiceren…",publishedCount:"{{ok}} gepubliceerd, {{failed}} mislukt.",unpublish:"Depubliceren ({{count}})",unpublishing:"Depubliceren…",unpublishedCount:"{{ok}} gedepubliceerd, {{failed}} mislukt.",delete:"Verwijderen",deleting:"Verwijderen…",deletedCount:"{{ok}} verwijderd, {{failed}} mislukt.",confirmDelete_one:"{{count}} bericht verwijderen? Dit depubliceert van Flexweg en kan niet ongedaan worden gemaakt.",confirmDelete_other:"{{count}} berichten verwijderen? Dit depubliceert van Flexweg en kan niet ongedaan worden gemaakt.",noDraftSelected:"Geen conceptberichten geselecteerd.",noOnlineSelected:"Geen online berichten geselecteerd.",clear:"Selectie wissen"},filters:{all:"Alle",draft:"Concept",online:"Online"},fields:{title:"Titel",slug:"Slug",excerpt:"Samenvatting",content:"Inhoud",category:"Categorie",tags:"Tags",heroImage:"Uitgelichte afbeelding",seoTitle:"SEO-titel",seoDescription:"SEO-beschrijving",createdAt:"Aangemaakt op",updatedAt:"Laatst bijgewerkt",publishedAt:"Gepubliceerd op"},edit:{newTitle:"Nieuw bericht",editTitle:"Bericht bewerken",saved:"Opgeslagen.",savedAndRepublished:"Opgeslagen en opnieuw gepubliceerd.",saveFailed:"Opslaan mislukt.",saveAndRepublish:"Opslaan en opnieuw publiceren",draftSaved:"Concept opgeslagen.",slugCollision:{post:'Deze URL wordt al gebruikt door bericht: "{{label}}".',page:'Deze URL wordt al gebruikt door pagina: "{{label}}".',category:'Deze URL wordt al gebruikt door categorie: "{{label}}".'},publish:"Publiceren",unpublish:"Depubliceren",publishing:"Publiceren…",unpublishing:"Depubliceren…",titlePlaceholder:"Titel toevoegen",permalink:"Permalink",slugFormatHint:"Alleen kleine letters, ASCII, gescheiden door streepjes.",slugAutoSuffixed:'Suffix toegevoegd omdat "{{base}}" al wordt gebruikt door {{owner}}.',slugAutoSuffixedOwner:{post:'bericht: "{{label}}"',page:'pagina: "{{label}}"',category:'categorie: "{{label}}"'},saveBlocked:{titleRequired:"Voeg een titel toe voordat u opslaat.",slugRequired:"Een titel en URL-slug zijn vereist om op te slaan.",slugInvalid:"Ongeldig slug-formaat (ASCII in kleine letters + streepjes).",slugCollision:"Los het URL-conflict op voordat u opslaat."},viewPublished:"Bekijken",confirmDelete:"Dit item verwijderen?",inspector:{document:"Document",block:"Blok",blockEmpty:"Selecteer een blok in de editor om de opties te zien.",publishing:"Publicatie",permalink:"Permalink",categories:"Categorieën & tags",featured:"Uitgelichte afbeelding",seo:"SEO",excerpt:"Samenvatting",dates:"Datums"},blocks:{addBlock:"Blok toevoegen",transform:"Omzetten naar",moveUp:"Omhoog verplaatsen",moveDown:"Omlaag verplaatsen",duplicate:"Dupliceren",remove:"Blok verwijderen",paragraph:"Paragraaf",heading2:"Kop 2",heading3:"Kop 3",bulletList:"Opsomming",orderedList:"Genummerde lijst",blockquote:"Citaat",codeBlock:"Code",image:"Afbeelding",horizontalRule:"Scheiding",categories:{text:"Tekst",media:"Media",layout:"Lay-out",embed:"Insluitingen",advanced:"Geavanceerd"},noSettings:"Dit blok heeft geen instellingen.",noSelection:"Selecteer een blok in de editor om de opties te zien.",slash:{noResults:"Geen overeenkomend blok."}}},status:{draft:"Concept",online:"Online"},preview:{title:"Voorbeeld",rendering:"Voorbeeld renderen…",error:"Voorbeeld mislukt: {{error}}",viewports:{mobile:"Mobiel",tablet:"Tablet",desktop:"Desktop"}}},use={title:"Pagina's",newPage:"Nieuwe pagina",noPages:"Nog geen pagina's.",homeBadge:"Startpagina",homeBadgeTooltip:"Wordt gebruikt als startpagina van de site"},dse={title:"Categorieën & Tags",categories:"Categorieën",tags:"Tags",newCategory:"Nieuwe categorie",newTag:"Nieuwe tag",noCategories:"Nog geen categorieën.",noTags:"Nog geen tags.",slugCollision:'Deze slug wordt al gebruikt door "{{label}}".',seo:{button:"SEO",buttonTitle:"SEO-metatags bewerken",title:"SEO-metatags",subtitle:'Aangepaste titel en beschrijving voor de archiefpagina van "{{name}}".',metaTitle:"Metatitel",metaTitleHint:"Gebruikt als <title> van de pagina. Standaard: de naam van de term.",metaDescription:"Metabeschrijving",metaDescriptionHint:"Gebruikt als metabeschrijving van de pagina. Standaard: de beschrijving van de term."}},hse={title:"Mediabibliotheek",upload:"Uploaden",uploading:"Uploaden…",finalizing:"Afronden…",uploadFailed:"Upload mislukt",retry:"Opnieuw proberen",noMedia:"Nog geen media.",alt:"Alt-tekst",caption:"Bijschrift",filename:"Bestandsnaam",size:"Grootte",type:"Type"},fse={title:"Thema's",active:"Actief",activate:"Activeren",installExternal:"Thema installeren",uninstallDisabledTitle:"Schakel naar een ander thema voordat u dit deïnstalleert.",syncAssets:"Thema-bestanden synchroniseren",regenerateSite:"Site opnieuw genereren",regenerating:"Opnieuw genereren…",regenerate:{button:"Opnieuw genereren",running:"Bezig…",groupBuiltins:"Site",groupPlugins:"Plugins",home:"Alleen homepage",homeHelp:"Genereert alleen index.html opnieuw — snelste optie.",allHtml:"Alle HTML-pagina's",allHtmlHelp:"Elke post, pagina, archief en lijst — plus menu / posts / authors JSON-snapshots.",repair:"URL's herstellen",repairHelp:"Berekent de canonieke URL van elke online post opnieuw en verplaatst bestanden die op de verkeerde URL terechtkwamen. Handig na een import die liep voordat de termen gesynchroniseerd waren.",assets:"Thema-bestanden",assetsHelp:"Uploadt CSS + bijbehorende scripts van het actieve thema naar /theme-assets/.",everything:"Alles",everythingHelp:"Thema-bestanden + alle HTML + elke plugin-uitvoer. Langzaamste optie.",noPluginTargets:"Geen plugin-regeneraties — activeer een plugin die regenereren ondersteunt."},confirmSwitch:{title:"Overschakelen naar {{theme}}?",body:"Wisselen van thema vereist het opnieuw uploaden van de thema-bestanden en het regenereren van elke gepubliceerde pagina zodat het nieuwe uiterlijk overal doorwerkt. Dit kan even duren.",confirm:"Overschakelen en regenereren",cancel:"Annuleren"}},pse={title:"Plugins",enabled:"Ingeschakeld",disabled:"Uitgeschakeld",enable:"Inschakelen",disable:"Uitschakelen",configure:"Configureren",author:"auteur",learnMore:"Meer info",mustUseBadge:"Verplicht",installExternal:"Plugin installeren",tabs:{regular:"Plugins",mustUse:"Verplichte plugins"}},mse={titlePlugin:"Een plugin installeren",titleTheme:"Een thema installeren",labelPlugin:"plugin",labelTheme:"thema",intro:"Sleep een ZIP-bestand met een {{label}}-bundle (manifest.json + bundle.js in de root van de ZIP) hierheen. De {{label}} wordt naar uw Flexweg-site geüpload en na een herlaad geregistreerd. Een ZIP met dezelfde manifest-id opnieuw uploaden werkt het bestaande item ter plaatse bij — geen deïnstallatie nodig.",zipField:"Bundle-ZIP-bestand",install:"Installeren",installing:"Bezig met installeren…",installSuccess:"{{name}} geïnstalleerd ({{count}} bestanden geüpload). Herladen…",upgradeSuccess:"{{name}} bijgewerkt van v{{previousVersion}} naar v{{newVersion}} ({{count}} bestanden geüpload). Herladen…",installedTitle:"Al geïnstalleerd",bundledDefaultsTitle:"Meegeleverde standaards beschikbaar",bundledDefaultsHint:"{{count}} meegeleverde plugin/thema is momenteel gedeïnstalleerd. Herstel ze om terug te krijgen wat met deze admin-versie werd meegeleverd.",bundledDefaultsRestore:"Herstellen",bundledDefaultsRestored:"{{plugins}} plugin(s) en {{themes}} thema('s) hersteld. Herladen…",uninstall:"Deïnstalleren",uninstallSuccess:"{{id}} gedeïnstalleerd. Herladen…",confirmUninstall:"{{id}} deïnstalleren? Bestanden worden verwijderd van Flexweg.",errors:{"no-manifest":"ZIP mist manifest.json in de root.","invalid-manifest":"manifest.json is ongeldig (verplichte velden ontbreken of het is geen geldig JSON).","incompatible-api":"De bundle is gebouwd tegen een incompatibele runtime-API-versie.","no-bundle":"De ZIP bevat niet het in het manifest opgegeven entry-bestand.","fetch-manifest":"Kon de huidige external.json op Flexweg niet lezen.","upload-failed":"Upload mislukt — controleer uw Flexweg-API-sleutel en uw verbinding."}},gse={someFailed:"{{count}} externe bundle(s) konden niet worden geladen. Bekijk de browserconsole."},bse={title:"Menu's",header:"Hoofdmenu",footer:"Voettekstmenu",label:"Label",saveAndPublish:"Opslaan & genereren",discard:"Negeren",saved:"Menu's opgeslagen en gepubliceerd.",saveFailed:"Kon menu's niet opslaan.",unsavedChanges:"U heeft niet-opgeslagen wijzigingen."},yse={title:"Instellingen",tabs:{general:"Algemeen"},site:{title:"Site",siteTitle:"Sitetitel",siteDescription:"Sitebeschrijving",siteLanguage:"Sitetaal",siteLanguageHelp:'BCP-47-tag (bv. en, fr-CA) die op elke gepubliceerde pagina in <html lang="…"> wordt geplaatst. Het voorvoegsel wordt vergeleken met de ondersteunde vertaallocales voor sitemap-/RSS-labels en in het thema ingebakken teksten; niet-ondersteunde locales vallen terug op Engels.',siteLanguageResolved:"Vertalingen gebruiken: {{label}}",baseUrl:"Publieke site-URL",postsPerPage:"Berichten per pagina",homeMode:"Inhoud startpagina",homeLatest:"Laatste berichten",homeStatic:"Statische pagina",homePage:"Startpagina",discourageIndexing:"Zoekmachines ontmoedigen deze site te indexeren",discourageIndexingHelp:"Indien ingeschakeld krijgt elke gepubliceerde pagina een noindex/nofollow-metatag en blokkeert robots.txt alle crawlers. Volgt het gedrag van WordPress — handig voor stagingsites of controles vóór de lancering. Zoekmachines die de instructie respecteren, indexeren de site niet.",discourageRegenerateHint:"Indexeringsinstelling opgeslagen. Klik in Thema's op 'Alles opnieuw genereren' om de wijziging toe te passen op alle gepubliceerde pagina's en robots.txt."},flexweg:{title:"Flexweg-API",apiKey:"API-sleutel",apiKeyHelp:"Aangemaakt vanuit uw Flexweg-account → API.",siteUrl:"Site-URL",siteUrlHelp:"Publieke URL van uw Flexweg-site zonder slash op het einde.",apiBaseUrl:"API-basis-URL",storageHelpFirebase:"Opgeslagen in Firestore (config/flexweg). Te lezen door elk ingelogd teamlid, alleen door beheerders te schrijven.",storageHelpSqlite:"Opgeslagen in de lokale SQLite-tabel config. Te lezen door elk ingelogd teamlid, alleen door beheerders te schrijven."},backend:{title:"Data-backend",active:"Actief backend:",switchButton:"Backend wisselen…",confirmTitle:"Alle huidige data gaat verloren.",confirmBody:"Wisselen wist de configuratie in de browser en herlaadt het instelformulier. Het nieuwe backend start leeg — de data van het vorige backend blijft staan (in Firestore of als .sqlite-bestand op Flexweg), maar het CMS leest het pas weer wanneer u terug wisselt.",confirmYes:"Ja, backend wisselen",downloadBackup:"Download een back-up van het .sqlite-bestand",downloadBackupHelp:"doe dit voordat u van backend wisselt.",markdownGit:"Markdown — {{source}}",localFolder:"lokale map",localBrowser:"Deze browser (lokaal, één gebruiker)",sqliteFile:"SQLite-bestand — {{location}}"},performance:{title:"Prestaties",help:"Hoe de admin berichten en pagina's laadt. De standaardmodus werkt op het gratis Firestore-plan zonder setup; de gepagineerde modus is voor zeer grote sites en vereist eenmalige index-setup.",mode:"Laadmodus",modeGlobal:"Standaard (geen setup nodig)",modePaginated:"Server-side gepagineerd (Firestore-indexen vereist)",globalHelp:"Laadt de hele berichten-collectie in één live abonnement. Sorteren, filteren en zoeken gebeurt in het geheugen. Aanbevolen voor sites met minder dan ~5 000 berichten.",paginatedHelp:"Cursor-gepagineerde abonnementen, één pagina per keer. Vereist Firestore-composite-indexen — zie README. Aanbevolen voor zeer grote sites.",savedReload:"Opgeslagen. Herlaad de admin om de nieuwe modus toe te passen."},editor:{title:"Editor",help:"Typografie binnen de bericht-/pagina-editor. Onafhankelijk van het publieke thema.",fontFamily:"Lettertypefamilie",bodySize:"Tekstgrootte",h1Size:"H1-grootte",h2Size:"H2-grootte",h3Size:"H3-grootte",sizeHelp:"CSS-lengte, bijv. 16px of 1rem. Laat leeg voor standaard.",reset:"Terugzetten naar standaard"},profile:{title:"Profiel",adminLocale:"Admin-taal",adminLocaleHelp:"Taal die wordt gebruikt door de adminschermen. Opgeslagen in uw profiel.",firstName:"Voornaam",lastName:"Achternaam",headline:"Titel",headlinePlaceholder:"bv. Journalist, Hoofdredacteur…",headlineHelp:"Wordt openbaar onder uw naam getoond in auteurkaarten en op uw archiefpagina.",bio:"Biografie",bioPlaceholder:"Een korte alinea die op uw auteurspagina en onder uw artikelen verschijnt.",bioHelp:"Zichtbaar op de publieke site in de auteur-zijbalk en op de auteursarchiefpagina.",socials:"Sociale profielen",socialsHelp:`Voeg de URL's toe van de profielen die u op de publieke site wilt tonen en vink "Tonen" aan voor de zichtbare. Lege URL's worden genegeerd.`,socialsShow:"Tonen",socialsShowHelp:"Schakelt de zichtbaarheid van dit netwerk op de publieke site om.",avatar:"Profielfoto",avatarHelp:"Kies een afbeelding uit uw mediabibliotheek. Vierkante afbeeldingen werken het best.",pickAvatar:"Kies uit media",changeAvatar:"Foto wijzigen",removeAvatar:"Verwijderen",save:"Profiel opslaan"},transfer:{title:"Content verplaatsen of back-uppen",help:"Exporteer alles (posts, pagina's, categorieën, metadata van media, profielen, instellingen) als één JSON-bestand. Op een Markdown- of lokaal backend kunt u zo'n bestand importeren met behoud van de id's — zo migreert u vanaf Firebase of SQLite. Mediabestanden en geheime sleutels worden niet meegenomen.",export:"Content exporteren (JSON)",import:"Content importeren…",modeMerge:"Samenvoegen (zelfde id's overschrijven)",modeReplace:"Geïmporteerde collecties vervangen",replaceConfirm:"De modus Vervangen verwijdert vóór het importeren alle bestaande items van de collecties die in het bestand staan. Doorgaan?",invalidFile:"Dit bestand is geen contentexport van AgentCMS.",imported:"{{posts}} posts/pagina's, {{terms}} termen en {{media}} media geïmporteerd. Voer Opnieuw genereren → Alles uit om ze te publiceren."},encryption:{title:"Databaseversleuteling:",on:"aan",off:"uit",onHelp:"Het databasebestand is onleesbaar zonder de wachtzin. Wijzigen slaat het bestand opnieuw op met een nieuwe sleutel; andere browsers vragen om de nieuwe wachtzin.",offHelp:"Het databasebestand is leesbaar voor iedereen die het kan downloaden (statische hosting serveert het als elke pagina). Versleutel het met een wachtzin.",enable:"Database versleutelen…",change:"Wachtzin wijzigen…",savedConfirm:"Ik heb deze wachtzin in mijn wachtwoordmanager bewaard — zonder kan de inhoud niet worden geopend.",enableConfirm:"Nu versleutelen",changeConfirm:"Wachtzin wijzigen",done:"Database opnieuw opgeslagen met de nieuwe wachtzin."}},vse={title:"Gebruikers",noUsers:"Nog geen gebruikers.",role:"Rol",disabled:"Uitgeschakeld",editProfileTitle:"Profiel bewerken — {{email}}",profileSaved:"Profiel opgeslagen.",descriptionFirebase:"Beheer uw team. Nieuwe accounts worden aangemaakt in de Firebase Console en hier gespiegeld bij de eerste keer inloggen.",descriptionSqlite:"Beheer uw team. Gebruik de knop +Gebruiker toevoegen hieronder om accounts direct aan te maken.",addUser:"Gebruiker toevoegen",addUserSuccess:"{{email}} toegevoegd.",removeConfirmFirebase:"Het record van {{email}} verwijderen? Hiermee verwijdert u hun profiel en rol uit het CMS. Om hun login-toegang in te trekken, verwijdert u het account ook in de Firebase Console.",removeConfirmSqlite:"{{email}} definitief verwijderen? Dit trekt hun login-toegang in EN verwijdert hun profiel en rol. Dit kan niet ongedaan worden gemaakt.",empty:{title:"Nog geen teamleden",descriptionFirebase:"Maak het eerste account aan in de Firebase Console en log hier daarna één keer in om het profiel te registreren.",descriptionSqlite:"Klik op +Gebruiker toevoegen hierboven om het eerste teamlid uit te nodigen."},help:{title:"Hoe u een nieuw teamlid toevoegt",bootstrapLine:"De bootstrap-admin (altijd volledige toegang) is:",firebase:{step1:"Open de Firebase Console → Authentication → Add user.",step2:"Stel een e-mail en wachtwoord in en stuur ze naar het nieuwe teamlid.",step3:"Vraag hen om hier één keer in te loggen — hun profiel verschijnt in de lijst hierboven en u kunt hun rol en gegevens bewerken."},sqlite:{step1:"Klik op de knop +Gebruiker toevoegen hierboven.",step2:"Voer hun e-mail en een tijdelijk wachtwoord (8+ tekens) in.",step3:"Deel de inloggegevens veilig — ze kunnen het wachtwoord vanuit hun profiel wijzigen zodra ze zijn ingelogd."},git:{step1:"Voeg de persoon toe als collaborator van de content-repository (schrijftoegang = redacteur, admin / maintainer = admin).",step2:"Diegene maakt een eigen persoonlijk toegangstoken aan op GitHub / GitLab.",step3:"Diegene opent de admin en logt in met dat token — het profiel wordt hier automatisch aangemaakt."}},addUserModal:{title:"Een nieuw teamlid toevoegen",intro:"Maakt het account direct aan in de Flexweg SQLite Auth-database. De nieuwe gebruiker krijgt standaard de rol editor; promoveer hem of haar via de lijst hieronder als adminrechten nodig zijn.",submit:"Gebruiker aanmaken",submitting:"Aanmaken…"},actions:{editProfile:"Profiel bewerken",promote:"Promoveren tot beheerder",demote:"Degraderen tot redacteur",disable:"Uitschakelen",enable:"Inschakelen",delete:"Record verwijderen"},descriptionGit:"Teamleden zijn de personen met schrijftoegang tot de content-repository. Ze verschijnen hier na hun eerste login; hun rol volgt hun rechten op de repository.",descriptionLocal:"Deze admin draait in modus voor één gebruiker: content wordt in deze browser opgeslagen en er zijn geen accounts.",descriptionSqliteFile:"Geen gebruikersaccounts met dit backend: iedereen die de admin kan openen, kan bewerken. Beveilig de admin-map op het niveau van uw hosting. De auteursprofielen hieronder zijn ter informatie."},xse={title:"Firestore-setup vereist",intro:"De berichten- en pagina-overzichtspagina's hebben enkele Firestore composite indexes nodig om efficiënt te queryen. Die moeten handmatig worden aangemaakt — Firebase reserveert het aanmaken van indexes voor projectbeheerders.",checking:"Uw Firestore-indexes controleren…",missingCount_one:"{{count}} index ontbreekt:",missingCount_other:"{{count}} indexes ontbreken:",openConsole:"Firebase Console openen om aan te maken",noUrl:"Auto-suggestie-URL niet extraheerbaar — zie README voor het gcloud-commando.",howItWorks:"Hoe het werkt",step1:"Klik op de link voor elke ontbrekende index — Firebase Console opent met de definitie vooraf ingevuld.",step2:'Klik op "Create" en wacht 1–5 minuten tot de index is opgebouwd (status in de console).',step3:"Kom terug en klik op Opnieuw proberen. Zodra beide queries slagen, laadt de admin.",retry:"Opnieuw proberen",retrying:"Opnieuw proberen…",buildHint:"Het opbouwen van een index kan na aanmaak een paar minuten duren.",allReady:"Alle indexes klaar.",unexpectedTitle:"Firestore niet bereikbaar",unexpectedHint:"Controleer uw verbinding en Firestore-regels. Als u net de indexes hebt aangemaakt, wacht tot ze klaar zijn en probeer opnieuw."},wse={appError:"Toepassingsfout",loadAccountFailed:"Kon uw account niet laden",loadAccountHint:"Als het probleem aanhoudt, log uit en probeer opnieuw.",accountDisabled:"Account uitgeschakeld",accountDisabledMessage:"Uw toegang tot deze CMS is uitgeschakeld. Neem contact op met uw beheerder.",firebaseNotConfigured:"Firebase is niet geconfigureerd",firebaseEnvMissing:`De volgende omgevingsvariabelen ontbreken:
|
|
3860
3860
|
{{vars}}
|
|
3861
3861
|
|
|
3862
|
-
Kopieer .env.example naar .env, vul uw Firebase-projectgegevens in en herstart de dev-server.`,adminEmailNotConfigured:"Admin-e-mail is niet geconfigureerd",adminEmailMessage:"VITE_ADMIN_EMAIL ontbreekt in .env. Stel deze in op het e-mailadres van de bootstrap-beheerder.",consoleHint:"Controleer de browserconsole en uw .env-configuratie. Zie de README voor instellingsinstructies."},kse={brandTitle:"Flexweg CMS",brandSubtitle:"Statische publisher",login:{heading:"Inloggen",intro:"Gebruik het e-mailadres en wachtwoord die uw beheerder met u heeft gedeeld.",submit:"Inloggen",submitting:"Inloggen…"},fields:{name:"Weergavenaam (optioneel)",namePlaceholder:"Jan Jansen",email:"E-mail",password:"Wachtwoord",passwordHint:"Minimaal 8 tekens."},footer:"Nieuwe accounts worden door een beheerder aangemaakt vanaf de Gebruikers-pagina.",errors:{invalidEmail:"Voer een geldig e-mailadres in.",missingPassword:"Wachtwoord is vereist.",passwordTooShort:"Het wachtwoord moet minimaal 8 tekens lang zijn."}},Sse=JSON.parse(`{"title":"Welkom bij Flexweg CMS","subtitle":"Eerste configuratie","intro":"Vul uw Firebase-gegevens in, het bootstrap-beheerderaccount en uw Flexweg-API-sleutel. De waarden worden gevalideerd, opgeslagen in uw project (Firestore + een config.js-bestand op Flexweg) en de admin laadt opnieuw met het normale aanmeldproces. U doet dit slechts één keer.","introFirebase":"Stap 1 — Firebase. Vul uw Firebase-projectgegevens en het bootstrap-beheerdersaccount in. We melden u aan, verifiëren het e-mailadres en controleren of uw Firestore-regels deze admin herkennen voordat we doorgaan naar de Flexweg-stap.","introFlexweg":"Stap 2 — Flexweg. Vul uw Flexweg-API-sleutel en site-URL in. We testen de API, slaan de configuratie op in Firestore, uploaden config.js naar uw site en synchroniseren de thema-assets.","continueToFlexweg":"Firebase valideren en doorgaan","stepper":{"terms":"Voorwaarden","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Content & publicatie","data":"Gegevens","hosting":"Hosting","install":"Installatie"},"backend":{"title":"Kies een data-backend","intro":"Kies waar het CMS uw berichten, pagina's, gebruikers en instellingen opslaat. U kunt later wisselen via Instellingen (data wordt niet gemigreerd).","sqliteTitle":"Flexweg SQLite (aanbevolen)","sqliteHint":"Alle data blijft op uw Flexweg-site als SQLite-bestand. Geen externe dienst. Auth wordt geleverd door de Flexweg SQLite-API.","firebaseTitle":"Firebase","firebaseHint":"Gebruik een Firebase-project voor Firestore + Auth. Gratis met het Spark-plan. Realtime updates via onSnapshot.","continue":"Doorgaan","markdownGitTitle":"Markdown-bestanden in een Git-repository","markdownGitHint":"Posts als .md-bestanden op GitHub / GitLab (of een lokale clone). Elke redacteur logt in met een eigen toegangstoken; elke wijziging is een commit. Geen database, werkt met meerdere redacteuren en computers.","localTitle":"Alleen deze browser","localHint":"Eén gebruiker, geen login, niets in te stellen. Content blijft in deze browser (exporteer via Instellingen). Ideaal voor een admin die op uw eigen computer draait."},"sqlite":{"heading":"Verbind uw Flexweg-site","intro":"We gebruiken uw Flexweg-master-API-sleutel ÉÉN KEER om een beperkt token aan te maken voor de SQLite-database. Na de installatie wordt de master-sleutel weggegooid en wordt alleen het beperkte token (begrensd tot dit ene SQLite-bestand) opgeslagen.","apiKeyHint":"Master Flexweg-API-sleutel. Alleen gebruikt om te installeren — daarna nooit opgeslagen.","detectedFromUrl":"Gedetecteerd uit URL","advanced":"Geavanceerde instellingen (Site-URL, SQLite-pad…)","pathHint":"Waar het SQLite-bestand op uw Flexweg-site staat. Mappen worden automatisch aangemaakt.","adminHeading":"Beheerdersaccount","adminIntro":"Maak de eerste gebruiker aan — dit account krijgt automatisch adminrechten. Volgende leden worden vanaf de Gebruikers-pagina onboarded zodra u bent ingelogd.","passwordHint":"Minimaal 8 tekens.","submit":"SQLite-database installeren"},"terms":{"title":"Gebruiksvoorwaarden","intro":"Lees en accepteer de onderstaande voorwaarden voordat u Flexweg CMS gebruikt. Ze zijn in eenvoudige taal geschreven zodat ze snel te lezen zijn.","section1":{"title":"1. Gratis dienst","body":"Flexweg CMS wordt door Flexweg gratis aangeboden. U kunt het zonder beperking gebruiken met uw Flexweg-hosting — Flexweg zal u het gebruik van het CMS zelf nooit in rekening brengen. De gebruikelijke kosten van uw Flexweg-hostingplan en uw Firebase-plan blijven van toepassing op de respectieve accounts."},"section2":{"title":"2. Geleverd „as-is“, zonder garantie","body":"Het CMS wordt as-is geleverd. We werken eraan om het stabiel te houden en in de loop van de tijd te verbeteren, maar we kunnen niet garanderen dat het vrij is van bugs, defecten of onderbrekingen. Gebruik het met dezelfde voorzichtigheid als bij elke tool die u niet zelf heeft geschreven: bewaar back-ups van belangrijke content."},"section3":{"title":"3. Uw content, uw verantwoordelijkheid","body":"U bent als enige verantwoordelijk voor de content die u via het CMS publiceert — tekst, afbeeldingen, video's, formulieren, code-embeds en alle andere media. U moet de toepasselijke wetgeving in uw rechtsgebied (en in de rechtsgebieden waarop u zich richt) naleven, evenals auteursrechten, beeld- en persoonlijkheidsrechten, regels voor de bescherming van persoonsgegevens en de voorwaarden van eventuele derde-diensten die u gebruikt (ingebedde fonts, video's, enz.). Flexweg is niet verantwoordelijk voor content die door gebruikers van het CMS wordt gepubliceerd."},"section4":{"title":"4. Uw Firebase-account, uw beveiliging","body":"Het CMS slaat zijn data op in uw eigen Firebase-project. U bent verantwoordelijk voor de beveiliging van dat project: kies een sterk wachtwoord voor het bootstrap-beheerderaccount, stel de Firestore-beveiligingsregels in zoals gedocumenteerd, rouleer uw API-sleutels wanneer nodig en controleer wie toegang heeft. Flexweg kan in geen geval verantwoordelijk worden gehouden voor ongeautoriseerde toegang, datalekken, hacks of verlies als gevolg van verkeerde configuratie of compromittering van uw Firebase-account."},"section5":{"title":"5. Beperking van aansprakelijkheid","body":"Flexweg kan niet aansprakelijk worden gesteld voor enige inkomstenderving, dataverlies, gemiste zakelijke kansen of enige directe of indirecte schade voortvloeiend uit het gebruik, misbruik of de onbeschikbaarheid van het CMS. Wanneer de toepasselijke wet Flexweg verplicht enige aansprakelijkheid op zich te nemen, is deze beperkt tot het bedrag dat in de afgelopen 12 maanden daadwerkelijk aan Flexweg voor het CMS is betaald — dat is nul, aangezien het CMS gratis is."},"section6":{"title":"6. Uw data blijft van u","body":"Content die u met het CMS aanmaakt wordt opgeslagen in uw eigen Firebase-project (tekst, instellingen, media-metadata) en op uw eigen Flexweg-hosting (gepubliceerde HTML, afbeeldingen, theme-assets). Het CMS zelf stuurt uw content niet door naar enige derde-dienst. Plugins of themes die u activeert kunnen hun eigen gedrag hebben — controleer wat ze doen voordat u ze activeert."},"section7":{"title":"7. Eerlijk gebruik","body":"Gebruik van het CMS voor onwettige, frauduleuze of schadelijke activiteiten, of op een manier die in strijd is met de algemene voorwaarden van Flexweg, kan leiden tot opschorting van uw toegang tot Flexweg-hosting. We kunnen deze CMS-voorwaarden in de loop van de tijd ook bijwerken; significante wijzigingen worden gecommuniceerd via de admin of per e-mail."},"accept":"Ik heb de Gebruiksvoorwaarden gelezen en ga ermee akkoord.","continue":"Door naar configuratie","back":"Terug"},"sections":{"firebase":"Firebase","admin":"Bootstrap-beheerder","flexweg":"Flexweg-API"},"help":{"firebase":"Vind deze waarden in Firebase Console → Projectinstellingen → Algemeen → Uw apps → SDK-installatie en configuratie.","admin":"Gebruik een bestaande gebruiker uit Firebase Authentication. Iedereen die aanmeldt met dit e-mailadres wordt als beheerder behandeld en omzeilt de gebruikersrecord-controle. Maak de gebruiker via Firebase Console → Authentication als deze nog niet bestaat.","flexweg":"Genereer een permanente API-sleutel in uw Flexweg-account → API. De site-URL is het publieke adres van uw Flexweg-site (bijv. https://uw-site.flexweg.com).","flexwegApiKeyHint":"Haal uw API-sleutel op uit uw Flexweg-accountinstellingen.","flexwegApiKeyLink":"Accountinstellingen openen"},"fields":{"apiKey":"API-sleutel","authDomain":"Auth-domein","projectId":"Project-ID","storageBucket":"Storage-bucket","messagingSenderId":"Messaging-afzender-ID","appId":"App-ID","adminEmail":"E-mail","adminPassword":"Wachtwoord","flexwegApiKey":"API-sleutel","flexwegSiteUrl":"Site-URL","flexwegApiBaseUrl":"API-basis-URL","sqlitePath":"SQLite-pad"},"submit":"Opslaan en doorgaan","submitting":"Bezig met instellen…","success":"Configuratie voltooid!","reloadingHint":"De admin wordt zo herladen — even geduld.","footer":"Deze waarden worden opgeslagen in uw project (Firestore + Flexweg). Ze worden nergens anders heen gestuurd.","steps":{"signInFirebase":"Aanmelden bij Firebase…","testFlexweg":"Flexweg-API testen…","writeFirestore":"Configuratie opslaan…","uploadConfig":"config.js uploaden naar Flexweg…","syncThemes":"Theme-assets synchroniseren naar Flexweg…","sqliteInstall":"Beperkt SQLite-token aanmaken…","sqliteRegisterAdmin":"Admin-account registreren…","sqliteSchema":"SQLite-schema initialiseren…"},"stepsDone":{"sqliteInstall":"Beperkt SQLite-token uitgegeven","sqliteRegisterAdmin":"Admin geregistreerd en ingelogd","sqliteSchema":"SQLite-schema klaar"},"errors":{"missingFields":"Vul alle velden in.","rootDeploymentTitle":"De admin moet in een submap staan, niet in de hoofdmap van de site.","rootDeploymentHint":"Verplaats de admin-bestanden (index.html, config.js, runtime/, …) naar een submap op Flexweg — bijvoorbeeld /admin/ of een willekeurige naam zoals /erf34f654GH3/ voor extra onopvallendheid. Herlaad de admin vervolgens vanuit de URL van de submap en voer de configuratie opnieuw uit.","firebaseAuthGeneric":"Aanmelden bij Firebase mislukt.","firebaseAuthInvalidCredential":"Firebase heeft de combinatie van e-mailadres en wachtwoord geweigerd.","firebaseAuthInvalidCredentialHint":"Moderne Firebase-projecten activeren standaard bescherming tegen e-mailopsomming, waardoor dezelfde fout wordt teruggegeven of het wachtwoord nu fout is, de gebruiker niet bestaat, of de gebruiker zich met een andere provider aanmeldt. Te controleren:\\n• Voer het wachtwoord opnieuw in — kopieer/plak vanuit een wachtwoordbeheerder om typfouten uit te sluiten. Minimale lengte is 6 tekens.\\n• Open Firebase Console → Authentication → Users en bevestig dat het e-mailadres bestaat. Controleer de kolom 'Providers': als deze alleen Google (of een andere provider) toont en niet 'Email/Password', stel het wachtwoord in of reset het via het rijmenu (⋮ → Wachtwoord resetten).\\n• Controleer of de spelling van het e-mailadres exact overeenkomt met wat in Firebase staat opgeslagen.","firebaseAuthUserNotFound":"Geen Firebase-gebruiker met dit e-mailadres. Maak er eerst een aan in Firebase Console → Authentication → Users.","firebaseAuthInvalidEmail":"Het admin-e-mailadres is geen geldig e-mailadres.","firebaseInvalidApiKey":"De Firebase-API-sleutel is ongeldig. Controleer de waarde in Firebase Console.","firebaseNetwork":"Netwerkfout bij aanmelden bij Firebase. Controleer uw verbinding.","firebaseTooManyRequests":"Te veel aanmeldpogingen. Probeer het later opnieuw of reset het wachtwoord via Firebase Console.","firebaseOperationNotAllowed":"Inloggen met e-mail/wachtwoord is niet ingeschakeld op dit Firebase-project. Open Firebase Console → Authentication → Sign-in method en schakel de provider Email/Password in.","firebaseUserDisabled":"Dit Firebase-gebruikersaccount is uitgeschakeld. Schakel het opnieuw in via Firebase Console → Authentication → Users.","wrongAdminEmail":"Het Firebase-account waarmee u bent aangemeld komt niet overeen met het ingevoerde admin-e-mailadres. Probeer het opnieuw.","rulesNotPinnedTitle":"De Firestore-regels herkennen u nog niet als bootstrap-admin.","rulesNotPinnedHint":"Open Firebase Console → Firestore → Rules en vervang de waarde van \`bootstrapAdminEmail()\` door: {{email}} — klik daarna op Publiceren. De regelsjabloon in de README bevat een placeholder \`you@example.com\` die vervangen moet worden door uw echte admin-e-mailadres. Klik na het publiceren van de nieuwe regels hier opnieuw op Verzenden.","flexwegAuth":"Flexweg-API-sleutel geweigerd. Controleer de waarde in uw Flexweg-account → API.","flexwegNetwork":"Netwerkfout bij contact met Flexweg. Controleer de API-basis-URL en uw verbinding.","flexwegHttp":"Flexweg-API-fout ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore weigerde het schrijven van de configuratie.","firestoreRulesHint":"Open Firebase Console → Firestore → Regels en zorg dat het bootstrap-admin-e-mailadres is ingesteld op '{{email}}'. De README bevat een kant-en-klare regelsjabloon.","firestoreOther":"Schrijven naar Firestore mislukt","uploadFailed":"Kon config.js niet uploaden naar Flexweg","generic":"Er is iets misgegaan."},"docstore":{"contentTitle":"Content-repository","contentIntro":"Waar uw posts, pagina's en instellingen worden opgeslagen als Markdown- + JSON-bestanden. Een lege repository is prima — het CMS maakt de bestanden aan.","provider":"Repository","localClone":"Lokale map (git-clone)","localCloneHint":"Kies de map van uw clone. Synchroniseer die met uw gebruikelijke git-client — het CMS leest en schrijft bestanden, het voert geen git uit.","contentDir":"Contentmap in de repository","privateRepo":"Gebruik een privé-repository: concepten worden daarin opgeslagen.","folderRequired":"Kies eerst de contentmap.","checking":"Toegang tot de repository controleren…","publishIntro":"Waar de gegenereerde site wordt gepubliceerd. U kunt dit later wijzigen in Instellingen.","existingSite":"Deze repository is al ingesteld — de site blijft publiceren naar: {{target}}. U kunt dit later wijzigen in Instellingen (eventuele geheime sleutels moeten daar opnieuw worden ingevoerd).","install":"Installeren","steps":{"config":"Configuratie opslaan…","content":"Content laden…","target":"Publicatiedoel opslaan…","testTarget":"Publicatiedoel testen…"},"doneTitle":"Alles klaar!","doneBody":"De configuratie is opgeslagen in deze browser. Om andere redacteuren deze stap te besparen, downloadt u config.js en vervangt u het bestand in de admin-map van uw hosting.","downloadConfig":"config.js downloaden","open":"Admin openen","footer":"Content blijft in uw repository of in deze browser; toegangstokens verlaten deze browser nooit."},"data":{"title":"1. Waar slaat u uw gegevens op?","intro":"Uw posts, pagina's, gebruikers en instellingen — de eigen gegevens van de admin. Dit staat los van waar de publieke site wordt gehost (volgende stap).","localNote":"Niets te configureren: content wordt in deze browser opgeslagen. Exporteer die via Instellingen om een back-up te maken of later te verhuizen.","options":{"sqlite-file":{"title":"SQLite","hint":"Een SQLite-database die wordt opgeslagen op de hosting die u in de volgende stap kiest (Flexweg, uw server, S3, Git…). Zonder gebruikersaccounts — of de SQLite-dienst van Flexweg, met accounts, als u op Flexweg host."},"flexweg-sqlite":{"title":"SQLite (Flexweg-dienst)","hint":"Een SQLite-database die door de dienst van Flexweg wordt beheerd, met ingebouwde gebruikersaccounts. Vereist een Flexweg-account, ongeacht waar de site wordt gehost."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth in uw Google-project. Realtime, gratis Spark-abonnement."},"markdown-git":{"title":"Markdown-bestanden in Git","hint":"Posts als .md-bestanden in een GitHub- / GitLab-repository (of een lokale clone). Elke redacteur gebruikt een eigen token; elke wijziging is een commit."},"local":{"title":"Deze browser","hint":"Eén gebruiker, geen login, niets in te stellen. Ideaal voor een admin die op uw computer draait."}}},"hosting":{"title":"2. Waar wordt de site gepubliceerd?","intro":"Waar de gegenereerde statische site (HTML, CSS, afbeeldingen) bij elke publicatie naartoe wordt geüpload. U kunt dit later wijzigen in Instellingen.","existing":"Deze content-repository publiceert al naar het onderstaande doel. Behoud het of kies een ander."},"install":{"title":"3. Installatie","intro":"Controleer het overzicht en installeer daarna.","data":"Gegevens","hosting":"Hosting","saveTarget":"Publicatiedoel opslaan…","noteConfigJs":"De admin-configuratie (config.js) wordt indien mogelijk naast de admin op Flexweg geüpload; anders wordt u aangeboden haar te downloaden.","noteLocalConfig":"De configuratie wordt in deze browser opgeslagen; u krijgt config.js aangeboden om in de admin-map te plaatsen, zodat andere redacteuren deze installatie kunnen overslaan."},"sqliteFile":{"security":"Geen gebruikersaccounts: iedereen die dit admin kan openen, kan de inhoud bewerken — beveilig de admin-map bij je hosting. Het databasebestand wordt als elk ander bestand geserveerd: houd het versleuteld of bewaar het op een aparte privélocatie.","intro":"Waar het databasebestand wordt opgeslagen. Deze admin leest en bewaart het via dezelfde connectoren als de hosting.","path":"Pad van het databasebestand","pathHint":"Wordt bij de eerste keer opslaan aangemaakt als het nog niet bestaat. Bij een Git-repository is elke keer opslaan een commit — kies bij voorkeur een repository of branch die geen build van de site start.","existing":"bestaande database","new":"nieuwe database","dataNote":"Hier valt niets te configureren: de database wordt opgeslagen op de hosting die u in de volgende stap kiest.","heading":"SQLite-database","flexwegService":"De SQLite-dienst van Flexweg gebruiken","flexwegServiceHint":"De database wordt door Flexweg beheerd en heeft ingebouwde gebruikersaccounts (e-mail + wachtwoord). Anders is het een gewoon bestand op deze hosting, zonder accounts.","summaryFile":"Bestand {{path}} op deze hosting","summaryService":"SQLite-dienst van Flexweg ({{path}})","encrypt":"Database versleutelen","encryptHint":"Aanbevolen bij openbare hosting: zonder wachtzin is het bestand onleesbaar. Elke nieuwe browser vraagt er één keer om.","passphrase":"Wachtzin","passphraseHint":"Bewaar hem nu in je wachtwoordmanager: zonder wachtzin kan niemand de database openen, ook jij niet.","copy":"Kopiëren","copied":"Gekopieerd","generate":"Nieuw","passphraseTooShort":"De wachtzin moet minstens 12 tekens lang zijn.","existingEncrypted":"Op dit pad staat al een versleutelde database: voer de wachtzin ervan in.","separate":"Database op een aparte privélocatie bewaren","separateHint":"Bijv. een privé S3- / R2-bucket of een privé Git-repository: de database wordt dan nooit door de openbare site geserveerd.","summaryEncrypted":"versleuteld","summaryLocation":"opgeslagen in {{location}}","locationLabel":"Locatie van de database","gitBranchNote":"De database staat op de branch {{branch}} van deze repository, die nooit wordt gepubliceerd: inhoud opslaan bouwt de site niet opnieuw.","summaryBranch":"op branch {{branch}}"},"adminHosting":{"deploying":"De admin wordt naar de site gekopieerd…","label":"De admin ook op deze site hosten","hint":"De admin wordt met zijn config.js (zonder geheimen) naar {{url}} gekopieerd — elke redacteur kan hem daar dan openen. Elke redacteur logt nog steeds in met de eigen toegang.","folder":"Admin-map","alreadyHere":"Deze admin draait al vanaf deze site: de config.js wordt ter plekke bijgewerkt.","doneBody":"De admin staat nu op uw site. Schakel bij GitHub Pages eerst Pages in voor de repository als dat nog niet is gebeurd (Settings → Pages) en open hem daarna:","open":"Online admin openen","continueHere":"Doorgaan in deze admin"}}`),Ese={actions:{upload:"Bestand uploaden",delete:"Bestand verwijderen",rename:"Bestand hernoemen",get:"Bestand lezen",list:"Bestanden lijsten",createFolder:"Map aanmaken",renameFolder:"Map hernoemen",deleteFolder:"Map verwijderen",storageLimits:"Opslaglimieten ophalen",commit:"Wijzigingen publiceren"},errors:{configMissing:"Het publicatiedoel is niet ingesteld. Stel het in via Instellingen voordat je publiceert.",network:"{{action}}: netwerkfout of CORS geblokkeerd. Controleer uw verbinding.",auth:"{{action}}: authenticatie mislukt. Controleer de gegevens van het publicatiedoel in Instellingen.",notFound:"{{action}}: niet gevonden op het publicatiedoel.",tooLarge:"{{action}}: bestand te groot voor het publicatiedoel.",rateLimited:"{{action}}: te veel verzoeken, probeer het zo opnieuw.",serverError:"{{action}}: serverfout van het publicatiedoel ({{status}}). Probeer het opnieuw.",generic:"{{action}} mislukt ({{status}}){{detail}}.",unsupported:'{{action}}: niet ondersteund door publicatiedoel "{{connector}}".',unknownConnector:'Onbekend publicatiedoel "{{connector}}". Controleer Instellingen → Publicatiedoel.',folderAccess:"Geen toegang tot de lokale map. Open Instellingen → Publicatiedoel en klik op ‘Map opnieuw verbinden’."}},_se={log:{rendering:"Pagina renderen…",uploading:"{{path}} uploaden…",deleting:"{{path}} verwijderen…",regenerating:"Lijsten opnieuw genereren…",skipped:"{{path}} overgeslagen (geen wijzigingen)",done:"Gepubliceerd op {{url}}",failed:"Mislukt: {{error}}"}},Cse={errors:{notConnected:"Niet verbonden met de contentrepository. Meld je opnieuw aan met je toegangstoken.",conflict:"Iemand anders heeft dit item intussen gewijzigd. Die versie wordt nu getoond — pas je wijziging opnieuw toe.",sqliteUnsupported:"Het doel ‘{{connector}}’ kan geen databasebestand opslaan."}},Ase={target:"Publicatiedoel",settingsTitle:"Publicatiedoel",settingsHelp:"Waar de gerenderde site naartoe wordt geüpload bij publiceren. Inloggegevens worden opgeslagen bij uw content-backend (of in deze browser bij Git-content-repository's) en zijn leesbaar voor alle admins.",saved:"Publicatiedoel opgeslagen. Voer Opnieuw genereren → Alles uit om de hele site naar het nieuwe doel te publiceren.",test:"Verbinding testen",testOk:"Verbinding OK",testFailed:"Verbinding mislukt",names:{flexweg:"Flexweg","git-pages":"Git-repository (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"S3-compatibele bucket (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Uw eigen server (PHP-bridge)","browser-mirror":"Downloaden als ZIP","local-folder":"Lokale map op deze computer"},hints:{flexweg:"Upload via de Flexweg Files API.","git-pages":"Elke publicatie is één commit in de repository; de host bouwt de site daaruit opnieuw op.",s3:"Vereist een CORS-regel op de bucket die de origin van deze admin toestaat, en websitehosting (of een CDN) om index.html-bestanden te serveren.","php-bridge":"Upload external/bridges/php/flexweg-bridge.php naar uw server, stel de API-sleutel in en vul hier de URL in.","browser-mirror":"De site wordt in deze browser bewaard; download het ZIP en upload het handmatig waar u maar wilt.","local-folder":"Schrijft de site rechtstreeks naar een map (Chrome / Edge). Serveer hem lokaal of push hem met uw eigen tools."},fields:{flexweg:{apiKey:"API-sleutel",siteUrl:"Site-URL",apiBaseUrl:"Basis-URL van de API"},"git-pages":{host:"Hosting",provider:"Git-provider",owner:"Eigenaar (gebruiker of organisatie)",repo:"Repository",project:"Projectpad",branch:"Branch",dir:"Map in de repository",token:"Toegangstoken",siteUrl:"Publieke site-URL",apiBaseUrl:"API-URL (alleen self-hosted)"},s3:{endpoint:"Endpoint",region:"Regio",bucket:"Bucket",prefix:"Sleutelvoorvoegsel (optioneel)",accessKeyId:"Access key-ID",secretAccessKey:"Geheime toegangssleutel",siteUrl:"Publieke site-URL",forcePathStyle:"Padgebaseerde URL's (MinIO, R2, de meeste compatibele diensten)",publicRead:"Geüploade bestanden openbaar maken (ACL public-read) — voor buckets die niet via een bucketbeleid openbaar zijn (OVHcloud, Scaleway…). Laat uit bij AWS-buckets met ‘bucket owner enforced’."},"php-bridge":{apiBaseUrl:"Bridge-URL",apiKey:"API-sleutel van de bridge",siteUrl:"Publieke site-URL"},"browser-mirror":{siteUrl:"Publieke site-URL (optioneel)"},"local-folder":{siteUrl:"URL waarop de map wordt geserveerd (optioneel)"}},help:{flexweg:{apiKey:"Aangemaakt vanuit uw Flexweg-account → API."},"git-pages":{host:"Cloudflare Pages: koppel het project aan deze repository zonder build-commando en met de uitvoermap hieronder. Werkt met privé-repository's.",dir:'Leeg laten voor de root van de repository. GitHub Pages: "" of "docs". GitLab Pages: "public".',token:"Fine-grained token op deze repository met Contents: read & write (GitHub) — voeg Pages: read & write toe zodat het CMS GitHub Pages kan inschakelen — of een token met de scope api (GitLab). Leeg laten om het eigen toegangstoken van elke redacteur te gebruiken wanneer de content bij dezelfde provider staat.",siteUrl:"bv. https://user.github.io/repo — een URL met submap is prima, links worden automatisch aangepast."},s3:{endpoint:"Leeg laten voor AWS (afgeleid van de regio). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"De website-URL van de bucket of uw CDN-domein."},"php-bridge":{apiBaseUrl:"De volledige URL van flexweg-bridge.php op uw server (HTTPS)."},"browser-mirror":{siteUrl:"Waar u het ZIP gaat uploaden — gebruikt voor absolute URL's (sitemaps, RSS, media)."},"local-folder":{siteUrl:"bv. http://localhost:8080 wanneer een lokale webserver de map serveert."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (gekoppeld aan de repository)","gitlab-pages":"GitLab Pages",other:"Anders (Netlify, Vercel, git pull op de server…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Map kiezen…",change:"Andere map…",reconnect:"Map opnieuw koppelen",unsupported:"Deze browser kan niet naar lokale mappen schrijven. Gebruik Chrome of Edge."},mirror:{download:"Site downloaden (ZIP)",count:"{{count}} bestanden in deze browser"},adminHosting:{title:"Admin op deze site",help:"Kopieer deze admin naar het publicatiedoel (eerste uitrol, of bijwerken na een nieuwe versie). De config.js bevat geen geheimen.",deploy:"Admin uitrollen / bijwerken",deployed:"Admin uitgerold ({{count}} bestanden) — {{url}}"},pages:{enabled:"GitHub Pages ingeschakeld voor deze repository — de site staat over ongeveer een minuut online.",enableHint:'Publiceren gelukt. Schakel GitHub Pages in voor {{repo}} om de site online te zetten: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Of geef het token de machtiging "Pages: read and write" en het CMS doet het voor u.)'},siteUrl:{mismatch:"De openbare URL van de site (Instellingen → Site) is {{site}}, maar dit doel serveert de site op {{target}}. Links, CSS en sitemaps volgen de site-URL — ze kloppen niet op deze hosting.",use:"{{url}} gebruiken voor de site",updated:"Site-URL bijgewerkt. Voer Opnieuw genereren → Alles uit om de pagina's met de nieuwe links opnieuw te publiceren."}},Tse={heading:"Verbinden met de content-repository",tokenIntro:"De content staat in de {{provider}}-repository {{repo}}. Log in met uw eigen persoonlijke toegangstoken — uw rechten op de repository bepalen uw rol (schrijftoegang = redacteur, admin / maintainer = admin).",token:"Persoonlijk toegangstoken",tokenHelpGithub:"Fine-grained token, alleen toegang tot deze repository, recht Contents: lezen en schrijven.",tokenHelpGitlab:"Token met de api scope, rol Developer of hoger op dit project.",createToken:"Token aanmaken",connect:"Verbinden",tokenStorage:"Het token wordt alleen in deze browser bewaard. Uitloggen wist het.",failed:"Met dit token kan niet naar de repository worden geschreven (ongeldig, verlopen of alleen-lezen). Controleer de rechten.",folderIntro:"De content staat in een map op deze computer (meestal een git-clone die u synchroniseert met uw eigen git-client). Geef deze browser toegang — browsers vragen het na elke herlaadbeurt opnieuw.",openFolder:"Contentmap openen"},Ise={flexweg:{title:"Flexweg",short:"Flexweg-hosting",hint:"Uploadt via de Flexweg Files API. API-sleutel uit uw Flexweg-account."},"github-pages":{title:"GitHub Pages",short:"Gratis, vanuit een GitHub-repository",hint:"Elke publicatie is één commit naar de repository; GitHub Pages serveert die. Settings → Pages → Deploy from a branch. Publieke repositories bij het gratis abonnement."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Gratis, privé-repositories mogelijk",hint:"Het CMS commit de site naar een GitHub- / GitLab-repository; koppel er een Cloudflare Pages-project aan (geen build-commando, uitvoermap = de map hieronder)."},"gitlab-pages":{title:"GitLab Pages",short:"Gratis, vanuit een GitLab-repository",hint:"Elke publicatie is één commit; het CMS voegt een minimale .gitlab-ci.yml toe die de map public/ publiceert."},"git-other":{title:"Netlify, Vercel…",short:"Elke host die een repository deployt",hint:"Het CMS commit de site naar een Git-repository; koppel uw host (Netlify, Vercel, een server die git pull uitvoert…) aan die repository."},s3:{title:"S3 / R2 / B2…",short:"Object-storage-bucket",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Vereist een CORS-regel op de bucket en website-hosting of een CDN ervoor."},"own-server":{title:"Uw eigen server (FTP / SFTP)",short:"Gedeelde hosting, VPS…",hint:"Browsers spreken geen FTP of SFTP: upload de PHP-bridge (external/bridges/php/flexweg-bridge.php) eenmalig met uw FTP-client, stel de API-sleutel ervan in en vul hier daarna de URL in. Werkt op elke PHP-host."},"local-folder":{title:"Lokale map",short:"Op deze computer",hint:"Schrijft de site naar een map op deze computer (Chrome / Edge). Serveer hem lokaal of push hem met uw eigen tools."},zip:{title:"Downloaden als ZIP",short:"Handmatig uploaden",hint:"De site wordt in deze browser bewaard; download een ZIP via Instellingen en upload die waar u maar wilt (Netlify Drop, FTP-client…)."}},Nse={heading:"Verbinding maken met de database",intro:"Deze admin slaat zijn content op in {{path}}. Voer de toegangsgegevens voor deze browser in.",storage:"De toegangsgegevens worden alleen in deze browser bewaard. Afmelden wist ze.",passphrase:"Wachtzin van de database",passphraseHint:"De database is versleuteld. Voer de wachtzin in die bij de installatie is gekozen (alleen in deze browser bewaard).",passphraseWrong:"Verkeerde wachtzin: de database kon niet worden geopend.",passphraseMissing:"Voer de wachtzin van de database in."},Pse={common:ise,auth:ase,nav:ose,dashboard:lse,posts:cse,pages:use,taxonomies:dse,media:hse,themes:fse,plugins:pse,externalInstall:mse,externalLoader:gse,menus:bse,settings:yse,users:vse,firestoreSetup:xse,errors:wse,identity:kse,setup:Sse,flexweg:Ese,publish:_se,docstore:Cse,connectors:Ase,gitAccess:Tse,hosting:Ise,sqliteAccess:Nse},Rse={save:"Guardar",saving:"A guardar…",saved:"Guardado",cancel:"Cancelar",delete:"Eliminar",deleting:"A eliminar…",edit:"Editar",create:"Criar",search:"Pesquisar",loading:"A carregar…",yes:"Sim",no:"Não",confirm:"Confirmar",back:"Voltar",next:"Seguinte",previous:"Anterior",close:"Fechar",all:"Todos",none:"Nenhum",actions:"Ações",name:"Nome",slug:"Slug",description:"Descrição",status:"Estado",createdAt:"Criado",updatedAt:"Atualizado",publishedAt:"Publicado",language:"Idioma",darkMode:"Modo escuro",lightMode:"Modo claro",signOut:"Terminar sessão",administrator:"Administrador",editor:"Editor",appName:"Flexweg CMS"},jse={signIn:"Iniciar sessão",signingIn:"A iniciar sessão…",email:"E-mail",password:"Palavra-passe",emailPlaceholder:"voce@empresa.com",passwordPlaceholder:"••••••••",forgotPassword:"Esqueceu-se da palavra-passe?",resetEmailSent:"E-mail de redefinição de palavra-passe enviado para {{email}}.",enterEmailFirst:"Introduza primeiro o seu e-mail acima e depois clique em redefinir.",emailPasswordRequired:"E-mail e palavra-passe são obrigatórios.",signInSubtitle:"Use o seu e-mail de trabalho e palavra-passe.",footer:"Os pedidos de conta passam pelo seu administrador.",errors:{invalidEmail:"Endereço de e-mail inválido.",invalidCredentials:"E-mail ou palavra-passe inválidos.",tooManyRequests:"Demasiadas tentativas. Tente novamente mais tarde ou redefina a sua palavra-passe.",userDisabled:"Esta conta foi desativada.",networkFailed:"Erro de rede. Verifique a sua ligação.",generic:"Falha na autenticação."}},Mse={openMenu:"Abrir menu",closeMenu:"Fechar menu",dashboard:"Painel",posts:"Artigos",pages:"Páginas",taxonomies:"Categorias e etiquetas",media:"Multimédia",themes:"Temas",themeSettings:"Definições do tema",plugins:"Plugins",menus:"Menus",users:"Utilizadores",settings:"Definições"},Lse={title:"Painel",welcome:"Bem-vindo de volta, {{email}}.",stats:{totalPosts:"Artigos",totalPages:"Páginas",online:"Online",drafts:"Rascunhos"}},Dse={title:"Artigos",newPost:"Novo artigo",noPosts:"Ainda não há artigos. Crie o primeiro para começar.",noPostsInFilter:"Nenhum artigo corresponde ao filtro atual.",search:{placeholder:"Procurar artigos…",clear:"Limpar pesquisa",noResults:"Nenhum artigo corresponde à sua pesquisa."},pagination:{previous:"Anterior",next:"Seguinte",showing:"A mostrar {{from}}–{{to}} de {{total}}",pageOf:"Página {{page}} de {{total}}"},bulk:{selectedCount_one:"{{count}} selecionado",selectedCount_other:"{{count}} selecionados",selectPage_one:"Selecionar {{count}} nesta página",selectPage_other:"Selecionar os {{count}} desta página",deselectPage:"Desmarcar página",allOnPageSelected_one:"{{count}} nesta página selecionado.",allOnPageSelected_other:"Os {{count}} desta página estão selecionados.",selectAllMatching_one:"Selecionar o artigo correspondente",selectAllMatching_other:"Selecionar os {{count}} artigos correspondentes",allMatchingSelected_one:"O artigo correspondente está selecionado.",allMatchingSelected_other:"Os {{count}} artigos correspondentes estão selecionados.",selectOne:"Selecionar «{{title}}»",publish:"Publicar ({{count}})",publishing:"A publicar…",publishedCount:"{{ok}} publicado(s), {{failed}} falha(s).",unpublish:"Despublicar ({{count}})",unpublishing:"A despublicar…",unpublishedCount:"{{ok}} despublicado(s), {{failed}} falha(s).",delete:"Eliminar",deleting:"A eliminar…",deletedCount:"{{ok}} eliminado(s), {{failed}} falha(s).",confirmDelete_one:"Eliminar {{count}} artigo? Será despublicado do Flexweg e não pode ser desfeito.",confirmDelete_other:"Eliminar {{count}} artigos? Serão despublicados do Flexweg e não pode ser desfeito.",noDraftSelected:"Nenhum artigo em rascunho selecionado.",noOnlineSelected:"Nenhum artigo online selecionado.",clear:"Limpar seleção"},filters:{all:"Todos",draft:"Rascunho",online:"Online"},fields:{title:"Título",slug:"Slug",excerpt:"Excerto",content:"Conteúdo",category:"Categoria",tags:"Etiquetas",heroImage:"Imagem de destaque",seoTitle:"Título SEO",seoDescription:"Descrição SEO",createdAt:"Criado em",updatedAt:"Última atualização",publishedAt:"Publicado em"},edit:{newTitle:"Novo artigo",editTitle:"Editar artigo",saved:"Guardado.",savedAndRepublished:"Guardado e republicado.",saveFailed:"Falha ao guardar.",saveAndRepublish:"Guardar e republicar",draftSaved:"Rascunho guardado.",slugCollision:{post:'Este URL já é usado pelo artigo: "{{label}}".',page:'Este URL já é usado pela página: "{{label}}".',category:'Este URL já é usado pela categoria: "{{label}}".'},publish:"Publicar",unpublish:"Despublicar",publishing:"A publicar…",unpublishing:"A despublicar…",titlePlaceholder:"Adicionar título",permalink:"Ligação permanente",slugFormatHint:"Apenas minúsculas, ASCII, separadas por hífens.",slugAutoSuffixed:'Sufixo adicionado porque "{{base}}" já é usado por {{owner}}.',slugAutoSuffixedOwner:{post:'publicação: "{{label}}"',page:'página: "{{label}}"',category:'categoria: "{{label}}"'},saveBlocked:{titleRequired:"Adicione um título antes de guardar.",slugRequired:"São necessários um título e um slug de URL para guardar.",slugInvalid:"Formato de slug inválido (ASCII minúsculo + hífens).",slugCollision:"Resolva o conflito de URL antes de guardar."},viewPublished:"Ver",confirmDelete:"Eliminar este registo?",inspector:{document:"Documento",block:"Bloco",blockEmpty:"Selecione um bloco no editor para ver as suas opções.",publishing:"Publicação",permalink:"Ligação permanente",categories:"Categorias e etiquetas",featured:"Imagem de destaque",seo:"SEO",excerpt:"Excerto",dates:"Datas"},blocks:{addBlock:"Adicionar bloco",transform:"Transformar em",moveUp:"Mover para cima",moveDown:"Mover para baixo",duplicate:"Duplicar",remove:"Eliminar bloco",paragraph:"Parágrafo",heading2:"Título 2",heading3:"Título 3",bulletList:"Lista com marcadores",orderedList:"Lista numerada",blockquote:"Citação",codeBlock:"Código",image:"Imagem",horizontalRule:"Separador",categories:{text:"Texto",media:"Multimédia",layout:"Disposição",embed:"Incorporações",advanced:"Avançado"},noSettings:"Este bloco não tem definições.",noSelection:"Selecione um bloco no editor para ver as suas opções.",slash:{noResults:"Nenhum bloco corresponde."}}},status:{draft:"Rascunho",online:"Online"},preview:{title:"Pré-visualização",rendering:"A renderizar pré-visualização…",error:"Pré-visualização falhou: {{error}}",viewports:{mobile:"Telemóvel",tablet:"Tablet",desktop:"Computador"}}},Fse={title:"Páginas",newPage:"Nova página",noPages:"Ainda não há páginas.",homeBadge:"Início",homeBadgeTooltip:"Usada como página inicial do site"},Ose={title:"Categorias e etiquetas",categories:"Categorias",tags:"Etiquetas",newCategory:"Nova categoria",newTag:"Nova etiqueta",noCategories:"Ainda não há categorias.",noTags:"Ainda não há etiquetas.",slugCollision:'Este slug já é usado por "{{label}}".',seo:{button:"SEO",buttonTitle:"Editar metatags SEO",title:"Metatags SEO",subtitle:'Título e descrição personalizados para a página de arquivo de "{{name}}".',metaTitle:"Meta título",metaTitleHint:"Usado como <title> da página. Padrão: o nome do termo.",metaDescription:"Meta descrição",metaDescriptionHint:"Usada como meta descrição da página. Padrão: a descrição do termo."}},zse={title:"Biblioteca multimédia",upload:"Carregar",uploading:"A carregar…",finalizing:"A finalizar…",uploadFailed:"Falha no carregamento",retry:"Tentar novamente",noMedia:"Ainda não há multimédia.",alt:"Texto alternativo",caption:"Legenda",filename:"Nome do ficheiro",size:"Tamanho",type:"Tipo"},Use={title:"Temas",active:"Ativo",activate:"Ativar",installExternal:"Instalar tema",uninstallDisabledTitle:"Mude para outro tema antes de desinstalar este.",syncAssets:"Sincronizar recursos do tema",regenerateSite:"Regenerar o site",regenerating:"A regenerar…",regenerate:{button:"Regenerar",running:"Em execução…",groupBuiltins:"Site",groupPlugins:"Plugins",home:"Apenas página inicial",homeHelp:"Regenera apenas index.html — opção mais rápida.",allHtml:"Todas as páginas HTML",allHtmlHelp:"Todos os posts, páginas, arquivos e listagens — mais os snapshots menu / posts / authors JSON.",repair:"Reparar URLs",repairHelp:"Recalcula a URL canônica de cada post online e move os arquivos que ficaram na URL errada. Útil após uma importação executada antes que os termos fossem sincronizados.",assets:"Recursos do tema",assetsHelp:"Envia o CSS e os scripts do tema ativo para /theme-assets/.",everything:"Tudo",everythingHelp:"Recursos do tema + todos os HTML + cada saída de plugin. Opção mais lenta.",noPluginTargets:"Sem regenerações de plugin — ative um plugin que suporte regenerar."},confirmSwitch:{title:"Mudar para {{theme}}?",body:"Mudar de tema requer reenviar os recursos do tema e regenerar todas as páginas publicadas para que o novo aspeto se propague em todo o lado. Pode demorar um momento.",confirm:"Mudar e regenerar",cancel:"Cancelar"}},Bse={title:"Plugins",enabled:"Ativado",disabled:"Desativado",enable:"Ativar",disable:"Desativar",configure:"Configurar",author:"autor",learnMore:"Saber mais",mustUseBadge:"Obrigatório",installExternal:"Instalar plugin",tabs:{regular:"Plugins",mustUse:"Obrigatórios"}},$se={titlePlugin:"Instalar um plugin",titleTheme:"Instalar um tema",labelPlugin:"plugin",labelTheme:"tema",intro:"Largue um ficheiro ZIP com um pacote de {{label}} (manifest.json + bundle.js na raiz do ZIP). O {{label}} será carregado para o seu site Flexweg e registado após uma recarga. Voltar a carregar um ZIP com o mesmo id de manifest atualiza o registo existente no local — não é preciso desinstalar.",zipField:"Ficheiro ZIP do pacote",install:"Instalar",installing:"A instalar…",installSuccess:"{{name}} instalado ({{count}} ficheiros carregados). A recarregar…",upgradeSuccess:"{{name}} atualizado de v{{previousVersion}} para v{{newVersion}} ({{count}} ficheiros carregados). A recarregar…",installedTitle:"Já instalado",bundledDefaultsTitle:"Plugins/temas incluídos disponíveis",bundledDefaultsHint:"{{count}} plugin/tema incluído está atualmente desinstalado. Restaure-os para recuperar o que vinha com esta versão do admin.",bundledDefaultsRestore:"Restaurar",bundledDefaultsRestored:"{{plugins}} plugin(s) e {{themes}} tema(s) restaurados. A recarregar…",uninstall:"Desinstalar",uninstallSuccess:"{{id}} desinstalado. A recarregar…",confirmUninstall:"Desinstalar {{id}}? Os ficheiros serão eliminados do Flexweg.",errors:{"no-manifest":"Ao ZIP falta manifest.json na raiz.","invalid-manifest":"O manifest.json é inválido (campos obrigatórios em falta ou JSON inválido).","incompatible-api":"O pacote foi construído contra uma versão de API runtime incompatível.","no-bundle":"O ZIP não contém o ficheiro de entrada declarado no manifest.","fetch-manifest":"Não foi possível ler o external.json atual no Flexweg.","upload-failed":"Falha no carregamento — verifique a sua chave API Flexweg e a sua ligação."}},Hse={someFailed:"{{count}} pacote(s) externo(s) falharam ao carregar. Veja a consola do browser."},Vse={title:"Menus",header:"Menu de cabeçalho",footer:"Menu de rodapé",label:"Etiqueta",saveAndPublish:"Guardar e gerar",discard:"Descartar",saved:"Menus guardados e publicados.",saveFailed:"Não foi possível guardar os menus.",unsavedChanges:"Tem alterações por guardar."},qse={title:"Definições",tabs:{general:"Geral"},site:{title:"Site",siteTitle:"Título do site",siteDescription:"Descrição do site",siteLanguage:"Idioma do site",siteLanguageHelp:'Tag BCP-47 (p. ex. en, fr-CA) inserida em <html lang="…"> em cada página publicada. O prefixo é correspondido com os locais de tradução suportados para os rótulos de sitemap / RSS e textos integrados no tema; os locais não suportados recorrem ao inglês.',siteLanguageResolved:"As traduções usarão: {{label}}",baseUrl:"URL público do site",postsPerPage:"Artigos por página",homeMode:"Conteúdo da página inicial",homeLatest:"Artigos mais recentes",homeStatic:"Página estática",homePage:"Página inicial",discourageIndexing:"Desencorajar os motores de pesquisa de indexar este site",discourageIndexingHelp:"Quando ativado, cada página publicada recebe uma meta tag noindex/nofollow e o robots.txt bloqueia todos os rastreadores. Replica o comportamento do WordPress — útil para sites de staging ou revisões antes do lançamento. Os motores de pesquisa que respeitam a diretiva não indexarão o site.",discourageRegenerateHint:"Definição de indexação guardada. Clique em «Regenerar tudo» em Temas para aplicar a alteração a todas as páginas publicadas e ao robots.txt."},flexweg:{title:"API Flexweg",apiKey:"Chave da API",apiKeyHelp:"Gerada na sua conta Flexweg → API.",siteUrl:"URL do site",siteUrlHelp:"URL público do seu site Flexweg sem barra final.",apiBaseUrl:"URL base da API",storageHelpFirebase:"Guardada no Firestore (config/flexweg). Legível por qualquer membro com sessão iniciada, gravável apenas por administradores.",storageHelpSqlite:"Guardada na tabela SQLite local config. Legível por qualquer membro com sessão iniciada, gravável apenas por administradores."},backend:{title:"Backend de dados",active:"Backend ativo:",switchButton:"Mudar de backend…",confirmTitle:"Todos os dados atuais serão perdidos.",confirmBody:"Mudar limpa a configuração no browser e recarrega o formulário de configuração. O novo backend começa vazio — os dados do backend anterior permanecem onde estavam (no Firestore ou como um ficheiro .sqlite no Flexweg), mas o CMS só voltará a lê-los quando trocar de volta.",confirmYes:"Sim, mudar de backend",downloadBackup:"Descarregar uma cópia de segurança do ficheiro .sqlite",downloadBackupHelp:"faça isto antes de mudar de backend.",markdownGit:"Markdown — {{source}}",localFolder:"pasta local",localBrowser:"Este browser (local, um só utilizador)",sqliteFile:"Ficheiro SQLite — {{location}}"},performance:{title:"Desempenho",help:"Como o admin carrega artigos e páginas. O modo padrão funciona no plano gratuito do Firestore sem configuração; o modo paginado é para sites muito grandes e requer criação de índices uma vez.",mode:"Modo de carregamento",modeGlobal:"Padrão (sem configuração)",modePaginated:"Paginação no servidor (índices Firestore necessários)",globalHelp:"Carrega toda a coleção de artigos numa subscrição ao vivo. Ordenação, filtros e pesquisa em memória. Recomendado para sites com menos de ~5 000 artigos.",paginatedHelp:"Subscrições paginadas por cursor, uma página de cada vez. Requer índices compostos do Firestore — ver README. Recomendado para sites muito grandes.",savedReload:"Guardado. Recarregue o admin para aplicar o novo modo."},editor:{title:"Editor",help:"Tipografia usada no editor de artigos / páginas. Independente do tema público.",fontFamily:"Família tipográfica",bodySize:"Tamanho do corpo",h1Size:"Tamanho H1",h2Size:"Tamanho H2",h3Size:"Tamanho H3",sizeHelp:"Comprimento CSS, p. ex. 16px ou 1rem. Deixe em branco para o valor predefinido.",reset:"Repor predefinições"},profile:{title:"Perfil",adminLocale:"Idioma do admin",adminLocaleHelp:"Idioma usado pela interface de administração. Guardado no seu perfil.",firstName:"Nome próprio",lastName:"Apelido",headline:"Título",headlinePlaceholder:"ex. Jornalista, Editor-chefe…",headlineHelp:"Mostrado publicamente sob o seu nome nos cartões de autor e na sua página de arquivo.",bio:"Biografia",bioPlaceholder:"Um parágrafo curto mostrado na sua página de autor e por baixo dos seus artigos.",bioHelp:"Visível no site público na barra lateral do autor e na página de arquivo do autor.",socials:"Perfis sociais",socialsHelp:"Adicione os URLs dos perfis que quer expor no site público e ative «Mostrar» nos que devem ser visíveis. URLs vazios são ignorados.",socialsShow:"Mostrar",socialsShowHelp:"Alterna a visibilidade desta rede no site público.",avatar:"Foto de perfil",avatarHelp:"Escolha uma imagem da sua biblioteca multimédia. Imagens quadradas ficam melhor.",pickAvatar:"Escolher dos média",changeAvatar:"Alterar foto",removeAvatar:"Remover",save:"Guardar perfil"},transfer:{title:"Mover ou fazer cópia de segurança do conteúdo",help:"Exporte tudo (posts, páginas, categorias, metadados de multimédia, perfis, definições) num único ficheiro JSON. Num backend Markdown ou local pode importar esse ficheiro mantendo os ids — é assim que se migra a partir do Firebase ou do SQLite. Os ficheiros multimédia e as chaves secretas não são incluídos.",export:"Exportar o conteúdo (JSON)",import:"Importar conteúdo…",modeMerge:"Combinar (substitui os mesmos ids)",modeReplace:"Substituir as coleções importadas",replaceConfirm:"O modo Substituir elimina todos os itens existentes das coleções presentes no ficheiro antes de importar. Continuar?",invalidFile:"Este ficheiro não é uma exportação de conteúdo do Flexweg CMS.",imported:"Importados {{posts}} posts/páginas, {{terms}} termos e {{media}} multimédia. Execute Regenerar → Tudo para os publicar."},encryption:{title:"Cifra da base de dados:",on:"ativa",off:"inativa",onHelp:"O ficheiro da base de dados é ilegível sem a frase-passe. Alterá-la volta a guardar o ficheiro com uma nova chave; os outros navegadores vão pedir a nova frase.",offHelp:"Quem conseguir descarregar o ficheiro da base de dados pode lê-lo (um alojamento estático serve-o como qualquer página). Cifre-o com uma frase-passe.",enable:"Cifrar a base de dados…",change:"Alterar a frase-passe…",savedConfirm:"Guardei esta frase-passe no meu gestor de palavras-passe — sem ela o conteúdo não pode ser aberto.",enableConfirm:"Cifrar agora",changeConfirm:"Alterar a frase",done:"Base de dados guardada com a nova frase-passe."}},Wse={title:"Utilizadores",noUsers:"Ainda não há utilizadores.",role:"Função",disabled:"Desativado",editProfileTitle:"Editar perfil — {{email}}",profileSaved:"Perfil guardado.",descriptionFirebase:"Faça a gestão da sua equipa. As novas contas são criadas na Firebase Console e replicadas aqui no primeiro início de sessão.",descriptionSqlite:"Faça a gestão da sua equipa. Use o botão +Adicionar utilizador abaixo para criar contas diretamente.",addUser:"Adicionar utilizador",addUserSuccess:"{{email}} adicionado.",removeConfirmFirebase:"Eliminar o registo de {{email}}? Isto remove o perfil e a função do CMS. Para revogar o acesso, elimine também a conta na Firebase Console.",removeConfirmSqlite:"Eliminar permanentemente {{email}}? Isto revoga o acesso E remove o perfil e a função. Esta ação não pode ser desfeita.",empty:{title:"Ainda não há membros na equipa",descriptionFirebase:"Crie a primeira conta na Firebase Console e depois inicie sessão aqui uma vez para registar o perfil.",descriptionSqlite:"Clique em +Adicionar utilizador acima para convidar o primeiro membro."},help:{title:"Como adicionar um novo membro à equipa",bootstrapLine:"O admin inicial (sempre com acesso total) é:",firebase:{step1:"Abra a Firebase Console → Authentication → Add user.",step2:"Defina um e-mail e palavra-passe e envie-os ao novo membro.",step3:"Peça-lhe para iniciar sessão aqui uma vez — o perfil aparece na lista acima e pode editar a função e os dados."},sqlite:{step1:"Clique no botão +Adicionar utilizador acima.",step2:"Introduza o e-mail e uma palavra-passe temporária (8+ caracteres).",step3:"Partilhe as credenciais de forma segura — ele pode alterar a palavra-passe a partir do perfil depois de iniciar sessão."},git:{step1:"Adicione a pessoa como colaboradora do repositório de conteúdo (escrita = editor, admin / maintainer = admin).",step2:"A pessoa cria o seu próprio token de acesso pessoal no GitHub / GitLab.",step3:"Abre o admin e inicia sessão com esse token — o perfil é criado aqui automaticamente."}},addUserModal:{title:"Adicionar um novo membro à equipa",intro:"Cria a conta diretamente na base de dados Flexweg SQLite Auth. O novo utilizador fica com a função editor por defeito; promova-o a partir da lista abaixo se precisar de acesso admin.",submit:"Criar utilizador",submitting:"A criar…"},actions:{editProfile:"Editar perfil",promote:"Promover a administrador",demote:"Despromover a editor",disable:"Desativar",enable:"Ativar",delete:"Eliminar registo"},descriptionGit:"Os membros da equipa são as pessoas com acesso de escrita ao repositório de conteúdo. Aparecem aqui após o primeiro início de sessão; a função acompanha as permissões no repositório.",descriptionLocal:"Este admin funciona em modo de utilizador único: o conteúdo é guardado neste browser e não há contas.",descriptionSqliteFile:"Sem contas de utilizador com este backend: qualquer pessoa que consiga abrir o admin pode editar. Proteja a pasta do admin ao nível do seu alojamento. Os perfis de autor abaixo são meramente informativos."},Gse={title:"Configuração do Firestore necessária",intro:"As páginas de listagem de artigos e páginas precisam de alguns índices compostos do Firestore para consultas eficientes. Precisam de ser criados manualmente — o Firebase reserva a criação de índices aos administradores do projeto.",checking:"A verificar os seus índices Firestore…",missingCount_one:"{{count}} índice em falta:",missingCount_other:"{{count}} índices em falta:",openConsole:"Abrir Firebase Console para criar",noUrl:"Não foi possível extrair o URL de auto-sugestão — consulte o README para o comando gcloud.",howItWorks:"Como funciona",step1:"Clique no link de cada índice em falta — Firebase Console abre com a definição pré-preenchida.",step2:"Clique em «Create» e espere 1–5 minutos pela construção do índice (estado na consola).",step3:"Volte aqui e clique em Tentar novamente. Quando ambas as consultas tiverem êxito, o admin carrega.",retry:"Tentar novamente",retrying:"A tentar…",buildHint:"A construção de um índice pode demorar alguns minutos após a criação.",allReady:"Todos os índices estão prontos.",unexpectedTitle:"Firestore inacessível",unexpectedHint:"Verifique a sua ligação e as regras do Firestore. Se acabou de criar os índices, espere que terminem e tente novamente."},Kse={appError:"Erro da aplicação",loadAccountFailed:"Não foi possível carregar a sua conta",loadAccountHint:"Se o problema persistir, termine sessão e tente novamente.",accountDisabled:"Conta desativada",accountDisabledMessage:"O seu acesso a este CMS foi desativado. Contacte o seu administrador.",firebaseNotConfigured:"Firebase não está configurado",firebaseEnvMissing:`Faltam as seguintes variáveis de ambiente:
|
|
3862
|
+
Kopieer .env.example naar .env, vul uw Firebase-projectgegevens in en herstart de dev-server.`,adminEmailNotConfigured:"Admin-e-mail is niet geconfigureerd",adminEmailMessage:"VITE_ADMIN_EMAIL ontbreekt in .env. Stel deze in op het e-mailadres van de bootstrap-beheerder.",consoleHint:"Controleer de browserconsole en uw .env-configuratie. Zie de README voor instellingsinstructies."},kse={brandTitle:"AgentCMS",brandSubtitle:"Statische publisher",login:{heading:"Inloggen",intro:"Gebruik het e-mailadres en wachtwoord die uw beheerder met u heeft gedeeld.",submit:"Inloggen",submitting:"Inloggen…"},fields:{name:"Weergavenaam (optioneel)",namePlaceholder:"Jan Jansen",email:"E-mail",password:"Wachtwoord",passwordHint:"Minimaal 8 tekens."},footer:"Nieuwe accounts worden door een beheerder aangemaakt vanaf de Gebruikers-pagina.",errors:{invalidEmail:"Voer een geldig e-mailadres in.",missingPassword:"Wachtwoord is vereist.",passwordTooShort:"Het wachtwoord moet minimaal 8 tekens lang zijn."}},Sse=JSON.parse(`{"title":"Welkom bij AgentCMS","subtitle":"Eerste configuratie","intro":"Vul uw Firebase-gegevens in, het bootstrap-beheerderaccount en uw Flexweg-API-sleutel. De waarden worden gevalideerd, opgeslagen in uw project (Firestore + een config.js-bestand op Flexweg) en de admin laadt opnieuw met het normale aanmeldproces. U doet dit slechts één keer.","introFirebase":"Stap 1 — Firebase. Vul uw Firebase-projectgegevens en het bootstrap-beheerdersaccount in. We melden u aan, verifiëren het e-mailadres en controleren of uw Firestore-regels deze admin herkennen voordat we doorgaan naar de Flexweg-stap.","introFlexweg":"Stap 2 — Flexweg. Vul uw Flexweg-API-sleutel en site-URL in. We testen de API, slaan de configuratie op in Firestore, uploaden config.js naar uw site en synchroniseren de thema-assets.","continueToFlexweg":"Firebase valideren en doorgaan","stepper":{"terms":"Voorwaarden","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Content & publicatie","data":"Gegevens","hosting":"Hosting","install":"Installatie"},"backend":{"title":"Kies een data-backend","intro":"Kies waar het CMS uw berichten, pagina's, gebruikers en instellingen opslaat. U kunt later wisselen via Instellingen (data wordt niet gemigreerd).","sqliteTitle":"Flexweg SQLite (aanbevolen)","sqliteHint":"Alle data blijft op uw Flexweg-site als SQLite-bestand. Geen externe dienst. Auth wordt geleverd door de Flexweg SQLite-API.","firebaseTitle":"Firebase","firebaseHint":"Gebruik een Firebase-project voor Firestore + Auth. Gratis met het Spark-plan. Realtime updates via onSnapshot.","continue":"Doorgaan","markdownGitTitle":"Markdown-bestanden in een Git-repository","markdownGitHint":"Posts als .md-bestanden op GitHub / GitLab (of een lokale clone). Elke redacteur logt in met een eigen toegangstoken; elke wijziging is een commit. Geen database, werkt met meerdere redacteuren en computers.","localTitle":"Alleen deze browser","localHint":"Eén gebruiker, geen login, niets in te stellen. Content blijft in deze browser (exporteer via Instellingen). Ideaal voor een admin die op uw eigen computer draait."},"sqlite":{"heading":"Verbind uw Flexweg-site","intro":"We gebruiken uw Flexweg-master-API-sleutel ÉÉN KEER om een beperkt token aan te maken voor de SQLite-database. Na de installatie wordt de master-sleutel weggegooid en wordt alleen het beperkte token (begrensd tot dit ene SQLite-bestand) opgeslagen.","apiKeyHint":"Master Flexweg-API-sleutel. Alleen gebruikt om te installeren — daarna nooit opgeslagen.","detectedFromUrl":"Gedetecteerd uit URL","advanced":"Geavanceerde instellingen (Site-URL, SQLite-pad…)","pathHint":"Waar het SQLite-bestand op uw Flexweg-site staat. Mappen worden automatisch aangemaakt.","adminHeading":"Beheerdersaccount","adminIntro":"Maak de eerste gebruiker aan — dit account krijgt automatisch adminrechten. Volgende leden worden vanaf de Gebruikers-pagina onboarded zodra u bent ingelogd.","passwordHint":"Minimaal 8 tekens.","submit":"SQLite-database installeren"},"terms":{"title":"Gebruiksvoorwaarden","intro":"Lees en accepteer de onderstaande voorwaarden voordat u AgentCMS gebruikt. Ze zijn in eenvoudige taal geschreven zodat ze snel te lezen zijn.","section1":{"title":"1. Gratis dienst","body":"AgentCMS wordt door Flexweg gratis aangeboden. U kunt het zonder beperking gebruiken met uw Flexweg-hosting — Flexweg zal u het gebruik van het CMS zelf nooit in rekening brengen. De gebruikelijke kosten van uw Flexweg-hostingplan en uw Firebase-plan blijven van toepassing op de respectieve accounts."},"section2":{"title":"2. Geleverd „as-is“, zonder garantie","body":"Het CMS wordt as-is geleverd. We werken eraan om het stabiel te houden en in de loop van de tijd te verbeteren, maar we kunnen niet garanderen dat het vrij is van bugs, defecten of onderbrekingen. Gebruik het met dezelfde voorzichtigheid als bij elke tool die u niet zelf heeft geschreven: bewaar back-ups van belangrijke content."},"section3":{"title":"3. Uw content, uw verantwoordelijkheid","body":"U bent als enige verantwoordelijk voor de content die u via het CMS publiceert — tekst, afbeeldingen, video's, formulieren, code-embeds en alle andere media. U moet de toepasselijke wetgeving in uw rechtsgebied (en in de rechtsgebieden waarop u zich richt) naleven, evenals auteursrechten, beeld- en persoonlijkheidsrechten, regels voor de bescherming van persoonsgegevens en de voorwaarden van eventuele derde-diensten die u gebruikt (ingebedde fonts, video's, enz.). Flexweg is niet verantwoordelijk voor content die door gebruikers van het CMS wordt gepubliceerd."},"section4":{"title":"4. Uw Firebase-account, uw beveiliging","body":"Het CMS slaat zijn data op in uw eigen Firebase-project. U bent verantwoordelijk voor de beveiliging van dat project: kies een sterk wachtwoord voor het bootstrap-beheerderaccount, stel de Firestore-beveiligingsregels in zoals gedocumenteerd, rouleer uw API-sleutels wanneer nodig en controleer wie toegang heeft. Flexweg kan in geen geval verantwoordelijk worden gehouden voor ongeautoriseerde toegang, datalekken, hacks of verlies als gevolg van verkeerde configuratie of compromittering van uw Firebase-account."},"section5":{"title":"5. Beperking van aansprakelijkheid","body":"Flexweg kan niet aansprakelijk worden gesteld voor enige inkomstenderving, dataverlies, gemiste zakelijke kansen of enige directe of indirecte schade voortvloeiend uit het gebruik, misbruik of de onbeschikbaarheid van het CMS. Wanneer de toepasselijke wet Flexweg verplicht enige aansprakelijkheid op zich te nemen, is deze beperkt tot het bedrag dat in de afgelopen 12 maanden daadwerkelijk aan Flexweg voor het CMS is betaald — dat is nul, aangezien het CMS gratis is."},"section6":{"title":"6. Uw data blijft van u","body":"Content die u met het CMS aanmaakt wordt opgeslagen in uw eigen Firebase-project (tekst, instellingen, media-metadata) en op uw eigen Flexweg-hosting (gepubliceerde HTML, afbeeldingen, theme-assets). Het CMS zelf stuurt uw content niet door naar enige derde-dienst. Plugins of themes die u activeert kunnen hun eigen gedrag hebben — controleer wat ze doen voordat u ze activeert."},"section7":{"title":"7. Eerlijk gebruik","body":"Gebruik van het CMS voor onwettige, frauduleuze of schadelijke activiteiten, of op een manier die in strijd is met de algemene voorwaarden van Flexweg, kan leiden tot opschorting van uw toegang tot Flexweg-hosting. We kunnen deze CMS-voorwaarden in de loop van de tijd ook bijwerken; significante wijzigingen worden gecommuniceerd via de admin of per e-mail."},"accept":"Ik heb de Gebruiksvoorwaarden gelezen en ga ermee akkoord.","continue":"Door naar configuratie","back":"Terug"},"sections":{"firebase":"Firebase","admin":"Bootstrap-beheerder","flexweg":"Flexweg-API"},"help":{"firebase":"Vind deze waarden in Firebase Console → Projectinstellingen → Algemeen → Uw apps → SDK-installatie en configuratie.","admin":"Gebruik een bestaande gebruiker uit Firebase Authentication. Iedereen die aanmeldt met dit e-mailadres wordt als beheerder behandeld en omzeilt de gebruikersrecord-controle. Maak de gebruiker via Firebase Console → Authentication als deze nog niet bestaat.","flexweg":"Genereer een permanente API-sleutel in uw Flexweg-account → API. De site-URL is het publieke adres van uw Flexweg-site (bijv. https://uw-site.flexweg.com).","flexwegApiKeyHint":"Haal uw API-sleutel op uit uw Flexweg-accountinstellingen.","flexwegApiKeyLink":"Accountinstellingen openen"},"fields":{"apiKey":"API-sleutel","authDomain":"Auth-domein","projectId":"Project-ID","storageBucket":"Storage-bucket","messagingSenderId":"Messaging-afzender-ID","appId":"App-ID","adminEmail":"E-mail","adminPassword":"Wachtwoord","flexwegApiKey":"API-sleutel","flexwegSiteUrl":"Site-URL","flexwegApiBaseUrl":"API-basis-URL","sqlitePath":"SQLite-pad"},"submit":"Opslaan en doorgaan","submitting":"Bezig met instellen…","success":"Configuratie voltooid!","reloadingHint":"De admin wordt zo herladen — even geduld.","footer":"Deze waarden worden opgeslagen in uw project (Firestore + Flexweg). Ze worden nergens anders heen gestuurd.","steps":{"signInFirebase":"Aanmelden bij Firebase…","testFlexweg":"Flexweg-API testen…","writeFirestore":"Configuratie opslaan…","uploadConfig":"config.js uploaden naar Flexweg…","syncThemes":"Theme-assets synchroniseren naar Flexweg…","sqliteInstall":"Beperkt SQLite-token aanmaken…","sqliteRegisterAdmin":"Admin-account registreren…","sqliteSchema":"SQLite-schema initialiseren…"},"stepsDone":{"sqliteInstall":"Beperkt SQLite-token uitgegeven","sqliteRegisterAdmin":"Admin geregistreerd en ingelogd","sqliteSchema":"SQLite-schema klaar"},"errors":{"missingFields":"Vul alle velden in.","rootDeploymentTitle":"De admin moet in een submap staan, niet in de hoofdmap van de site.","rootDeploymentHint":"Verplaats de admin-bestanden (index.html, config.js, runtime/, …) naar een submap op Flexweg — bijvoorbeeld /admin/ of een willekeurige naam zoals /erf34f654GH3/ voor extra onopvallendheid. Herlaad de admin vervolgens vanuit de URL van de submap en voer de configuratie opnieuw uit.","firebaseAuthGeneric":"Aanmelden bij Firebase mislukt.","firebaseAuthInvalidCredential":"Firebase heeft de combinatie van e-mailadres en wachtwoord geweigerd.","firebaseAuthInvalidCredentialHint":"Moderne Firebase-projecten activeren standaard bescherming tegen e-mailopsomming, waardoor dezelfde fout wordt teruggegeven of het wachtwoord nu fout is, de gebruiker niet bestaat, of de gebruiker zich met een andere provider aanmeldt. Te controleren:\\n• Voer het wachtwoord opnieuw in — kopieer/plak vanuit een wachtwoordbeheerder om typfouten uit te sluiten. Minimale lengte is 6 tekens.\\n• Open Firebase Console → Authentication → Users en bevestig dat het e-mailadres bestaat. Controleer de kolom 'Providers': als deze alleen Google (of een andere provider) toont en niet 'Email/Password', stel het wachtwoord in of reset het via het rijmenu (⋮ → Wachtwoord resetten).\\n• Controleer of de spelling van het e-mailadres exact overeenkomt met wat in Firebase staat opgeslagen.","firebaseAuthUserNotFound":"Geen Firebase-gebruiker met dit e-mailadres. Maak er eerst een aan in Firebase Console → Authentication → Users.","firebaseAuthInvalidEmail":"Het admin-e-mailadres is geen geldig e-mailadres.","firebaseInvalidApiKey":"De Firebase-API-sleutel is ongeldig. Controleer de waarde in Firebase Console.","firebaseNetwork":"Netwerkfout bij aanmelden bij Firebase. Controleer uw verbinding.","firebaseTooManyRequests":"Te veel aanmeldpogingen. Probeer het later opnieuw of reset het wachtwoord via Firebase Console.","firebaseOperationNotAllowed":"Inloggen met e-mail/wachtwoord is niet ingeschakeld op dit Firebase-project. Open Firebase Console → Authentication → Sign-in method en schakel de provider Email/Password in.","firebaseUserDisabled":"Dit Firebase-gebruikersaccount is uitgeschakeld. Schakel het opnieuw in via Firebase Console → Authentication → Users.","wrongAdminEmail":"Het Firebase-account waarmee u bent aangemeld komt niet overeen met het ingevoerde admin-e-mailadres. Probeer het opnieuw.","rulesNotPinnedTitle":"De Firestore-regels herkennen u nog niet als bootstrap-admin.","rulesNotPinnedHint":"Open Firebase Console → Firestore → Rules en vervang de waarde van \`bootstrapAdminEmail()\` door: {{email}} — klik daarna op Publiceren. De regelsjabloon in de README bevat een placeholder \`you@example.com\` die vervangen moet worden door uw echte admin-e-mailadres. Klik na het publiceren van de nieuwe regels hier opnieuw op Verzenden.","flexwegAuth":"Flexweg-API-sleutel geweigerd. Controleer de waarde in uw Flexweg-account → API.","flexwegNetwork":"Netwerkfout bij contact met Flexweg. Controleer de API-basis-URL en uw verbinding.","flexwegHttp":"Flexweg-API-fout ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore weigerde het schrijven van de configuratie.","firestoreRulesHint":"Open Firebase Console → Firestore → Regels en zorg dat het bootstrap-admin-e-mailadres is ingesteld op '{{email}}'. De README bevat een kant-en-klare regelsjabloon.","firestoreOther":"Schrijven naar Firestore mislukt","uploadFailed":"Kon config.js niet uploaden naar Flexweg","generic":"Er is iets misgegaan."},"docstore":{"contentTitle":"Content-repository","contentIntro":"Waar uw posts, pagina's en instellingen worden opgeslagen als Markdown- + JSON-bestanden. Een lege repository is prima — het CMS maakt de bestanden aan.","provider":"Repository","localClone":"Lokale map (git-clone)","localCloneHint":"Kies de map van uw clone. Synchroniseer die met uw gebruikelijke git-client — het CMS leest en schrijft bestanden, het voert geen git uit.","contentDir":"Contentmap in de repository","privateRepo":"Gebruik een privé-repository: concepten worden daarin opgeslagen.","folderRequired":"Kies eerst de contentmap.","checking":"Toegang tot de repository controleren…","publishIntro":"Waar de gegenereerde site wordt gepubliceerd. U kunt dit later wijzigen in Instellingen.","existingSite":"Deze repository is al ingesteld — de site blijft publiceren naar: {{target}}. U kunt dit later wijzigen in Instellingen (eventuele geheime sleutels moeten daar opnieuw worden ingevoerd).","install":"Installeren","steps":{"config":"Configuratie opslaan…","content":"Content laden…","target":"Publicatiedoel opslaan…","testTarget":"Publicatiedoel testen…"},"doneTitle":"Alles klaar!","doneBody":"De configuratie is opgeslagen in deze browser. Om andere redacteuren deze stap te besparen, downloadt u config.js en vervangt u het bestand in de admin-map van uw hosting.","downloadConfig":"config.js downloaden","open":"Admin openen","footer":"Content blijft in uw repository of in deze browser; toegangstokens verlaten deze browser nooit."},"data":{"title":"1. Waar slaat u uw gegevens op?","intro":"Uw posts, pagina's, gebruikers en instellingen — de eigen gegevens van de admin. Dit staat los van waar de publieke site wordt gehost (volgende stap).","localNote":"Niets te configureren: content wordt in deze browser opgeslagen. Exporteer die via Instellingen om een back-up te maken of later te verhuizen.","options":{"sqlite-file":{"title":"SQLite","hint":"Een SQLite-database die wordt opgeslagen op de hosting die u in de volgende stap kiest (Flexweg, uw server, S3, Git…). Zonder gebruikersaccounts — of de SQLite-dienst van Flexweg, met accounts, als u op Flexweg host."},"flexweg-sqlite":{"title":"SQLite (Flexweg-dienst)","hint":"Een SQLite-database die door de dienst van Flexweg wordt beheerd, met ingebouwde gebruikersaccounts. Vereist een Flexweg-account, ongeacht waar de site wordt gehost."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth in uw Google-project. Realtime, gratis Spark-abonnement."},"markdown-git":{"title":"Markdown-bestanden in Git","hint":"Posts als .md-bestanden in een GitHub- / GitLab-repository (of een lokale clone). Elke redacteur gebruikt een eigen token; elke wijziging is een commit."},"local":{"title":"Deze browser","hint":"Eén gebruiker, geen login, niets in te stellen. Ideaal voor een admin die op uw computer draait."}}},"hosting":{"title":"2. Waar wordt de site gepubliceerd?","intro":"Waar de gegenereerde statische site (HTML, CSS, afbeeldingen) bij elke publicatie naartoe wordt geüpload. U kunt dit later wijzigen in Instellingen.","existing":"Deze content-repository publiceert al naar het onderstaande doel. Behoud het of kies een ander."},"install":{"title":"3. Installatie","intro":"Controleer het overzicht en installeer daarna.","data":"Gegevens","hosting":"Hosting","saveTarget":"Publicatiedoel opslaan…","noteConfigJs":"De admin-configuratie (config.js) wordt indien mogelijk naast de admin op Flexweg geüpload; anders wordt u aangeboden haar te downloaden.","noteLocalConfig":"De configuratie wordt in deze browser opgeslagen; u krijgt config.js aangeboden om in de admin-map te plaatsen, zodat andere redacteuren deze installatie kunnen overslaan."},"sqliteFile":{"security":"Geen gebruikersaccounts: iedereen die dit admin kan openen, kan de inhoud bewerken — beveilig de admin-map bij je hosting. Het databasebestand wordt als elk ander bestand geserveerd: houd het versleuteld of bewaar het op een aparte privélocatie.","intro":"Waar het databasebestand wordt opgeslagen. Deze admin leest en bewaart het via dezelfde connectoren als de hosting.","path":"Pad van het databasebestand","pathHint":"Wordt bij de eerste keer opslaan aangemaakt als het nog niet bestaat. Bij een Git-repository is elke keer opslaan een commit — kies bij voorkeur een repository of branch die geen build van de site start.","existing":"bestaande database","new":"nieuwe database","dataNote":"Hier valt niets te configureren: de database wordt opgeslagen op de hosting die u in de volgende stap kiest.","heading":"SQLite-database","flexwegService":"De SQLite-dienst van Flexweg gebruiken","flexwegServiceHint":"De database wordt door Flexweg beheerd en heeft ingebouwde gebruikersaccounts (e-mail + wachtwoord). Anders is het een gewoon bestand op deze hosting, zonder accounts.","summaryFile":"Bestand {{path}} op deze hosting","summaryService":"SQLite-dienst van Flexweg ({{path}})","encrypt":"Database versleutelen","encryptHint":"Aanbevolen bij openbare hosting: zonder wachtzin is het bestand onleesbaar. Elke nieuwe browser vraagt er één keer om.","passphrase":"Wachtzin","passphraseHint":"Bewaar hem nu in je wachtwoordmanager: zonder wachtzin kan niemand de database openen, ook jij niet.","copy":"Kopiëren","copied":"Gekopieerd","generate":"Nieuw","passphraseTooShort":"De wachtzin moet minstens 12 tekens lang zijn.","existingEncrypted":"Op dit pad staat al een versleutelde database: voer de wachtzin ervan in.","separate":"Database op een aparte privélocatie bewaren","separateHint":"Bijv. een privé S3- / R2-bucket of een privé Git-repository: de database wordt dan nooit door de openbare site geserveerd.","summaryEncrypted":"versleuteld","summaryLocation":"opgeslagen in {{location}}","locationLabel":"Locatie van de database","gitBranchNote":"De database staat op de branch {{branch}} van deze repository, die nooit wordt gepubliceerd: inhoud opslaan bouwt de site niet opnieuw.","summaryBranch":"op branch {{branch}}"},"adminHosting":{"deploying":"De admin wordt naar de site gekopieerd…","label":"De admin ook op deze site hosten","hint":"De admin wordt met zijn config.js (zonder geheimen) naar {{url}} gekopieerd — elke redacteur kan hem daar dan openen. Elke redacteur logt nog steeds in met de eigen toegang.","folder":"Admin-map","alreadyHere":"Deze admin draait al vanaf deze site: de config.js wordt ter plekke bijgewerkt.","doneBody":"De admin staat nu op uw site. Schakel bij GitHub Pages eerst Pages in voor de repository als dat nog niet is gebeurd (Settings → Pages) en open hem daarna:","open":"Online admin openen","continueHere":"Doorgaan in deze admin"}}`),Ese={actions:{upload:"Bestand uploaden",delete:"Bestand verwijderen",rename:"Bestand hernoemen",get:"Bestand lezen",list:"Bestanden lijsten",createFolder:"Map aanmaken",renameFolder:"Map hernoemen",deleteFolder:"Map verwijderen",storageLimits:"Opslaglimieten ophalen",commit:"Wijzigingen publiceren"},errors:{configMissing:"Het publicatiedoel is niet ingesteld. Stel het in via Instellingen voordat je publiceert.",network:"{{action}}: netwerkfout of CORS geblokkeerd. Controleer uw verbinding.",auth:"{{action}}: authenticatie mislukt. Controleer de gegevens van het publicatiedoel in Instellingen.",notFound:"{{action}}: niet gevonden op het publicatiedoel.",tooLarge:"{{action}}: bestand te groot voor het publicatiedoel.",rateLimited:"{{action}}: te veel verzoeken, probeer het zo opnieuw.",serverError:"{{action}}: serverfout van het publicatiedoel ({{status}}). Probeer het opnieuw.",generic:"{{action}} mislukt ({{status}}){{detail}}.",unsupported:'{{action}}: niet ondersteund door publicatiedoel "{{connector}}".',unknownConnector:'Onbekend publicatiedoel "{{connector}}". Controleer Instellingen → Publicatiedoel.',folderAccess:"Geen toegang tot de lokale map. Open Instellingen → Publicatiedoel en klik op ‘Map opnieuw verbinden’."}},_se={log:{rendering:"Pagina renderen…",uploading:"{{path}} uploaden…",deleting:"{{path}} verwijderen…",regenerating:"Lijsten opnieuw genereren…",skipped:"{{path}} overgeslagen (geen wijzigingen)",done:"Gepubliceerd op {{url}}",failed:"Mislukt: {{error}}"}},Cse={errors:{notConnected:"Niet verbonden met de contentrepository. Meld je opnieuw aan met je toegangstoken.",conflict:"Iemand anders heeft dit item intussen gewijzigd. Die versie wordt nu getoond — pas je wijziging opnieuw toe.",sqliteUnsupported:"Het doel ‘{{connector}}’ kan geen databasebestand opslaan."}},Ase={target:"Publicatiedoel",settingsTitle:"Publicatiedoel",settingsHelp:"Waar de gerenderde site naartoe wordt geüpload bij publiceren. Inloggegevens worden opgeslagen bij uw content-backend (of in deze browser bij Git-content-repository's) en zijn leesbaar voor alle admins.",saved:"Publicatiedoel opgeslagen. Voer Opnieuw genereren → Alles uit om de hele site naar het nieuwe doel te publiceren.",test:"Verbinding testen",testOk:"Verbinding OK",testFailed:"Verbinding mislukt",names:{flexweg:"Flexweg","git-pages":"Git-repository (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"S3-compatibele bucket (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"Uw eigen server (PHP-bridge)","browser-mirror":"Downloaden als ZIP","local-folder":"Lokale map op deze computer"},hints:{flexweg:"Upload via de Flexweg Files API.","git-pages":"Elke publicatie is één commit in de repository; de host bouwt de site daaruit opnieuw op.",s3:"Vereist een CORS-regel op de bucket die de origin van deze admin toestaat, en websitehosting (of een CDN) om index.html-bestanden te serveren.","php-bridge":"Upload external/bridges/php/flexweg-bridge.php naar uw server, stel de API-sleutel in en vul hier de URL in.","browser-mirror":"De site wordt in deze browser bewaard; download het ZIP en upload het handmatig waar u maar wilt.","local-folder":"Schrijft de site rechtstreeks naar een map (Chrome / Edge). Serveer hem lokaal of push hem met uw eigen tools."},fields:{flexweg:{apiKey:"API-sleutel",siteUrl:"Site-URL",apiBaseUrl:"Basis-URL van de API"},"git-pages":{host:"Hosting",provider:"Git-provider",owner:"Eigenaar (gebruiker of organisatie)",repo:"Repository",project:"Projectpad",branch:"Branch",dir:"Map in de repository",token:"Toegangstoken",siteUrl:"Publieke site-URL",apiBaseUrl:"API-URL (alleen self-hosted)"},s3:{endpoint:"Endpoint",region:"Regio",bucket:"Bucket",prefix:"Sleutelvoorvoegsel (optioneel)",accessKeyId:"Access key-ID",secretAccessKey:"Geheime toegangssleutel",siteUrl:"Publieke site-URL",forcePathStyle:"Padgebaseerde URL's (MinIO, R2, de meeste compatibele diensten)",publicRead:"Geüploade bestanden openbaar maken (ACL public-read) — voor buckets die niet via een bucketbeleid openbaar zijn (OVHcloud, Scaleway…). Laat uit bij AWS-buckets met ‘bucket owner enforced’."},"php-bridge":{apiBaseUrl:"Bridge-URL",apiKey:"API-sleutel van de bridge",siteUrl:"Publieke site-URL"},"browser-mirror":{siteUrl:"Publieke site-URL (optioneel)"},"local-folder":{siteUrl:"URL waarop de map wordt geserveerd (optioneel)"}},help:{flexweg:{apiKey:"Aangemaakt vanuit uw Flexweg-account → API."},"git-pages":{host:"Cloudflare Pages: koppel het project aan deze repository zonder build-commando en met de uitvoermap hieronder. Werkt met privé-repository's.",dir:'Leeg laten voor de root van de repository. GitHub Pages: "" of "docs". GitLab Pages: "public".',token:"Fine-grained token op deze repository met Contents: read & write (GitHub) — voeg Pages: read & write toe zodat het CMS GitHub Pages kan inschakelen — of een token met de scope api (GitLab). Leeg laten om het eigen toegangstoken van elke redacteur te gebruiken wanneer de content bij dezelfde provider staat.",siteUrl:"bv. https://user.github.io/repo — een URL met submap is prima, links worden automatisch aangepast."},s3:{endpoint:"Leeg laten voor AWS (afgeleid van de regio). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"De website-URL van de bucket of uw CDN-domein."},"php-bridge":{apiBaseUrl:"De volledige URL van flexweg-bridge.php op uw server (HTTPS)."},"browser-mirror":{siteUrl:"Waar u het ZIP gaat uploaden — gebruikt voor absolute URL's (sitemaps, RSS, media)."},"local-folder":{siteUrl:"bv. http://localhost:8080 wanneer een lokale webserver de map serveert."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (gekoppeld aan de repository)","gitlab-pages":"GitLab Pages",other:"Anders (Netlify, Vercel, git pull op de server…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Map kiezen…",change:"Andere map…",reconnect:"Map opnieuw koppelen",unsupported:"Deze browser kan niet naar lokale mappen schrijven. Gebruik Chrome of Edge."},mirror:{download:"Site downloaden (ZIP)",count:"{{count}} bestanden in deze browser"},adminHosting:{title:"Admin op deze site",help:"Kopieer deze admin naar het publicatiedoel (eerste uitrol, of bijwerken na een nieuwe versie). De config.js bevat geen geheimen.",deploy:"Admin uitrollen / bijwerken",deployed:"Admin uitgerold ({{count}} bestanden) — {{url}}"},pages:{enabled:"GitHub Pages ingeschakeld voor deze repository — de site staat over ongeveer een minuut online.",enableHint:'Publiceren gelukt. Schakel GitHub Pages in voor {{repo}} om de site online te zetten: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Of geef het token de machtiging "Pages: read and write" en het CMS doet het voor u.)'},siteUrl:{mismatch:"De openbare URL van de site (Instellingen → Site) is {{site}}, maar dit doel serveert de site op {{target}}. Links, CSS en sitemaps volgen de site-URL — ze kloppen niet op deze hosting.",use:"{{url}} gebruiken voor de site",updated:"Site-URL bijgewerkt. Voer Opnieuw genereren → Alles uit om de pagina's met de nieuwe links opnieuw te publiceren."}},Tse={heading:"Verbinden met de content-repository",tokenIntro:"De content staat in de {{provider}}-repository {{repo}}. Log in met uw eigen persoonlijke toegangstoken — uw rechten op de repository bepalen uw rol (schrijftoegang = redacteur, admin / maintainer = admin).",token:"Persoonlijk toegangstoken",tokenHelpGithub:"Fine-grained token, alleen toegang tot deze repository, recht Contents: lezen en schrijven.",tokenHelpGitlab:"Token met de api scope, rol Developer of hoger op dit project.",createToken:"Token aanmaken",connect:"Verbinden",tokenStorage:"Het token wordt alleen in deze browser bewaard. Uitloggen wist het.",failed:"Met dit token kan niet naar de repository worden geschreven (ongeldig, verlopen of alleen-lezen). Controleer de rechten.",folderIntro:"De content staat in een map op deze computer (meestal een git-clone die u synchroniseert met uw eigen git-client). Geef deze browser toegang — browsers vragen het na elke herlaadbeurt opnieuw.",openFolder:"Contentmap openen"},Ise={flexweg:{title:"Flexweg",short:"Flexweg-hosting",hint:"Uploadt via de Flexweg Files API. API-sleutel uit uw Flexweg-account."},"github-pages":{title:"GitHub Pages",short:"Gratis, vanuit een GitHub-repository",hint:"Elke publicatie is één commit naar de repository; GitHub Pages serveert die. Settings → Pages → Deploy from a branch. Publieke repositories bij het gratis abonnement."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Gratis, privé-repositories mogelijk",hint:"Het CMS commit de site naar een GitHub- / GitLab-repository; koppel er een Cloudflare Pages-project aan (geen build-commando, uitvoermap = de map hieronder)."},"gitlab-pages":{title:"GitLab Pages",short:"Gratis, vanuit een GitLab-repository",hint:"Elke publicatie is één commit; het CMS voegt een minimale .gitlab-ci.yml toe die de map public/ publiceert."},"git-other":{title:"Netlify, Vercel…",short:"Elke host die een repository deployt",hint:"Het CMS commit de site naar een Git-repository; koppel uw host (Netlify, Vercel, een server die git pull uitvoert…) aan die repository."},s3:{title:"S3 / R2 / B2…",short:"Object-storage-bucket",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Vereist een CORS-regel op de bucket en website-hosting of een CDN ervoor."},"own-server":{title:"Uw eigen server (FTP / SFTP)",short:"Gedeelde hosting, VPS…",hint:"Browsers spreken geen FTP of SFTP: upload de PHP-bridge (external/bridges/php/flexweg-bridge.php) eenmalig met uw FTP-client, stel de API-sleutel ervan in en vul hier daarna de URL in. Werkt op elke PHP-host."},"local-folder":{title:"Lokale map",short:"Op deze computer",hint:"Schrijft de site naar een map op deze computer (Chrome / Edge). Serveer hem lokaal of push hem met uw eigen tools."},zip:{title:"Downloaden als ZIP",short:"Handmatig uploaden",hint:"De site wordt in deze browser bewaard; download een ZIP via Instellingen en upload die waar u maar wilt (Netlify Drop, FTP-client…)."}},Nse={heading:"Verbinding maken met de database",intro:"Deze admin slaat zijn content op in {{path}}. Voer de toegangsgegevens voor deze browser in.",storage:"De toegangsgegevens worden alleen in deze browser bewaard. Afmelden wist ze.",passphrase:"Wachtzin van de database",passphraseHint:"De database is versleuteld. Voer de wachtzin in die bij de installatie is gekozen (alleen in deze browser bewaard).",passphraseWrong:"Verkeerde wachtzin: de database kon niet worden geopend.",passphraseMissing:"Voer de wachtzin van de database in."},Pse={common:ise,auth:ase,nav:ose,dashboard:lse,posts:cse,pages:use,taxonomies:dse,media:hse,themes:fse,plugins:pse,externalInstall:mse,externalLoader:gse,menus:bse,settings:yse,users:vse,firestoreSetup:xse,errors:wse,identity:kse,setup:Sse,flexweg:Ese,publish:_se,docstore:Cse,connectors:Ase,gitAccess:Tse,hosting:Ise,sqliteAccess:Nse},Rse={save:"Guardar",saving:"A guardar…",saved:"Guardado",cancel:"Cancelar",delete:"Eliminar",deleting:"A eliminar…",edit:"Editar",create:"Criar",search:"Pesquisar",loading:"A carregar…",yes:"Sim",no:"Não",confirm:"Confirmar",back:"Voltar",next:"Seguinte",previous:"Anterior",close:"Fechar",all:"Todos",none:"Nenhum",actions:"Ações",name:"Nome",slug:"Slug",description:"Descrição",status:"Estado",createdAt:"Criado",updatedAt:"Atualizado",publishedAt:"Publicado",language:"Idioma",darkMode:"Modo escuro",lightMode:"Modo claro",signOut:"Terminar sessão",administrator:"Administrador",editor:"Editor",appName:"AgentCMS"},jse={signIn:"Iniciar sessão",signingIn:"A iniciar sessão…",email:"E-mail",password:"Palavra-passe",emailPlaceholder:"voce@empresa.com",passwordPlaceholder:"••••••••",forgotPassword:"Esqueceu-se da palavra-passe?",resetEmailSent:"E-mail de redefinição de palavra-passe enviado para {{email}}.",enterEmailFirst:"Introduza primeiro o seu e-mail acima e depois clique em redefinir.",emailPasswordRequired:"E-mail e palavra-passe são obrigatórios.",signInSubtitle:"Use o seu e-mail de trabalho e palavra-passe.",footer:"Os pedidos de conta passam pelo seu administrador.",errors:{invalidEmail:"Endereço de e-mail inválido.",invalidCredentials:"E-mail ou palavra-passe inválidos.",tooManyRequests:"Demasiadas tentativas. Tente novamente mais tarde ou redefina a sua palavra-passe.",userDisabled:"Esta conta foi desativada.",networkFailed:"Erro de rede. Verifique a sua ligação.",generic:"Falha na autenticação."}},Mse={openMenu:"Abrir menu",closeMenu:"Fechar menu",dashboard:"Painel",posts:"Artigos",pages:"Páginas",taxonomies:"Categorias e etiquetas",media:"Multimédia",themes:"Temas",themeSettings:"Definições do tema",plugins:"Plugins",menus:"Menus",users:"Utilizadores",settings:"Definições"},Lse={title:"Painel",welcome:"Bem-vindo de volta, {{email}}.",stats:{totalPosts:"Artigos",totalPages:"Páginas",online:"Online",drafts:"Rascunhos"}},Dse={title:"Artigos",newPost:"Novo artigo",noPosts:"Ainda não há artigos. Crie o primeiro para começar.",noPostsInFilter:"Nenhum artigo corresponde ao filtro atual.",search:{placeholder:"Procurar artigos…",clear:"Limpar pesquisa",noResults:"Nenhum artigo corresponde à sua pesquisa."},pagination:{previous:"Anterior",next:"Seguinte",showing:"A mostrar {{from}}–{{to}} de {{total}}",pageOf:"Página {{page}} de {{total}}"},bulk:{selectedCount_one:"{{count}} selecionado",selectedCount_other:"{{count}} selecionados",selectPage_one:"Selecionar {{count}} nesta página",selectPage_other:"Selecionar os {{count}} desta página",deselectPage:"Desmarcar página",allOnPageSelected_one:"{{count}} nesta página selecionado.",allOnPageSelected_other:"Os {{count}} desta página estão selecionados.",selectAllMatching_one:"Selecionar o artigo correspondente",selectAllMatching_other:"Selecionar os {{count}} artigos correspondentes",allMatchingSelected_one:"O artigo correspondente está selecionado.",allMatchingSelected_other:"Os {{count}} artigos correspondentes estão selecionados.",selectOne:"Selecionar «{{title}}»",publish:"Publicar ({{count}})",publishing:"A publicar…",publishedCount:"{{ok}} publicado(s), {{failed}} falha(s).",unpublish:"Despublicar ({{count}})",unpublishing:"A despublicar…",unpublishedCount:"{{ok}} despublicado(s), {{failed}} falha(s).",delete:"Eliminar",deleting:"A eliminar…",deletedCount:"{{ok}} eliminado(s), {{failed}} falha(s).",confirmDelete_one:"Eliminar {{count}} artigo? Será despublicado do Flexweg e não pode ser desfeito.",confirmDelete_other:"Eliminar {{count}} artigos? Serão despublicados do Flexweg e não pode ser desfeito.",noDraftSelected:"Nenhum artigo em rascunho selecionado.",noOnlineSelected:"Nenhum artigo online selecionado.",clear:"Limpar seleção"},filters:{all:"Todos",draft:"Rascunho",online:"Online"},fields:{title:"Título",slug:"Slug",excerpt:"Excerto",content:"Conteúdo",category:"Categoria",tags:"Etiquetas",heroImage:"Imagem de destaque",seoTitle:"Título SEO",seoDescription:"Descrição SEO",createdAt:"Criado em",updatedAt:"Última atualização",publishedAt:"Publicado em"},edit:{newTitle:"Novo artigo",editTitle:"Editar artigo",saved:"Guardado.",savedAndRepublished:"Guardado e republicado.",saveFailed:"Falha ao guardar.",saveAndRepublish:"Guardar e republicar",draftSaved:"Rascunho guardado.",slugCollision:{post:'Este URL já é usado pelo artigo: "{{label}}".',page:'Este URL já é usado pela página: "{{label}}".',category:'Este URL já é usado pela categoria: "{{label}}".'},publish:"Publicar",unpublish:"Despublicar",publishing:"A publicar…",unpublishing:"A despublicar…",titlePlaceholder:"Adicionar título",permalink:"Ligação permanente",slugFormatHint:"Apenas minúsculas, ASCII, separadas por hífens.",slugAutoSuffixed:'Sufixo adicionado porque "{{base}}" já é usado por {{owner}}.',slugAutoSuffixedOwner:{post:'publicação: "{{label}}"',page:'página: "{{label}}"',category:'categoria: "{{label}}"'},saveBlocked:{titleRequired:"Adicione um título antes de guardar.",slugRequired:"São necessários um título e um slug de URL para guardar.",slugInvalid:"Formato de slug inválido (ASCII minúsculo + hífens).",slugCollision:"Resolva o conflito de URL antes de guardar."},viewPublished:"Ver",confirmDelete:"Eliminar este registo?",inspector:{document:"Documento",block:"Bloco",blockEmpty:"Selecione um bloco no editor para ver as suas opções.",publishing:"Publicação",permalink:"Ligação permanente",categories:"Categorias e etiquetas",featured:"Imagem de destaque",seo:"SEO",excerpt:"Excerto",dates:"Datas"},blocks:{addBlock:"Adicionar bloco",transform:"Transformar em",moveUp:"Mover para cima",moveDown:"Mover para baixo",duplicate:"Duplicar",remove:"Eliminar bloco",paragraph:"Parágrafo",heading2:"Título 2",heading3:"Título 3",bulletList:"Lista com marcadores",orderedList:"Lista numerada",blockquote:"Citação",codeBlock:"Código",image:"Imagem",horizontalRule:"Separador",categories:{text:"Texto",media:"Multimédia",layout:"Disposição",embed:"Incorporações",advanced:"Avançado"},noSettings:"Este bloco não tem definições.",noSelection:"Selecione um bloco no editor para ver as suas opções.",slash:{noResults:"Nenhum bloco corresponde."}}},status:{draft:"Rascunho",online:"Online"},preview:{title:"Pré-visualização",rendering:"A renderizar pré-visualização…",error:"Pré-visualização falhou: {{error}}",viewports:{mobile:"Telemóvel",tablet:"Tablet",desktop:"Computador"}}},Fse={title:"Páginas",newPage:"Nova página",noPages:"Ainda não há páginas.",homeBadge:"Início",homeBadgeTooltip:"Usada como página inicial do site"},Ose={title:"Categorias e etiquetas",categories:"Categorias",tags:"Etiquetas",newCategory:"Nova categoria",newTag:"Nova etiqueta",noCategories:"Ainda não há categorias.",noTags:"Ainda não há etiquetas.",slugCollision:'Este slug já é usado por "{{label}}".',seo:{button:"SEO",buttonTitle:"Editar metatags SEO",title:"Metatags SEO",subtitle:'Título e descrição personalizados para a página de arquivo de "{{name}}".',metaTitle:"Meta título",metaTitleHint:"Usado como <title> da página. Padrão: o nome do termo.",metaDescription:"Meta descrição",metaDescriptionHint:"Usada como meta descrição da página. Padrão: a descrição do termo."}},zse={title:"Biblioteca multimédia",upload:"Carregar",uploading:"A carregar…",finalizing:"A finalizar…",uploadFailed:"Falha no carregamento",retry:"Tentar novamente",noMedia:"Ainda não há multimédia.",alt:"Texto alternativo",caption:"Legenda",filename:"Nome do ficheiro",size:"Tamanho",type:"Tipo"},Use={title:"Temas",active:"Ativo",activate:"Ativar",installExternal:"Instalar tema",uninstallDisabledTitle:"Mude para outro tema antes de desinstalar este.",syncAssets:"Sincronizar recursos do tema",regenerateSite:"Regenerar o site",regenerating:"A regenerar…",regenerate:{button:"Regenerar",running:"Em execução…",groupBuiltins:"Site",groupPlugins:"Plugins",home:"Apenas página inicial",homeHelp:"Regenera apenas index.html — opção mais rápida.",allHtml:"Todas as páginas HTML",allHtmlHelp:"Todos os posts, páginas, arquivos e listagens — mais os snapshots menu / posts / authors JSON.",repair:"Reparar URLs",repairHelp:"Recalcula a URL canônica de cada post online e move os arquivos que ficaram na URL errada. Útil após uma importação executada antes que os termos fossem sincronizados.",assets:"Recursos do tema",assetsHelp:"Envia o CSS e os scripts do tema ativo para /theme-assets/.",everything:"Tudo",everythingHelp:"Recursos do tema + todos os HTML + cada saída de plugin. Opção mais lenta.",noPluginTargets:"Sem regenerações de plugin — ative um plugin que suporte regenerar."},confirmSwitch:{title:"Mudar para {{theme}}?",body:"Mudar de tema requer reenviar os recursos do tema e regenerar todas as páginas publicadas para que o novo aspeto se propague em todo o lado. Pode demorar um momento.",confirm:"Mudar e regenerar",cancel:"Cancelar"}},Bse={title:"Plugins",enabled:"Ativado",disabled:"Desativado",enable:"Ativar",disable:"Desativar",configure:"Configurar",author:"autor",learnMore:"Saber mais",mustUseBadge:"Obrigatório",installExternal:"Instalar plugin",tabs:{regular:"Plugins",mustUse:"Obrigatórios"}},$se={titlePlugin:"Instalar um plugin",titleTheme:"Instalar um tema",labelPlugin:"plugin",labelTheme:"tema",intro:"Largue um ficheiro ZIP com um pacote de {{label}} (manifest.json + bundle.js na raiz do ZIP). O {{label}} será carregado para o seu site Flexweg e registado após uma recarga. Voltar a carregar um ZIP com o mesmo id de manifest atualiza o registo existente no local — não é preciso desinstalar.",zipField:"Ficheiro ZIP do pacote",install:"Instalar",installing:"A instalar…",installSuccess:"{{name}} instalado ({{count}} ficheiros carregados). A recarregar…",upgradeSuccess:"{{name}} atualizado de v{{previousVersion}} para v{{newVersion}} ({{count}} ficheiros carregados). A recarregar…",installedTitle:"Já instalado",bundledDefaultsTitle:"Plugins/temas incluídos disponíveis",bundledDefaultsHint:"{{count}} plugin/tema incluído está atualmente desinstalado. Restaure-os para recuperar o que vinha com esta versão do admin.",bundledDefaultsRestore:"Restaurar",bundledDefaultsRestored:"{{plugins}} plugin(s) e {{themes}} tema(s) restaurados. A recarregar…",uninstall:"Desinstalar",uninstallSuccess:"{{id}} desinstalado. A recarregar…",confirmUninstall:"Desinstalar {{id}}? Os ficheiros serão eliminados do Flexweg.",errors:{"no-manifest":"Ao ZIP falta manifest.json na raiz.","invalid-manifest":"O manifest.json é inválido (campos obrigatórios em falta ou JSON inválido).","incompatible-api":"O pacote foi construído contra uma versão de API runtime incompatível.","no-bundle":"O ZIP não contém o ficheiro de entrada declarado no manifest.","fetch-manifest":"Não foi possível ler o external.json atual no Flexweg.","upload-failed":"Falha no carregamento — verifique a sua chave API Flexweg e a sua ligação."}},Hse={someFailed:"{{count}} pacote(s) externo(s) falharam ao carregar. Veja a consola do browser."},Vse={title:"Menus",header:"Menu de cabeçalho",footer:"Menu de rodapé",label:"Etiqueta",saveAndPublish:"Guardar e gerar",discard:"Descartar",saved:"Menus guardados e publicados.",saveFailed:"Não foi possível guardar os menus.",unsavedChanges:"Tem alterações por guardar."},qse={title:"Definições",tabs:{general:"Geral"},site:{title:"Site",siteTitle:"Título do site",siteDescription:"Descrição do site",siteLanguage:"Idioma do site",siteLanguageHelp:'Tag BCP-47 (p. ex. en, fr-CA) inserida em <html lang="…"> em cada página publicada. O prefixo é correspondido com os locais de tradução suportados para os rótulos de sitemap / RSS e textos integrados no tema; os locais não suportados recorrem ao inglês.',siteLanguageResolved:"As traduções usarão: {{label}}",baseUrl:"URL público do site",postsPerPage:"Artigos por página",homeMode:"Conteúdo da página inicial",homeLatest:"Artigos mais recentes",homeStatic:"Página estática",homePage:"Página inicial",discourageIndexing:"Desencorajar os motores de pesquisa de indexar este site",discourageIndexingHelp:"Quando ativado, cada página publicada recebe uma meta tag noindex/nofollow e o robots.txt bloqueia todos os rastreadores. Replica o comportamento do WordPress — útil para sites de staging ou revisões antes do lançamento. Os motores de pesquisa que respeitam a diretiva não indexarão o site.",discourageRegenerateHint:"Definição de indexação guardada. Clique em «Regenerar tudo» em Temas para aplicar a alteração a todas as páginas publicadas e ao robots.txt."},flexweg:{title:"API Flexweg",apiKey:"Chave da API",apiKeyHelp:"Gerada na sua conta Flexweg → API.",siteUrl:"URL do site",siteUrlHelp:"URL público do seu site Flexweg sem barra final.",apiBaseUrl:"URL base da API",storageHelpFirebase:"Guardada no Firestore (config/flexweg). Legível por qualquer membro com sessão iniciada, gravável apenas por administradores.",storageHelpSqlite:"Guardada na tabela SQLite local config. Legível por qualquer membro com sessão iniciada, gravável apenas por administradores."},backend:{title:"Backend de dados",active:"Backend ativo:",switchButton:"Mudar de backend…",confirmTitle:"Todos os dados atuais serão perdidos.",confirmBody:"Mudar limpa a configuração no browser e recarrega o formulário de configuração. O novo backend começa vazio — os dados do backend anterior permanecem onde estavam (no Firestore ou como um ficheiro .sqlite no Flexweg), mas o CMS só voltará a lê-los quando trocar de volta.",confirmYes:"Sim, mudar de backend",downloadBackup:"Descarregar uma cópia de segurança do ficheiro .sqlite",downloadBackupHelp:"faça isto antes de mudar de backend.",markdownGit:"Markdown — {{source}}",localFolder:"pasta local",localBrowser:"Este browser (local, um só utilizador)",sqliteFile:"Ficheiro SQLite — {{location}}"},performance:{title:"Desempenho",help:"Como o admin carrega artigos e páginas. O modo padrão funciona no plano gratuito do Firestore sem configuração; o modo paginado é para sites muito grandes e requer criação de índices uma vez.",mode:"Modo de carregamento",modeGlobal:"Padrão (sem configuração)",modePaginated:"Paginação no servidor (índices Firestore necessários)",globalHelp:"Carrega toda a coleção de artigos numa subscrição ao vivo. Ordenação, filtros e pesquisa em memória. Recomendado para sites com menos de ~5 000 artigos.",paginatedHelp:"Subscrições paginadas por cursor, uma página de cada vez. Requer índices compostos do Firestore — ver README. Recomendado para sites muito grandes.",savedReload:"Guardado. Recarregue o admin para aplicar o novo modo."},editor:{title:"Editor",help:"Tipografia usada no editor de artigos / páginas. Independente do tema público.",fontFamily:"Família tipográfica",bodySize:"Tamanho do corpo",h1Size:"Tamanho H1",h2Size:"Tamanho H2",h3Size:"Tamanho H3",sizeHelp:"Comprimento CSS, p. ex. 16px ou 1rem. Deixe em branco para o valor predefinido.",reset:"Repor predefinições"},profile:{title:"Perfil",adminLocale:"Idioma do admin",adminLocaleHelp:"Idioma usado pela interface de administração. Guardado no seu perfil.",firstName:"Nome próprio",lastName:"Apelido",headline:"Título",headlinePlaceholder:"ex. Jornalista, Editor-chefe…",headlineHelp:"Mostrado publicamente sob o seu nome nos cartões de autor e na sua página de arquivo.",bio:"Biografia",bioPlaceholder:"Um parágrafo curto mostrado na sua página de autor e por baixo dos seus artigos.",bioHelp:"Visível no site público na barra lateral do autor e na página de arquivo do autor.",socials:"Perfis sociais",socialsHelp:"Adicione os URLs dos perfis que quer expor no site público e ative «Mostrar» nos que devem ser visíveis. URLs vazios são ignorados.",socialsShow:"Mostrar",socialsShowHelp:"Alterna a visibilidade desta rede no site público.",avatar:"Foto de perfil",avatarHelp:"Escolha uma imagem da sua biblioteca multimédia. Imagens quadradas ficam melhor.",pickAvatar:"Escolher dos média",changeAvatar:"Alterar foto",removeAvatar:"Remover",save:"Guardar perfil"},transfer:{title:"Mover ou fazer cópia de segurança do conteúdo",help:"Exporte tudo (posts, páginas, categorias, metadados de multimédia, perfis, definições) num único ficheiro JSON. Num backend Markdown ou local pode importar esse ficheiro mantendo os ids — é assim que se migra a partir do Firebase ou do SQLite. Os ficheiros multimédia e as chaves secretas não são incluídos.",export:"Exportar o conteúdo (JSON)",import:"Importar conteúdo…",modeMerge:"Combinar (substitui os mesmos ids)",modeReplace:"Substituir as coleções importadas",replaceConfirm:"O modo Substituir elimina todos os itens existentes das coleções presentes no ficheiro antes de importar. Continuar?",invalidFile:"Este ficheiro não é uma exportação de conteúdo do AgentCMS.",imported:"Importados {{posts}} posts/páginas, {{terms}} termos e {{media}} multimédia. Execute Regenerar → Tudo para os publicar."},encryption:{title:"Cifra da base de dados:",on:"ativa",off:"inativa",onHelp:"O ficheiro da base de dados é ilegível sem a frase-passe. Alterá-la volta a guardar o ficheiro com uma nova chave; os outros navegadores vão pedir a nova frase.",offHelp:"Quem conseguir descarregar o ficheiro da base de dados pode lê-lo (um alojamento estático serve-o como qualquer página). Cifre-o com uma frase-passe.",enable:"Cifrar a base de dados…",change:"Alterar a frase-passe…",savedConfirm:"Guardei esta frase-passe no meu gestor de palavras-passe — sem ela o conteúdo não pode ser aberto.",enableConfirm:"Cifrar agora",changeConfirm:"Alterar a frase",done:"Base de dados guardada com a nova frase-passe."}},Wse={title:"Utilizadores",noUsers:"Ainda não há utilizadores.",role:"Função",disabled:"Desativado",editProfileTitle:"Editar perfil — {{email}}",profileSaved:"Perfil guardado.",descriptionFirebase:"Faça a gestão da sua equipa. As novas contas são criadas na Firebase Console e replicadas aqui no primeiro início de sessão.",descriptionSqlite:"Faça a gestão da sua equipa. Use o botão +Adicionar utilizador abaixo para criar contas diretamente.",addUser:"Adicionar utilizador",addUserSuccess:"{{email}} adicionado.",removeConfirmFirebase:"Eliminar o registo de {{email}}? Isto remove o perfil e a função do CMS. Para revogar o acesso, elimine também a conta na Firebase Console.",removeConfirmSqlite:"Eliminar permanentemente {{email}}? Isto revoga o acesso E remove o perfil e a função. Esta ação não pode ser desfeita.",empty:{title:"Ainda não há membros na equipa",descriptionFirebase:"Crie a primeira conta na Firebase Console e depois inicie sessão aqui uma vez para registar o perfil.",descriptionSqlite:"Clique em +Adicionar utilizador acima para convidar o primeiro membro."},help:{title:"Como adicionar um novo membro à equipa",bootstrapLine:"O admin inicial (sempre com acesso total) é:",firebase:{step1:"Abra a Firebase Console → Authentication → Add user.",step2:"Defina um e-mail e palavra-passe e envie-os ao novo membro.",step3:"Peça-lhe para iniciar sessão aqui uma vez — o perfil aparece na lista acima e pode editar a função e os dados."},sqlite:{step1:"Clique no botão +Adicionar utilizador acima.",step2:"Introduza o e-mail e uma palavra-passe temporária (8+ caracteres).",step3:"Partilhe as credenciais de forma segura — ele pode alterar a palavra-passe a partir do perfil depois de iniciar sessão."},git:{step1:"Adicione a pessoa como colaboradora do repositório de conteúdo (escrita = editor, admin / maintainer = admin).",step2:"A pessoa cria o seu próprio token de acesso pessoal no GitHub / GitLab.",step3:"Abre o admin e inicia sessão com esse token — o perfil é criado aqui automaticamente."}},addUserModal:{title:"Adicionar um novo membro à equipa",intro:"Cria a conta diretamente na base de dados Flexweg SQLite Auth. O novo utilizador fica com a função editor por defeito; promova-o a partir da lista abaixo se precisar de acesso admin.",submit:"Criar utilizador",submitting:"A criar…"},actions:{editProfile:"Editar perfil",promote:"Promover a administrador",demote:"Despromover a editor",disable:"Desativar",enable:"Ativar",delete:"Eliminar registo"},descriptionGit:"Os membros da equipa são as pessoas com acesso de escrita ao repositório de conteúdo. Aparecem aqui após o primeiro início de sessão; a função acompanha as permissões no repositório.",descriptionLocal:"Este admin funciona em modo de utilizador único: o conteúdo é guardado neste browser e não há contas.",descriptionSqliteFile:"Sem contas de utilizador com este backend: qualquer pessoa que consiga abrir o admin pode editar. Proteja a pasta do admin ao nível do seu alojamento. Os perfis de autor abaixo são meramente informativos."},Gse={title:"Configuração do Firestore necessária",intro:"As páginas de listagem de artigos e páginas precisam de alguns índices compostos do Firestore para consultas eficientes. Precisam de ser criados manualmente — o Firebase reserva a criação de índices aos administradores do projeto.",checking:"A verificar os seus índices Firestore…",missingCount_one:"{{count}} índice em falta:",missingCount_other:"{{count}} índices em falta:",openConsole:"Abrir Firebase Console para criar",noUrl:"Não foi possível extrair o URL de auto-sugestão — consulte o README para o comando gcloud.",howItWorks:"Como funciona",step1:"Clique no link de cada índice em falta — Firebase Console abre com a definição pré-preenchida.",step2:"Clique em «Create» e espere 1–5 minutos pela construção do índice (estado na consola).",step3:"Volte aqui e clique em Tentar novamente. Quando ambas as consultas tiverem êxito, o admin carrega.",retry:"Tentar novamente",retrying:"A tentar…",buildHint:"A construção de um índice pode demorar alguns minutos após a criação.",allReady:"Todos os índices estão prontos.",unexpectedTitle:"Firestore inacessível",unexpectedHint:"Verifique a sua ligação e as regras do Firestore. Se acabou de criar os índices, espere que terminem e tente novamente."},Kse={appError:"Erro da aplicação",loadAccountFailed:"Não foi possível carregar a sua conta",loadAccountHint:"Se o problema persistir, termine sessão e tente novamente.",accountDisabled:"Conta desativada",accountDisabledMessage:"O seu acesso a este CMS foi desativado. Contacte o seu administrador.",firebaseNotConfigured:"Firebase não está configurado",firebaseEnvMissing:`Faltam as seguintes variáveis de ambiente:
|
|
3863
3863
|
{{vars}}
|
|
3864
3864
|
|
|
3865
|
-
Copie .env.example para .env, preencha as credenciais do seu projeto Firebase e reinicie o servidor de desenvolvimento.`,adminEmailNotConfigured:"E-mail do admin não configurado",adminEmailMessage:"VITE_ADMIN_EMAIL está em falta no .env. Defina-o com o e-mail do administrador inicial.",consoleHint:"Verifique a consola do browser e a sua configuração .env. Consulte o README para instruções de configuração."},Jse={brandTitle:"Flexweg CMS",brandSubtitle:"Publicador estático",login:{heading:"Iniciar sessão",intro:"Use o e-mail e a palavra-passe que o seu administrador lhe forneceu.",submit:"Iniciar sessão",submitting:"A iniciar sessão…"},fields:{name:"Nome a apresentar (opcional)",namePlaceholder:"Maria Silva",email:"E-mail",password:"Palavra-passe",passwordHint:"Pelo menos 8 caracteres."},footer:"As novas contas são criadas por um administrador a partir da página Utilizadores.",errors:{invalidEmail:"Introduza um endereço de e-mail válido.",missingPassword:"A palavra-passe é obrigatória.",passwordTooShort:"A palavra-passe deve ter pelo menos 8 caracteres."}},Qse=JSON.parse('{"title":"Bem-vindo ao Flexweg CMS","subtitle":"Configuração inicial","intro":"Insira as suas credenciais Firebase, a conta de administrador inicial e a sua chave API Flexweg. Os valores são validados, guardados no seu projeto (Firestore + um ficheiro config.js no Flexweg) e o admin recarrega no fluxo de início de sessão normal. Só faz isto uma vez.","introFirebase":"Passo 1 — Firebase. Preencha as credenciais do seu projeto Firebase e a conta de administrador bootstrap. Iniciamos sessão, verificamos o e-mail e confirmamos que as suas regras Firestore reconhecem este admin antes de avançarmos para o passo Flexweg.","introFlexweg":"Passo 2 — Flexweg. Preencha a sua chave API Flexweg e o URL do site. Testamos a API, guardamos a configuração no Firestore, fazemos upload do config.js para o seu site e sincronizamos os ativos do tema.","continueToFlexweg":"Validar Firebase e continuar","stepper":{"terms":"Condições","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Conteúdo e publicação","data":"Dados","hosting":"Alojamento","install":"Instalação"},"backend":{"title":"Escolha um backend de dados","intro":"Escolha onde o CMS irá guardar os seus artigos, páginas, utilizadores e definições. Pode trocar depois nas Definições (os dados não são migrados).","sqliteTitle":"Flexweg SQLite (recomendado)","sqliteHint":"Todos os dados ficam no seu site Flexweg como um ficheiro SQLite. Sem serviço externo. A auth é fornecida pela API SQLite do Flexweg.","firebaseTitle":"Firebase","firebaseHint":"Use um projeto Firebase para Firestore + Auth. Gratuito no plano Spark. Atualizações em tempo real via onSnapshot.","continue":"Continuar","markdownGitTitle":"Ficheiros Markdown num repositório Git","markdownGitHint":"Posts como ficheiros .md no GitHub / GitLab (ou num clone local). Cada editor inicia sessão com o seu próprio token de acesso; cada alteração é um commit. Sem base de dados, funciona com vários editores e computadores.","localTitle":"Apenas este browser","localHint":"Um só utilizador, sem início de sessão, nada para configurar. O conteúdo fica neste browser (exporte-o a partir das Definições). Ideal para um admin a correr no seu próprio computador."},"sqlite":{"heading":"Conectar o seu site Flexweg","intro":"Vamos usar a sua chave API mestre Flexweg UMA VEZ para criar um token de âmbito limitado para a base de dados SQLite. Após a instalação, a chave mestre é descartada e apenas o token limitado (restrito a este ficheiro SQLite) é guardado.","apiKeyHint":"Chave API mestre Flexweg. Usada apenas para instalar — nunca guardada depois.","detectedFromUrl":"Detetado do URL","advanced":"Definições avançadas (URL do site, caminho SQLite…)","pathHint":"Onde fica o ficheiro SQLite no seu site Flexweg. As pastas são criadas automaticamente.","adminHeading":"Conta de administrador","adminIntro":"Crie o primeiro utilizador — esta conta obtém direitos de admin automaticamente. Os membros seguintes são integrados a partir da página Utilizadores depois de ter sessão iniciada.","passwordHint":"Pelo menos 8 caracteres.","submit":"Instalar base de dados SQLite"},"terms":{"title":"Condições de utilização","intro":"Leia e aceite as condições abaixo antes de utilizar o Flexweg CMS. Estão escritas em linguagem clara para serem rápidas de ler.","section1":{"title":"1. Serviço gratuito","body":"O Flexweg CMS é disponibilizado gratuitamente pelo Flexweg. Pode utilizá-lo sem limites com o seu alojamento Flexweg — o Flexweg nunca lhe vai cobrar pelo uso do CMS em si. As tarifas habituais do seu plano de alojamento Flexweg e do seu plano Firebase mantêm-se aplicáveis, cada uma na conta correspondente."},"section2":{"title":"2. Fornecido «tal como está», sem garantia","body":"O CMS é fornecido tal como está. Trabalhamos para o manter estável e melhorá-lo ao longo do tempo, mas não podemos garantir que esteja livre de bugs, defeitos ou interrupções. Utilize-o com a mesma cautela que teria com qualquer ferramenta que não tenha escrito por si: mantenha cópias de segurança dos conteúdos importantes."},"section3":{"title":"3. Os seus conteúdos, a sua responsabilidade","body":"É o único responsável pelos conteúdos que publica através do CMS — textos, imagens, vídeos, formulários, integrações de código e quaisquer outros media. Deve cumprir a lei aplicável na sua jurisdição (e nas que visa), os direitos de autor, os direitos de imagem e de personalidade, as regras de proteção de dados pessoais e as condições de quaisquer serviços de terceiros que utilize (fontes incorporadas, vídeos, etc.). O Flexweg não é responsável pelos conteúdos publicados pelos utilizadores do CMS."},"section4":{"title":"4. A sua conta Firebase, a sua segurança","body":"O CMS guarda os seus dados no seu próprio projeto Firebase. É responsável pela segurança desse projeto: escolha uma palavra-passe forte para a conta de administrador inicial, configure as regras de segurança do Firestore como documentado, faça rotação das suas chaves API quando necessário e verifique quem tem acesso. O Flexweg não pode em caso algum ser responsabilizado por acessos não autorizados, fugas de dados, ataques informáticos ou perdas resultantes de uma má configuração ou comprometimento da sua conta Firebase."},"section5":{"title":"5. Limitação de responsabilidade","body":"O Flexweg não pode ser responsabilizado por qualquer perda de receitas, perda de dados, perda de oportunidade comercial, ou por quaisquer danos diretos ou indiretos decorrentes do uso, mau uso ou indisponibilidade do CMS. Quando a lei aplicável obrigar o Flexweg a assumir alguma responsabilidade, esta limita-se ao montante efetivamente pago ao Flexweg pelo CMS nos últimos 12 meses — ou seja, zero, uma vez que o CMS é gratuito."},"section6":{"title":"6. Os seus dados continuam seus","body":"Os conteúdos que cria com o CMS são guardados no seu próprio projeto Firebase (textos, definições, metadados dos media) e no seu próprio alojamento Flexweg (HTML publicado, imagens, assets de tema). O CMS em si não transmite os seus conteúdos a nenhum serviço de terceiros. Os plugins ou temas que escolher ativar podem ter o seu próprio comportamento — verifique o que fazem antes de os ativar."},"section7":{"title":"7. Bom uso","body":"A utilização do CMS para atividades ilegais, fraudulentas ou nocivas, ou de forma contrária às condições gerais de utilização do Flexweg, pode levar à suspensão do acesso ao alojamento Flexweg. Podemos também atualizar estas condições do CMS ao longo do tempo; as alterações significativas serão comunicadas através do admin ou por e-mail."},"accept":"Li e aceito as Condições de utilização.","continue":"Continuar para a configuração","back":"Voltar"},"sections":{"firebase":"Firebase","admin":"Administrador inicial","flexweg":"API Flexweg"},"help":{"firebase":"Encontre estes valores em Firebase Console → Definições do projeto → Geral → As suas apps → Configuração do SDK.","admin":"Use um utilizador existente em Firebase Authentication. Quem inicie sessão com este e-mail é tratado como administrador e ignora a verificação de registo de utilizador. Crie o utilizador em Firebase Console → Authentication se ainda não existir.","flexweg":"Gere uma chave API permanente na sua conta Flexweg → API. O URL do site é o endereço público do seu site Flexweg (ex. https://o-seu-site.flexweg.com).","flexwegApiKeyHint":"Obtenha a sua chave API nas definições da sua conta Flexweg.","flexwegApiKeyLink":"Abrir definições da conta"},"fields":{"apiKey":"Chave API","authDomain":"Domínio de autenticação","projectId":"ID do projeto","storageBucket":"Bucket de armazenamento","messagingSenderId":"ID de remetente de mensagens","appId":"ID da app","adminEmail":"E-mail","adminPassword":"Palavra-passe","flexwegApiKey":"Chave API","flexwegSiteUrl":"URL do site","flexwegApiBaseUrl":"URL base da API","sqlitePath":"Caminho SQLite"},"submit":"Guardar e continuar","submitting":"A configurar…","success":"Configuração concluída!","reloadingHint":"O admin vai recarregar daqui a um instante — aguarde.","footer":"Estes valores são guardados no seu projeto (Firestore + Flexweg). Não são enviados para mais lado nenhum.","steps":{"signInFirebase":"A iniciar sessão no Firebase…","testFlexweg":"A testar a API Flexweg…","writeFirestore":"A guardar a configuração…","uploadConfig":"A carregar config.js para o Flexweg…","syncThemes":"A sincronizar assets do tema para o Flexweg…","sqliteInstall":"A criar token SQLite com âmbito limitado…","sqliteRegisterAdmin":"A registar a conta de admin…","sqliteSchema":"A inicializar o esquema SQLite…"},"stepsDone":{"sqliteInstall":"Token SQLite com âmbito limitado emitido","sqliteRegisterAdmin":"Admin registado e com sessão iniciada","sqliteSchema":"Esquema SQLite pronto"},"errors":{"missingFields":"Por favor, preencha todos os campos.","rootDeploymentTitle":"O admin deve estar numa subpasta, não na raiz do site.","rootDeploymentHint":"Mova os ficheiros do admin (index.html, config.js, runtime/, …) para uma subpasta no Flexweg — por exemplo /admin/ ou um nome aleatório como /erf34f654GH3/ por discrição. Em seguida recarregue o admin a partir do URL da subpasta e volte a executar a configuração.","firebaseAuthGeneric":"Não foi possível iniciar sessão no Firebase.","firebaseAuthInvalidCredential":"O Firebase rejeitou a combinação de e-mail e palavra-passe.","firebaseAuthInvalidCredentialHint":"Os projetos Firebase recentes ativam por defeito a proteção contra enumeração de e-mails, que devolve o mesmo erro quer a palavra-passe esteja errada, o utilizador não exista, ou o utilizador inicie sessão com outro fornecedor. A verificar:\\n• Reintroduza a palavra-passe — copie/cole de um gestor de palavras-passe para eliminar erros de digitação. O mínimo são 6 caracteres.\\n• Abra Firebase Console → Authentication → Users e confirme que o e-mail existe. Verifique a coluna «Providers»: se mostrar apenas Google (ou outro fornecedor) sem «Email/Password», defina ou redefina a palavra-passe pelo menu da linha (⋮ → Repor palavra-passe).\\n• Confirme que a ortografia do e-mail corresponde exatamente ao que está guardado no Firebase.","firebaseAuthUserNotFound":"Não existe utilizador Firebase com este e-mail. Crie um primeiro em Firebase Console → Authentication → Users.","firebaseAuthInvalidEmail":"O e-mail do administrador não é um endereço válido.","firebaseInvalidApiKey":"A chave API do Firebase é inválida. Verifique o valor na Firebase Console.","firebaseNetwork":"Erro de rede ao iniciar sessão no Firebase. Verifique a sua ligação.","firebaseTooManyRequests":"Demasiadas tentativas de início de sessão. Tente novamente mais tarde ou redefina a palavra-passe via Firebase Console.","firebaseOperationNotAllowed":"O início de sessão por e-mail/palavra-passe não está ativado neste projeto Firebase. Abra Firebase Console → Authentication → Sign-in method e ative o fornecedor Email/Password.","firebaseUserDisabled":"Esta conta de utilizador Firebase está desativada. Reative-a em Firebase Console → Authentication → Users.","wrongAdminEmail":"A conta Firebase com que iniciou sessão não corresponde ao e-mail de admin que escreveu. Tente novamente.","rulesNotPinnedTitle":"As regras do Firestore ainda não o reconhecem como admin bootstrap.","rulesNotPinnedHint":"Abra Firebase Console → Firestore → Rules e substitua o valor de `bootstrapAdminEmail()` por: {{email}} — depois clique em Publicar. O modelo de regras do README inclui um placeholder `you@example.com` que tem de ser substituído pelo seu e-mail de admin real. Depois de publicar as novas regras, clique novamente em Enviar aqui.","flexwegAuth":"Chave API Flexweg rejeitada. Verifique o valor na sua conta Flexweg → API.","flexwegNetwork":"Erro de rede ao contactar o Flexweg. Verifique o URL base da API e a sua ligação.","flexwegHttp":"Erro da API Flexweg ({{status}}): {{detail}}","firestoreRulesTitle":"O Firestore rejeitou a escrita da configuração.","firestoreRulesHint":"Abra Firebase Console → Firestore → Regras e confirme que o e-mail de admin de bootstrap está definido como \'{{email}}\'. O README inclui um modelo de regras pronto a copiar.","firestoreOther":"Falha ao escrever no Firestore","uploadFailed":"Não foi possível carregar config.js para o Flexweg","generic":"Algo correu mal."},"docstore":{"contentTitle":"Repositório de conteúdo","contentIntro":"Onde os seus posts, páginas e definições são guardados como ficheiros Markdown + JSON. Um repositório vazio serve — o CMS cria os ficheiros.","provider":"Repositório","localClone":"Pasta local (clone git)","localCloneHint":"Escolha a pasta do seu clone. Sincronize-a com o seu cliente git habitual — o CMS lê e escreve ficheiros, não executa git.","contentDir":"Pasta de conteúdo no repositório","privateRepo":"Utilize um repositório privado: os rascunhos são guardados lá.","folderRequired":"Escolha primeiro a pasta de conteúdo.","checking":"A verificar o acesso ao repositório…","publishIntro":"Onde o site gerado é publicado. Pode alterá-lo mais tarde nas Definições.","existingSite":"Este repositório já está configurado — o site continua a ser publicado em: {{target}}. Pode alterá-lo mais tarde nas Definições (as chaves secretas, se existirem, têm de ser introduzidas novamente lá).","install":"Instalar","steps":{"config":"A guardar a configuração…","content":"A carregar o conteúdo…","target":"A guardar o destino de publicação…","testTarget":"A testar o destino de publicação…"},"doneTitle":"Tudo pronto!","doneBody":"A configuração foi guardada neste browser. Para poupar este passo a outros editores, descarregue o config.js e substitua o que está na pasta admin do seu alojamento.","downloadConfig":"Descarregar config.js","open":"Abrir o admin","footer":"O conteúdo fica no seu repositório ou neste browser; os tokens de acesso nunca saem deste browser."},"data":{"title":"1. Onde guarda os seus dados?","intro":"Os seus posts, páginas, utilizadores e definições — os dados próprios do admin. Isto é independente de onde o site público está alojado (próximo passo).","localNote":"Nada a configurar: o conteúdo é guardado neste browser. Exporte-o nas Definições para fazer uma cópia de segurança ou movê-lo mais tarde.","options":{"sqlite-file":{"title":"SQLite","hint":"Uma base de dados SQLite guardada no alojamento que escolher no passo seguinte (Flexweg, o seu servidor, S3, Git…). Sem contas de utilizador — ou o serviço SQLite da Flexweg, com contas, se alojar na Flexweg."},"flexweg-sqlite":{"title":"SQLite (serviço Flexweg)","hint":"Uma base de dados SQLite gerida pelo serviço da Flexweg, com contas de utilizador integradas. Requer uma conta Flexweg, seja qual for o alojamento do site."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth no seu projeto Google. Tempo real, plano Spark gratuito."},"markdown-git":{"title":"Ficheiros Markdown em Git","hint":"Posts como ficheiros .md num repositório GitHub / GitLab (ou num clone local). Cada editor utiliza o seu próprio token; cada alteração é um commit."},"local":{"title":"Este browser","hint":"Um único utilizador, sem início de sessão, nada a configurar. Ideal para um admin a correr no seu computador."}}},"hosting":{"title":"2. Onde é publicado o site?","intro":"Para onde o site estático gerado (HTML, CSS, imagens) é carregado sempre que publica. Pode alterá-lo mais tarde nas Definições.","existing":"Este repositório de conteúdo já publica no destino abaixo. Mantenha-o ou escolha outro."},"install":{"title":"3. Instalação","intro":"Verifique o resumo e depois instale.","data":"Dados","hosting":"Alojamento","saveTarget":"A guardar o destino de publicação…","noteConfigJs":"A configuração do admin (config.js) é carregada junto ao admin no Flexweg quando possível; caso contrário, ser-lhe-á proposto descarregá-la.","noteLocalConfig":"A configuração é guardada neste browser; ser-lhe-á proposto o config.js para colocar na pasta do admin, para que outros editores saltem esta configuração."},"sqliteFile":{"security":"Sem contas de utilizador: quem conseguir abrir este admin pode editar o conteúdo — proteja a pasta do admin no seu alojamento. O ficheiro da base de dados é servido como qualquer outro ficheiro: mantenha-o cifrado ou guarde-o num local privado separado.","intro":"Onde o ficheiro de base de dados é guardado. Este admin lê-o e guarda-o através dos mesmos conectores que o alojamento.","path":"Caminho do ficheiro de base de dados","pathHint":"É criado no primeiro guardar, se ainda não existir. Com um repositório Git, cada gravação é um commit — prefira um repositório ou ramo que não desencadeie um build do site.","existing":"base de dados existente","new":"nova base de dados","dataNote":"Nada a configurar aqui: a base de dados será guardada no alojamento que escolher no passo seguinte.","heading":"Base de dados SQLite","flexwegService":"Utilizar o serviço SQLite da Flexweg","flexwegServiceHint":"A base de dados é gerida pela Flexweg e inclui contas de utilizador integradas (e-mail + palavra-passe). Caso contrário, é um simples ficheiro neste alojamento, sem contas.","summaryFile":"Ficheiro {{path}} neste alojamento","summaryService":"Serviço SQLite da Flexweg ({{path}})","encrypt":"Cifrar a base de dados","encryptHint":"Recomendado num alojamento público: o ficheiro fica ilegível sem a frase-passe. Cada novo navegador pede-a uma vez.","passphrase":"Frase-passe","passphraseHint":"Guarde-a já no seu gestor de palavras-passe: sem ela ninguém consegue abrir a base de dados, nem mesmo você.","copy":"Copiar","copied":"Copiada","generate":"Nova","passphraseTooShort":"A frase-passe deve ter pelo menos 12 caracteres.","existingEncrypted":"Já existe uma base de dados cifrada neste caminho: introduza a respetiva frase-passe.","separate":"Guardar a base de dados num local privado separado","separateHint":"Por ex. um bucket S3 / R2 privado ou um repositório Git privado: a base de dados nunca é servida pelo site público.","summaryEncrypted":"cifrada","summaryLocation":"guardada em {{location}}","locationLabel":"Local da base de dados","gitBranchNote":"A base de dados fica no ramo {{branch}} deste repositório, que nunca é publicado: guardar conteúdo não volta a gerar o site.","summaryBranch":"no ramo {{branch}}"},"adminHosting":{"deploying":"A copiar o admin para o site…","label":"Alojar também o admin neste site","hint":"O admin é copiado para {{url}} com o seu config.js (sem segredos) — cada editor pode então abri-lo aí. Cada editor continua a iniciar sessão com o seu próprio acesso.","folder":"Pasta do admin","alreadyHere":"Este admin já está a correr a partir deste site: o seu config.js será atualizado no local.","doneBody":"O admin está agora no seu site. No GitHub Pages, ative primeiro o Pages para o repositório se ainda não o fez (Settings → Pages) e depois abra-o:","open":"Abrir o admin online","continueHere":"Continuar neste admin"}}'),Xse={actions:{upload:"A carregar ficheiro",delete:"A eliminar ficheiro",rename:"A renomear ficheiro",get:"A ler ficheiro",list:"A listar ficheiros",createFolder:"A criar pasta",renameFolder:"A renomear pasta",deleteFolder:"A eliminar pasta",storageLimits:"A obter limites de armazenamento",commit:"A publicar alterações"},errors:{configMissing:"O destino de publicação não está configurado. Configure-o nas Definições antes de publicar.",network:"{{action}}: erro de rede ou CORS bloqueado. Verifique a sua ligação.",auth:"{{action}}: falha na autenticação. Verifique as credenciais do destino de publicação nas Definições.",notFound:"{{action}}: não encontrado no destino de publicação.",tooLarge:"{{action}}: ficheiro demasiado grande para o destino de publicação.",rateLimited:"{{action}}: demasiados pedidos, tente novamente daqui a um momento.",serverError:"{{action}}: erro do servidor do destino de publicação ({{status}}). Tente novamente.",generic:"{{action}} falhou ({{status}}){{detail}}.",unsupported:"{{action}}: não suportado pelo destino de publicação «{{connector}}».",unknownConnector:"Destino de publicação desconhecido «{{connector}}». Verifique Definições → Destino de publicação.",folderAccess:"Sem acesso à pasta local. Abra Definições → Destino de publicação e clique em «Religar pasta»."}},Zse={log:{rendering:"A renderizar página…",uploading:"A carregar {{path}}…",deleting:"A eliminar {{path}}…",regenerating:"A regenerar listagens…",skipped:"{{path}} ignorado (sem alterações)",done:"Publicado em {{url}}",failed:"Falhou: {{error}}"}},Yse={errors:{notConnected:"Sem ligação ao repositório de conteúdo. Volte a iniciar sessão com o seu token de acesso.",conflict:"Outra pessoa alterou este item entretanto. A versão dela é agora apresentada — volte a aplicar a sua alteração.",sqliteUnsupported:"O destino «{{connector}}» não consegue guardar um ficheiro de base de dados."}},eie={target:"Destino de publicação",settingsTitle:"Destino de publicação",settingsHelp:"Onde o site renderizado é enviado ao publicar. As credenciais são guardadas com o seu backend de conteúdo (ou neste browser para repositórios Git de conteúdo) e podem ser lidas por todos os admins.",saved:"Destino de publicação guardado. Execute Regenerar → Tudo para publicar o site completo no novo destino.",test:"Testar a ligação",testOk:"Ligação OK",testFailed:"Falha na ligação",names:{flexweg:"Flexweg","git-pages":"Repositório Git (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"Bucket compatível com S3 (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"O seu próprio servidor (bridge PHP)","browser-mirror":"Descarregar como ZIP","local-folder":"Pasta local neste computador"},hints:{flexweg:"Envio através da API Files do Flexweg.","git-pages":"Cada publicação é um commit no repositório; o alojamento reconstrói o site a partir dele.",s3:"Requer uma regra CORS no bucket que permita a origem deste admin, e alojamento de site (ou uma CDN) para servir os ficheiros index.html.","php-bridge":"Envie external/bridges/php/flexweg-bridge.php para o seu servidor, defina a respetiva chave de API e depois preencha o URL aqui.","browser-mirror":"O site é guardado neste browser; descarregue o ZIP e envie-o manualmente para onde quiser.","local-folder":"Escreve o site diretamente numa pasta (Chrome / Edge). Sirva-o localmente ou envie-o com as suas próprias ferramentas."},fields:{flexweg:{apiKey:"Chave de API",siteUrl:"URL do site",apiBaseUrl:"URL base da API"},"git-pages":{host:"Alojamento",provider:"Fornecedor Git",owner:"Proprietário (utilizador ou organização)",repo:"Repositório",project:"Caminho do projeto",branch:"Ramo",dir:"Pasta no repositório",token:"Token de acesso",siteUrl:"URL pública do site",apiBaseUrl:"URL da API (apenas auto-alojado)"},s3:{endpoint:"Endpoint",region:"Região",bucket:"Bucket",prefix:"Prefixo das chaves (opcional)",accessKeyId:"ID da chave de acesso",secretAccessKey:"Chave de acesso secreta",siteUrl:"URL pública do site",forcePathStyle:"URLs do tipo caminho (MinIO, R2, a maioria dos compatíveis)",publicRead:"Tornar públicos os ficheiros carregados (ACL public-read) — para buckets que não são públicos através de uma política (OVHcloud, Scaleway…). Deixe desativado em buckets AWS com «bucket owner enforced»."},"php-bridge":{apiBaseUrl:"URL do bridge",apiKey:"Chave de API do bridge",siteUrl:"URL pública do site"},"browser-mirror":{siteUrl:"URL pública do site (opcional)"},"local-folder":{siteUrl:"URL onde a pasta é servida (opcional)"}},help:{flexweg:{apiKey:"Gerada a partir da sua conta Flexweg → API."},"git-pages":{host:"Cloudflare Pages: ligue o projeto a este repositório sem comando de build e com a pasta de saída abaixo. Funciona com repositórios privados.",dir:'Deixe vazio para a raiz do repositório. GitHub Pages: "" ou "docs". GitLab Pages: "public".',token:"Token fine-grained neste repositório com Contents: read & write (GitHub) — adicione Pages: read & write para permitir que o CMS ative o GitHub Pages — ou um token com o scope api (GitLab). Deixe vazio para usar o token de acesso de cada editor quando o conteúdo está no mesmo fornecedor.",siteUrl:"p. ex. https://user.github.io/repo — um URL com subpasta funciona, as ligações são ajustadas automaticamente."},s3:{endpoint:"Deixe vazio para AWS (deduzido da região). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"O URL de alojamento do bucket ou o seu domínio CDN."},"php-bridge":{apiBaseUrl:"O URL completo de flexweg-bridge.php no seu servidor (HTTPS)."},"browser-mirror":{siteUrl:"Onde vai enviar o ZIP — usado para os URLs absolutos (sitemaps, RSS, multimédia)."},"local-folder":{siteUrl:"p. ex. http://localhost:8080 quando um servidor web local serve a pasta."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (ligado ao repositório)","gitlab-pages":"GitLab Pages",other:"Outro (Netlify, Vercel, git pull no servidor…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Escolher pasta…",change:"Mudar de pasta…",reconnect:"Voltar a ligar a pasta",unsupported:"Este browser não consegue escrever em pastas locais. Utilize o Chrome ou o Edge."},mirror:{download:"Descarregar o site (ZIP)",count:"{{count}} ficheiros neste browser"},adminHosting:{title:"Admin neste site",help:"Copie este admin para o destino de publicação (primeira implementação, ou atualização após uma nova versão). O seu config.js não contém segredos.",deploy:"Implementar / atualizar o admin",deployed:"Admin implementado ({{count}} ficheiros) — {{url}}"},pages:{enabled:"GitHub Pages ativado para este repositório — o site estará online dentro de cerca de um minuto.",enableHint:'Publicação concluída. Para colocar o site online, ative o GitHub Pages para {{repo}}: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Ou dê ao token a permissão "Pages: read and write" e o CMS faz isso por si.)'},siteUrl:{mismatch:"O URL público do site (Definições → Site) é {{site}}, mas este destino serve o site em {{target}}. As ligações, o CSS e os sitemaps seguem o URL do site — estarão errados neste alojamento.",use:"Usar {{url}} para o site",updated:"URL do site atualizado. Execute Regenerar → Tudo para voltar a publicar as páginas com as novas ligações."}},tie={heading:"Ligar ao repositório de conteúdo",tokenIntro:"O conteúdo está guardado no repositório {{provider}} {{repo}}. Inicie sessão com o seu próprio token de acesso pessoal — as suas permissões no repositório determinam a sua função (escrita = editor, admin / maintainer = admin).",token:"Token de acesso pessoal",tokenHelpGithub:"Token fine-grained, com acesso apenas a este repositório, permissão Contents: leitura e escrita.",tokenHelpGitlab:"Token com o api scope, função Developer ou superior neste projeto.",createToken:"Criar um token",connect:"Ligar",tokenStorage:"O token é guardado apenas neste browser. Terminar sessão apaga-o.",failed:"Este token não consegue escrever no repositório (inválido, expirado ou só de leitura). Verifique as permissões.",folderIntro:"O conteúdo está guardado numa pasta deste computador (normalmente um clone git que sincroniza com o seu próprio cliente git). Conceda acesso a este browser — os browsers voltam a pedir após cada recarregamento.",openFolder:"Abrir a pasta de conteúdo"},nie={flexweg:{title:"Flexweg",short:"Alojamento Flexweg",hint:"Carrega através da Flexweg Files API. Chave API da sua conta Flexweg."},"github-pages":{title:"GitHub Pages",short:"Gratuito, a partir de um repositório GitHub",hint:"Cada publicação é um commit no repositório; o GitHub Pages serve-o. Settings → Pages → Deploy from a branch. Repositórios públicos no plano gratuito."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Gratuito, repositórios privados OK",hint:"O CMS faz commit do site num repositório GitHub / GitLab; ligue-lhe um projeto Cloudflare Pages (sem comando de build, pasta de saída = a pasta abaixo)."},"gitlab-pages":{title:"GitLab Pages",short:"Gratuito, a partir de um repositório GitLab",hint:"Cada publicação é um commit; o CMS adiciona um .gitlab-ci.yml mínimo que publica a pasta public/."},"git-other":{title:"Netlify, Vercel…",short:"Qualquer alojamento que implemente um repositório",hint:"O CMS faz commit do site num repositório Git; ligue o seu alojamento (Netlify, Vercel, um servidor que executa git pull…) a esse repositório."},s3:{title:"S3 / R2 / B2…",short:"Bucket de armazenamento de objetos",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Requer uma regra CORS no bucket e alojamento de sites ou um CDN à frente."},"own-server":{title:"O seu próprio servidor (FTP / SFTP)",short:"Alojamento partilhado, VPS…",hint:"Os browsers não falam FTP nem SFTP: carregue uma vez a ponte PHP (external/bridges/php/flexweg-bridge.php) com o seu cliente FTP, defina a respetiva chave API e depois indique aqui o seu URL. Funciona em qualquer alojamento PHP."},"local-folder":{title:"Pasta local",short:"Neste computador",hint:"Escreve o site numa pasta deste computador (Chrome / Edge). Sirva-o localmente ou envie-o com as suas próprias ferramentas."},zip:{title:"Descarregar como ZIP",short:"Carregue-o manualmente",hint:"O site é guardado neste browser; descarregue um ZIP nas Definições e carregue-o onde quiser (Netlify Drop, cliente FTP…)."}},rie={heading:"Ligar à base de dados",intro:"Este admin guarda o seu conteúdo em {{path}}. Introduza as credenciais de acesso para este browser.",storage:"As credenciais são guardadas apenas neste browser. Terminar sessão apaga-as.",passphrase:"Frase-passe da base de dados",passphraseHint:"A base de dados está cifrada. Introduza a frase-passe escolhida na instalação (guardada apenas neste navegador).",passphraseWrong:"Frase-passe incorreta: não foi possível abrir a base de dados.",passphraseMissing:"Introduza a frase-passe da base de dados."},sie={common:Rse,auth:jse,nav:Mse,dashboard:Lse,posts:Dse,pages:Fse,taxonomies:Ose,media:zse,themes:Use,plugins:Bse,externalInstall:$se,externalLoader:Hse,menus:Vse,settings:qse,users:Wse,firestoreSetup:Gse,errors:Kse,identity:Jse,setup:Qse,flexweg:Xse,publish:Zse,docstore:Yse,connectors:eie,gitAccess:tie,hosting:nie,sqliteAccess:rie},iie={save:"저장",saving:"저장 중…",saved:"저장됨",cancel:"취소",delete:"삭제",deleting:"삭제 중…",edit:"편집",create:"만들기",search:"검색",loading:"불러오는 중…",yes:"예",no:"아니요",confirm:"확인",back:"뒤로",next:"다음",previous:"이전",close:"닫기",all:"전체",none:"없음",actions:"작업",name:"이름",slug:"슬러그",description:"설명",status:"상태",createdAt:"생성됨",updatedAt:"업데이트됨",publishedAt:"게시됨",language:"언어",darkMode:"다크 모드",lightMode:"라이트 모드",signOut:"로그아웃",administrator:"관리자",editor:"편집자",appName:"Flexweg CMS"},aie={signIn:"로그인",signingIn:"로그인 중…",email:"이메일",password:"비밀번호",emailPlaceholder:"you@company.com",passwordPlaceholder:"••••••••",forgotPassword:"비밀번호를 잊으셨나요?",resetEmailSent:"{{email}} 주소로 비밀번호 재설정 이메일을 보냈습니다.",enterEmailFirst:"위에 이메일을 먼저 입력한 다음 재설정을 클릭하세요.",emailPasswordRequired:"이메일과 비밀번호를 모두 입력해 주세요.",signInSubtitle:"업무용 이메일과 비밀번호를 사용하세요.",footer:"계정 요청은 관리자를 통해 처리됩니다.",errors:{invalidEmail:"유효하지 않은 이메일 주소입니다.",invalidCredentials:"이메일 또는 비밀번호가 올바르지 않습니다.",tooManyRequests:"시도 횟수가 너무 많습니다. 나중에 다시 시도하거나 비밀번호를 재설정하세요.",userDisabled:"이 계정은 비활성화되었습니다.",networkFailed:"네트워크 오류입니다. 연결 상태를 확인하세요.",generic:"인증에 실패했습니다."}},oie={openMenu:"메뉴 열기",closeMenu:"메뉴 닫기",dashboard:"대시보드",posts:"게시물",pages:"페이지",taxonomies:"카테고리 및 태그",media:"미디어",themes:"테마",themeSettings:"테마 설정",plugins:"플러그인",menus:"메뉴",users:"사용자",settings:"설정"},lie={title:"대시보드",welcome:"{{email}}님, 다시 오신 것을 환영합니다.",stats:{totalPosts:"게시물",totalPages:"페이지",online:"온라인",drafts:"초안"}},cie={title:"게시물",newPost:"새 게시물",noPosts:"아직 게시물이 없습니다. 첫 게시물을 만들어 시작하세요.",noPostsInFilter:"현재 필터와 일치하는 게시물이 없습니다.",search:{placeholder:"게시물 검색…",clear:"검색 지우기",noResults:"검색과 일치하는 게시물이 없습니다."},pagination:{previous:"이전",next:"다음",showing:"{{total}}개 중 {{from}}–{{to}} 표시",pageOf:"{{total}}페이지 중 {{page}}페이지"},bulk:{selectedCount_one:"{{count}}개 선택됨",selectedCount_other:"{{count}}개 선택됨",selectPage_one:"이 페이지에서 {{count}}개 선택",selectPage_other:"이 페이지의 {{count}}개 모두 선택",deselectPage:"페이지 선택 해제",allOnPageSelected_one:"이 페이지에서 {{count}}개가 선택되었습니다.",allOnPageSelected_other:"이 페이지의 {{count}}개가 모두 선택되었습니다.",selectAllMatching_one:"일치하는 게시물 선택",selectAllMatching_other:"일치하는 {{count}}개 게시물 모두 선택",allMatchingSelected_one:"일치하는 게시물이 선택되었습니다.",allMatchingSelected_other:"일치하는 {{count}}개 게시물이 모두 선택되었습니다.",selectOne:'"{{title}}" 선택',publish:"게시 ({{count}})",publishing:"게시 중…",publishedCount:"{{ok}}개 게시됨, {{failed}}개 실패.",unpublish:"게시 취소 ({{count}})",unpublishing:"게시 취소 중…",unpublishedCount:"{{ok}}개 게시 취소됨, {{failed}}개 실패.",delete:"삭제",deleting:"삭제 중…",deletedCount:"{{ok}}개 삭제됨, {{failed}}개 실패.",confirmDelete_one:"게시물 {{count}}개를 삭제하시겠습니까? Flexweg에서 게시 취소되며 되돌릴 수 없습니다.",confirmDelete_other:"게시물 {{count}}개를 삭제하시겠습니까? Flexweg에서 게시 취소되며 되돌릴 수 없습니다.",noDraftSelected:"선택된 초안 게시물이 없습니다.",noOnlineSelected:"선택된 온라인 게시물이 없습니다.",clear:"선택 해제"},filters:{all:"전체",draft:"초안",online:"온라인"},fields:{title:"제목",slug:"슬러그",excerpt:"발췌문",content:"본문",category:"카테고리",tags:"태그",heroImage:"대표 이미지",seoTitle:"SEO 제목",seoDescription:"SEO 설명",createdAt:"작성일",updatedAt:"마지막 업데이트",publishedAt:"게시일"},edit:{newTitle:"새 게시물",editTitle:"게시물 편집",saved:"저장되었습니다.",savedAndRepublished:"저장 및 재게시되었습니다.",saveFailed:"저장에 실패했습니다.",saveAndRepublish:"저장 및 재게시",draftSaved:"초안이 저장되었습니다.",slugCollision:{post:'이 URL은 이미 게시물에서 사용 중입니다: "{{label}}".',page:'이 URL은 이미 페이지에서 사용 중입니다: "{{label}}".',category:'이 URL은 이미 카테고리에서 사용 중입니다: "{{label}}".'},publish:"게시",unpublish:"게시 취소",publishing:"게시 중…",unpublishing:"게시 취소 중…",titlePlaceholder:"제목 추가",permalink:"고유 링크",slugFormatHint:"소문자 ASCII와 하이픈만 사용할 수 있습니다.",slugAutoSuffixed:'"{{base}}"이(가) 이미 {{owner}}에서 사용 중이므로 접미사를 추가했습니다.',slugAutoSuffixedOwner:{post:'게시물: "{{label}}"',page:'페이지: "{{label}}"',category:'카테고리: "{{label}}"'},saveBlocked:{titleRequired:"저장하기 전에 제목을 추가하세요.",slugRequired:"저장하려면 제목과 URL 슬러그가 필요합니다.",slugInvalid:"슬러그 형식이 잘못되었습니다 (소문자 ASCII + 하이픈).",slugCollision:"저장하기 전에 URL 충돌을 해결하세요."},viewPublished:"보기",confirmDelete:"이 항목을 삭제하시겠습니까?",inspector:{document:"문서",block:"블록",blockEmpty:"옵션을 보려면 편집기에서 블록을 선택하세요.",publishing:"게시",permalink:"고유 링크",categories:"카테고리 및 태그",featured:"대표 이미지",seo:"SEO",excerpt:"발췌문",dates:"날짜"},blocks:{addBlock:"블록 추가",transform:"변환",moveUp:"위로 이동",moveDown:"아래로 이동",duplicate:"복제",remove:"블록 삭제",paragraph:"단락",heading2:"제목 2",heading3:"제목 3",bulletList:"글머리 기호 목록",orderedList:"번호 매기기 목록",blockquote:"인용",codeBlock:"코드",image:"이미지",horizontalRule:"구분선",categories:{text:"텍스트",media:"미디어",layout:"레이아웃",embed:"임베드",advanced:"고급"},noSettings:"이 블록에는 설정이 없습니다.",noSelection:"옵션을 보려면 편집기에서 블록을 선택하세요.",slash:{noResults:"일치하는 블록이 없습니다."}}},status:{draft:"초안",online:"온라인"},preview:{title:"미리보기",rendering:"미리보기 렌더링 중…",error:"미리보기 실패: {{error}}",viewports:{mobile:"모바일",tablet:"태블릿",desktop:"데스크탑"}}},uie={title:"페이지",newPage:"새 페이지",noPages:"아직 페이지가 없습니다.",homeBadge:"홈",homeBadgeTooltip:"사이트 홈 페이지로 사용됨"},die={title:"카테고리 및 태그",categories:"카테고리",tags:"태그",newCategory:"새 카테고리",newTag:"새 태그",noCategories:"아직 카테고리가 없습니다.",noTags:"아직 태그가 없습니다.",slugCollision:'이 슬러그는 이미 "{{label}}"에서 사용 중입니다.',seo:{button:"SEO",buttonTitle:"SEO 메타 태그 편집",title:"SEO 메타 태그",subtitle:'"{{name}}" 아카이브 페이지의 사용자 지정 제목과 설명입니다.',metaTitle:"메타 제목",metaTitleHint:"페이지 <title>로 사용됩니다. 기본값: 용어 이름.",metaDescription:"메타 설명",metaDescriptionHint:"페이지 메타 설명으로 사용됩니다. 기본값: 용어 설명."}},hie={title:"미디어 라이브러리",upload:"업로드",uploading:"업로드 중…",finalizing:"마무리 중…",uploadFailed:"업로드 실패",retry:"재시도",noMedia:"아직 미디어가 없습니다.",alt:"대체 텍스트",caption:"캡션",filename:"파일명",size:"크기",type:"유형"},fie={title:"테마",active:"활성",activate:"활성화",installExternal:"테마 설치",uninstallDisabledTitle:"이 테마를 제거하기 전에 다른 테마로 전환하세요.",syncAssets:"테마 자산 동기화",regenerateSite:"사이트 재생성",regenerating:"재생성 중…",regenerate:{button:"재생성",running:"실행 중…",groupBuiltins:"사이트",groupPlugins:"플러그인",home:"홈 페이지만",homeHelp:"index.html만 재생성합니다 — 가장 빠른 옵션입니다.",allHtml:"모든 HTML 페이지",allHtmlHelp:"모든 게시물, 페이지, 아카이브, 목록 + menu / posts / authors JSON 스냅샷.",repair:"URL 복구",repairHelp:"온라인 상태의 모든 게시물에 대해 정규 경로를 다시 계산하고 잘못된 URL에 업로드된 파일을 옮깁니다. 용어 동기화 전에 실행된 import 이후 유용합니다.",assets:"테마 자산",assetsHelp:"활성 테마의 CSS와 부속 스크립트를 /theme-assets/에 업로드합니다.",everything:"전체",everythingHelp:"테마 자산 + 모든 HTML + 모든 플러그인 출력. 가장 느린 옵션입니다.",noPluginTargets:"플러그인 재생성 대상 없음 — 재생성을 지원하는 플러그인을 활성화하세요."},confirmSwitch:{title:"{{theme}}(으)로 전환하시겠습니까?",body:"테마 전환 시 새 디자인이 모든 곳에 적용되도록 테마 자산을 다시 업로드하고 게시된 모든 페이지를 재생성해야 합니다. 잠시 시간이 걸릴 수 있습니다.",confirm:"전환 및 재생성",cancel:"취소"}},pie={title:"플러그인",enabled:"활성화됨",disabled:"비활성화됨",enable:"활성화",disable:"비활성화",configure:"설정",author:"제작자",learnMore:"자세히 보기",mustUseBadge:"필수",installExternal:"플러그인 설치",tabs:{regular:"플러그인",mustUse:"필수 플러그인"}},mie={titlePlugin:"플러그인 설치",titleTheme:"테마 설치",labelPlugin:"플러그인",labelTheme:"테마",intro:"{{label}} 번들이 들어 있는 ZIP 파일을 드롭하세요 (ZIP 루트에 manifest.json + bundle.js). 해당 {{label}}이(가) Flexweg 사이트에 업로드되고 새로고침 후 등록됩니다. 같은 manifest id의 ZIP을 다시 업로드하면 기존 항목이 그 자리에서 업그레이드됩니다 — 제거할 필요가 없습니다.",zipField:"번들 ZIP 파일",install:"설치",installing:"설치 중…",installSuccess:"{{name}} 설치됨 ({{count}}개 파일 업로드). 새로고침 중…",upgradeSuccess:"{{name}} v{{previousVersion}}에서 v{{newVersion}}(으)로 업그레이드됨 ({{count}}개 파일 업로드). 새로고침 중…",installedTitle:"이미 설치됨",bundledDefaultsTitle:"내장 기본 항목 사용 가능",bundledDefaultsHint:"현재 {{count}}개의 내장 플러그인/테마가 제거된 상태입니다. 복원하면 이 관리자 버전에 함께 배포된 항목을 되살릴 수 있습니다.",bundledDefaultsRestore:"복원",bundledDefaultsRestored:"플러그인 {{plugins}}개, 테마 {{themes}}개가 복원되었습니다. 새로고침 중…",uninstall:"제거",uninstallSuccess:"{{id}} 제거됨. 새로고침 중…",confirmUninstall:"{{id}}을(를) 제거하시겠습니까? 파일이 Flexweg에서 삭제됩니다.",errors:{"no-manifest":"ZIP 루트에 manifest.json이 없습니다.","invalid-manifest":"manifest.json이 유효하지 않습니다 (필수 필드 누락 또는 유효하지 않은 JSON).","incompatible-api":"번들이 호환되지 않는 런타임 API 버전으로 빌드되었습니다.","no-bundle":"ZIP에 manifest에 선언된 진입 파일이 없습니다.","fetch-manifest":"Flexweg에서 현재 external.json을 읽을 수 없습니다.","upload-failed":"업로드 실패 — Flexweg API 키와 연결 상태를 확인하세요."}},gie={someFailed:"{{count}}개의 외부 번들 로드에 실패했습니다. 브라우저 콘솔을 확인하세요."},bie={title:"메뉴",header:"헤더 메뉴",footer:"푸터 메뉴",label:"레이블",saveAndPublish:"저장 및 생성",discard:"변경 취소",saved:"메뉴가 저장되어 게시되었습니다.",saveFailed:"메뉴를 저장할 수 없습니다.",unsavedChanges:"저장되지 않은 변경 사항이 있습니다."},yie={title:"설정",tabs:{general:"일반"},site:{title:"사이트",siteTitle:"사이트 제목",siteDescription:"사이트 설명",siteLanguage:"사이트 언어",siteLanguageHelp:'게시되는 모든 페이지의 <html lang="…">에 삽입되는 BCP-47 태그 (예: en, fr-CA)입니다. 접두사는 지원되는 번역 로케일과 비교되어 사이트맵 / RSS 라벨 및 테마에 포함된 문자열에 사용됩니다. 지원되지 않는 로케일은 영어로 대체됩니다.',siteLanguageResolved:"번역에 사용될 언어: {{label}}",baseUrl:"공개 사이트 URL",postsPerPage:"페이지당 게시물 수",homeMode:"홈 콘텐츠",homeLatest:"최신 게시물",homeStatic:"정적 페이지",homePage:"홈 페이지",discourageIndexing:"검색 엔진이 이 사이트를 색인하지 않도록 요청",discourageIndexingHelp:"활성화하면 게시되는 모든 페이지에 noindex/nofollow 메타 태그가 추가되고 robots.txt가 모든 크롤러를 차단합니다. WordPress의 동작과 같으며 — 스테이징 사이트나 출시 전 검토에 유용합니다. 이 지시를 따르는 검색 엔진은 사이트를 색인하지 않습니다.",discourageRegenerateHint:"색인 설정이 저장되었습니다. 테마에서 '모두 재생성'을 클릭하면 게시된 모든 페이지와 robots.txt에 변경 사항이 적용됩니다."},flexweg:{title:"Flexweg API",apiKey:"API 키",apiKeyHelp:"Flexweg 계정 → API에서 생성됩니다.",siteUrl:"사이트 URL",siteUrlHelp:"끝에 슬래시가 없는 Flexweg 사이트의 공개 URL.",apiBaseUrl:"API 기본 URL",storageHelpFirebase:"Firestore (config/flexweg)에 저장됩니다. 로그인한 팀원 누구나 읽을 수 있고, 관리자만 쓸 수 있습니다.",storageHelpSqlite:"로컬 SQLite의 config 테이블에 저장됩니다. 로그인한 팀원 누구나 읽을 수 있고, 관리자만 쓸 수 있습니다."},backend:{title:"데이터 백엔드",active:"활성 백엔드:",switchButton:"백엔드 전환…",confirmTitle:"현재의 모든 데이터가 사라집니다.",confirmBody:"전환하면 브라우저 내 구성이 지워지고 설정 양식이 다시 로드됩니다. 새 백엔드는 비어 있는 상태로 시작하며 — 이전 백엔드의 데이터는 그대로 남아 있지만 (Firestore 또는 Flexweg의 .sqlite 파일에) 다시 전환할 때까지 CMS가 그 데이터를 읽지 않습니다.",confirmYes:"예, 백엔드를 전환합니다",downloadBackup:".sqlite 파일 백업 다운로드",downloadBackupHelp:"백엔드 전환 전에 수행하세요.",markdownGit:"Markdown — {{source}}",localFolder:"로컬 폴더",localBrowser:"이 브라우저 (로컬, 단일 사용자)",sqliteFile:"SQLite 파일 — {{location}}"},performance:{title:"성능",help:"관리자가 게시물과 페이지를 로드하는 방식입니다. 기본 모드는 무료 Firestore 플랜에서 추가 설정 없이 동작합니다. 페이지네이션 모드는 매우 큰 사이트용이며 한 번의 인덱스 생성이 필요합니다.",mode:"로딩 모드",modeGlobal:"표준 (설정 불필요)",modePaginated:"서버 측 페이지네이션 (Firestore 인덱스 필요)",globalHelp:"전체 게시물 컬렉션을 하나의 실시간 구독으로 로드합니다. 정렬, 필터링, 검색을 메모리에서 수행합니다. 게시물 약 5,000개 미만 사이트에 권장됩니다.",paginatedHelp:"커서 기반 페이지네이션 구독으로 한 번에 한 페이지씩 가져옵니다. Firestore 복합 인덱스가 필요합니다 — README 참조. 매우 큰 사이트에 권장됩니다.",savedReload:"저장되었습니다. 새 모드를 적용하려면 관리자를 다시 로드하세요."},editor:{title:"편집기",help:"게시물 / 페이지 편집기 내부의 타이포그래피. 공개 테마와는 별개입니다.",fontFamily:"글꼴",bodySize:"본문 크기",h1Size:"H1 크기",h2Size:"H2 크기",h3Size:"H3 크기",sizeHelp:"CSS 길이 (예: 16px, 1rem). 비워두면 기본값이 적용됩니다.",reset:"기본값으로 재설정"},profile:{title:"프로필",adminLocale:"관리자 언어",adminLocaleHelp:"관리자 인터페이스에서 사용되는 언어입니다. 프로필에 저장됩니다.",firstName:"이름",lastName:"성",headline:"직함",headlinePlaceholder:"예: 기자, 편집장…",headlineHelp:"이름 아래의 작성자 카드와 아카이브 페이지에 공개적으로 표시됩니다.",bio:"소개",bioPlaceholder:"작성자 페이지와 기사 하단에 표시되는 짧은 단락입니다.",bioHelp:"공개 사이트의 작성자 사이드바와 작성자 아카이브 페이지에 표시됩니다.",socials:"소셜 프로필",socialsHelp:'공개 사이트에 노출할 프로필의 URL을 입력하고, 표시할 항목에 "표시"를 체크하세요. URL이 비어 있으면 무시됩니다.',socialsShow:"표시",socialsShowHelp:"공개 사이트에서 이 네트워크의 표시 여부를 전환합니다.",avatar:"프로필 사진",avatarHelp:"미디어 라이브러리에서 이미지를 선택하세요. 정사각형 이미지가 가장 잘 표시됩니다.",pickAvatar:"미디어에서 선택",changeAvatar:"사진 변경",removeAvatar:"삭제",save:"프로필 저장"},transfer:{title:"콘텐츠 이동 또는 백업",help:"모든 것 (게시물, 페이지, 카테고리, 미디어 메타데이터, 프로필, 설정)을 하나의 JSON 파일로 내보냅니다. Markdown 또는 로컬 백엔드에서는 ID를 유지한 채 이 파일을 가져올 수 있습니다 — Firebase나 SQLite에서 마이그레이션하는 방법입니다. 미디어 파일과 비밀 키는 포함되지 않습니다.",export:"콘텐츠 내보내기 (JSON)",import:"콘텐츠 가져오기…",modeMerge:"병합 (같은 ID 덮어쓰기)",modeReplace:"가져온 컬렉션 교체",replaceConfirm:"교체 모드는 가져오기 전에 파일에 포함된 컬렉션의 기존 항목을 모두 삭제합니다. 계속하시겠습니까?",invalidFile:"이 파일은 Flexweg CMS 콘텐츠 내보내기 파일이 아닙니다.",imported:"게시물/페이지 {{posts}}개, 용어 {{terms}}개, 미디어 {{media}}개를 가져왔습니다. 재생성 → 전체를 실행해 게시하세요."},encryption:{title:"데이터베이스 암호화:",on:"켜짐",off:"꺼짐",onHelp:"암호 문구 없이는 데이터베이스 파일을 읽을 수 없습니다. 변경하면 새 키로 파일을 다시 저장하며, 다른 브라우저에서는 새 암호 문구를 요청합니다.",offHelp:"파일을 내려받을 수 있는 사람은 누구나 데이터베이스를 읽을 수 있습니다(정적 호스팅은 일반 페이지처럼 제공합니다). 암호 문구로 암호화하세요.",enable:"데이터베이스 암호화…",change:"암호 문구 변경…",savedConfirm:"이 암호 문구를 비밀번호 관리자에 저장했습니다. 암호 문구가 없으면 콘텐츠를 열 수 없습니다.",enableConfirm:"지금 암호화",changeConfirm:"암호 문구 변경",done:"새 암호 문구로 데이터베이스를 다시 저장했습니다."}},vie={title:"사용자",noUsers:"아직 사용자가 없습니다.",role:"역할",disabled:"비활성화됨",editProfileTitle:"프로필 편집 — {{email}}",profileSaved:"프로필이 저장되었습니다.",descriptionFirebase:"팀을 관리하세요. 새 계정은 Firebase Console에서 만들어지며, 첫 로그인 시 여기에 동기화됩니다.",descriptionSqlite:"팀을 관리하세요. 아래의 +사용자 추가 버튼으로 계정을 직접 만들 수 있습니다.",addUser:"사용자 추가",addUserSuccess:"{{email}}을(를) 추가했습니다.",removeConfirmFirebase:"{{email}}의 사용자 기록을 삭제하시겠습니까? CMS에서 프로필과 역할이 제거됩니다. 로그인 권한도 회수하려면 Firebase Console에서 계정도 삭제하세요.",removeConfirmSqlite:"{{email}}을(를) 영구적으로 삭제하시겠습니까? 로그인 권한이 회수되고 프로필과 역할도 제거됩니다. 이 작업은 되돌릴 수 없습니다.",empty:{title:"아직 팀원이 없습니다",descriptionFirebase:"Firebase Console에서 첫 계정을 만든 다음, 이곳에 한 번 로그인하여 프로필을 등록하세요.",descriptionSqlite:"위의 +사용자 추가를 눌러 첫 팀원을 초대하세요."},help:{title:"새 팀원을 추가하는 방법",bootstrapLine:"부트스트랩 관리자 (항상 전체 권한)는 다음과 같습니다:",firebase:{step1:"Firebase Console → Authentication → Add user를 여세요.",step2:"이메일과 비밀번호를 설정해 새 팀원에게 전달하세요.",step3:"여기에 한 번 로그인하도록 요청하세요 — 프로필이 위 목록에 나타나며 역할과 세부 정보를 편집할 수 있습니다."},sqlite:{step1:"위의 +사용자 추가 버튼을 누르세요.",step2:"이메일과 임시 비밀번호 (8자 이상)를 입력하세요.",step3:"자격 증명을 안전하게 공유하세요 — 로그인 후 프로필에서 비밀번호를 변경할 수 있습니다."},git:{step1:"해당 사용자를 콘텐츠 저장소의 협업자로 추가하세요 (쓰기 권한 = 편집자, admin / maintainer = 관리자).",step2:"해당 사용자가 GitHub / GitLab에서 자신의 개인 액세스 토큰을 생성합니다.",step3:"관리자 화면을 열고 그 토큰으로 로그인하면 — 프로필이 여기에 자동으로 생성됩니다."}},addUserModal:{title:"새 팀원 추가",intro:"Flexweg SQLite Auth 데이터베이스에 계정을 직접 만듭니다. 새 사용자는 기본적으로 editor 역할을 갖습니다. 관리자 권한이 필요하면 아래 목록에서 승격하세요.",submit:"사용자 만들기",submitting:"만드는 중…"},actions:{editProfile:"프로필 편집",promote:"관리자로 승격",demote:"편집자로 강등",disable:"비활성화",enable:"활성화",delete:"기록 삭제"},descriptionGit:"팀원은 콘텐츠 저장소에 쓰기 권한이 있는 사람들입니다. 처음 로그인한 후 여기에 표시되며, 역할은 저장소 권한을 따릅니다.",descriptionLocal:"이 관리자는 단일 사용자 모드로 실행됩니다: 콘텐츠는 이 브라우저에 저장되며 계정이 없습니다.",descriptionSqliteFile:"이 백엔드에는 사용자 계정이 없습니다: 관리자를 열 수 있는 사람은 누구나 편집할 수 있습니다. 호스팅 수준에서 관리자 폴더를 보호하세요. 아래 작성자 프로필은 참고용입니다."},xie={title:"Firestore 설정 필요",intro:"게시물 및 페이지 목록 페이지는 효율적인 쿼리를 위해 몇 개의 Firestore 복합 인덱스가 필요합니다. 수동으로 생성해야 합니다 — Firebase는 인덱스 생성을 프로젝트 관리자에게만 허용합니다.",checking:"Firestore 인덱스 확인 중…",missingCount_one:"{{count}}개의 인덱스가 누락되었습니다:",missingCount_other:"{{count}}개의 인덱스가 누락되었습니다:",openConsole:"생성하려면 Firebase Console 열기",noUrl:"자동 제안 URL을 추출할 수 없습니다 — gcloud 명령은 README를 참조하세요.",howItWorks:"작동 방식",step1:"각 누락된 인덱스의 링크를 클릭하세요 — Firebase Console이 정의가 미리 채워진 상태로 열립니다.",step2:"'Create'를 클릭하고 인덱스가 빌드될 때까지 1~5분 기다리세요 (콘솔에서 상태 확인).",step3:"여기로 돌아와 재시도를 클릭하세요. 두 쿼리가 모두 성공하면 관리자가 로드됩니다.",retry:"재시도",retrying:"재시도 중…",buildHint:"인덱스 생성 후 빌드까지 몇 분이 걸릴 수 있습니다.",allReady:"모든 인덱스가 준비되었습니다.",unexpectedTitle:"Firestore에 도달할 수 없음",unexpectedHint:"네트워크 연결과 Firestore 규칙을 확인하세요. 인덱스를 방금 생성했다면 빌드가 끝날 때까지 기다린 후 재시도하세요."},wie={appError:"애플리케이션 오류",loadAccountFailed:"계정을 불러올 수 없습니다",loadAccountHint:"문제가 지속되면 로그아웃한 뒤 다시 시도하세요.",accountDisabled:"계정 비활성화됨",accountDisabledMessage:"이 CMS에 대한 접근 권한이 비활성화되었습니다. 관리자에게 문의하세요.",firebaseNotConfigured:"Firebase가 설정되지 않았습니다",firebaseEnvMissing:`다음 환경 변수가 누락되었습니다:
|
|
3865
|
+
Copie .env.example para .env, preencha as credenciais do seu projeto Firebase e reinicie o servidor de desenvolvimento.`,adminEmailNotConfigured:"E-mail do admin não configurado",adminEmailMessage:"VITE_ADMIN_EMAIL está em falta no .env. Defina-o com o e-mail do administrador inicial.",consoleHint:"Verifique a consola do browser e a sua configuração .env. Consulte o README para instruções de configuração."},Jse={brandTitle:"AgentCMS",brandSubtitle:"Publicador estático",login:{heading:"Iniciar sessão",intro:"Use o e-mail e a palavra-passe que o seu administrador lhe forneceu.",submit:"Iniciar sessão",submitting:"A iniciar sessão…"},fields:{name:"Nome a apresentar (opcional)",namePlaceholder:"Maria Silva",email:"E-mail",password:"Palavra-passe",passwordHint:"Pelo menos 8 caracteres."},footer:"As novas contas são criadas por um administrador a partir da página Utilizadores.",errors:{invalidEmail:"Introduza um endereço de e-mail válido.",missingPassword:"A palavra-passe é obrigatória.",passwordTooShort:"A palavra-passe deve ter pelo menos 8 caracteres."}},Qse=JSON.parse('{"title":"Bem-vindo ao AgentCMS","subtitle":"Configuração inicial","intro":"Insira as suas credenciais Firebase, a conta de administrador inicial e a sua chave API Flexweg. Os valores são validados, guardados no seu projeto (Firestore + um ficheiro config.js no Flexweg) e o admin recarrega no fluxo de início de sessão normal. Só faz isto uma vez.","introFirebase":"Passo 1 — Firebase. Preencha as credenciais do seu projeto Firebase e a conta de administrador bootstrap. Iniciamos sessão, verificamos o e-mail e confirmamos que as suas regras Firestore reconhecem este admin antes de avançarmos para o passo Flexweg.","introFlexweg":"Passo 2 — Flexweg. Preencha a sua chave API Flexweg e o URL do site. Testamos a API, guardamos a configuração no Firestore, fazemos upload do config.js para o seu site e sincronizamos os ativos do tema.","continueToFlexweg":"Validar Firebase e continuar","stepper":{"terms":"Condições","backend":"Backend","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"Conteúdo e publicação","data":"Dados","hosting":"Alojamento","install":"Instalação"},"backend":{"title":"Escolha um backend de dados","intro":"Escolha onde o CMS irá guardar os seus artigos, páginas, utilizadores e definições. Pode trocar depois nas Definições (os dados não são migrados).","sqliteTitle":"Flexweg SQLite (recomendado)","sqliteHint":"Todos os dados ficam no seu site Flexweg como um ficheiro SQLite. Sem serviço externo. A auth é fornecida pela API SQLite do Flexweg.","firebaseTitle":"Firebase","firebaseHint":"Use um projeto Firebase para Firestore + Auth. Gratuito no plano Spark. Atualizações em tempo real via onSnapshot.","continue":"Continuar","markdownGitTitle":"Ficheiros Markdown num repositório Git","markdownGitHint":"Posts como ficheiros .md no GitHub / GitLab (ou num clone local). Cada editor inicia sessão com o seu próprio token de acesso; cada alteração é um commit. Sem base de dados, funciona com vários editores e computadores.","localTitle":"Apenas este browser","localHint":"Um só utilizador, sem início de sessão, nada para configurar. O conteúdo fica neste browser (exporte-o a partir das Definições). Ideal para um admin a correr no seu próprio computador."},"sqlite":{"heading":"Conectar o seu site Flexweg","intro":"Vamos usar a sua chave API mestre Flexweg UMA VEZ para criar um token de âmbito limitado para a base de dados SQLite. Após a instalação, a chave mestre é descartada e apenas o token limitado (restrito a este ficheiro SQLite) é guardado.","apiKeyHint":"Chave API mestre Flexweg. Usada apenas para instalar — nunca guardada depois.","detectedFromUrl":"Detetado do URL","advanced":"Definições avançadas (URL do site, caminho SQLite…)","pathHint":"Onde fica o ficheiro SQLite no seu site Flexweg. As pastas são criadas automaticamente.","adminHeading":"Conta de administrador","adminIntro":"Crie o primeiro utilizador — esta conta obtém direitos de admin automaticamente. Os membros seguintes são integrados a partir da página Utilizadores depois de ter sessão iniciada.","passwordHint":"Pelo menos 8 caracteres.","submit":"Instalar base de dados SQLite"},"terms":{"title":"Condições de utilização","intro":"Leia e aceite as condições abaixo antes de utilizar o AgentCMS. Estão escritas em linguagem clara para serem rápidas de ler.","section1":{"title":"1. Serviço gratuito","body":"O AgentCMS é disponibilizado gratuitamente pelo Flexweg. Pode utilizá-lo sem limites com o seu alojamento Flexweg — o Flexweg nunca lhe vai cobrar pelo uso do CMS em si. As tarifas habituais do seu plano de alojamento Flexweg e do seu plano Firebase mantêm-se aplicáveis, cada uma na conta correspondente."},"section2":{"title":"2. Fornecido «tal como está», sem garantia","body":"O CMS é fornecido tal como está. Trabalhamos para o manter estável e melhorá-lo ao longo do tempo, mas não podemos garantir que esteja livre de bugs, defeitos ou interrupções. Utilize-o com a mesma cautela que teria com qualquer ferramenta que não tenha escrito por si: mantenha cópias de segurança dos conteúdos importantes."},"section3":{"title":"3. Os seus conteúdos, a sua responsabilidade","body":"É o único responsável pelos conteúdos que publica através do CMS — textos, imagens, vídeos, formulários, integrações de código e quaisquer outros media. Deve cumprir a lei aplicável na sua jurisdição (e nas que visa), os direitos de autor, os direitos de imagem e de personalidade, as regras de proteção de dados pessoais e as condições de quaisquer serviços de terceiros que utilize (fontes incorporadas, vídeos, etc.). O Flexweg não é responsável pelos conteúdos publicados pelos utilizadores do CMS."},"section4":{"title":"4. A sua conta Firebase, a sua segurança","body":"O CMS guarda os seus dados no seu próprio projeto Firebase. É responsável pela segurança desse projeto: escolha uma palavra-passe forte para a conta de administrador inicial, configure as regras de segurança do Firestore como documentado, faça rotação das suas chaves API quando necessário e verifique quem tem acesso. O Flexweg não pode em caso algum ser responsabilizado por acessos não autorizados, fugas de dados, ataques informáticos ou perdas resultantes de uma má configuração ou comprometimento da sua conta Firebase."},"section5":{"title":"5. Limitação de responsabilidade","body":"O Flexweg não pode ser responsabilizado por qualquer perda de receitas, perda de dados, perda de oportunidade comercial, ou por quaisquer danos diretos ou indiretos decorrentes do uso, mau uso ou indisponibilidade do CMS. Quando a lei aplicável obrigar o Flexweg a assumir alguma responsabilidade, esta limita-se ao montante efetivamente pago ao Flexweg pelo CMS nos últimos 12 meses — ou seja, zero, uma vez que o CMS é gratuito."},"section6":{"title":"6. Os seus dados continuam seus","body":"Os conteúdos que cria com o CMS são guardados no seu próprio projeto Firebase (textos, definições, metadados dos media) e no seu próprio alojamento Flexweg (HTML publicado, imagens, assets de tema). O CMS em si não transmite os seus conteúdos a nenhum serviço de terceiros. Os plugins ou temas que escolher ativar podem ter o seu próprio comportamento — verifique o que fazem antes de os ativar."},"section7":{"title":"7. Bom uso","body":"A utilização do CMS para atividades ilegais, fraudulentas ou nocivas, ou de forma contrária às condições gerais de utilização do Flexweg, pode levar à suspensão do acesso ao alojamento Flexweg. Podemos também atualizar estas condições do CMS ao longo do tempo; as alterações significativas serão comunicadas através do admin ou por e-mail."},"accept":"Li e aceito as Condições de utilização.","continue":"Continuar para a configuração","back":"Voltar"},"sections":{"firebase":"Firebase","admin":"Administrador inicial","flexweg":"API Flexweg"},"help":{"firebase":"Encontre estes valores em Firebase Console → Definições do projeto → Geral → As suas apps → Configuração do SDK.","admin":"Use um utilizador existente em Firebase Authentication. Quem inicie sessão com este e-mail é tratado como administrador e ignora a verificação de registo de utilizador. Crie o utilizador em Firebase Console → Authentication se ainda não existir.","flexweg":"Gere uma chave API permanente na sua conta Flexweg → API. O URL do site é o endereço público do seu site Flexweg (ex. https://o-seu-site.flexweg.com).","flexwegApiKeyHint":"Obtenha a sua chave API nas definições da sua conta Flexweg.","flexwegApiKeyLink":"Abrir definições da conta"},"fields":{"apiKey":"Chave API","authDomain":"Domínio de autenticação","projectId":"ID do projeto","storageBucket":"Bucket de armazenamento","messagingSenderId":"ID de remetente de mensagens","appId":"ID da app","adminEmail":"E-mail","adminPassword":"Palavra-passe","flexwegApiKey":"Chave API","flexwegSiteUrl":"URL do site","flexwegApiBaseUrl":"URL base da API","sqlitePath":"Caminho SQLite"},"submit":"Guardar e continuar","submitting":"A configurar…","success":"Configuração concluída!","reloadingHint":"O admin vai recarregar daqui a um instante — aguarde.","footer":"Estes valores são guardados no seu projeto (Firestore + Flexweg). Não são enviados para mais lado nenhum.","steps":{"signInFirebase":"A iniciar sessão no Firebase…","testFlexweg":"A testar a API Flexweg…","writeFirestore":"A guardar a configuração…","uploadConfig":"A carregar config.js para o Flexweg…","syncThemes":"A sincronizar assets do tema para o Flexweg…","sqliteInstall":"A criar token SQLite com âmbito limitado…","sqliteRegisterAdmin":"A registar a conta de admin…","sqliteSchema":"A inicializar o esquema SQLite…"},"stepsDone":{"sqliteInstall":"Token SQLite com âmbito limitado emitido","sqliteRegisterAdmin":"Admin registado e com sessão iniciada","sqliteSchema":"Esquema SQLite pronto"},"errors":{"missingFields":"Por favor, preencha todos os campos.","rootDeploymentTitle":"O admin deve estar numa subpasta, não na raiz do site.","rootDeploymentHint":"Mova os ficheiros do admin (index.html, config.js, runtime/, …) para uma subpasta no Flexweg — por exemplo /admin/ ou um nome aleatório como /erf34f654GH3/ por discrição. Em seguida recarregue o admin a partir do URL da subpasta e volte a executar a configuração.","firebaseAuthGeneric":"Não foi possível iniciar sessão no Firebase.","firebaseAuthInvalidCredential":"O Firebase rejeitou a combinação de e-mail e palavra-passe.","firebaseAuthInvalidCredentialHint":"Os projetos Firebase recentes ativam por defeito a proteção contra enumeração de e-mails, que devolve o mesmo erro quer a palavra-passe esteja errada, o utilizador não exista, ou o utilizador inicie sessão com outro fornecedor. A verificar:\\n• Reintroduza a palavra-passe — copie/cole de um gestor de palavras-passe para eliminar erros de digitação. O mínimo são 6 caracteres.\\n• Abra Firebase Console → Authentication → Users e confirme que o e-mail existe. Verifique a coluna «Providers»: se mostrar apenas Google (ou outro fornecedor) sem «Email/Password», defina ou redefina a palavra-passe pelo menu da linha (⋮ → Repor palavra-passe).\\n• Confirme que a ortografia do e-mail corresponde exatamente ao que está guardado no Firebase.","firebaseAuthUserNotFound":"Não existe utilizador Firebase com este e-mail. Crie um primeiro em Firebase Console → Authentication → Users.","firebaseAuthInvalidEmail":"O e-mail do administrador não é um endereço válido.","firebaseInvalidApiKey":"A chave API do Firebase é inválida. Verifique o valor na Firebase Console.","firebaseNetwork":"Erro de rede ao iniciar sessão no Firebase. Verifique a sua ligação.","firebaseTooManyRequests":"Demasiadas tentativas de início de sessão. Tente novamente mais tarde ou redefina a palavra-passe via Firebase Console.","firebaseOperationNotAllowed":"O início de sessão por e-mail/palavra-passe não está ativado neste projeto Firebase. Abra Firebase Console → Authentication → Sign-in method e ative o fornecedor Email/Password.","firebaseUserDisabled":"Esta conta de utilizador Firebase está desativada. Reative-a em Firebase Console → Authentication → Users.","wrongAdminEmail":"A conta Firebase com que iniciou sessão não corresponde ao e-mail de admin que escreveu. Tente novamente.","rulesNotPinnedTitle":"As regras do Firestore ainda não o reconhecem como admin bootstrap.","rulesNotPinnedHint":"Abra Firebase Console → Firestore → Rules e substitua o valor de `bootstrapAdminEmail()` por: {{email}} — depois clique em Publicar. O modelo de regras do README inclui um placeholder `you@example.com` que tem de ser substituído pelo seu e-mail de admin real. Depois de publicar as novas regras, clique novamente em Enviar aqui.","flexwegAuth":"Chave API Flexweg rejeitada. Verifique o valor na sua conta Flexweg → API.","flexwegNetwork":"Erro de rede ao contactar o Flexweg. Verifique o URL base da API e a sua ligação.","flexwegHttp":"Erro da API Flexweg ({{status}}): {{detail}}","firestoreRulesTitle":"O Firestore rejeitou a escrita da configuração.","firestoreRulesHint":"Abra Firebase Console → Firestore → Regras e confirme que o e-mail de admin de bootstrap está definido como \'{{email}}\'. O README inclui um modelo de regras pronto a copiar.","firestoreOther":"Falha ao escrever no Firestore","uploadFailed":"Não foi possível carregar config.js para o Flexweg","generic":"Algo correu mal."},"docstore":{"contentTitle":"Repositório de conteúdo","contentIntro":"Onde os seus posts, páginas e definições são guardados como ficheiros Markdown + JSON. Um repositório vazio serve — o CMS cria os ficheiros.","provider":"Repositório","localClone":"Pasta local (clone git)","localCloneHint":"Escolha a pasta do seu clone. Sincronize-a com o seu cliente git habitual — o CMS lê e escreve ficheiros, não executa git.","contentDir":"Pasta de conteúdo no repositório","privateRepo":"Utilize um repositório privado: os rascunhos são guardados lá.","folderRequired":"Escolha primeiro a pasta de conteúdo.","checking":"A verificar o acesso ao repositório…","publishIntro":"Onde o site gerado é publicado. Pode alterá-lo mais tarde nas Definições.","existingSite":"Este repositório já está configurado — o site continua a ser publicado em: {{target}}. Pode alterá-lo mais tarde nas Definições (as chaves secretas, se existirem, têm de ser introduzidas novamente lá).","install":"Instalar","steps":{"config":"A guardar a configuração…","content":"A carregar o conteúdo…","target":"A guardar o destino de publicação…","testTarget":"A testar o destino de publicação…"},"doneTitle":"Tudo pronto!","doneBody":"A configuração foi guardada neste browser. Para poupar este passo a outros editores, descarregue o config.js e substitua o que está na pasta admin do seu alojamento.","downloadConfig":"Descarregar config.js","open":"Abrir o admin","footer":"O conteúdo fica no seu repositório ou neste browser; os tokens de acesso nunca saem deste browser."},"data":{"title":"1. Onde guarda os seus dados?","intro":"Os seus posts, páginas, utilizadores e definições — os dados próprios do admin. Isto é independente de onde o site público está alojado (próximo passo).","localNote":"Nada a configurar: o conteúdo é guardado neste browser. Exporte-o nas Definições para fazer uma cópia de segurança ou movê-lo mais tarde.","options":{"sqlite-file":{"title":"SQLite","hint":"Uma base de dados SQLite guardada no alojamento que escolher no passo seguinte (Flexweg, o seu servidor, S3, Git…). Sem contas de utilizador — ou o serviço SQLite da Flexweg, com contas, se alojar na Flexweg."},"flexweg-sqlite":{"title":"SQLite (serviço Flexweg)","hint":"Uma base de dados SQLite gerida pelo serviço da Flexweg, com contas de utilizador integradas. Requer uma conta Flexweg, seja qual for o alojamento do site."},"firebase":{"title":"Firebase","hint":"Firestore + Firebase Auth no seu projeto Google. Tempo real, plano Spark gratuito."},"markdown-git":{"title":"Ficheiros Markdown em Git","hint":"Posts como ficheiros .md num repositório GitHub / GitLab (ou num clone local). Cada editor utiliza o seu próprio token; cada alteração é um commit."},"local":{"title":"Este browser","hint":"Um único utilizador, sem início de sessão, nada a configurar. Ideal para um admin a correr no seu computador."}}},"hosting":{"title":"2. Onde é publicado o site?","intro":"Para onde o site estático gerado (HTML, CSS, imagens) é carregado sempre que publica. Pode alterá-lo mais tarde nas Definições.","existing":"Este repositório de conteúdo já publica no destino abaixo. Mantenha-o ou escolha outro."},"install":{"title":"3. Instalação","intro":"Verifique o resumo e depois instale.","data":"Dados","hosting":"Alojamento","saveTarget":"A guardar o destino de publicação…","noteConfigJs":"A configuração do admin (config.js) é carregada junto ao admin no Flexweg quando possível; caso contrário, ser-lhe-á proposto descarregá-la.","noteLocalConfig":"A configuração é guardada neste browser; ser-lhe-á proposto o config.js para colocar na pasta do admin, para que outros editores saltem esta configuração."},"sqliteFile":{"security":"Sem contas de utilizador: quem conseguir abrir este admin pode editar o conteúdo — proteja a pasta do admin no seu alojamento. O ficheiro da base de dados é servido como qualquer outro ficheiro: mantenha-o cifrado ou guarde-o num local privado separado.","intro":"Onde o ficheiro de base de dados é guardado. Este admin lê-o e guarda-o através dos mesmos conectores que o alojamento.","path":"Caminho do ficheiro de base de dados","pathHint":"É criado no primeiro guardar, se ainda não existir. Com um repositório Git, cada gravação é um commit — prefira um repositório ou ramo que não desencadeie um build do site.","existing":"base de dados existente","new":"nova base de dados","dataNote":"Nada a configurar aqui: a base de dados será guardada no alojamento que escolher no passo seguinte.","heading":"Base de dados SQLite","flexwegService":"Utilizar o serviço SQLite da Flexweg","flexwegServiceHint":"A base de dados é gerida pela Flexweg e inclui contas de utilizador integradas (e-mail + palavra-passe). Caso contrário, é um simples ficheiro neste alojamento, sem contas.","summaryFile":"Ficheiro {{path}} neste alojamento","summaryService":"Serviço SQLite da Flexweg ({{path}})","encrypt":"Cifrar a base de dados","encryptHint":"Recomendado num alojamento público: o ficheiro fica ilegível sem a frase-passe. Cada novo navegador pede-a uma vez.","passphrase":"Frase-passe","passphraseHint":"Guarde-a já no seu gestor de palavras-passe: sem ela ninguém consegue abrir a base de dados, nem mesmo você.","copy":"Copiar","copied":"Copiada","generate":"Nova","passphraseTooShort":"A frase-passe deve ter pelo menos 12 caracteres.","existingEncrypted":"Já existe uma base de dados cifrada neste caminho: introduza a respetiva frase-passe.","separate":"Guardar a base de dados num local privado separado","separateHint":"Por ex. um bucket S3 / R2 privado ou um repositório Git privado: a base de dados nunca é servida pelo site público.","summaryEncrypted":"cifrada","summaryLocation":"guardada em {{location}}","locationLabel":"Local da base de dados","gitBranchNote":"A base de dados fica no ramo {{branch}} deste repositório, que nunca é publicado: guardar conteúdo não volta a gerar o site.","summaryBranch":"no ramo {{branch}}"},"adminHosting":{"deploying":"A copiar o admin para o site…","label":"Alojar também o admin neste site","hint":"O admin é copiado para {{url}} com o seu config.js (sem segredos) — cada editor pode então abri-lo aí. Cada editor continua a iniciar sessão com o seu próprio acesso.","folder":"Pasta do admin","alreadyHere":"Este admin já está a correr a partir deste site: o seu config.js será atualizado no local.","doneBody":"O admin está agora no seu site. No GitHub Pages, ative primeiro o Pages para o repositório se ainda não o fez (Settings → Pages) e depois abra-o:","open":"Abrir o admin online","continueHere":"Continuar neste admin"}}'),Xse={actions:{upload:"A carregar ficheiro",delete:"A eliminar ficheiro",rename:"A renomear ficheiro",get:"A ler ficheiro",list:"A listar ficheiros",createFolder:"A criar pasta",renameFolder:"A renomear pasta",deleteFolder:"A eliminar pasta",storageLimits:"A obter limites de armazenamento",commit:"A publicar alterações"},errors:{configMissing:"O destino de publicação não está configurado. Configure-o nas Definições antes de publicar.",network:"{{action}}: erro de rede ou CORS bloqueado. Verifique a sua ligação.",auth:"{{action}}: falha na autenticação. Verifique as credenciais do destino de publicação nas Definições.",notFound:"{{action}}: não encontrado no destino de publicação.",tooLarge:"{{action}}: ficheiro demasiado grande para o destino de publicação.",rateLimited:"{{action}}: demasiados pedidos, tente novamente daqui a um momento.",serverError:"{{action}}: erro do servidor do destino de publicação ({{status}}). Tente novamente.",generic:"{{action}} falhou ({{status}}){{detail}}.",unsupported:"{{action}}: não suportado pelo destino de publicação «{{connector}}».",unknownConnector:"Destino de publicação desconhecido «{{connector}}». Verifique Definições → Destino de publicação.",folderAccess:"Sem acesso à pasta local. Abra Definições → Destino de publicação e clique em «Religar pasta»."}},Zse={log:{rendering:"A renderizar página…",uploading:"A carregar {{path}}…",deleting:"A eliminar {{path}}…",regenerating:"A regenerar listagens…",skipped:"{{path}} ignorado (sem alterações)",done:"Publicado em {{url}}",failed:"Falhou: {{error}}"}},Yse={errors:{notConnected:"Sem ligação ao repositório de conteúdo. Volte a iniciar sessão com o seu token de acesso.",conflict:"Outra pessoa alterou este item entretanto. A versão dela é agora apresentada — volte a aplicar a sua alteração.",sqliteUnsupported:"O destino «{{connector}}» não consegue guardar um ficheiro de base de dados."}},eie={target:"Destino de publicação",settingsTitle:"Destino de publicação",settingsHelp:"Onde o site renderizado é enviado ao publicar. As credenciais são guardadas com o seu backend de conteúdo (ou neste browser para repositórios Git de conteúdo) e podem ser lidas por todos os admins.",saved:"Destino de publicação guardado. Execute Regenerar → Tudo para publicar o site completo no novo destino.",test:"Testar a ligação",testOk:"Ligação OK",testFailed:"Falha na ligação",names:{flexweg:"Flexweg","git-pages":"Repositório Git (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"Bucket compatível com S3 (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"O seu próprio servidor (bridge PHP)","browser-mirror":"Descarregar como ZIP","local-folder":"Pasta local neste computador"},hints:{flexweg:"Envio através da API Files do Flexweg.","git-pages":"Cada publicação é um commit no repositório; o alojamento reconstrói o site a partir dele.",s3:"Requer uma regra CORS no bucket que permita a origem deste admin, e alojamento de site (ou uma CDN) para servir os ficheiros index.html.","php-bridge":"Envie external/bridges/php/flexweg-bridge.php para o seu servidor, defina a respetiva chave de API e depois preencha o URL aqui.","browser-mirror":"O site é guardado neste browser; descarregue o ZIP e envie-o manualmente para onde quiser.","local-folder":"Escreve o site diretamente numa pasta (Chrome / Edge). Sirva-o localmente ou envie-o com as suas próprias ferramentas."},fields:{flexweg:{apiKey:"Chave de API",siteUrl:"URL do site",apiBaseUrl:"URL base da API"},"git-pages":{host:"Alojamento",provider:"Fornecedor Git",owner:"Proprietário (utilizador ou organização)",repo:"Repositório",project:"Caminho do projeto",branch:"Ramo",dir:"Pasta no repositório",token:"Token de acesso",siteUrl:"URL pública do site",apiBaseUrl:"URL da API (apenas auto-alojado)"},s3:{endpoint:"Endpoint",region:"Região",bucket:"Bucket",prefix:"Prefixo das chaves (opcional)",accessKeyId:"ID da chave de acesso",secretAccessKey:"Chave de acesso secreta",siteUrl:"URL pública do site",forcePathStyle:"URLs do tipo caminho (MinIO, R2, a maioria dos compatíveis)",publicRead:"Tornar públicos os ficheiros carregados (ACL public-read) — para buckets que não são públicos através de uma política (OVHcloud, Scaleway…). Deixe desativado em buckets AWS com «bucket owner enforced»."},"php-bridge":{apiBaseUrl:"URL do bridge",apiKey:"Chave de API do bridge",siteUrl:"URL pública do site"},"browser-mirror":{siteUrl:"URL pública do site (opcional)"},"local-folder":{siteUrl:"URL onde a pasta é servida (opcional)"}},help:{flexweg:{apiKey:"Gerada a partir da sua conta Flexweg → API."},"git-pages":{host:"Cloudflare Pages: ligue o projeto a este repositório sem comando de build e com a pasta de saída abaixo. Funciona com repositórios privados.",dir:'Deixe vazio para a raiz do repositório. GitHub Pages: "" ou "docs". GitLab Pages: "public".',token:"Token fine-grained neste repositório com Contents: read & write (GitHub) — adicione Pages: read & write para permitir que o CMS ative o GitHub Pages — ou um token com o scope api (GitLab). Deixe vazio para usar o token de acesso de cada editor quando o conteúdo está no mesmo fornecedor.",siteUrl:"p. ex. https://user.github.io/repo — um URL com subpasta funciona, as ligações são ajustadas automaticamente."},s3:{endpoint:"Deixe vazio para AWS (deduzido da região). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"O URL de alojamento do bucket ou o seu domínio CDN."},"php-bridge":{apiBaseUrl:"O URL completo de flexweg-bridge.php no seu servidor (HTTPS)."},"browser-mirror":{siteUrl:"Onde vai enviar o ZIP — usado para os URLs absolutos (sitemaps, RSS, multimédia)."},"local-folder":{siteUrl:"p. ex. http://localhost:8080 quando um servidor web local serve a pasta."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (ligado ao repositório)","gitlab-pages":"GitLab Pages",other:"Outro (Netlify, Vercel, git pull no servidor…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"Escolher pasta…",change:"Mudar de pasta…",reconnect:"Voltar a ligar a pasta",unsupported:"Este browser não consegue escrever em pastas locais. Utilize o Chrome ou o Edge."},mirror:{download:"Descarregar o site (ZIP)",count:"{{count}} ficheiros neste browser"},adminHosting:{title:"Admin neste site",help:"Copie este admin para o destino de publicação (primeira implementação, ou atualização após uma nova versão). O seu config.js não contém segredos.",deploy:"Implementar / atualizar o admin",deployed:"Admin implementado ({{count}} ficheiros) — {{url}}"},pages:{enabled:"GitHub Pages ativado para este repositório — o site estará online dentro de cerca de um minuto.",enableHint:'Publicação concluída. Para colocar o site online, ative o GitHub Pages para {{repo}}: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (Ou dê ao token a permissão "Pages: read and write" e o CMS faz isso por si.)'},siteUrl:{mismatch:"O URL público do site (Definições → Site) é {{site}}, mas este destino serve o site em {{target}}. As ligações, o CSS e os sitemaps seguem o URL do site — estarão errados neste alojamento.",use:"Usar {{url}} para o site",updated:"URL do site atualizado. Execute Regenerar → Tudo para voltar a publicar as páginas com as novas ligações."}},tie={heading:"Ligar ao repositório de conteúdo",tokenIntro:"O conteúdo está guardado no repositório {{provider}} {{repo}}. Inicie sessão com o seu próprio token de acesso pessoal — as suas permissões no repositório determinam a sua função (escrita = editor, admin / maintainer = admin).",token:"Token de acesso pessoal",tokenHelpGithub:"Token fine-grained, com acesso apenas a este repositório, permissão Contents: leitura e escrita.",tokenHelpGitlab:"Token com o api scope, função Developer ou superior neste projeto.",createToken:"Criar um token",connect:"Ligar",tokenStorage:"O token é guardado apenas neste browser. Terminar sessão apaga-o.",failed:"Este token não consegue escrever no repositório (inválido, expirado ou só de leitura). Verifique as permissões.",folderIntro:"O conteúdo está guardado numa pasta deste computador (normalmente um clone git que sincroniza com o seu próprio cliente git). Conceda acesso a este browser — os browsers voltam a pedir após cada recarregamento.",openFolder:"Abrir a pasta de conteúdo"},nie={flexweg:{title:"Flexweg",short:"Alojamento Flexweg",hint:"Carrega através da Flexweg Files API. Chave API da sua conta Flexweg."},"github-pages":{title:"GitHub Pages",short:"Gratuito, a partir de um repositório GitHub",hint:"Cada publicação é um commit no repositório; o GitHub Pages serve-o. Settings → Pages → Deploy from a branch. Repositórios públicos no plano gratuito."},"cloudflare-pages":{title:"Cloudflare Pages",short:"Gratuito, repositórios privados OK",hint:"O CMS faz commit do site num repositório GitHub / GitLab; ligue-lhe um projeto Cloudflare Pages (sem comando de build, pasta de saída = a pasta abaixo)."},"gitlab-pages":{title:"GitLab Pages",short:"Gratuito, a partir de um repositório GitLab",hint:"Cada publicação é um commit; o CMS adiciona um .gitlab-ci.yml mínimo que publica a pasta public/."},"git-other":{title:"Netlify, Vercel…",short:"Qualquer alojamento que implemente um repositório",hint:"O CMS faz commit do site num repositório Git; ligue o seu alojamento (Netlify, Vercel, um servidor que executa git pull…) a esse repositório."},s3:{title:"S3 / R2 / B2…",short:"Bucket de armazenamento de objetos",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… Requer uma regra CORS no bucket e alojamento de sites ou um CDN à frente."},"own-server":{title:"O seu próprio servidor (FTP / SFTP)",short:"Alojamento partilhado, VPS…",hint:"Os browsers não falam FTP nem SFTP: carregue uma vez a ponte PHP (external/bridges/php/flexweg-bridge.php) com o seu cliente FTP, defina a respetiva chave API e depois indique aqui o seu URL. Funciona em qualquer alojamento PHP."},"local-folder":{title:"Pasta local",short:"Neste computador",hint:"Escreve o site numa pasta deste computador (Chrome / Edge). Sirva-o localmente ou envie-o com as suas próprias ferramentas."},zip:{title:"Descarregar como ZIP",short:"Carregue-o manualmente",hint:"O site é guardado neste browser; descarregue um ZIP nas Definições e carregue-o onde quiser (Netlify Drop, cliente FTP…)."}},rie={heading:"Ligar à base de dados",intro:"Este admin guarda o seu conteúdo em {{path}}. Introduza as credenciais de acesso para este browser.",storage:"As credenciais são guardadas apenas neste browser. Terminar sessão apaga-as.",passphrase:"Frase-passe da base de dados",passphraseHint:"A base de dados está cifrada. Introduza a frase-passe escolhida na instalação (guardada apenas neste navegador).",passphraseWrong:"Frase-passe incorreta: não foi possível abrir a base de dados.",passphraseMissing:"Introduza a frase-passe da base de dados."},sie={common:Rse,auth:jse,nav:Mse,dashboard:Lse,posts:Dse,pages:Fse,taxonomies:Ose,media:zse,themes:Use,plugins:Bse,externalInstall:$se,externalLoader:Hse,menus:Vse,settings:qse,users:Wse,firestoreSetup:Gse,errors:Kse,identity:Jse,setup:Qse,flexweg:Xse,publish:Zse,docstore:Yse,connectors:eie,gitAccess:tie,hosting:nie,sqliteAccess:rie},iie={save:"저장",saving:"저장 중…",saved:"저장됨",cancel:"취소",delete:"삭제",deleting:"삭제 중…",edit:"편집",create:"만들기",search:"검색",loading:"불러오는 중…",yes:"예",no:"아니요",confirm:"확인",back:"뒤로",next:"다음",previous:"이전",close:"닫기",all:"전체",none:"없음",actions:"작업",name:"이름",slug:"슬러그",description:"설명",status:"상태",createdAt:"생성됨",updatedAt:"업데이트됨",publishedAt:"게시됨",language:"언어",darkMode:"다크 모드",lightMode:"라이트 모드",signOut:"로그아웃",administrator:"관리자",editor:"편집자",appName:"AgentCMS"},aie={signIn:"로그인",signingIn:"로그인 중…",email:"이메일",password:"비밀번호",emailPlaceholder:"you@company.com",passwordPlaceholder:"••••••••",forgotPassword:"비밀번호를 잊으셨나요?",resetEmailSent:"{{email}} 주소로 비밀번호 재설정 이메일을 보냈습니다.",enterEmailFirst:"위에 이메일을 먼저 입력한 다음 재설정을 클릭하세요.",emailPasswordRequired:"이메일과 비밀번호를 모두 입력해 주세요.",signInSubtitle:"업무용 이메일과 비밀번호를 사용하세요.",footer:"계정 요청은 관리자를 통해 처리됩니다.",errors:{invalidEmail:"유효하지 않은 이메일 주소입니다.",invalidCredentials:"이메일 또는 비밀번호가 올바르지 않습니다.",tooManyRequests:"시도 횟수가 너무 많습니다. 나중에 다시 시도하거나 비밀번호를 재설정하세요.",userDisabled:"이 계정은 비활성화되었습니다.",networkFailed:"네트워크 오류입니다. 연결 상태를 확인하세요.",generic:"인증에 실패했습니다."}},oie={openMenu:"메뉴 열기",closeMenu:"메뉴 닫기",dashboard:"대시보드",posts:"게시물",pages:"페이지",taxonomies:"카테고리 및 태그",media:"미디어",themes:"테마",themeSettings:"테마 설정",plugins:"플러그인",menus:"메뉴",users:"사용자",settings:"설정"},lie={title:"대시보드",welcome:"{{email}}님, 다시 오신 것을 환영합니다.",stats:{totalPosts:"게시물",totalPages:"페이지",online:"온라인",drafts:"초안"}},cie={title:"게시물",newPost:"새 게시물",noPosts:"아직 게시물이 없습니다. 첫 게시물을 만들어 시작하세요.",noPostsInFilter:"현재 필터와 일치하는 게시물이 없습니다.",search:{placeholder:"게시물 검색…",clear:"검색 지우기",noResults:"검색과 일치하는 게시물이 없습니다."},pagination:{previous:"이전",next:"다음",showing:"{{total}}개 중 {{from}}–{{to}} 표시",pageOf:"{{total}}페이지 중 {{page}}페이지"},bulk:{selectedCount_one:"{{count}}개 선택됨",selectedCount_other:"{{count}}개 선택됨",selectPage_one:"이 페이지에서 {{count}}개 선택",selectPage_other:"이 페이지의 {{count}}개 모두 선택",deselectPage:"페이지 선택 해제",allOnPageSelected_one:"이 페이지에서 {{count}}개가 선택되었습니다.",allOnPageSelected_other:"이 페이지의 {{count}}개가 모두 선택되었습니다.",selectAllMatching_one:"일치하는 게시물 선택",selectAllMatching_other:"일치하는 {{count}}개 게시물 모두 선택",allMatchingSelected_one:"일치하는 게시물이 선택되었습니다.",allMatchingSelected_other:"일치하는 {{count}}개 게시물이 모두 선택되었습니다.",selectOne:'"{{title}}" 선택',publish:"게시 ({{count}})",publishing:"게시 중…",publishedCount:"{{ok}}개 게시됨, {{failed}}개 실패.",unpublish:"게시 취소 ({{count}})",unpublishing:"게시 취소 중…",unpublishedCount:"{{ok}}개 게시 취소됨, {{failed}}개 실패.",delete:"삭제",deleting:"삭제 중…",deletedCount:"{{ok}}개 삭제됨, {{failed}}개 실패.",confirmDelete_one:"게시물 {{count}}개를 삭제하시겠습니까? Flexweg에서 게시 취소되며 되돌릴 수 없습니다.",confirmDelete_other:"게시물 {{count}}개를 삭제하시겠습니까? Flexweg에서 게시 취소되며 되돌릴 수 없습니다.",noDraftSelected:"선택된 초안 게시물이 없습니다.",noOnlineSelected:"선택된 온라인 게시물이 없습니다.",clear:"선택 해제"},filters:{all:"전체",draft:"초안",online:"온라인"},fields:{title:"제목",slug:"슬러그",excerpt:"발췌문",content:"본문",category:"카테고리",tags:"태그",heroImage:"대표 이미지",seoTitle:"SEO 제목",seoDescription:"SEO 설명",createdAt:"작성일",updatedAt:"마지막 업데이트",publishedAt:"게시일"},edit:{newTitle:"새 게시물",editTitle:"게시물 편집",saved:"저장되었습니다.",savedAndRepublished:"저장 및 재게시되었습니다.",saveFailed:"저장에 실패했습니다.",saveAndRepublish:"저장 및 재게시",draftSaved:"초안이 저장되었습니다.",slugCollision:{post:'이 URL은 이미 게시물에서 사용 중입니다: "{{label}}".',page:'이 URL은 이미 페이지에서 사용 중입니다: "{{label}}".',category:'이 URL은 이미 카테고리에서 사용 중입니다: "{{label}}".'},publish:"게시",unpublish:"게시 취소",publishing:"게시 중…",unpublishing:"게시 취소 중…",titlePlaceholder:"제목 추가",permalink:"고유 링크",slugFormatHint:"소문자 ASCII와 하이픈만 사용할 수 있습니다.",slugAutoSuffixed:'"{{base}}"이(가) 이미 {{owner}}에서 사용 중이므로 접미사를 추가했습니다.',slugAutoSuffixedOwner:{post:'게시물: "{{label}}"',page:'페이지: "{{label}}"',category:'카테고리: "{{label}}"'},saveBlocked:{titleRequired:"저장하기 전에 제목을 추가하세요.",slugRequired:"저장하려면 제목과 URL 슬러그가 필요합니다.",slugInvalid:"슬러그 형식이 잘못되었습니다 (소문자 ASCII + 하이픈).",slugCollision:"저장하기 전에 URL 충돌을 해결하세요."},viewPublished:"보기",confirmDelete:"이 항목을 삭제하시겠습니까?",inspector:{document:"문서",block:"블록",blockEmpty:"옵션을 보려면 편집기에서 블록을 선택하세요.",publishing:"게시",permalink:"고유 링크",categories:"카테고리 및 태그",featured:"대표 이미지",seo:"SEO",excerpt:"발췌문",dates:"날짜"},blocks:{addBlock:"블록 추가",transform:"변환",moveUp:"위로 이동",moveDown:"아래로 이동",duplicate:"복제",remove:"블록 삭제",paragraph:"단락",heading2:"제목 2",heading3:"제목 3",bulletList:"글머리 기호 목록",orderedList:"번호 매기기 목록",blockquote:"인용",codeBlock:"코드",image:"이미지",horizontalRule:"구분선",categories:{text:"텍스트",media:"미디어",layout:"레이아웃",embed:"임베드",advanced:"고급"},noSettings:"이 블록에는 설정이 없습니다.",noSelection:"옵션을 보려면 편집기에서 블록을 선택하세요.",slash:{noResults:"일치하는 블록이 없습니다."}}},status:{draft:"초안",online:"온라인"},preview:{title:"미리보기",rendering:"미리보기 렌더링 중…",error:"미리보기 실패: {{error}}",viewports:{mobile:"모바일",tablet:"태블릿",desktop:"데스크탑"}}},uie={title:"페이지",newPage:"새 페이지",noPages:"아직 페이지가 없습니다.",homeBadge:"홈",homeBadgeTooltip:"사이트 홈 페이지로 사용됨"},die={title:"카테고리 및 태그",categories:"카테고리",tags:"태그",newCategory:"새 카테고리",newTag:"새 태그",noCategories:"아직 카테고리가 없습니다.",noTags:"아직 태그가 없습니다.",slugCollision:'이 슬러그는 이미 "{{label}}"에서 사용 중입니다.',seo:{button:"SEO",buttonTitle:"SEO 메타 태그 편집",title:"SEO 메타 태그",subtitle:'"{{name}}" 아카이브 페이지의 사용자 지정 제목과 설명입니다.',metaTitle:"메타 제목",metaTitleHint:"페이지 <title>로 사용됩니다. 기본값: 용어 이름.",metaDescription:"메타 설명",metaDescriptionHint:"페이지 메타 설명으로 사용됩니다. 기본값: 용어 설명."}},hie={title:"미디어 라이브러리",upload:"업로드",uploading:"업로드 중…",finalizing:"마무리 중…",uploadFailed:"업로드 실패",retry:"재시도",noMedia:"아직 미디어가 없습니다.",alt:"대체 텍스트",caption:"캡션",filename:"파일명",size:"크기",type:"유형"},fie={title:"테마",active:"활성",activate:"활성화",installExternal:"테마 설치",uninstallDisabledTitle:"이 테마를 제거하기 전에 다른 테마로 전환하세요.",syncAssets:"테마 자산 동기화",regenerateSite:"사이트 재생성",regenerating:"재생성 중…",regenerate:{button:"재생성",running:"실행 중…",groupBuiltins:"사이트",groupPlugins:"플러그인",home:"홈 페이지만",homeHelp:"index.html만 재생성합니다 — 가장 빠른 옵션입니다.",allHtml:"모든 HTML 페이지",allHtmlHelp:"모든 게시물, 페이지, 아카이브, 목록 + menu / posts / authors JSON 스냅샷.",repair:"URL 복구",repairHelp:"온라인 상태의 모든 게시물에 대해 정규 경로를 다시 계산하고 잘못된 URL에 업로드된 파일을 옮깁니다. 용어 동기화 전에 실행된 import 이후 유용합니다.",assets:"테마 자산",assetsHelp:"활성 테마의 CSS와 부속 스크립트를 /theme-assets/에 업로드합니다.",everything:"전체",everythingHelp:"테마 자산 + 모든 HTML + 모든 플러그인 출력. 가장 느린 옵션입니다.",noPluginTargets:"플러그인 재생성 대상 없음 — 재생성을 지원하는 플러그인을 활성화하세요."},confirmSwitch:{title:"{{theme}}(으)로 전환하시겠습니까?",body:"테마 전환 시 새 디자인이 모든 곳에 적용되도록 테마 자산을 다시 업로드하고 게시된 모든 페이지를 재생성해야 합니다. 잠시 시간이 걸릴 수 있습니다.",confirm:"전환 및 재생성",cancel:"취소"}},pie={title:"플러그인",enabled:"활성화됨",disabled:"비활성화됨",enable:"활성화",disable:"비활성화",configure:"설정",author:"제작자",learnMore:"자세히 보기",mustUseBadge:"필수",installExternal:"플러그인 설치",tabs:{regular:"플러그인",mustUse:"필수 플러그인"}},mie={titlePlugin:"플러그인 설치",titleTheme:"테마 설치",labelPlugin:"플러그인",labelTheme:"테마",intro:"{{label}} 번들이 들어 있는 ZIP 파일을 드롭하세요 (ZIP 루트에 manifest.json + bundle.js). 해당 {{label}}이(가) Flexweg 사이트에 업로드되고 새로고침 후 등록됩니다. 같은 manifest id의 ZIP을 다시 업로드하면 기존 항목이 그 자리에서 업그레이드됩니다 — 제거할 필요가 없습니다.",zipField:"번들 ZIP 파일",install:"설치",installing:"설치 중…",installSuccess:"{{name}} 설치됨 ({{count}}개 파일 업로드). 새로고침 중…",upgradeSuccess:"{{name}} v{{previousVersion}}에서 v{{newVersion}}(으)로 업그레이드됨 ({{count}}개 파일 업로드). 새로고침 중…",installedTitle:"이미 설치됨",bundledDefaultsTitle:"내장 기본 항목 사용 가능",bundledDefaultsHint:"현재 {{count}}개의 내장 플러그인/테마가 제거된 상태입니다. 복원하면 이 관리자 버전에 함께 배포된 항목을 되살릴 수 있습니다.",bundledDefaultsRestore:"복원",bundledDefaultsRestored:"플러그인 {{plugins}}개, 테마 {{themes}}개가 복원되었습니다. 새로고침 중…",uninstall:"제거",uninstallSuccess:"{{id}} 제거됨. 새로고침 중…",confirmUninstall:"{{id}}을(를) 제거하시겠습니까? 파일이 Flexweg에서 삭제됩니다.",errors:{"no-manifest":"ZIP 루트에 manifest.json이 없습니다.","invalid-manifest":"manifest.json이 유효하지 않습니다 (필수 필드 누락 또는 유효하지 않은 JSON).","incompatible-api":"번들이 호환되지 않는 런타임 API 버전으로 빌드되었습니다.","no-bundle":"ZIP에 manifest에 선언된 진입 파일이 없습니다.","fetch-manifest":"Flexweg에서 현재 external.json을 읽을 수 없습니다.","upload-failed":"업로드 실패 — Flexweg API 키와 연결 상태를 확인하세요."}},gie={someFailed:"{{count}}개의 외부 번들 로드에 실패했습니다. 브라우저 콘솔을 확인하세요."},bie={title:"메뉴",header:"헤더 메뉴",footer:"푸터 메뉴",label:"레이블",saveAndPublish:"저장 및 생성",discard:"변경 취소",saved:"메뉴가 저장되어 게시되었습니다.",saveFailed:"메뉴를 저장할 수 없습니다.",unsavedChanges:"저장되지 않은 변경 사항이 있습니다."},yie={title:"설정",tabs:{general:"일반"},site:{title:"사이트",siteTitle:"사이트 제목",siteDescription:"사이트 설명",siteLanguage:"사이트 언어",siteLanguageHelp:'게시되는 모든 페이지의 <html lang="…">에 삽입되는 BCP-47 태그 (예: en, fr-CA)입니다. 접두사는 지원되는 번역 로케일과 비교되어 사이트맵 / RSS 라벨 및 테마에 포함된 문자열에 사용됩니다. 지원되지 않는 로케일은 영어로 대체됩니다.',siteLanguageResolved:"번역에 사용될 언어: {{label}}",baseUrl:"공개 사이트 URL",postsPerPage:"페이지당 게시물 수",homeMode:"홈 콘텐츠",homeLatest:"최신 게시물",homeStatic:"정적 페이지",homePage:"홈 페이지",discourageIndexing:"검색 엔진이 이 사이트를 색인하지 않도록 요청",discourageIndexingHelp:"활성화하면 게시되는 모든 페이지에 noindex/nofollow 메타 태그가 추가되고 robots.txt가 모든 크롤러를 차단합니다. WordPress의 동작과 같으며 — 스테이징 사이트나 출시 전 검토에 유용합니다. 이 지시를 따르는 검색 엔진은 사이트를 색인하지 않습니다.",discourageRegenerateHint:"색인 설정이 저장되었습니다. 테마에서 '모두 재생성'을 클릭하면 게시된 모든 페이지와 robots.txt에 변경 사항이 적용됩니다."},flexweg:{title:"Flexweg API",apiKey:"API 키",apiKeyHelp:"Flexweg 계정 → API에서 생성됩니다.",siteUrl:"사이트 URL",siteUrlHelp:"끝에 슬래시가 없는 Flexweg 사이트의 공개 URL.",apiBaseUrl:"API 기본 URL",storageHelpFirebase:"Firestore (config/flexweg)에 저장됩니다. 로그인한 팀원 누구나 읽을 수 있고, 관리자만 쓸 수 있습니다.",storageHelpSqlite:"로컬 SQLite의 config 테이블에 저장됩니다. 로그인한 팀원 누구나 읽을 수 있고, 관리자만 쓸 수 있습니다."},backend:{title:"데이터 백엔드",active:"활성 백엔드:",switchButton:"백엔드 전환…",confirmTitle:"현재의 모든 데이터가 사라집니다.",confirmBody:"전환하면 브라우저 내 구성이 지워지고 설정 양식이 다시 로드됩니다. 새 백엔드는 비어 있는 상태로 시작하며 — 이전 백엔드의 데이터는 그대로 남아 있지만 (Firestore 또는 Flexweg의 .sqlite 파일에) 다시 전환할 때까지 CMS가 그 데이터를 읽지 않습니다.",confirmYes:"예, 백엔드를 전환합니다",downloadBackup:".sqlite 파일 백업 다운로드",downloadBackupHelp:"백엔드 전환 전에 수행하세요.",markdownGit:"Markdown — {{source}}",localFolder:"로컬 폴더",localBrowser:"이 브라우저 (로컬, 단일 사용자)",sqliteFile:"SQLite 파일 — {{location}}"},performance:{title:"성능",help:"관리자가 게시물과 페이지를 로드하는 방식입니다. 기본 모드는 무료 Firestore 플랜에서 추가 설정 없이 동작합니다. 페이지네이션 모드는 매우 큰 사이트용이며 한 번의 인덱스 생성이 필요합니다.",mode:"로딩 모드",modeGlobal:"표준 (설정 불필요)",modePaginated:"서버 측 페이지네이션 (Firestore 인덱스 필요)",globalHelp:"전체 게시물 컬렉션을 하나의 실시간 구독으로 로드합니다. 정렬, 필터링, 검색을 메모리에서 수행합니다. 게시물 약 5,000개 미만 사이트에 권장됩니다.",paginatedHelp:"커서 기반 페이지네이션 구독으로 한 번에 한 페이지씩 가져옵니다. Firestore 복합 인덱스가 필요합니다 — README 참조. 매우 큰 사이트에 권장됩니다.",savedReload:"저장되었습니다. 새 모드를 적용하려면 관리자를 다시 로드하세요."},editor:{title:"편집기",help:"게시물 / 페이지 편집기 내부의 타이포그래피. 공개 테마와는 별개입니다.",fontFamily:"글꼴",bodySize:"본문 크기",h1Size:"H1 크기",h2Size:"H2 크기",h3Size:"H3 크기",sizeHelp:"CSS 길이 (예: 16px, 1rem). 비워두면 기본값이 적용됩니다.",reset:"기본값으로 재설정"},profile:{title:"프로필",adminLocale:"관리자 언어",adminLocaleHelp:"관리자 인터페이스에서 사용되는 언어입니다. 프로필에 저장됩니다.",firstName:"이름",lastName:"성",headline:"직함",headlinePlaceholder:"예: 기자, 편집장…",headlineHelp:"이름 아래의 작성자 카드와 아카이브 페이지에 공개적으로 표시됩니다.",bio:"소개",bioPlaceholder:"작성자 페이지와 기사 하단에 표시되는 짧은 단락입니다.",bioHelp:"공개 사이트의 작성자 사이드바와 작성자 아카이브 페이지에 표시됩니다.",socials:"소셜 프로필",socialsHelp:'공개 사이트에 노출할 프로필의 URL을 입력하고, 표시할 항목에 "표시"를 체크하세요. URL이 비어 있으면 무시됩니다.',socialsShow:"표시",socialsShowHelp:"공개 사이트에서 이 네트워크의 표시 여부를 전환합니다.",avatar:"프로필 사진",avatarHelp:"미디어 라이브러리에서 이미지를 선택하세요. 정사각형 이미지가 가장 잘 표시됩니다.",pickAvatar:"미디어에서 선택",changeAvatar:"사진 변경",removeAvatar:"삭제",save:"프로필 저장"},transfer:{title:"콘텐츠 이동 또는 백업",help:"모든 것 (게시물, 페이지, 카테고리, 미디어 메타데이터, 프로필, 설정)을 하나의 JSON 파일로 내보냅니다. Markdown 또는 로컬 백엔드에서는 ID를 유지한 채 이 파일을 가져올 수 있습니다 — Firebase나 SQLite에서 마이그레이션하는 방법입니다. 미디어 파일과 비밀 키는 포함되지 않습니다.",export:"콘텐츠 내보내기 (JSON)",import:"콘텐츠 가져오기…",modeMerge:"병합 (같은 ID 덮어쓰기)",modeReplace:"가져온 컬렉션 교체",replaceConfirm:"교체 모드는 가져오기 전에 파일에 포함된 컬렉션의 기존 항목을 모두 삭제합니다. 계속하시겠습니까?",invalidFile:"이 파일은 AgentCMS 콘텐츠 내보내기 파일이 아닙니다.",imported:"게시물/페이지 {{posts}}개, 용어 {{terms}}개, 미디어 {{media}}개를 가져왔습니다. 재생성 → 전체를 실행해 게시하세요."},encryption:{title:"데이터베이스 암호화:",on:"켜짐",off:"꺼짐",onHelp:"암호 문구 없이는 데이터베이스 파일을 읽을 수 없습니다. 변경하면 새 키로 파일을 다시 저장하며, 다른 브라우저에서는 새 암호 문구를 요청합니다.",offHelp:"파일을 내려받을 수 있는 사람은 누구나 데이터베이스를 읽을 수 있습니다(정적 호스팅은 일반 페이지처럼 제공합니다). 암호 문구로 암호화하세요.",enable:"데이터베이스 암호화…",change:"암호 문구 변경…",savedConfirm:"이 암호 문구를 비밀번호 관리자에 저장했습니다. 암호 문구가 없으면 콘텐츠를 열 수 없습니다.",enableConfirm:"지금 암호화",changeConfirm:"암호 문구 변경",done:"새 암호 문구로 데이터베이스를 다시 저장했습니다."}},vie={title:"사용자",noUsers:"아직 사용자가 없습니다.",role:"역할",disabled:"비활성화됨",editProfileTitle:"프로필 편집 — {{email}}",profileSaved:"프로필이 저장되었습니다.",descriptionFirebase:"팀을 관리하세요. 새 계정은 Firebase Console에서 만들어지며, 첫 로그인 시 여기에 동기화됩니다.",descriptionSqlite:"팀을 관리하세요. 아래의 +사용자 추가 버튼으로 계정을 직접 만들 수 있습니다.",addUser:"사용자 추가",addUserSuccess:"{{email}}을(를) 추가했습니다.",removeConfirmFirebase:"{{email}}의 사용자 기록을 삭제하시겠습니까? CMS에서 프로필과 역할이 제거됩니다. 로그인 권한도 회수하려면 Firebase Console에서 계정도 삭제하세요.",removeConfirmSqlite:"{{email}}을(를) 영구적으로 삭제하시겠습니까? 로그인 권한이 회수되고 프로필과 역할도 제거됩니다. 이 작업은 되돌릴 수 없습니다.",empty:{title:"아직 팀원이 없습니다",descriptionFirebase:"Firebase Console에서 첫 계정을 만든 다음, 이곳에 한 번 로그인하여 프로필을 등록하세요.",descriptionSqlite:"위의 +사용자 추가를 눌러 첫 팀원을 초대하세요."},help:{title:"새 팀원을 추가하는 방법",bootstrapLine:"부트스트랩 관리자 (항상 전체 권한)는 다음과 같습니다:",firebase:{step1:"Firebase Console → Authentication → Add user를 여세요.",step2:"이메일과 비밀번호를 설정해 새 팀원에게 전달하세요.",step3:"여기에 한 번 로그인하도록 요청하세요 — 프로필이 위 목록에 나타나며 역할과 세부 정보를 편집할 수 있습니다."},sqlite:{step1:"위의 +사용자 추가 버튼을 누르세요.",step2:"이메일과 임시 비밀번호 (8자 이상)를 입력하세요.",step3:"자격 증명을 안전하게 공유하세요 — 로그인 후 프로필에서 비밀번호를 변경할 수 있습니다."},git:{step1:"해당 사용자를 콘텐츠 저장소의 협업자로 추가하세요 (쓰기 권한 = 편집자, admin / maintainer = 관리자).",step2:"해당 사용자가 GitHub / GitLab에서 자신의 개인 액세스 토큰을 생성합니다.",step3:"관리자 화면을 열고 그 토큰으로 로그인하면 — 프로필이 여기에 자동으로 생성됩니다."}},addUserModal:{title:"새 팀원 추가",intro:"Flexweg SQLite Auth 데이터베이스에 계정을 직접 만듭니다. 새 사용자는 기본적으로 editor 역할을 갖습니다. 관리자 권한이 필요하면 아래 목록에서 승격하세요.",submit:"사용자 만들기",submitting:"만드는 중…"},actions:{editProfile:"프로필 편집",promote:"관리자로 승격",demote:"편집자로 강등",disable:"비활성화",enable:"활성화",delete:"기록 삭제"},descriptionGit:"팀원은 콘텐츠 저장소에 쓰기 권한이 있는 사람들입니다. 처음 로그인한 후 여기에 표시되며, 역할은 저장소 권한을 따릅니다.",descriptionLocal:"이 관리자는 단일 사용자 모드로 실행됩니다: 콘텐츠는 이 브라우저에 저장되며 계정이 없습니다.",descriptionSqliteFile:"이 백엔드에는 사용자 계정이 없습니다: 관리자를 열 수 있는 사람은 누구나 편집할 수 있습니다. 호스팅 수준에서 관리자 폴더를 보호하세요. 아래 작성자 프로필은 참고용입니다."},xie={title:"Firestore 설정 필요",intro:"게시물 및 페이지 목록 페이지는 효율적인 쿼리를 위해 몇 개의 Firestore 복합 인덱스가 필요합니다. 수동으로 생성해야 합니다 — Firebase는 인덱스 생성을 프로젝트 관리자에게만 허용합니다.",checking:"Firestore 인덱스 확인 중…",missingCount_one:"{{count}}개의 인덱스가 누락되었습니다:",missingCount_other:"{{count}}개의 인덱스가 누락되었습니다:",openConsole:"생성하려면 Firebase Console 열기",noUrl:"자동 제안 URL을 추출할 수 없습니다 — gcloud 명령은 README를 참조하세요.",howItWorks:"작동 방식",step1:"각 누락된 인덱스의 링크를 클릭하세요 — Firebase Console이 정의가 미리 채워진 상태로 열립니다.",step2:"'Create'를 클릭하고 인덱스가 빌드될 때까지 1~5분 기다리세요 (콘솔에서 상태 확인).",step3:"여기로 돌아와 재시도를 클릭하세요. 두 쿼리가 모두 성공하면 관리자가 로드됩니다.",retry:"재시도",retrying:"재시도 중…",buildHint:"인덱스 생성 후 빌드까지 몇 분이 걸릴 수 있습니다.",allReady:"모든 인덱스가 준비되었습니다.",unexpectedTitle:"Firestore에 도달할 수 없음",unexpectedHint:"네트워크 연결과 Firestore 규칙을 확인하세요. 인덱스를 방금 생성했다면 빌드가 끝날 때까지 기다린 후 재시도하세요."},wie={appError:"애플리케이션 오류",loadAccountFailed:"계정을 불러올 수 없습니다",loadAccountHint:"문제가 지속되면 로그아웃한 뒤 다시 시도하세요.",accountDisabled:"계정 비활성화됨",accountDisabledMessage:"이 CMS에 대한 접근 권한이 비활성화되었습니다. 관리자에게 문의하세요.",firebaseNotConfigured:"Firebase가 설정되지 않았습니다",firebaseEnvMissing:`다음 환경 변수가 누락되었습니다:
|
|
3866
3866
|
{{vars}}
|
|
3867
3867
|
|
|
3868
|
-
.env.example을 .env로 복사하고 Firebase 프로젝트 자격 증명을 입력한 후 개발 서버를 재시작하세요.`,adminEmailNotConfigured:"관리자 이메일이 설정되지 않았습니다",adminEmailMessage:".env에 VITE_ADMIN_EMAIL이 누락되었습니다. 부트스트랩 관리자의 이메일로 설정하세요.",consoleHint:"브라우저 콘솔과 .env 설정을 확인하세요. 설정 방법은 README를 참조하세요."},kie={brandTitle:"Flexweg CMS",brandSubtitle:"정적 퍼블리셔",login:{heading:"로그인",intro:"관리자가 공유한 이메일과 비밀번호를 사용하세요.",submit:"로그인",submitting:"로그인 중…"},fields:{name:"표시 이름 (선택)",namePlaceholder:"홍길동",email:"이메일",password:"비밀번호",passwordHint:"최소 8자 이상."},footer:"새 계정은 관리자가 사용자 페이지에서 만듭니다.",errors:{invalidEmail:"유효한 이메일 주소를 입력하세요.",missingPassword:"비밀번호는 필수입니다.",passwordTooShort:"비밀번호는 최소 8자 이상이어야 합니다."}},Sie=JSON.parse(`{"title":"Flexweg CMS에 오신 것을 환영합니다","subtitle":"최초 설정","intro":"Firebase 자격 증명, 부트스트랩 관리자 계정, Flexweg API 키를 입력하세요. 값은 검증된 후 프로젝트에 저장되며(Firestore + Flexweg의 config.js 파일) 관리자가 일반 로그인 흐름으로 다시 로드됩니다. 한 번만 수행하면 됩니다.","introFirebase":"1단계 — Firebase. Firebase 프로젝트 자격 증명과 부트스트랩 관리자 계정을 입력하세요. 로그인하고 이메일을 확인하며 Firestore 규칙이 이 관리자를 인식하는지 확인한 후 Flexweg 단계로 넘어갑니다.","introFlexweg":"2단계 — Flexweg. Flexweg API 키와 사이트 URL을 입력하세요. API를 테스트하고 Firestore에 구성을 저장하며 사이트에 config.js를 업로드하고 테마 자산을 동기화합니다.","continueToFlexweg":"Firebase 확인 후 계속","stepper":{"terms":"약관","backend":"백엔드","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"콘텐츠 및 게시","data":"데이터","hosting":"호스팅","install":"설치"},"backend":{"title":"데이터 백엔드 선택","intro":"CMS가 게시물, 페이지, 사용자, 설정을 어디에 저장할지 선택하세요. 나중에 설정에서 변경할 수 있습니다 (데이터는 마이그레이션되지 않습니다).","sqliteTitle":"Flexweg SQLite (권장)","sqliteHint":"모든 데이터가 Flexweg 사이트에 SQLite 파일로 저장됩니다. 외부 서비스 없음. 인증은 Flexweg SQLite API가 제공합니다.","firebaseTitle":"Firebase","firebaseHint":"Firestore + Auth를 위해 Firebase 프로젝트를 사용합니다. Spark 플랜 무료. onSnapshot을 통한 실시간 업데이트.","continue":"계속","markdownGitTitle":"Git 저장소의 Markdown 파일","markdownGitHint":"게시물을 GitHub / GitLab (또는 로컬 클론)의 .md 파일로 관리합니다. 각 편집자는 자신의 액세스 토큰으로 로그인하며, 모든 변경은 하나의 커밋이 됩니다. 데이터베이스가 필요 없고, 여러 편집자와 여러 컴퓨터에서 사용할 수 있습니다.","localTitle":"이 브라우저만","localHint":"단일 사용자, 로그인 없음, 설정할 것도 없습니다. 콘텐츠는 이 브라우저에 남습니다 (설정에서 내보내기 가능). 내 컴퓨터에서 실행하는 관리자에 가장 적합합니다."},"sqlite":{"heading":"Flexweg 사이트 연결","intro":"Flexweg 마스터 API 키를 한 번만 사용해 SQLite 데이터베이스용으로 범위가 한정된 토큰을 생성합니다. 설치 후에는 마스터 키가 폐기되고 이 SQLite 파일 하나로 범위가 한정된 토큰만 저장됩니다.","apiKeyHint":"Flexweg 마스터 API 키. 설치에만 사용되며 — 이후에는 저장되지 않습니다.","detectedFromUrl":"URL에서 감지됨","advanced":"고급 설정 (사이트 URL, SQLite 경로…)","pathHint":"SQLite 파일이 Flexweg 사이트에 위치할 경로입니다. 폴더는 자동으로 생성됩니다.","adminHeading":"관리자 계정","adminIntro":"첫 사용자를 만드세요 — 이 계정은 자동으로 관리자 권한을 갖게 됩니다. 이후 멤버는 로그인한 후 사용자 페이지에서 온보딩합니다.","passwordHint":"최소 8자 이상.","submit":"SQLite 데이터베이스 설치"},"terms":{"title":"이용 약관","intro":"Flexweg CMS를 사용하기 전에 아래 약관을 읽고 동의해 주세요. 빠르게 읽을 수 있도록 평이한 언어로 작성되었습니다.","section1":{"title":"1. 무료 서비스","body":"Flexweg CMS는 Flexweg가 무료로 제공합니다. Flexweg 호스팅과 함께 무제한으로 사용할 수 있으며 — Flexweg는 CMS 자체의 사용에 대해 결코 청구하지 않습니다. Flexweg 호스팅 요금제와 Firebase 요금제의 일반 요금은 각각 해당 계정에 적용됩니다."},"section2":{"title":"2. \\"있는 그대로\\" 제공, 무보증","body":"CMS는 있는 그대로 제공됩니다. 안정적으로 유지하고 시간이 지남에 따라 개선하기 위해 노력하지만, 버그, 결함 또는 중단이 없음을 보장할 수는 없습니다. 직접 작성하지 않은 도구를 사용할 때와 동일한 주의를 기울여 사용하세요: 중요한 콘텐츠는 백업을 보관하세요."},"section3":{"title":"3. 귀하의 콘텐츠, 귀하의 책임","body":"귀하는 CMS를 통해 게시하는 콘텐츠 — 텍스트, 이미지, 비디오, 양식, 코드 임베드 및 기타 미디어 — 에 대해 단독 책임을 집니다. 귀하의 관할권(및 대상으로 하는 관할권)에서 적용되는 법률, 저작권, 초상권 및 인격권, 개인정보 보호 규칙, 그리고 사용하는 모든 제3자 서비스의 약관(임베드된 폰트, 비디오 등)을 준수해야 합니다. Flexweg는 CMS 사용자가 게시한 콘텐츠에 대해 책임지지 않습니다."},"section4":{"title":"4. 귀하의 Firebase 계정, 귀하의 보안","body":"CMS는 데이터를 귀하의 Firebase 프로젝트에 저장합니다. 해당 프로젝트의 보안은 귀하의 책임입니다: 부트스트랩 관리자 계정에 강력한 비밀번호를 선택하고, 문서에 따라 Firestore 보안 규칙을 설정하고, 필요할 때 API 키를 교체하고, 누가 접근할 수 있는지 검토하세요. Flexweg는 어떠한 경우에도 귀하의 Firebase 계정의 잘못된 구성이나 침해로 인한 무단 접근, 데이터 유출, 해킹 또는 손실에 대해 책임지지 않습니다."},"section5":{"title":"5. 책임의 제한","body":"Flexweg는 CMS의 사용, 오용 또는 사용 불가로 인한 수익 손실, 데이터 손실, 비즈니스 기회 손실 또는 직간접적인 손해에 대해 책임지지 않습니다. 적용 법률이 Flexweg에 일정 책임을 부과하는 경우, 그 책임은 지난 12개월 동안 CMS에 대해 Flexweg에 실제로 지불된 금액으로 제한됩니다 — CMS가 무료이므로 0입니다."},"section6":{"title":"6. 귀하의 데이터는 귀하의 것","body":"CMS로 만든 콘텐츠는 귀하의 Firebase 프로젝트(텍스트, 설정, 미디어 메타데이터)와 귀하의 Flexweg 호스팅(게시된 HTML, 이미지, 테마 에셋)에 저장됩니다. CMS 자체는 귀하의 콘텐츠를 어떤 제3자 서비스로도 전송하지 않습니다. 활성화하기로 선택한 플러그인이나 테마는 자체 동작을 가질 수 있습니다 — 활성화하기 전에 무엇을 하는지 확인하세요."},"section7":{"title":"7. 공정한 사용","body":"CMS를 불법, 사기 또는 유해한 활동에 사용하거나 Flexweg의 일반 이용 약관에 위배되는 방식으로 사용하면 Flexweg 호스팅 액세스가 정지될 수 있습니다. 또한 시간이 지남에 따라 이러한 CMS 약관을 업데이트할 수 있으며, 중요한 변경 사항은 관리자 또는 이메일을 통해 전달됩니다."},"accept":"이용 약관을 읽고 동의합니다.","continue":"구성으로 계속","back":"뒤로"},"sections":{"firebase":"Firebase","admin":"부트스트랩 관리자","flexweg":"Flexweg API"},"help":{"firebase":"이 값은 Firebase 콘솔 → 프로젝트 설정 → 일반 → 내 앱 → SDK 설정 및 구성에서 찾을 수 있습니다.","admin":"Firebase Authentication의 기존 사용자를 사용하세요. 이 이메일로 로그인하는 사람은 관리자로 처리되며 사용자 레코드 확인을 우회합니다. 사용자가 없으면 Firebase 콘솔 → Authentication에서 만드세요.","flexweg":"Flexweg 계정 → API에서 영구 API 키를 생성하세요. 사이트 URL은 Flexweg 사이트의 공개 주소입니다(예: https://your-site.flexweg.com).","flexwegApiKeyHint":"Flexweg 계정 설정에서 API 키를 받으세요.","flexwegApiKeyLink":"계정 설정 열기"},"fields":{"apiKey":"API 키","authDomain":"인증 도메인","projectId":"프로젝트 ID","storageBucket":"스토리지 버킷","messagingSenderId":"메시징 발신자 ID","appId":"앱 ID","adminEmail":"이메일","adminPassword":"비밀번호","flexwegApiKey":"API 키","flexwegSiteUrl":"사이트 URL","flexwegApiBaseUrl":"API 기본 URL","sqlitePath":"SQLite 경로"},"submit":"저장하고 계속","submitting":"설정 중…","success":"설정 완료!","reloadingHint":"잠시 후 관리자 페이지가 새로고침됩니다. 잠시만 기다려 주세요.","footer":"이 값은 프로젝트(Firestore + Flexweg)에 저장됩니다. 다른 곳으로 전송되지 않습니다.","steps":{"signInFirebase":"Firebase에 로그인 중…","testFlexweg":"Flexweg API 테스트 중…","writeFirestore":"구성 저장 중…","uploadConfig":"config.js를 Flexweg에 업로드 중…","syncThemes":"테마 에셋을 Flexweg에 동기화하는 중…","sqliteInstall":"범위가 한정된 SQLite 토큰 생성 중…","sqliteRegisterAdmin":"관리자 계정 등록 중…","sqliteSchema":"SQLite 스키마 초기화 중…"},"stepsDone":{"sqliteInstall":"범위가 한정된 SQLite 토큰이 발급되었습니다","sqliteRegisterAdmin":"관리자가 등록되고 로그인되었습니다","sqliteSchema":"SQLite 스키마가 준비되었습니다"},"errors":{"missingFields":"모든 필드를 입력해 주세요.","rootDeploymentTitle":"관리자는 사이트 루트가 아닌 하위 폴더에 있어야 합니다.","rootDeploymentHint":"관리자 파일(index.html, config.js, runtime/, …)을 Flexweg의 하위 폴더로 이동하세요 — 예를 들어 /admin/ 또는 보안을 위한 무작위 이름인 /erf34f654GH3/ 등으로. 그런 다음 해당 하위 폴더 URL에서 관리자를 다시 로드하고 설정을 다시 실행하세요.","firebaseAuthGeneric":"Firebase 로그인에 실패했습니다.","firebaseAuthInvalidCredential":"Firebase가 이메일과 비밀번호 조합을 거부했습니다.","firebaseAuthInvalidCredentialHint":"최신 Firebase 프로젝트는 이메일 열거 방지가 기본으로 켜져 있어, 비밀번호가 틀렸을 때, 사용자가 존재하지 않을 때, 또는 사용자가 다른 제공업체로 로그인할 때 모두 같은 오류를 반환합니다. 확인 사항:\\n• 비밀번호를 다시 입력하세요 — 오타를 배제하기 위해 비밀번호 관리자에서 복사/붙여넣기하세요. 최소 길이는 6자입니다.\\n• Firebase 콘솔 → Authentication → Users를 열어 이메일이 존재하는지 확인하세요. 'Providers' 열을 확인하세요: 'Email/Password'가 없고 Google(또는 다른 제공업체)만 표시되면, 행 메뉴(⋮ → 비밀번호 재설정)에서 비밀번호를 설정하거나 재설정하세요.\\n• 이메일 철자가 Firebase에 저장된 값과 정확히 일치하는지 확인하세요.","firebaseAuthUserNotFound":"이 이메일을 사용하는 Firebase 사용자가 없습니다. 먼저 Firebase 콘솔 → Authentication → Users에서 만드세요.","firebaseAuthInvalidEmail":"관리자 이메일이 유효한 주소가 아닙니다.","firebaseInvalidApiKey":"Firebase API 키가 잘못되었습니다. Firebase 콘솔에서 값을 다시 확인하세요.","firebaseNetwork":"Firebase 로그인 중 네트워크 오류가 발생했습니다. 연결을 확인하세요.","firebaseTooManyRequests":"로그인 시도가 너무 많습니다. 잠시 후 다시 시도하거나 Firebase 콘솔에서 비밀번호를 재설정하세요.","firebaseOperationNotAllowed":"이 Firebase 프로젝트에서는 이메일/비밀번호 로그인이 활성화되어 있지 않습니다. Firebase 콘솔 → Authentication → Sign-in method를 열어 Email/Password 제공업체를 활성화하세요.","firebaseUserDisabled":"이 Firebase 사용자 계정은 비활성화되어 있습니다. Firebase 콘솔 → Authentication → Users에서 다시 활성화하세요.","wrongAdminEmail":"로그인한 Firebase 계정이 입력한 관리자 이메일과 일치하지 않습니다. 다시 시도하세요.","rulesNotPinnedTitle":"Firestore 규칙이 아직 부트스트랩 관리자로 인식하지 못합니다.","rulesNotPinnedHint":"Firebase 콘솔 → Firestore → 규칙을 열고 \`bootstrapAdminEmail()\`의 값을 다음으로 교체하세요: {{email}} — 그런 다음 게시를 클릭하세요. README의 규칙 템플릿에는 자리표시자 \`you@example.com\`이 있으며, 실제 관리자 이메일로 교체해야 합니다. 업데이트된 규칙을 게시한 후 여기에서 제출을 다시 클릭하세요.","flexwegAuth":"Flexweg API 키가 거부되었습니다. Flexweg 계정 → API에서 값을 확인하세요.","flexwegNetwork":"Flexweg에 연결하는 중 네트워크 오류가 발생했습니다. API 기본 URL과 연결을 확인하세요.","flexwegHttp":"Flexweg API 오류 ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore가 구성 쓰기를 거부했습니다.","firestoreRulesHint":"Firebase 콘솔 → Firestore → 규칙을 열고 부트스트랩 관리자 이메일이 '{{email}}'로 설정되어 있는지 확인하세요. README에 복사해서 붙여 넣을 수 있는 규칙 템플릿이 있습니다.","firestoreOther":"Firestore 쓰기 실패","uploadFailed":"config.js를 Flexweg에 업로드할 수 없습니다","generic":"문제가 발생했습니다."},"docstore":{"contentTitle":"콘텐츠 저장소","contentIntro":"게시물, 페이지, 설정이 Markdown + JSON 파일로 저장되는 곳입니다. 빈 저장소도 괜찮습니다 — CMS가 파일을 생성합니다.","provider":"저장소","localClone":"로컬 폴더 (git 클론)","localCloneHint":"클론한 폴더를 선택하세요. 평소 사용하는 git 클라이언트로 동기화하세요 — CMS는 파일을 읽고 쓸 뿐 git을 실행하지 않습니다.","contentDir":"저장소 내 콘텐츠 폴더","privateRepo":"비공개 저장소를 사용하세요: 초안이 그곳에 저장됩니다.","folderRequired":"먼저 콘텐츠 폴더를 선택하세요.","checking":"저장소 접근 권한 확인 중…","publishIntro":"생성된 사이트가 게시되는 곳입니다. 나중에 설정에서 변경할 수 있습니다.","existingSite":"이 저장소는 이미 설정되어 있습니다 — 사이트는 계속 다음 위치에 게시됩니다: {{target}}. 나중에 설정에서 변경할 수 있습니다 (비밀 키가 있다면 그곳에서 다시 입력해야 합니다).","install":"설치","steps":{"config":"구성 저장 중…","content":"콘텐츠 불러오는 중…","target":"게시 대상 저장 중…","testTarget":"게시 대상 테스트 중…"},"doneTitle":"모두 준비되었습니다!","doneBody":"구성이 이 브라우저에 저장되었습니다. 다른 편집자가 이 설정을 반복하지 않도록 config.js를 다운로드해 호스팅의 관리자 폴더에 있는 파일을 교체하세요.","downloadConfig":"config.js 다운로드","open":"관리자 열기","footer":"콘텐츠는 저장소 또는 이 브라우저에 남으며, 액세스 토큰은 절대 이 브라우저 밖으로 나가지 않습니다."},"data":{"title":"1. 데이터를 어디에 저장하시겠어요?","intro":"게시물, 페이지, 사용자, 설정 — 관리자 자체의 데이터입니다. 공개 사이트를 호스팅하는 위치(다음 단계)와는 별개입니다.","localNote":"설정할 것이 없습니다: 콘텐츠는 이 브라우저에 저장됩니다. 백업하거나 나중에 옮기려면 설정에서 내보내세요.","options":{"sqlite-file":{"title":"SQLite","hint":"다음 단계에서 선택하는 호스팅(Flexweg, 자체 서버, S3, Git…)에 저장되는 SQLite 데이터베이스입니다. 사용자 계정이 없습니다 — Flexweg에서 호스팅한다면 계정이 포함된 Flexweg의 SQLite 서비스를 사용할 수도 있습니다."},"flexweg-sqlite":{"title":"SQLite (Flexweg 서비스)","hint":"Flexweg 서비스가 운영하는 SQLite 데이터베이스로, 사용자 계정이 내장되어 있습니다. 사이트를 어디에서 호스팅하든 Flexweg 계정이 필요합니다."},"firebase":{"title":"Firebase","hint":"Google 프로젝트의 Firestore + Firebase Auth. 실시간, 무료 Spark 요금제."},"markdown-git":{"title":"Git의 Markdown 파일","hint":"게시물을 GitHub / GitLab 저장소(또는 로컬 클론)의 .md 파일로 저장합니다. 각 편집자는 자신의 토큰을 사용하며, 모든 변경은 커밋이 됩니다."},"local":{"title":"이 브라우저","hint":"단일 사용자, 로그인 없음, 설정할 것 없음. 컴퓨터에서 실행하는 관리자에 적합합니다."}}},"hosting":{"title":"2. 사이트를 어디에 게시하시겠어요?","intro":"게시할 때마다 생성된 정적 사이트(HTML, CSS, 이미지)가 업로드되는 곳입니다. 나중에 설정에서 변경할 수 있습니다.","existing":"이 콘텐츠 저장소는 이미 아래 대상에 게시하고 있습니다. 그대로 유지하거나 다른 대상을 선택하세요."},"install":{"title":"3. 설치","intro":"요약을 확인한 후 설치하세요.","data":"데이터","hosting":"호스팅","saveTarget":"게시 대상 저장 중…","noteConfigJs":"관리자 구성(config.js)은 가능하면 Flexweg의 관리자 옆에 업로드됩니다. 그렇지 않으면 다운로드하도록 안내됩니다.","noteLocalConfig":"구성은 이 브라우저에 저장됩니다. 다른 편집자가 이 설정을 건너뛸 수 있도록 관리자 폴더에 넣을 config.js가 제공됩니다."},"sqliteFile":{"security":"사용자 계정이 없습니다. 이 관리자 화면을 열 수 있는 사람은 누구나 콘텐츠를 수정할 수 있으니 호스팅에서 관리자 폴더를 보호하세요. 데이터베이스 파일은 다른 파일처럼 공개적으로 제공되므로 암호화하거나 별도의 비공개 위치에 저장하세요.","intro":"데이터베이스 파일이 저장되는 위치입니다. 이 관리자는 호스팅과 동일한 커넥터를 통해 파일을 읽고 저장합니다.","path":"데이터베이스 파일 경로","pathHint":"아직 없으면 처음 저장할 때 생성됩니다. Git 저장소를 사용하면 저장할 때마다 커밋이 생성되므로 — 사이트 빌드를 트리거하지 않는 저장소나 브랜치를 사용하세요.","existing":"기존 데이터베이스","new":"새 데이터베이스","dataNote":"여기서는 설정할 것이 없습니다: 데이터베이스는 다음 단계에서 선택하는 호스팅에 저장됩니다.","heading":"SQLite 데이터베이스","flexwegService":"Flexweg의 SQLite 서비스 사용","flexwegServiceHint":"데이터베이스는 Flexweg가 운영하며 사용자 계정(이메일 + 비밀번호)이 내장되어 있습니다. 그렇지 않으면 계정 없이 이 호스팅에 저장되는 일반 파일입니다.","summaryFile":"이 호스팅의 파일 {{path}}","summaryService":"Flexweg SQLite 서비스 ({{path}})","encrypt":"데이터베이스 암호화","encryptHint":"공개 호스팅에서 권장: 암호 문구 없이는 파일을 읽을 수 없습니다. 새 브라우저마다 한 번 입력합니다.","passphrase":"암호 문구","passphraseHint":"지금 비밀번호 관리자에 저장하세요. 암호 문구가 없으면 본인을 포함해 누구도 데이터베이스를 열 수 없습니다.","copy":"복사","copied":"복사됨","generate":"새로 만들기","passphraseTooShort":"암호 문구는 12자 이상이어야 합니다.","existingEncrypted":"이 경로에 암호화된 데이터베이스가 이미 있습니다. 해당 암호 문구를 입력하세요.","separate":"데이터베이스를 별도의 비공개 위치에 저장","separateHint":"예: 비공개 S3 / R2 버킷 또는 비공개 Git 저장소. 이렇게 하면 공개 사이트가 데이터베이스를 제공하지 않습니다.","summaryEncrypted":"암호화됨","summaryLocation":"{{location}}에 저장됨","locationLabel":"데이터베이스 위치","gitBranchNote":"데이터베이스는 게시되지 않는 이 저장소의 {{branch}} 브랜치에 보관됩니다. 콘텐츠를 저장해도 사이트가 다시 빌드되지 않습니다.","summaryBranch":"{{branch}} 브랜치"},"adminHosting":{"deploying":"관리자를 사이트에 복사하는 중…","label":"이 사이트에 관리자도 호스팅","hint":"관리자가 config.js(비밀 정보 없음)와 함께 {{url}}에 복사되며, 모든 편집자가 그곳에서 열 수 있습니다. 각 편집자는 여전히 자신의 액세스로 로그인합니다.","folder":"관리자 폴더","alreadyHere":"이 관리자는 이미 이 사이트에서 실행 중입니다. config.js가 그 자리에서 업데이트됩니다.","doneBody":"관리자가 이제 사이트에 있습니다. GitHub Pages를 사용한다면 아직 활성화하지 않은 경우 먼저 저장소의 Pages를 활성화한 다음(Settings → Pages) 여세요:","open":"온라인 관리자 열기","continueHere":"이 관리자에서 계속하기"}}`),Eie={actions:{upload:"파일 업로드",delete:"파일 삭제",rename:"파일 이름 변경",get:"파일 읽기",list:"파일 목록 조회",createFolder:"폴더 생성",renameFolder:"폴더 이름 변경",deleteFolder:"폴더 삭제",storageLimits:"저장 용량 한도 조회",commit:"변경 사항 게시 중"},errors:{configMissing:"게시 대상이 설정되지 않았습니다. 게시하기 전에 설정에서 구성하세요.",network:"{{action}}: 네트워크 오류 또는 CORS가 차단되었습니다. 연결 상태를 확인하세요.",auth:"{{action}}: 인증에 실패했습니다. 설정에서 게시 대상 자격 증명을 확인하세요.",notFound:"{{action}}: 게시 대상에서 찾을 수 없습니다.",tooLarge:"{{action}}: 게시 대상에 비해 파일이 너무 큽니다.",rateLimited:"{{action}}: 요청이 너무 많습니다. 잠시 후 다시 시도하세요.",serverError:"{{action}}: 게시 대상 서버 오류({{status}}). 다시 시도하세요.",generic:"{{action}} 실패 ({{status}}){{detail}}.",unsupported:'{{action}}: "{{connector}}" 게시 대상에서 지원되지 않습니다.',unknownConnector:'알 수 없는 게시 대상 "{{connector}}". 설정 → 게시 대상을 확인하세요.',folderAccess:"로컬 폴더에 접근할 수 없습니다. 설정 → 게시 대상에서 “폴더 다시 연결”을 클릭하세요."}},_ie={log:{rendering:"페이지 렌더링 중…",uploading:"{{path}} 업로드 중…",deleting:"{{path}} 삭제 중…",regenerating:"목록 재생성 중…",skipped:"{{path}} 건너뜀 (변경 없음)",done:"{{url}}에 게시됨",failed:"실패: {{error}}"}},Cie={errors:{notConnected:"콘텐츠 저장소에 연결되어 있지 않습니다. 액세스 토큰으로 다시 로그인하세요.",conflict:"그 사이 다른 사람이 이 항목을 변경했습니다. 이제 그 버전이 표시됩니다 — 변경 사항을 다시 적용하세요.",sqliteUnsupported:'"{{connector}}" 대상에는 데이터베이스 파일을 저장할 수 없습니다.'}},Aie={target:"게시 대상",settingsTitle:"게시 대상",settingsHelp:"게시할 때 렌더링된 사이트가 업로드되는 곳입니다. 자격 증명은 콘텐츠 백엔드에 저장되며 (Git 콘텐츠 저장소의 경우 이 브라우저에 보관) 모든 관리자가 읽을 수 있습니다.",saved:"게시 대상이 저장되었습니다. 재생성 → 전체를 실행해 사이트 전체를 새 대상에 게시하세요.",test:"연결 테스트",testOk:"연결 정상",testFailed:"연결 실패",names:{flexweg:"Flexweg","git-pages":"Git 저장소 (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"S3 호환 버킷 (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"자체 서버 (PHP 브리지)","browser-mirror":"ZIP으로 다운로드","local-folder":"이 컴퓨터의 로컬 폴더"},hints:{flexweg:"Flexweg Files API를 통해 업로드합니다.","git-pages":"게시할 때마다 저장소에 커밋 하나가 생성되며, 호스트가 이를 바탕으로 사이트를 다시 빌드합니다.",s3:"버킷에 이 관리자의 오리진을 허용하는 CORS 규칙이 필요하며, index.html 파일을 제공하려면 웹사이트 호스팅 (또는 CDN)이 필요합니다.","php-bridge":"external/bridges/php/flexweg-bridge.php를 서버에 업로드하고 API 키를 설정한 다음 여기에 URL을 입력하세요.","browser-mirror":"사이트는 이 브라우저에 보관됩니다. ZIP을 다운로드해 원하는 곳에 직접 업로드하세요.","local-folder":"사이트를 폴더에 바로 기록합니다 (Chrome / Edge). 로컬에서 제공하거나 자신의 도구로 푸시하세요."},fields:{flexweg:{apiKey:"API 키",siteUrl:"사이트 URL",apiBaseUrl:"API 기본 URL"},"git-pages":{host:"호스팅",provider:"Git 제공자",owner:"소유자 (사용자 또는 조직)",repo:"저장소",project:"프로젝트 경로",branch:"브랜치",dir:"저장소 내 폴더",token:"액세스 토큰",siteUrl:"공개 사이트 URL",apiBaseUrl:"API URL (자체 호스팅 전용)"},s3:{endpoint:"엔드포인트",region:"리전",bucket:"버킷",prefix:"키 접두사 (선택 사항)",accessKeyId:"액세스 키 ID",secretAccessKey:"비밀 액세스 키",siteUrl:"공개 사이트 URL",forcePathStyle:"경로 스타일 URL (MinIO, R2, 대부분의 호환 서비스)",publicRead:"업로드한 파일을 공개로 설정(ACL public-read) — 버킷 정책으로 공개되지 않은 버킷용(OVHcloud, Scaleway 등). ‘bucket owner enforced’를 사용하는 AWS 버킷에서는 꺼 두세요."},"php-bridge":{apiBaseUrl:"브리지 URL",apiKey:"브리지 API 키",siteUrl:"공개 사이트 URL"},"browser-mirror":{siteUrl:"공개 사이트 URL (선택 사항)"},"local-folder":{siteUrl:"폴더가 제공되는 URL (선택 사항)"}},help:{flexweg:{apiKey:"Flexweg 계정 → API에서 생성합니다."},"git-pages":{host:"Cloudflare Pages: 빌드 명령 없이 아래 출력 폴더로 프로젝트를 이 저장소에 연결하세요. 비공개 저장소에서도 작동합니다.",dir:'저장소 루트를 사용하려면 비워 두세요. GitHub Pages: "" 또는 "docs". GitLab Pages: "public".',token:"이 저장소에 대해 Contents: read & write 권한이 있는 세분화된(fine-grained) 토큰(GitHub) — CMS가 GitHub Pages를 활성화하도록 하려면 Pages: read & write를 추가하세요 — 또는 api 스코프가 있는 토큰(GitLab). 콘텐츠가 같은 제공자에 있다면 비워 두어 각 편집자의 액세스 토큰을 사용하세요.",siteUrl:"예: https://user.github.io/repo — 하위 폴더 URL도 괜찮으며, 링크는 자동으로 조정됩니다."},s3:{endpoint:"AWS는 비워 두세요 (리전에서 자동 구성됨). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"버킷 웹사이트 URL 또는 CDN 도메인."},"php-bridge":{apiBaseUrl:"서버에 있는 flexweg-bridge.php의 전체 URL (HTTPS)."},"browser-mirror":{siteUrl:"ZIP을 업로드할 위치 — 절대 URL (사이트맵, RSS, 미디어)에 사용됩니다."},"local-folder":{siteUrl:"예: 로컬 웹 서버가 폴더를 제공하는 경우 http://localhost:8080."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (저장소에 연결됨)","gitlab-pages":"GitLab Pages",other:"기타 (Netlify, Vercel, 서버 git pull…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"폴더 선택…",change:"폴더 변경…",reconnect:"폴더 다시 연결",unsupported:"이 브라우저는 로컬 폴더에 쓸 수 없습니다. Chrome 또는 Edge를 사용하세요."},mirror:{download:"사이트 다운로드 (ZIP)",count:"이 브라우저에 있는 파일 {{count}}개"},adminHosting:{title:"이 사이트의 관리자",help:"이 관리자를 게시 대상에 복사합니다(최초 배포 또는 새 버전 이후 업데이트). config.js에는 비밀 정보가 없습니다.",deploy:"관리자 배포 / 업데이트",deployed:"관리자 배포 완료 ({{count}}개 파일) — {{url}}"},pages:{enabled:"이 저장소에 GitHub Pages가 활성화되었습니다 — 약 1분 후 사이트가 온라인 상태가 됩니다.",enableHint:'게시에 성공했습니다. 사이트를 온라인으로 만들려면 {{repo}}에 대해 GitHub Pages를 활성화하세요: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (또는 토큰에 "Pages: read and write" 권한을 부여하면 CMS가 대신 처리합니다.)'},siteUrl:{mismatch:"사이트 공개 URL(설정 → 사이트)은 {{site}}이지만, 이 대상은 사이트를 {{target}}에서 제공합니다. 링크, CSS, 사이트맵은 사이트 URL을 따르므로 이 호스팅에서는 잘못됩니다.",use:"사이트에 {{url}} 사용",updated:"사이트 URL을 업데이트했습니다. 재생성 → 전체를 실행해 새 링크로 페이지를 다시 게시하세요."}},Tie={heading:"콘텐츠 저장소에 연결",tokenIntro:"콘텐츠는 {{provider}} 저장소 {{repo}}에 저장됩니다. 자신의 개인 액세스 토큰으로 로그인하세요 — 저장소 권한에 따라 역할이 결정됩니다 (쓰기 권한 = 편집자, admin / maintainer = 관리자).",token:"개인 액세스 토큰",tokenHelpGithub:"이 저장소에만 접근 가능한 fine-grained 토큰, Contents 권한: 읽기 및 쓰기.",tokenHelpGitlab:"api scope가 있는 토큰, 이 프로젝트에서 Developer 이상의 역할.",createToken:"토큰 만들기",connect:"연결",tokenStorage:"토큰은 이 브라우저에만 보관됩니다. 로그아웃하면 삭제됩니다.",failed:"이 토큰으로는 저장소에 쓸 수 없습니다 (유효하지 않음, 만료됨 또는 읽기 전용). 권한을 확인하세요.",folderIntro:"콘텐츠는 이 컴퓨터의 폴더에 저장됩니다 (보통 자신의 git 클라이언트로 동기화하는 git 클론). 이 브라우저에 접근 권한을 허용하세요 — 브라우저는 새로고침할 때마다 다시 묻습니다.",openFolder:"콘텐츠 폴더 열기"},Iie={flexweg:{title:"Flexweg",short:"Flexweg 호스팅",hint:"Flexweg Files API를 통해 업로드합니다. Flexweg 계정의 API 키를 사용하세요."},"github-pages":{title:"GitHub Pages",short:"무료, GitHub 저장소에서",hint:"게시할 때마다 저장소에 커밋 하나가 생성되고 GitHub Pages가 이를 제공합니다. Settings → Pages → Deploy from a branch. 무료 요금제는 공개 저장소만 가능합니다."},"cloudflare-pages":{title:"Cloudflare Pages",short:"무료, 비공개 저장소 가능",hint:"CMS가 사이트를 GitHub / GitLab 저장소에 커밋합니다. 여기에 Cloudflare Pages 프로젝트를 연결하세요(빌드 명령 없음, 출력 폴더 = 아래 폴더)."},"gitlab-pages":{title:"GitLab Pages",short:"무료, GitLab 저장소에서",hint:"게시할 때마다 커밋 하나가 생성됩니다. CMS가 public/ 폴더를 게시하는 최소한의 .gitlab-ci.yml을 추가합니다."},"git-other":{title:"Netlify, Vercel…",short:"저장소를 배포하는 모든 호스트",hint:"CMS가 사이트를 Git 저장소에 커밋합니다. 호스트(Netlify, Vercel, git pull을 실행하는 서버…)를 해당 저장소에 연결하세요."},s3:{title:"S3 / R2 / B2…",short:"오브젝트 스토리지 버킷",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… 버킷에 CORS 규칙과 웹사이트 호스팅 또는 앞단의 CDN이 필요합니다."},"own-server":{title:"자체 서버 (FTP / SFTP)",short:"공유 호스팅, VPS…",hint:"브라우저는 FTP나 SFTP를 사용할 수 없습니다: FTP 클라이언트로 PHP 브리지(external/bridges/php/flexweg-bridge.php)를 한 번 업로드하고 API 키를 설정한 다음, 여기에 해당 URL을 입력하세요. 모든 PHP 호스트에서 작동합니다."},"local-folder":{title:"로컬 폴더",short:"이 컴퓨터에",hint:"사이트를 이 컴퓨터의 폴더에 씁니다(Chrome / Edge). 로컬에서 제공하거나 자체 도구로 푸시하세요."},zip:{title:"ZIP으로 다운로드",short:"직접 업로드",hint:"사이트는 이 브라우저에 보관됩니다. 설정에서 ZIP을 다운로드해 원하는 곳(Netlify Drop, FTP 클라이언트…)에 업로드하세요."}},Nie={heading:"데이터베이스에 연결",intro:"이 관리자는 콘텐츠를 {{path}}에 저장합니다. 이 브라우저의 액세스 자격 증명을 입력하세요.",storage:"자격 증명은 이 브라우저에만 보관됩니다. 로그아웃하면 삭제됩니다.",passphrase:"데이터베이스 암호 문구",passphraseHint:"데이터베이스가 암호화되어 있습니다. 설치 시 정한 암호 문구를 입력하세요(이 브라우저에만 저장됩니다).",passphraseWrong:"암호 문구가 올바르지 않아 데이터베이스를 열 수 없습니다.",passphraseMissing:"데이터베이스 암호 문구를 입력하세요."},Pie={common:iie,auth:aie,nav:oie,dashboard:lie,posts:cie,pages:uie,taxonomies:die,media:hie,themes:fie,plugins:pie,externalInstall:mie,externalLoader:gie,menus:bie,settings:yie,users:vie,firestoreSetup:xie,errors:wie,identity:kie,setup:Sie,flexweg:Eie,publish:_ie,docstore:Cie,connectors:Aie,gitAccess:Tie,hosting:Iie,sqliteAccess:Nie},r1=["en","fr","de","es","nl","pt","ko"],KA="en",PO="adminLocale",r_={fr:"🇫🇷 Français",en:"🇬🇧 English",de:"🇩🇪 Deutsch",es:"🇪🇸 Español",nl:"🇳🇱 Nederlands",pt:"🇵🇹 Português",ko:"🇰🇷 한국어"},Rie={fr:"🇫🇷",en:"🇬🇧",de:"🇩🇪",es:"🇪🇸",nl:"🇳🇱",pt:"🇵🇹",ko:"🇰🇷"};function Jy(t){return typeof t=="string"&&r1.includes(t)}function nh(t,e=KA){var r;const n=(r=(t??"").split("-")[0])==null?void 0:r.toLowerCase();return n&&r1.includes(n)?n:e}function jie(t){var e;if(Jy(t))return t;if(typeof window<"u"){const n=window.localStorage.getItem(PO);if(Jy(n))return n}if(typeof navigator<"u"&&typeof navigator.language=="string"){const n=(e=navigator.language.split("-")[0])==null?void 0:e.toLowerCase();if(Jy(n))return n}return KA}function Mie(t){try{window.localStorage.setItem(PO,t)}catch{}}jt.use(Q6).init({resources:{en:{translation:Pne},fr:{translation:sre},de:{translation:Pre},es:{translation:sse},nl:{translation:Pse},pt:{translation:sie},ko:{translation:Pie}},lng:jie(),fallbackLng:KA,interpolation:{escapeValue:!1},returnNull:!1,react:{useSuspense:!1}});async function s1(t){Jy(t)&&(Mie(t),await jt.changeLanguage(t))}const Lie="flexweg-git-blobs",Ag="texts",s_=new Map;let ty=null;function RO(){return ty||(ty=new Promise(t=>{try{if(typeof indexedDB>"u")return t(null);const e=indexedDB.open(Lie,1);e.onupgradeneeded=()=>e.result.createObjectStore(Ag),e.onsuccess=()=>t(e.result),e.onerror=()=>t(null),e.onblocked=()=>t(null)}catch{t(null)}}),ty)}async function jO(t){const e=new Map,n=[];for(const s of t){const i=s_.get(s);i!==void 0?e.set(s,i):n.push(s)}if(n.length===0)return e;const r=await RO();return r&&await new Promise(s=>{try{const i=r.transaction(Ag,"readonly"),a=i.objectStore(Ag);for(const o of n){const l=a.get(o);l.onsuccess=()=>{typeof l.result=="string"&&(e.set(o,l.result),s_.set(o,l.result))}}i.oncomplete=()=>s(),i.onerror=()=>s(),i.onabort=()=>s()}catch{s()}}),e}async function MO(t){for(const[n,r]of t)s_.set(n,r);const e=await RO();!e||t.size===0||await new Promise(n=>{try{const r=e.transaction(Ag,"readwrite"),s=r.objectStore(Ag);for(const[i,a]of t)s.put(a,i);r.oncomplete=()=>n(),r.onerror=()=>n(),r.onabort=()=>n()}catch{n()}})}function JA(t){let e="";for(let r=0;r<t.length;r+=32768)e+=String.fromCharCode(...t.subarray(r,r+32768));return btoa(e)}function rp(t){const e=atob(t.replace(/\s+/g,"")),n=new Uint8Array(e.length);for(let r=0;r<e.length;r++)n[r]=e.charCodeAt(r);return n}function Die(t){return JA(new TextEncoder().encode(t))}function LO(t){return new TextDecoder().decode(rp(t))}function Fie(t){return t.encoding==="base64"?rp(t.content):new TextEncoder().encode(t.content)}const i_=new Set;function Oie(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function ny(t){const e={...t,id:Oie(),createdAt:Date.now()};return i_.forEach(n=>{try{n(e)}catch(r){console.error("Toast subscriber threw:",r)}}),e}const at={info:(t,e)=>ny({level:"info",message:t,durationMs:e}),success:(t,e)=>ny({level:"success",message:t,durationMs:e}),warn:(t,e)=>ny({level:"warn",message:t,durationMs:e}),error:(t,e)=>ny({level:"error",message:t,durationMs:e})};function zie(t){return i_.add(t),()=>i_.delete(t)}function Uie(t){switch(t){case"error":return 6e3;case"warn":return 5e3;default:return 3500}}class Ns extends Error{constructor(e,n,r){super(e),this.status=n,this.body=r,this.name="StorageError"}}function QA(t){return jt.t(`flexweg.actions.${t}`)}function Bie(t){if(!t)return"";let e=t.trim();try{const n=JSON.parse(e);e=n.error??n.message??e}catch{}return e.length>240&&(e=e.slice(0,240)+"…"),e}function $ie(t,e,n){const r=QA(t),s=Bie(n);switch(e){case 401:case 403:return jt.t("flexweg.errors.auth",{action:r});case 404:return jt.t("flexweg.errors.notFound",{action:r});case 413:return jt.t("flexweg.errors.tooLarge",{action:r});case 429:return jt.t("flexweg.errors.rateLimited",{action:r});case 500:case 502:case 503:case 504:return jt.t("flexweg.errors.serverError",{action:r,status:e});default:return jt.t("flexweg.errors.generic",{action:r,status:e,detail:s?`: ${s}`:""})}}async function Hs(t,e){let n;try{n=await e()}catch(a){throw(a==null?void 0:a.name)==="AbortError"||at.error(jt.t("flexweg.errors.network",{action:QA(t)})),a}if(n.ok)return n;const r=await n.text().catch(()=>""),s=(t==="delete"||t==="deleteFolder")&&n.status===404,i=$ie(t,n.status,r);throw s||at.error(i),new Ns(i,n.status,r)}function i1(t,e){const n=jt.t("flexweg.errors.unsupported",{action:QA(t),connector:e});return at.error(n),new Ns(n,501)}async function Ka(t,e,n,r=[]){let s;try{s=await fetch(e,n)}catch(i){return Hs(t,()=>Promise.reject(i))}return s.ok||r.includes(s.status)?s:Hs(t,async()=>s)}async function XA(t,e,n){const r=new Array(t.length);let s=0;async function i(){for(;s<t.length;){const a=s++;r[a]=await n(t[a])}}return await Promise.all(Array.from({length:Math.min(e,t.length)},i)),r}class Hc extends Error{constructor(e,n){super(e),this.currentHeadSha=n,this.name="GitConflictError"}}const YR=300,ej=50,Hie=3;function Vie(t){const e=(t.apiBaseUrl||"https://api.github.com").replace(/\/+$/,""),n=e.endsWith("/api/v3")?e.replace(/\/api\/v3$/,"/api/graphql"):`${e}/graphql`,r=`${e}/repos/${encodeURIComponent(t.owner)}/${encodeURIComponent(t.repo)}`,s=`heads/${t.branch.split("/").map(encodeURIComponent).join("/")}`,i={Authorization:`Bearer ${t.token}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28"},a={...i,"Content-Type":"application/json"};async function o(P,D="get"){return await(await Ka(D,P,{headers:i,cache:"no-store"})).json()}async function l(P,D,I="POST"){return await(await Ka("commit",P,{method:I,headers:a,body:JSON.stringify(D)})).json()}async function c(){var I;const P=await Ka("get",`${r}/git/ref/${s}`,{headers:i,cache:"no-store"},[404,409]);if(!P.ok)return"";const D=await P.json();return Array.isArray(D)?"":((I=D.object)==null?void 0:I.sha)??""}async function h(P){return(await o(`${r}/git/commits/${P}`)).tree.sha}async function p(P,D,I){const L=await o(`${r}/git/trees/${P}`,"list");for(const j of L.tree){const q=D+j.path;j.type==="blob"?I.push({path:q,sha:j.sha,size:j.size}):j.type==="tree"&&await p(j.sha,q+"/",I)}}async function m(P){if(!P)return{headSha:"",entries:[]};const D=await h(P),I=await o(`${r}/git/trees/${D}?recursive=1`,"list");if(!I.truncated)return{headSha:P,entries:I.tree.filter(j=>j.type==="blob").map(j=>({path:j.path,sha:j.sha,size:j.size}))};const L=[];return await p(D,"",L),{headSha:P,entries:L}}async function g(P){return(await o(`${r}/git/blobs/${P}`)).content}async function y(P){var I;const D=new Map;for(let L=0;L<P.length;L+=ej){const j=P.slice(L,L+ej),V=`query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { ${j.map((O,$)=>`b${$}: object(oid: "${O}") { ... on Blob { text isBinary isTruncated } }`).join(`
|
|
3869
|
-
`)} } }`;try{const O=await fetch(n,{method:"POST",headers:a,body:JSON.stringify({query:V,variables:{owner:t.owner,name:t.repo}})});if(!O.ok)continue;const B=(I=(await O.json()).data)==null?void 0:I.repository;if(!B)continue;j.forEach((X,fe)=>{const ie=B[`b${fe}`];ie&&!ie.isBinary&&!ie.isTruncated&&typeof ie.text=="string"&&D.set(X,ie.text)})}catch{}}return D}async function x(P){const D=[...new Set(P.map(V=>V.sha))],I=await jO(D),L=D.filter(V=>!I.has(V)),j=new Map;if(L.length>0){const V=await y(L);for(const[$,B]of V)j.set($,B);const O=L.filter($=>!j.has($));await XA(O,6,async $=>{j.set($,LO(await g($)))}),await MO(j)}const q=new Map;for(const V of P){const O=I.get(V.sha)??j.get(V.sha);O!==void 0&&q.set(V.path,O)}return q}async function v(P){return rp(await g(P.sha))}async function k(P){const D=await o(r),I=D.default_branch?await Ka("get",`${r}/git/ref/heads/${encodeURIComponent(D.default_branch)}`,{headers:i,cache:"no-store"},[404,409]):null;if(!I||!I.ok)return(await l(`${r}/contents/.gitkeep`,{message:P,content:"",branch:t.branch},"PUT")).commit.sha;const L=await l(`${r}/git/trees`,{tree:[{path:".gitkeep",mode:"100644",type:"blob",content:""}]}),j=await l(`${r}/git/commits`,{message:P,tree:L.sha,parents:[]});return await l(`${r}/git/refs`,{ref:`refs/heads/${t.branch}`,sha:j.sha}),j.sha}async function C(P,D){const I=new Map;for(const L of P)if(L.type==="put"&&L.encoding==="base64"&&!I.has(L.path)){const j=await l(`${r}/git/blobs`,{content:L.content,encoding:"base64"});I.set(L.path,j.sha)}for(let L=0;;L++){let j=await c();if(D.expectedHeadSha!==void 0&&j!==D.expectedHeadSha)throw new Hc(`Branch ${t.branch} moved`,j);j||(j=await k("Initialize branch —
|
|
3868
|
+
.env.example을 .env로 복사하고 Firebase 프로젝트 자격 증명을 입력한 후 개발 서버를 재시작하세요.`,adminEmailNotConfigured:"관리자 이메일이 설정되지 않았습니다",adminEmailMessage:".env에 VITE_ADMIN_EMAIL이 누락되었습니다. 부트스트랩 관리자의 이메일로 설정하세요.",consoleHint:"브라우저 콘솔과 .env 설정을 확인하세요. 설정 방법은 README를 참조하세요."},kie={brandTitle:"AgentCMS",brandSubtitle:"정적 퍼블리셔",login:{heading:"로그인",intro:"관리자가 공유한 이메일과 비밀번호를 사용하세요.",submit:"로그인",submitting:"로그인 중…"},fields:{name:"표시 이름 (선택)",namePlaceholder:"홍길동",email:"이메일",password:"비밀번호",passwordHint:"최소 8자 이상."},footer:"새 계정은 관리자가 사용자 페이지에서 만듭니다.",errors:{invalidEmail:"유효한 이메일 주소를 입력하세요.",missingPassword:"비밀번호는 필수입니다.",passwordTooShort:"비밀번호는 최소 8자 이상이어야 합니다."}},Sie=JSON.parse(`{"title":"AgentCMS에 오신 것을 환영합니다","subtitle":"최초 설정","intro":"Firebase 자격 증명, 부트스트랩 관리자 계정, Flexweg API 키를 입력하세요. 값은 검증된 후 프로젝트에 저장되며(Firestore + Flexweg의 config.js 파일) 관리자가 일반 로그인 흐름으로 다시 로드됩니다. 한 번만 수행하면 됩니다.","introFirebase":"1단계 — Firebase. Firebase 프로젝트 자격 증명과 부트스트랩 관리자 계정을 입력하세요. 로그인하고 이메일을 확인하며 Firestore 규칙이 이 관리자를 인식하는지 확인한 후 Flexweg 단계로 넘어갑니다.","introFlexweg":"2단계 — Flexweg. Flexweg API 키와 사이트 URL을 입력하세요. API를 테스트하고 Firestore에 구성을 저장하며 사이트에 config.js를 업로드하고 테마 자산을 동기화합니다.","continueToFlexweg":"Firebase 확인 후 계속","stepper":{"terms":"약관","backend":"백엔드","firebase":"Firebase","flexweg":"Flexweg","sqlite":"SQLite","docstore":"콘텐츠 및 게시","data":"데이터","hosting":"호스팅","install":"설치"},"backend":{"title":"데이터 백엔드 선택","intro":"CMS가 게시물, 페이지, 사용자, 설정을 어디에 저장할지 선택하세요. 나중에 설정에서 변경할 수 있습니다 (데이터는 마이그레이션되지 않습니다).","sqliteTitle":"Flexweg SQLite (권장)","sqliteHint":"모든 데이터가 Flexweg 사이트에 SQLite 파일로 저장됩니다. 외부 서비스 없음. 인증은 Flexweg SQLite API가 제공합니다.","firebaseTitle":"Firebase","firebaseHint":"Firestore + Auth를 위해 Firebase 프로젝트를 사용합니다. Spark 플랜 무료. onSnapshot을 통한 실시간 업데이트.","continue":"계속","markdownGitTitle":"Git 저장소의 Markdown 파일","markdownGitHint":"게시물을 GitHub / GitLab (또는 로컬 클론)의 .md 파일로 관리합니다. 각 편집자는 자신의 액세스 토큰으로 로그인하며, 모든 변경은 하나의 커밋이 됩니다. 데이터베이스가 필요 없고, 여러 편집자와 여러 컴퓨터에서 사용할 수 있습니다.","localTitle":"이 브라우저만","localHint":"단일 사용자, 로그인 없음, 설정할 것도 없습니다. 콘텐츠는 이 브라우저에 남습니다 (설정에서 내보내기 가능). 내 컴퓨터에서 실행하는 관리자에 가장 적합합니다."},"sqlite":{"heading":"Flexweg 사이트 연결","intro":"Flexweg 마스터 API 키를 한 번만 사용해 SQLite 데이터베이스용으로 범위가 한정된 토큰을 생성합니다. 설치 후에는 마스터 키가 폐기되고 이 SQLite 파일 하나로 범위가 한정된 토큰만 저장됩니다.","apiKeyHint":"Flexweg 마스터 API 키. 설치에만 사용되며 — 이후에는 저장되지 않습니다.","detectedFromUrl":"URL에서 감지됨","advanced":"고급 설정 (사이트 URL, SQLite 경로…)","pathHint":"SQLite 파일이 Flexweg 사이트에 위치할 경로입니다. 폴더는 자동으로 생성됩니다.","adminHeading":"관리자 계정","adminIntro":"첫 사용자를 만드세요 — 이 계정은 자동으로 관리자 권한을 갖게 됩니다. 이후 멤버는 로그인한 후 사용자 페이지에서 온보딩합니다.","passwordHint":"최소 8자 이상.","submit":"SQLite 데이터베이스 설치"},"terms":{"title":"이용 약관","intro":"AgentCMS를 사용하기 전에 아래 약관을 읽고 동의해 주세요. 빠르게 읽을 수 있도록 평이한 언어로 작성되었습니다.","section1":{"title":"1. 무료 서비스","body":"AgentCMS는 Flexweg가 무료로 제공합니다. Flexweg 호스팅과 함께 무제한으로 사용할 수 있으며 — Flexweg는 CMS 자체의 사용에 대해 결코 청구하지 않습니다. Flexweg 호스팅 요금제와 Firebase 요금제의 일반 요금은 각각 해당 계정에 적용됩니다."},"section2":{"title":"2. \\"있는 그대로\\" 제공, 무보증","body":"CMS는 있는 그대로 제공됩니다. 안정적으로 유지하고 시간이 지남에 따라 개선하기 위해 노력하지만, 버그, 결함 또는 중단이 없음을 보장할 수는 없습니다. 직접 작성하지 않은 도구를 사용할 때와 동일한 주의를 기울여 사용하세요: 중요한 콘텐츠는 백업을 보관하세요."},"section3":{"title":"3. 귀하의 콘텐츠, 귀하의 책임","body":"귀하는 CMS를 통해 게시하는 콘텐츠 — 텍스트, 이미지, 비디오, 양식, 코드 임베드 및 기타 미디어 — 에 대해 단독 책임을 집니다. 귀하의 관할권(및 대상으로 하는 관할권)에서 적용되는 법률, 저작권, 초상권 및 인격권, 개인정보 보호 규칙, 그리고 사용하는 모든 제3자 서비스의 약관(임베드된 폰트, 비디오 등)을 준수해야 합니다. Flexweg는 CMS 사용자가 게시한 콘텐츠에 대해 책임지지 않습니다."},"section4":{"title":"4. 귀하의 Firebase 계정, 귀하의 보안","body":"CMS는 데이터를 귀하의 Firebase 프로젝트에 저장합니다. 해당 프로젝트의 보안은 귀하의 책임입니다: 부트스트랩 관리자 계정에 강력한 비밀번호를 선택하고, 문서에 따라 Firestore 보안 규칙을 설정하고, 필요할 때 API 키를 교체하고, 누가 접근할 수 있는지 검토하세요. Flexweg는 어떠한 경우에도 귀하의 Firebase 계정의 잘못된 구성이나 침해로 인한 무단 접근, 데이터 유출, 해킹 또는 손실에 대해 책임지지 않습니다."},"section5":{"title":"5. 책임의 제한","body":"Flexweg는 CMS의 사용, 오용 또는 사용 불가로 인한 수익 손실, 데이터 손실, 비즈니스 기회 손실 또는 직간접적인 손해에 대해 책임지지 않습니다. 적용 법률이 Flexweg에 일정 책임을 부과하는 경우, 그 책임은 지난 12개월 동안 CMS에 대해 Flexweg에 실제로 지불된 금액으로 제한됩니다 — CMS가 무료이므로 0입니다."},"section6":{"title":"6. 귀하의 데이터는 귀하의 것","body":"CMS로 만든 콘텐츠는 귀하의 Firebase 프로젝트(텍스트, 설정, 미디어 메타데이터)와 귀하의 Flexweg 호스팅(게시된 HTML, 이미지, 테마 에셋)에 저장됩니다. CMS 자체는 귀하의 콘텐츠를 어떤 제3자 서비스로도 전송하지 않습니다. 활성화하기로 선택한 플러그인이나 테마는 자체 동작을 가질 수 있습니다 — 활성화하기 전에 무엇을 하는지 확인하세요."},"section7":{"title":"7. 공정한 사용","body":"CMS를 불법, 사기 또는 유해한 활동에 사용하거나 Flexweg의 일반 이용 약관에 위배되는 방식으로 사용하면 Flexweg 호스팅 액세스가 정지될 수 있습니다. 또한 시간이 지남에 따라 이러한 CMS 약관을 업데이트할 수 있으며, 중요한 변경 사항은 관리자 또는 이메일을 통해 전달됩니다."},"accept":"이용 약관을 읽고 동의합니다.","continue":"구성으로 계속","back":"뒤로"},"sections":{"firebase":"Firebase","admin":"부트스트랩 관리자","flexweg":"Flexweg API"},"help":{"firebase":"이 값은 Firebase 콘솔 → 프로젝트 설정 → 일반 → 내 앱 → SDK 설정 및 구성에서 찾을 수 있습니다.","admin":"Firebase Authentication의 기존 사용자를 사용하세요. 이 이메일로 로그인하는 사람은 관리자로 처리되며 사용자 레코드 확인을 우회합니다. 사용자가 없으면 Firebase 콘솔 → Authentication에서 만드세요.","flexweg":"Flexweg 계정 → API에서 영구 API 키를 생성하세요. 사이트 URL은 Flexweg 사이트의 공개 주소입니다(예: https://your-site.flexweg.com).","flexwegApiKeyHint":"Flexweg 계정 설정에서 API 키를 받으세요.","flexwegApiKeyLink":"계정 설정 열기"},"fields":{"apiKey":"API 키","authDomain":"인증 도메인","projectId":"프로젝트 ID","storageBucket":"스토리지 버킷","messagingSenderId":"메시징 발신자 ID","appId":"앱 ID","adminEmail":"이메일","adminPassword":"비밀번호","flexwegApiKey":"API 키","flexwegSiteUrl":"사이트 URL","flexwegApiBaseUrl":"API 기본 URL","sqlitePath":"SQLite 경로"},"submit":"저장하고 계속","submitting":"설정 중…","success":"설정 완료!","reloadingHint":"잠시 후 관리자 페이지가 새로고침됩니다. 잠시만 기다려 주세요.","footer":"이 값은 프로젝트(Firestore + Flexweg)에 저장됩니다. 다른 곳으로 전송되지 않습니다.","steps":{"signInFirebase":"Firebase에 로그인 중…","testFlexweg":"Flexweg API 테스트 중…","writeFirestore":"구성 저장 중…","uploadConfig":"config.js를 Flexweg에 업로드 중…","syncThemes":"테마 에셋을 Flexweg에 동기화하는 중…","sqliteInstall":"범위가 한정된 SQLite 토큰 생성 중…","sqliteRegisterAdmin":"관리자 계정 등록 중…","sqliteSchema":"SQLite 스키마 초기화 중…"},"stepsDone":{"sqliteInstall":"범위가 한정된 SQLite 토큰이 발급되었습니다","sqliteRegisterAdmin":"관리자가 등록되고 로그인되었습니다","sqliteSchema":"SQLite 스키마가 준비되었습니다"},"errors":{"missingFields":"모든 필드를 입력해 주세요.","rootDeploymentTitle":"관리자는 사이트 루트가 아닌 하위 폴더에 있어야 합니다.","rootDeploymentHint":"관리자 파일(index.html, config.js, runtime/, …)을 Flexweg의 하위 폴더로 이동하세요 — 예를 들어 /admin/ 또는 보안을 위한 무작위 이름인 /erf34f654GH3/ 등으로. 그런 다음 해당 하위 폴더 URL에서 관리자를 다시 로드하고 설정을 다시 실행하세요.","firebaseAuthGeneric":"Firebase 로그인에 실패했습니다.","firebaseAuthInvalidCredential":"Firebase가 이메일과 비밀번호 조합을 거부했습니다.","firebaseAuthInvalidCredentialHint":"최신 Firebase 프로젝트는 이메일 열거 방지가 기본으로 켜져 있어, 비밀번호가 틀렸을 때, 사용자가 존재하지 않을 때, 또는 사용자가 다른 제공업체로 로그인할 때 모두 같은 오류를 반환합니다. 확인 사항:\\n• 비밀번호를 다시 입력하세요 — 오타를 배제하기 위해 비밀번호 관리자에서 복사/붙여넣기하세요. 최소 길이는 6자입니다.\\n• Firebase 콘솔 → Authentication → Users를 열어 이메일이 존재하는지 확인하세요. 'Providers' 열을 확인하세요: 'Email/Password'가 없고 Google(또는 다른 제공업체)만 표시되면, 행 메뉴(⋮ → 비밀번호 재설정)에서 비밀번호를 설정하거나 재설정하세요.\\n• 이메일 철자가 Firebase에 저장된 값과 정확히 일치하는지 확인하세요.","firebaseAuthUserNotFound":"이 이메일을 사용하는 Firebase 사용자가 없습니다. 먼저 Firebase 콘솔 → Authentication → Users에서 만드세요.","firebaseAuthInvalidEmail":"관리자 이메일이 유효한 주소가 아닙니다.","firebaseInvalidApiKey":"Firebase API 키가 잘못되었습니다. Firebase 콘솔에서 값을 다시 확인하세요.","firebaseNetwork":"Firebase 로그인 중 네트워크 오류가 발생했습니다. 연결을 확인하세요.","firebaseTooManyRequests":"로그인 시도가 너무 많습니다. 잠시 후 다시 시도하거나 Firebase 콘솔에서 비밀번호를 재설정하세요.","firebaseOperationNotAllowed":"이 Firebase 프로젝트에서는 이메일/비밀번호 로그인이 활성화되어 있지 않습니다. Firebase 콘솔 → Authentication → Sign-in method를 열어 Email/Password 제공업체를 활성화하세요.","firebaseUserDisabled":"이 Firebase 사용자 계정은 비활성화되어 있습니다. Firebase 콘솔 → Authentication → Users에서 다시 활성화하세요.","wrongAdminEmail":"로그인한 Firebase 계정이 입력한 관리자 이메일과 일치하지 않습니다. 다시 시도하세요.","rulesNotPinnedTitle":"Firestore 규칙이 아직 부트스트랩 관리자로 인식하지 못합니다.","rulesNotPinnedHint":"Firebase 콘솔 → Firestore → 규칙을 열고 \`bootstrapAdminEmail()\`의 값을 다음으로 교체하세요: {{email}} — 그런 다음 게시를 클릭하세요. README의 규칙 템플릿에는 자리표시자 \`you@example.com\`이 있으며, 실제 관리자 이메일로 교체해야 합니다. 업데이트된 규칙을 게시한 후 여기에서 제출을 다시 클릭하세요.","flexwegAuth":"Flexweg API 키가 거부되었습니다. Flexweg 계정 → API에서 값을 확인하세요.","flexwegNetwork":"Flexweg에 연결하는 중 네트워크 오류가 발생했습니다. API 기본 URL과 연결을 확인하세요.","flexwegHttp":"Flexweg API 오류 ({{status}}): {{detail}}","firestoreRulesTitle":"Firestore가 구성 쓰기를 거부했습니다.","firestoreRulesHint":"Firebase 콘솔 → Firestore → 규칙을 열고 부트스트랩 관리자 이메일이 '{{email}}'로 설정되어 있는지 확인하세요. README에 복사해서 붙여 넣을 수 있는 규칙 템플릿이 있습니다.","firestoreOther":"Firestore 쓰기 실패","uploadFailed":"config.js를 Flexweg에 업로드할 수 없습니다","generic":"문제가 발생했습니다."},"docstore":{"contentTitle":"콘텐츠 저장소","contentIntro":"게시물, 페이지, 설정이 Markdown + JSON 파일로 저장되는 곳입니다. 빈 저장소도 괜찮습니다 — CMS가 파일을 생성합니다.","provider":"저장소","localClone":"로컬 폴더 (git 클론)","localCloneHint":"클론한 폴더를 선택하세요. 평소 사용하는 git 클라이언트로 동기화하세요 — CMS는 파일을 읽고 쓸 뿐 git을 실행하지 않습니다.","contentDir":"저장소 내 콘텐츠 폴더","privateRepo":"비공개 저장소를 사용하세요: 초안이 그곳에 저장됩니다.","folderRequired":"먼저 콘텐츠 폴더를 선택하세요.","checking":"저장소 접근 권한 확인 중…","publishIntro":"생성된 사이트가 게시되는 곳입니다. 나중에 설정에서 변경할 수 있습니다.","existingSite":"이 저장소는 이미 설정되어 있습니다 — 사이트는 계속 다음 위치에 게시됩니다: {{target}}. 나중에 설정에서 변경할 수 있습니다 (비밀 키가 있다면 그곳에서 다시 입력해야 합니다).","install":"설치","steps":{"config":"구성 저장 중…","content":"콘텐츠 불러오는 중…","target":"게시 대상 저장 중…","testTarget":"게시 대상 테스트 중…"},"doneTitle":"모두 준비되었습니다!","doneBody":"구성이 이 브라우저에 저장되었습니다. 다른 편집자가 이 설정을 반복하지 않도록 config.js를 다운로드해 호스팅의 관리자 폴더에 있는 파일을 교체하세요.","downloadConfig":"config.js 다운로드","open":"관리자 열기","footer":"콘텐츠는 저장소 또는 이 브라우저에 남으며, 액세스 토큰은 절대 이 브라우저 밖으로 나가지 않습니다."},"data":{"title":"1. 데이터를 어디에 저장하시겠어요?","intro":"게시물, 페이지, 사용자, 설정 — 관리자 자체의 데이터입니다. 공개 사이트를 호스팅하는 위치(다음 단계)와는 별개입니다.","localNote":"설정할 것이 없습니다: 콘텐츠는 이 브라우저에 저장됩니다. 백업하거나 나중에 옮기려면 설정에서 내보내세요.","options":{"sqlite-file":{"title":"SQLite","hint":"다음 단계에서 선택하는 호스팅(Flexweg, 자체 서버, S3, Git…)에 저장되는 SQLite 데이터베이스입니다. 사용자 계정이 없습니다 — Flexweg에서 호스팅한다면 계정이 포함된 Flexweg의 SQLite 서비스를 사용할 수도 있습니다."},"flexweg-sqlite":{"title":"SQLite (Flexweg 서비스)","hint":"Flexweg 서비스가 운영하는 SQLite 데이터베이스로, 사용자 계정이 내장되어 있습니다. 사이트를 어디에서 호스팅하든 Flexweg 계정이 필요합니다."},"firebase":{"title":"Firebase","hint":"Google 프로젝트의 Firestore + Firebase Auth. 실시간, 무료 Spark 요금제."},"markdown-git":{"title":"Git의 Markdown 파일","hint":"게시물을 GitHub / GitLab 저장소(또는 로컬 클론)의 .md 파일로 저장합니다. 각 편집자는 자신의 토큰을 사용하며, 모든 변경은 커밋이 됩니다."},"local":{"title":"이 브라우저","hint":"단일 사용자, 로그인 없음, 설정할 것 없음. 컴퓨터에서 실행하는 관리자에 적합합니다."}}},"hosting":{"title":"2. 사이트를 어디에 게시하시겠어요?","intro":"게시할 때마다 생성된 정적 사이트(HTML, CSS, 이미지)가 업로드되는 곳입니다. 나중에 설정에서 변경할 수 있습니다.","existing":"이 콘텐츠 저장소는 이미 아래 대상에 게시하고 있습니다. 그대로 유지하거나 다른 대상을 선택하세요."},"install":{"title":"3. 설치","intro":"요약을 확인한 후 설치하세요.","data":"데이터","hosting":"호스팅","saveTarget":"게시 대상 저장 중…","noteConfigJs":"관리자 구성(config.js)은 가능하면 Flexweg의 관리자 옆에 업로드됩니다. 그렇지 않으면 다운로드하도록 안내됩니다.","noteLocalConfig":"구성은 이 브라우저에 저장됩니다. 다른 편집자가 이 설정을 건너뛸 수 있도록 관리자 폴더에 넣을 config.js가 제공됩니다."},"sqliteFile":{"security":"사용자 계정이 없습니다. 이 관리자 화면을 열 수 있는 사람은 누구나 콘텐츠를 수정할 수 있으니 호스팅에서 관리자 폴더를 보호하세요. 데이터베이스 파일은 다른 파일처럼 공개적으로 제공되므로 암호화하거나 별도의 비공개 위치에 저장하세요.","intro":"데이터베이스 파일이 저장되는 위치입니다. 이 관리자는 호스팅과 동일한 커넥터를 통해 파일을 읽고 저장합니다.","path":"데이터베이스 파일 경로","pathHint":"아직 없으면 처음 저장할 때 생성됩니다. Git 저장소를 사용하면 저장할 때마다 커밋이 생성되므로 — 사이트 빌드를 트리거하지 않는 저장소나 브랜치를 사용하세요.","existing":"기존 데이터베이스","new":"새 데이터베이스","dataNote":"여기서는 설정할 것이 없습니다: 데이터베이스는 다음 단계에서 선택하는 호스팅에 저장됩니다.","heading":"SQLite 데이터베이스","flexwegService":"Flexweg의 SQLite 서비스 사용","flexwegServiceHint":"데이터베이스는 Flexweg가 운영하며 사용자 계정(이메일 + 비밀번호)이 내장되어 있습니다. 그렇지 않으면 계정 없이 이 호스팅에 저장되는 일반 파일입니다.","summaryFile":"이 호스팅의 파일 {{path}}","summaryService":"Flexweg SQLite 서비스 ({{path}})","encrypt":"데이터베이스 암호화","encryptHint":"공개 호스팅에서 권장: 암호 문구 없이는 파일을 읽을 수 없습니다. 새 브라우저마다 한 번 입력합니다.","passphrase":"암호 문구","passphraseHint":"지금 비밀번호 관리자에 저장하세요. 암호 문구가 없으면 본인을 포함해 누구도 데이터베이스를 열 수 없습니다.","copy":"복사","copied":"복사됨","generate":"새로 만들기","passphraseTooShort":"암호 문구는 12자 이상이어야 합니다.","existingEncrypted":"이 경로에 암호화된 데이터베이스가 이미 있습니다. 해당 암호 문구를 입력하세요.","separate":"데이터베이스를 별도의 비공개 위치에 저장","separateHint":"예: 비공개 S3 / R2 버킷 또는 비공개 Git 저장소. 이렇게 하면 공개 사이트가 데이터베이스를 제공하지 않습니다.","summaryEncrypted":"암호화됨","summaryLocation":"{{location}}에 저장됨","locationLabel":"데이터베이스 위치","gitBranchNote":"데이터베이스는 게시되지 않는 이 저장소의 {{branch}} 브랜치에 보관됩니다. 콘텐츠를 저장해도 사이트가 다시 빌드되지 않습니다.","summaryBranch":"{{branch}} 브랜치"},"adminHosting":{"deploying":"관리자를 사이트에 복사하는 중…","label":"이 사이트에 관리자도 호스팅","hint":"관리자가 config.js(비밀 정보 없음)와 함께 {{url}}에 복사되며, 모든 편집자가 그곳에서 열 수 있습니다. 각 편집자는 여전히 자신의 액세스로 로그인합니다.","folder":"관리자 폴더","alreadyHere":"이 관리자는 이미 이 사이트에서 실행 중입니다. config.js가 그 자리에서 업데이트됩니다.","doneBody":"관리자가 이제 사이트에 있습니다. GitHub Pages를 사용한다면 아직 활성화하지 않은 경우 먼저 저장소의 Pages를 활성화한 다음(Settings → Pages) 여세요:","open":"온라인 관리자 열기","continueHere":"이 관리자에서 계속하기"}}`),Eie={actions:{upload:"파일 업로드",delete:"파일 삭제",rename:"파일 이름 변경",get:"파일 읽기",list:"파일 목록 조회",createFolder:"폴더 생성",renameFolder:"폴더 이름 변경",deleteFolder:"폴더 삭제",storageLimits:"저장 용량 한도 조회",commit:"변경 사항 게시 중"},errors:{configMissing:"게시 대상이 설정되지 않았습니다. 게시하기 전에 설정에서 구성하세요.",network:"{{action}}: 네트워크 오류 또는 CORS가 차단되었습니다. 연결 상태를 확인하세요.",auth:"{{action}}: 인증에 실패했습니다. 설정에서 게시 대상 자격 증명을 확인하세요.",notFound:"{{action}}: 게시 대상에서 찾을 수 없습니다.",tooLarge:"{{action}}: 게시 대상에 비해 파일이 너무 큽니다.",rateLimited:"{{action}}: 요청이 너무 많습니다. 잠시 후 다시 시도하세요.",serverError:"{{action}}: 게시 대상 서버 오류({{status}}). 다시 시도하세요.",generic:"{{action}} 실패 ({{status}}){{detail}}.",unsupported:'{{action}}: "{{connector}}" 게시 대상에서 지원되지 않습니다.',unknownConnector:'알 수 없는 게시 대상 "{{connector}}". 설정 → 게시 대상을 확인하세요.',folderAccess:"로컬 폴더에 접근할 수 없습니다. 설정 → 게시 대상에서 “폴더 다시 연결”을 클릭하세요."}},_ie={log:{rendering:"페이지 렌더링 중…",uploading:"{{path}} 업로드 중…",deleting:"{{path}} 삭제 중…",regenerating:"목록 재생성 중…",skipped:"{{path}} 건너뜀 (변경 없음)",done:"{{url}}에 게시됨",failed:"실패: {{error}}"}},Cie={errors:{notConnected:"콘텐츠 저장소에 연결되어 있지 않습니다. 액세스 토큰으로 다시 로그인하세요.",conflict:"그 사이 다른 사람이 이 항목을 변경했습니다. 이제 그 버전이 표시됩니다 — 변경 사항을 다시 적용하세요.",sqliteUnsupported:'"{{connector}}" 대상에는 데이터베이스 파일을 저장할 수 없습니다.'}},Aie={target:"게시 대상",settingsTitle:"게시 대상",settingsHelp:"게시할 때 렌더링된 사이트가 업로드되는 곳입니다. 자격 증명은 콘텐츠 백엔드에 저장되며 (Git 콘텐츠 저장소의 경우 이 브라우저에 보관) 모든 관리자가 읽을 수 있습니다.",saved:"게시 대상이 저장되었습니다. 재생성 → 전체를 실행해 사이트 전체를 새 대상에 게시하세요.",test:"연결 테스트",testOk:"연결 정상",testFailed:"연결 실패",names:{flexweg:"Flexweg","git-pages":"Git 저장소 (GitHub Pages, Cloudflare Pages, GitLab Pages…)",s3:"S3 호환 버킷 (AWS S3, Cloudflare R2, Backblaze B2, OVH…)","php-bridge":"자체 서버 (PHP 브리지)","browser-mirror":"ZIP으로 다운로드","local-folder":"이 컴퓨터의 로컬 폴더"},hints:{flexweg:"Flexweg Files API를 통해 업로드합니다.","git-pages":"게시할 때마다 저장소에 커밋 하나가 생성되며, 호스트가 이를 바탕으로 사이트를 다시 빌드합니다.",s3:"버킷에 이 관리자의 오리진을 허용하는 CORS 규칙이 필요하며, index.html 파일을 제공하려면 웹사이트 호스팅 (또는 CDN)이 필요합니다.","php-bridge":"external/bridges/php/flexweg-bridge.php를 서버에 업로드하고 API 키를 설정한 다음 여기에 URL을 입력하세요.","browser-mirror":"사이트는 이 브라우저에 보관됩니다. ZIP을 다운로드해 원하는 곳에 직접 업로드하세요.","local-folder":"사이트를 폴더에 바로 기록합니다 (Chrome / Edge). 로컬에서 제공하거나 자신의 도구로 푸시하세요."},fields:{flexweg:{apiKey:"API 키",siteUrl:"사이트 URL",apiBaseUrl:"API 기본 URL"},"git-pages":{host:"호스팅",provider:"Git 제공자",owner:"소유자 (사용자 또는 조직)",repo:"저장소",project:"프로젝트 경로",branch:"브랜치",dir:"저장소 내 폴더",token:"액세스 토큰",siteUrl:"공개 사이트 URL",apiBaseUrl:"API URL (자체 호스팅 전용)"},s3:{endpoint:"엔드포인트",region:"리전",bucket:"버킷",prefix:"키 접두사 (선택 사항)",accessKeyId:"액세스 키 ID",secretAccessKey:"비밀 액세스 키",siteUrl:"공개 사이트 URL",forcePathStyle:"경로 스타일 URL (MinIO, R2, 대부분의 호환 서비스)",publicRead:"업로드한 파일을 공개로 설정(ACL public-read) — 버킷 정책으로 공개되지 않은 버킷용(OVHcloud, Scaleway 등). ‘bucket owner enforced’를 사용하는 AWS 버킷에서는 꺼 두세요."},"php-bridge":{apiBaseUrl:"브리지 URL",apiKey:"브리지 API 키",siteUrl:"공개 사이트 URL"},"browser-mirror":{siteUrl:"공개 사이트 URL (선택 사항)"},"local-folder":{siteUrl:"폴더가 제공되는 URL (선택 사항)"}},help:{flexweg:{apiKey:"Flexweg 계정 → API에서 생성합니다."},"git-pages":{host:"Cloudflare Pages: 빌드 명령 없이 아래 출력 폴더로 프로젝트를 이 저장소에 연결하세요. 비공개 저장소에서도 작동합니다.",dir:'저장소 루트를 사용하려면 비워 두세요. GitHub Pages: "" 또는 "docs". GitLab Pages: "public".',token:"이 저장소에 대해 Contents: read & write 권한이 있는 세분화된(fine-grained) 토큰(GitHub) — CMS가 GitHub Pages를 활성화하도록 하려면 Pages: read & write를 추가하세요 — 또는 api 스코프가 있는 토큰(GitLab). 콘텐츠가 같은 제공자에 있다면 비워 두어 각 편집자의 액세스 토큰을 사용하세요.",siteUrl:"예: https://user.github.io/repo — 하위 폴더 URL도 괜찮으며, 링크는 자동으로 조정됩니다."},s3:{endpoint:"AWS는 비워 두세요 (리전에서 자동 구성됨). R2: https://<account-id>.r2.cloudflarestorage.com",siteUrl:"버킷 웹사이트 URL 또는 CDN 도메인."},"php-bridge":{apiBaseUrl:"서버에 있는 flexweg-bridge.php의 전체 URL (HTTPS)."},"browser-mirror":{siteUrl:"ZIP을 업로드할 위치 — 절대 URL (사이트맵, RSS, 미디어)에 사용됩니다."},"local-folder":{siteUrl:"예: 로컬 웹 서버가 폴더를 제공하는 경우 http://localhost:8080."}},options:{"github-pages":"GitHub Pages","cloudflare-pages":"Cloudflare Pages (저장소에 연결됨)","gitlab-pages":"GitLab Pages",other:"기타 (Netlify, Vercel, 서버 git pull…)",github:"GitHub",gitlab:"GitLab"},folder:{choose:"폴더 선택…",change:"폴더 변경…",reconnect:"폴더 다시 연결",unsupported:"이 브라우저는 로컬 폴더에 쓸 수 없습니다. Chrome 또는 Edge를 사용하세요."},mirror:{download:"사이트 다운로드 (ZIP)",count:"이 브라우저에 있는 파일 {{count}}개"},adminHosting:{title:"이 사이트의 관리자",help:"이 관리자를 게시 대상에 복사합니다(최초 배포 또는 새 버전 이후 업데이트). config.js에는 비밀 정보가 없습니다.",deploy:"관리자 배포 / 업데이트",deployed:"관리자 배포 완료 ({{count}}개 파일) — {{url}}"},pages:{enabled:"이 저장소에 GitHub Pages가 활성화되었습니다 — 약 1분 후 사이트가 온라인 상태가 됩니다.",enableHint:'게시에 성공했습니다. 사이트를 온라인으로 만들려면 {{repo}}에 대해 GitHub Pages를 활성화하세요: Settings → Pages → Deploy from a branch → {{branch}} / {{folder}}. (또는 토큰에 "Pages: read and write" 권한을 부여하면 CMS가 대신 처리합니다.)'},siteUrl:{mismatch:"사이트 공개 URL(설정 → 사이트)은 {{site}}이지만, 이 대상은 사이트를 {{target}}에서 제공합니다. 링크, CSS, 사이트맵은 사이트 URL을 따르므로 이 호스팅에서는 잘못됩니다.",use:"사이트에 {{url}} 사용",updated:"사이트 URL을 업데이트했습니다. 재생성 → 전체를 실행해 새 링크로 페이지를 다시 게시하세요."}},Tie={heading:"콘텐츠 저장소에 연결",tokenIntro:"콘텐츠는 {{provider}} 저장소 {{repo}}에 저장됩니다. 자신의 개인 액세스 토큰으로 로그인하세요 — 저장소 권한에 따라 역할이 결정됩니다 (쓰기 권한 = 편집자, admin / maintainer = 관리자).",token:"개인 액세스 토큰",tokenHelpGithub:"이 저장소에만 접근 가능한 fine-grained 토큰, Contents 권한: 읽기 및 쓰기.",tokenHelpGitlab:"api scope가 있는 토큰, 이 프로젝트에서 Developer 이상의 역할.",createToken:"토큰 만들기",connect:"연결",tokenStorage:"토큰은 이 브라우저에만 보관됩니다. 로그아웃하면 삭제됩니다.",failed:"이 토큰으로는 저장소에 쓸 수 없습니다 (유효하지 않음, 만료됨 또는 읽기 전용). 권한을 확인하세요.",folderIntro:"콘텐츠는 이 컴퓨터의 폴더에 저장됩니다 (보통 자신의 git 클라이언트로 동기화하는 git 클론). 이 브라우저에 접근 권한을 허용하세요 — 브라우저는 새로고침할 때마다 다시 묻습니다.",openFolder:"콘텐츠 폴더 열기"},Iie={flexweg:{title:"Flexweg",short:"Flexweg 호스팅",hint:"Flexweg Files API를 통해 업로드합니다. Flexweg 계정의 API 키를 사용하세요."},"github-pages":{title:"GitHub Pages",short:"무료, GitHub 저장소에서",hint:"게시할 때마다 저장소에 커밋 하나가 생성되고 GitHub Pages가 이를 제공합니다. Settings → Pages → Deploy from a branch. 무료 요금제는 공개 저장소만 가능합니다."},"cloudflare-pages":{title:"Cloudflare Pages",short:"무료, 비공개 저장소 가능",hint:"CMS가 사이트를 GitHub / GitLab 저장소에 커밋합니다. 여기에 Cloudflare Pages 프로젝트를 연결하세요(빌드 명령 없음, 출력 폴더 = 아래 폴더)."},"gitlab-pages":{title:"GitLab Pages",short:"무료, GitLab 저장소에서",hint:"게시할 때마다 커밋 하나가 생성됩니다. CMS가 public/ 폴더를 게시하는 최소한의 .gitlab-ci.yml을 추가합니다."},"git-other":{title:"Netlify, Vercel…",short:"저장소를 배포하는 모든 호스트",hint:"CMS가 사이트를 Git 저장소에 커밋합니다. 호스트(Netlify, Vercel, git pull을 실행하는 서버…)를 해당 저장소에 연결하세요."},s3:{title:"S3 / R2 / B2…",short:"오브젝트 스토리지 버킷",hint:"AWS S3, Cloudflare R2, Backblaze B2, OVH, Scaleway, MinIO… 버킷에 CORS 규칙과 웹사이트 호스팅 또는 앞단의 CDN이 필요합니다."},"own-server":{title:"자체 서버 (FTP / SFTP)",short:"공유 호스팅, VPS…",hint:"브라우저는 FTP나 SFTP를 사용할 수 없습니다: FTP 클라이언트로 PHP 브리지(external/bridges/php/flexweg-bridge.php)를 한 번 업로드하고 API 키를 설정한 다음, 여기에 해당 URL을 입력하세요. 모든 PHP 호스트에서 작동합니다."},"local-folder":{title:"로컬 폴더",short:"이 컴퓨터에",hint:"사이트를 이 컴퓨터의 폴더에 씁니다(Chrome / Edge). 로컬에서 제공하거나 자체 도구로 푸시하세요."},zip:{title:"ZIP으로 다운로드",short:"직접 업로드",hint:"사이트는 이 브라우저에 보관됩니다. 설정에서 ZIP을 다운로드해 원하는 곳(Netlify Drop, FTP 클라이언트…)에 업로드하세요."}},Nie={heading:"데이터베이스에 연결",intro:"이 관리자는 콘텐츠를 {{path}}에 저장합니다. 이 브라우저의 액세스 자격 증명을 입력하세요.",storage:"자격 증명은 이 브라우저에만 보관됩니다. 로그아웃하면 삭제됩니다.",passphrase:"데이터베이스 암호 문구",passphraseHint:"데이터베이스가 암호화되어 있습니다. 설치 시 정한 암호 문구를 입력하세요(이 브라우저에만 저장됩니다).",passphraseWrong:"암호 문구가 올바르지 않아 데이터베이스를 열 수 없습니다.",passphraseMissing:"데이터베이스 암호 문구를 입력하세요."},Pie={common:iie,auth:aie,nav:oie,dashboard:lie,posts:cie,pages:uie,taxonomies:die,media:hie,themes:fie,plugins:pie,externalInstall:mie,externalLoader:gie,menus:bie,settings:yie,users:vie,firestoreSetup:xie,errors:wie,identity:kie,setup:Sie,flexweg:Eie,publish:_ie,docstore:Cie,connectors:Aie,gitAccess:Tie,hosting:Iie,sqliteAccess:Nie},r1=["en","fr","de","es","nl","pt","ko"],KA="en",PO="adminLocale",r_={fr:"🇫🇷 Français",en:"🇬🇧 English",de:"🇩🇪 Deutsch",es:"🇪🇸 Español",nl:"🇳🇱 Nederlands",pt:"🇵🇹 Português",ko:"🇰🇷 한국어"},Rie={fr:"🇫🇷",en:"🇬🇧",de:"🇩🇪",es:"🇪🇸",nl:"🇳🇱",pt:"🇵🇹",ko:"🇰🇷"};function Jy(t){return typeof t=="string"&&r1.includes(t)}function nh(t,e=KA){var r;const n=(r=(t??"").split("-")[0])==null?void 0:r.toLowerCase();return n&&r1.includes(n)?n:e}function jie(t){var e;if(Jy(t))return t;if(typeof window<"u"){const n=window.localStorage.getItem(PO);if(Jy(n))return n}if(typeof navigator<"u"&&typeof navigator.language=="string"){const n=(e=navigator.language.split("-")[0])==null?void 0:e.toLowerCase();if(Jy(n))return n}return KA}function Mie(t){try{window.localStorage.setItem(PO,t)}catch{}}jt.use(Q6).init({resources:{en:{translation:Pne},fr:{translation:sre},de:{translation:Pre},es:{translation:sse},nl:{translation:Pse},pt:{translation:sie},ko:{translation:Pie}},lng:jie(),fallbackLng:KA,interpolation:{escapeValue:!1},returnNull:!1,react:{useSuspense:!1}});async function s1(t){Jy(t)&&(Mie(t),await jt.changeLanguage(t))}const Lie="flexweg-git-blobs",Ag="texts",s_=new Map;let ty=null;function RO(){return ty||(ty=new Promise(t=>{try{if(typeof indexedDB>"u")return t(null);const e=indexedDB.open(Lie,1);e.onupgradeneeded=()=>e.result.createObjectStore(Ag),e.onsuccess=()=>t(e.result),e.onerror=()=>t(null),e.onblocked=()=>t(null)}catch{t(null)}}),ty)}async function jO(t){const e=new Map,n=[];for(const s of t){const i=s_.get(s);i!==void 0?e.set(s,i):n.push(s)}if(n.length===0)return e;const r=await RO();return r&&await new Promise(s=>{try{const i=r.transaction(Ag,"readonly"),a=i.objectStore(Ag);for(const o of n){const l=a.get(o);l.onsuccess=()=>{typeof l.result=="string"&&(e.set(o,l.result),s_.set(o,l.result))}}i.oncomplete=()=>s(),i.onerror=()=>s(),i.onabort=()=>s()}catch{s()}}),e}async function MO(t){for(const[n,r]of t)s_.set(n,r);const e=await RO();!e||t.size===0||await new Promise(n=>{try{const r=e.transaction(Ag,"readwrite"),s=r.objectStore(Ag);for(const[i,a]of t)s.put(a,i);r.oncomplete=()=>n(),r.onerror=()=>n(),r.onabort=()=>n()}catch{n()}})}function JA(t){let e="";for(let r=0;r<t.length;r+=32768)e+=String.fromCharCode(...t.subarray(r,r+32768));return btoa(e)}function rp(t){const e=atob(t.replace(/\s+/g,"")),n=new Uint8Array(e.length);for(let r=0;r<e.length;r++)n[r]=e.charCodeAt(r);return n}function Die(t){return JA(new TextEncoder().encode(t))}function LO(t){return new TextDecoder().decode(rp(t))}function Fie(t){return t.encoding==="base64"?rp(t.content):new TextEncoder().encode(t.content)}const i_=new Set;function Oie(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,8)}`}function ny(t){const e={...t,id:Oie(),createdAt:Date.now()};return i_.forEach(n=>{try{n(e)}catch(r){console.error("Toast subscriber threw:",r)}}),e}const at={info:(t,e)=>ny({level:"info",message:t,durationMs:e}),success:(t,e)=>ny({level:"success",message:t,durationMs:e}),warn:(t,e)=>ny({level:"warn",message:t,durationMs:e}),error:(t,e)=>ny({level:"error",message:t,durationMs:e})};function zie(t){return i_.add(t),()=>i_.delete(t)}function Uie(t){switch(t){case"error":return 6e3;case"warn":return 5e3;default:return 3500}}class Ns extends Error{constructor(e,n,r){super(e),this.status=n,this.body=r,this.name="StorageError"}}function QA(t){return jt.t(`flexweg.actions.${t}`)}function Bie(t){if(!t)return"";let e=t.trim();try{const n=JSON.parse(e);e=n.error??n.message??e}catch{}return e.length>240&&(e=e.slice(0,240)+"…"),e}function $ie(t,e,n){const r=QA(t),s=Bie(n);switch(e){case 401:case 403:return jt.t("flexweg.errors.auth",{action:r});case 404:return jt.t("flexweg.errors.notFound",{action:r});case 413:return jt.t("flexweg.errors.tooLarge",{action:r});case 429:return jt.t("flexweg.errors.rateLimited",{action:r});case 500:case 502:case 503:case 504:return jt.t("flexweg.errors.serverError",{action:r,status:e});default:return jt.t("flexweg.errors.generic",{action:r,status:e,detail:s?`: ${s}`:""})}}async function Hs(t,e){let n;try{n=await e()}catch(a){throw(a==null?void 0:a.name)==="AbortError"||at.error(jt.t("flexweg.errors.network",{action:QA(t)})),a}if(n.ok)return n;const r=await n.text().catch(()=>""),s=(t==="delete"||t==="deleteFolder")&&n.status===404,i=$ie(t,n.status,r);throw s||at.error(i),new Ns(i,n.status,r)}function i1(t,e){const n=jt.t("flexweg.errors.unsupported",{action:QA(t),connector:e});return at.error(n),new Ns(n,501)}async function Ka(t,e,n,r=[]){let s;try{s=await fetch(e,n)}catch(i){return Hs(t,()=>Promise.reject(i))}return s.ok||r.includes(s.status)?s:Hs(t,async()=>s)}async function XA(t,e,n){const r=new Array(t.length);let s=0;async function i(){for(;s<t.length;){const a=s++;r[a]=await n(t[a])}}return await Promise.all(Array.from({length:Math.min(e,t.length)},i)),r}class Hc extends Error{constructor(e,n){super(e),this.currentHeadSha=n,this.name="GitConflictError"}}const YR=300,ej=50,Hie=3;function Vie(t){const e=(t.apiBaseUrl||"https://api.github.com").replace(/\/+$/,""),n=e.endsWith("/api/v3")?e.replace(/\/api\/v3$/,"/api/graphql"):`${e}/graphql`,r=`${e}/repos/${encodeURIComponent(t.owner)}/${encodeURIComponent(t.repo)}`,s=`heads/${t.branch.split("/").map(encodeURIComponent).join("/")}`,i={Authorization:`Bearer ${t.token}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28"},a={...i,"Content-Type":"application/json"};async function o(P,D="get"){return await(await Ka(D,P,{headers:i,cache:"no-store"})).json()}async function l(P,D,I="POST"){return await(await Ka("commit",P,{method:I,headers:a,body:JSON.stringify(D)})).json()}async function c(){var I;const P=await Ka("get",`${r}/git/ref/${s}`,{headers:i,cache:"no-store"},[404,409]);if(!P.ok)return"";const D=await P.json();return Array.isArray(D)?"":((I=D.object)==null?void 0:I.sha)??""}async function h(P){return(await o(`${r}/git/commits/${P}`)).tree.sha}async function p(P,D,I){const L=await o(`${r}/git/trees/${P}`,"list");for(const j of L.tree){const q=D+j.path;j.type==="blob"?I.push({path:q,sha:j.sha,size:j.size}):j.type==="tree"&&await p(j.sha,q+"/",I)}}async function m(P){if(!P)return{headSha:"",entries:[]};const D=await h(P),I=await o(`${r}/git/trees/${D}?recursive=1`,"list");if(!I.truncated)return{headSha:P,entries:I.tree.filter(j=>j.type==="blob").map(j=>({path:j.path,sha:j.sha,size:j.size}))};const L=[];return await p(D,"",L),{headSha:P,entries:L}}async function g(P){return(await o(`${r}/git/blobs/${P}`)).content}async function y(P){var I;const D=new Map;for(let L=0;L<P.length;L+=ej){const j=P.slice(L,L+ej),V=`query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { ${j.map((O,$)=>`b${$}: object(oid: "${O}") { ... on Blob { text isBinary isTruncated } }`).join(`
|
|
3869
|
+
`)} } }`;try{const O=await fetch(n,{method:"POST",headers:a,body:JSON.stringify({query:V,variables:{owner:t.owner,name:t.repo}})});if(!O.ok)continue;const B=(I=(await O.json()).data)==null?void 0:I.repository;if(!B)continue;j.forEach((X,fe)=>{const ie=B[`b${fe}`];ie&&!ie.isBinary&&!ie.isTruncated&&typeof ie.text=="string"&&D.set(X,ie.text)})}catch{}}return D}async function x(P){const D=[...new Set(P.map(V=>V.sha))],I=await jO(D),L=D.filter(V=>!I.has(V)),j=new Map;if(L.length>0){const V=await y(L);for(const[$,B]of V)j.set($,B);const O=L.filter($=>!j.has($));await XA(O,6,async $=>{j.set($,LO(await g($)))}),await MO(j)}const q=new Map;for(const V of P){const O=I.get(V.sha)??j.get(V.sha);O!==void 0&&q.set(V.path,O)}return q}async function v(P){return rp(await g(P.sha))}async function k(P){const D=await o(r),I=D.default_branch?await Ka("get",`${r}/git/ref/heads/${encodeURIComponent(D.default_branch)}`,{headers:i,cache:"no-store"},[404,409]):null;if(!I||!I.ok)return(await l(`${r}/contents/.gitkeep`,{message:P,content:"",branch:t.branch},"PUT")).commit.sha;const L=await l(`${r}/git/trees`,{tree:[{path:".gitkeep",mode:"100644",type:"blob",content:""}]}),j=await l(`${r}/git/commits`,{message:P,tree:L.sha,parents:[]});return await l(`${r}/git/refs`,{ref:`refs/heads/${t.branch}`,sha:j.sha}),j.sha}async function C(P,D){const I=new Map;for(const L of P)if(L.type==="put"&&L.encoding==="base64"&&!I.has(L.path)){const j=await l(`${r}/git/blobs`,{content:L.content,encoding:"base64"});I.set(L.path,j.sha)}for(let L=0;;L++){let j=await c();if(D.expectedHeadSha!==void 0&&j!==D.expectedHeadSha)throw new Hc(`Branch ${t.branch} moved`,j);j||(j=await k("Initialize branch — AgentCMS"));const q=await h(j);let V=null;P.some(fe=>fe.type==="delete")&&(V=new Set((await m(j)).entries.map(fe=>fe.path)));const O=[];for(const fe of P)fe.type==="delete"?V!=null&&V.has(fe.path)&&O.push({path:fe.path,mode:"100644",type:"blob",sha:null}):fe.encoding==="base64"?O.push({path:fe.path,mode:"100644",type:"blob",sha:I.get(fe.path)}):O.push({path:fe.path,mode:"100644",type:"blob",content:fe.content});let $=q;for(let fe=0;fe<O.length;fe+=YR)$=(await l(`${r}/git/trees`,{base_tree:$,tree:O.slice(fe,fe+YR)})).sha;if($===q)return j;const B=await l(`${r}/git/commits`,{message:D.message,tree:$,parents:[j]});if((await Ka("commit",`${r}/git/refs/${s}`,{method:"PATCH",headers:a,body:JSON.stringify({sha:B.sha,force:!1})},[409,422])).ok)return B.sha;if(D.expectedHeadSha!==void 0)throw new Hc(`Branch ${t.branch} moved`,await c());if(L>=Hie)throw new Hc(`Branch ${t.branch} kept moving`,await c())}}async function N(P,D){const I=[];for(const V of P){const O=await l(`${r}/git/blobs`,{content:V.content,encoding:"base64"});I.push({path:V.path,mode:"100644",type:"blob",sha:O.sha})}const L=await l(`${r}/git/trees`,{tree:I}),j=await l(`${r}/git/commits`,{message:D.message,tree:L.sha,parents:[]}),q=await c();if(q!==D.expectedHeadSha)throw new Hc(`Branch ${t.branch} moved`,q);return await Ka("commit",`${r}/git/refs/${s}`,{method:"PATCH",headers:a,body:JSON.stringify({sha:j.sha,force:!0})}),j.sha}async function _(){const[P,D]=await Promise.all([o(`${e}/user`),o(r)]),I=D.permissions??{};return{login:P.login,canWrite:!!(I.push||I.maintain||I.admin),isAdmin:!!(I.admin||I.maintain)}}return{kind:"github",label:`${t.owner}/${t.repo}@${t.branch}`,headSha:c,listTree:async()=>m(await c()),readTexts:x,readBytes:v,commit:C,permissions:_,resetBranch:N}}const qie=3,Wie=30,Gie=40;function Kie(t){const e=(t.apiBaseUrl||"https://gitlab.com/api/v4").replace(/\/+$/,""),n=`${e}/projects/${encodeURIComponent(t.project)}`,r={Authorization:`Bearer ${t.token}`},s={...r,"Content-Type":"application/json"},i=new Map;async function a(v,k="get"){return await(await Ka(k,v,{headers:r,cache:"no-store"})).json()}async function o(){var C;const v=await Ka("get",`${n}/repository/branches/${encodeURIComponent(t.branch)}`,{headers:r,cache:"no-store"},[404]);return v.ok?((C=(await v.json()).commit)==null?void 0:C.id)??"":""}async function l(v){if(!v)return{headSha:"",entries:[]};const k=[];for(let C=1;;C++){const N=`${n}/repository/tree?${new URLSearchParams({ref:v,recursive:"true",per_page:"100",page:String(C)})}`,_=await Ka("list",N,{headers:r,cache:"no-store"}),P=await _.json();for(const I of P)I.type==="blob"&&k.push({path:I.path,sha:I.id});if(!_.headers.get("x-next-page")||P.length===0)break}return i.set(v,new Set(k.map(C=>C.path))),{headSha:v,entries:k}}async function c(v){return Ka("get",`${n}/repository/blobs/${v}/raw`,{headers:r})}async function h(v){const k=[...new Set(v.map(D=>D.sha))],C=await jO(k),N=k.filter(D=>!C.has(D)),_=new Map;await XA(N,6,async D=>{_.set(D,await(await c(D)).text())}),await MO(_);const P=new Map;for(const D of v){const I=C.get(D.sha)??_.get(D.sha);I!==void 0&&P.set(D.path,I)}return P}async function p(v){return new Uint8Array(await(await c(v.sha)).arrayBuffer())}async function m(v){return v?i.get(v)??new Set((await l(v)).entries.map(k=>k.path)):new Set}async function g(){return(await a(n)).default_branch||void 0}async function y(v,k){for(let C=0;;C++){const N=await o();if(k.expectedHeadSha!==void 0&&N!==k.expectedHeadSha)throw new Hc(`Branch ${t.branch} moved`,N);const _=await m(N),P=[],D=new Set(_);for(const j of v)if(j.type==="delete"){if(!_.has(j.path))continue;P.push({action:"delete",file_path:j.path}),D.delete(j.path)}else P.push({action:_.has(j.path)?"update":"create",file_path:j.path,encoding:"base64",content:j.encoding==="base64"?j.content:Die(j.content)}),D.add(j.path);if(P.length===0)return N;const I={branch:t.branch,commit_message:k.message,actions:P};if(!N){const j=await g();j&&j!==t.branch&&(I.start_branch=j)}const L=await Ka("commit",`${n}/repository/commits`,{method:"POST",headers:s,body:JSON.stringify(I)},[400]);if(L.ok){const j=await L.json();return i.set(j.id,D),j.id}if(i.delete(N),k.expectedHeadSha!==void 0||C>=qie)throw new Hc(`Commit on ${t.branch} rejected: ${await L.text()}`,await o())}}async function x(){var N,_,P,D;const[v,k]=await Promise.all([a(`${e}/user`),a(n)]),C=Math.max(((_=(N=k.permissions)==null?void 0:N.project_access)==null?void 0:_.access_level)??0,((D=(P=k.permissions)==null?void 0:P.group_access)==null?void 0:D.access_level)??0);return{login:v.username,canWrite:C>=Wie,isAdmin:C>=Gie}}return{kind:"gitlab",label:`${t.project}@${t.branch}`,headSha:o,listTree:async()=>l(await o()),readTexts:h,readBytes:p,commit:y,permissions:x}}const Jie=new Set([".git","node_modules",".DS_Store","Thumbs.db"]);function Fv(){return typeof window<"u"&&"showDirectoryPicker"in window}async function ZA(){const t=window.showDirectoryPicker;return t({mode:"readwrite",id:"flexweg-cms"})}async function _0(t,e){var s;const n=t,r={mode:"readwrite"};return await((s=n.queryPermission)==null?void 0:s.call(n,r))==="granted"?!0:!e||!n.requestPermission?!1:await n.requestPermission(r)==="granted"}function Qie(t){let e=2166136261;for(const n of t){const r=`${n.path}\0${n.sha}
|
|
3870
3870
|
`;for(let s=0;s<r.length;s++)e^=r.charCodeAt(s),e=Math.imul(e,16777619)}return`local-${t.length}-${(e>>>0).toString(16)}`}function DO(t){const e=t,n=new Map;async function r(p,m,g){for await(const[y,x]of p.entries()){if(Jie.has(y))continue;const v=m+y;if(x.kind==="directory")await r(x,v+"/",g);else{const k=await x.getFile();n.set(v,x),g.push({path:v,sha:`${k.size}:${k.lastModified}`,size:k.size})}}}async function s(){n.clear();const p=[];return await r(e,"",p),p.sort((m,g)=>m.path<g.path?-1:m.path>g.path?1:0),{headSha:Qie(p),entries:p}}async function i(p){const m=n.get(p);if(m)return m;const g=p.split("/");let y=e;for(const x of g.slice(0,-1))y=await y.getDirectoryHandle(x);return y.getFileHandle(g[g.length-1])}async function a(p){const m=new Map;for(const g of p)try{m.set(g.path,await(await(await i(g.path)).getFile()).text())}catch{}return m}async function o(p){const m=await(await i(p.path)).getFile();return new Uint8Array(await m.arrayBuffer())}async function l(p,m){const g=p.split("/");let y=e;for(const k of g.slice(0,-1))y=await y.getDirectoryHandle(k,{create:!0});const x=await y.getFileHandle(g[g.length-1],{create:!0}),v=await x.createWritable();await v.write(m),await v.close(),n.set(p,x)}async function c(p){const m=p.split("/");try{let g=e;for(const y of m.slice(0,-1))g=await g.getDirectoryHandle(y);await g.removeEntry(m[m.length-1])}catch{}n.delete(p)}async function h(p,m){if(m.expectedHeadSha!==void 0){const g=(await s()).headSha;if(g!==m.expectedHeadSha)throw new Hc("Folder changed on disk",g)}for(const g of p)g.type==="delete"?await c(g.path):await l(g.path,Fie(g));return(await s()).headSha}return{kind:"local",label:e.name,headSha:async()=>(await s()).headSha,listTree:s,readTexts:a,readBytes:o,commit:h,permissions:async()=>({login:"local",canWrite:await _0(t,!1),isAdmin:!0})}}const Xie="flexweg-folder-handles",Tg="handles";function FO(){return new Promise((t,e)=>{const n=indexedDB.open(Xie,1);n.onupgradeneeded=()=>n.result.createObjectStore(Tg),n.onsuccess=()=>t(n.result),n.onerror=()=>e(n.error)})}async function YA(t,e){const n=await FO();await new Promise((r,s)=>{const i=n.transaction(Tg,"readwrite");i.objectStore(Tg).put(e,t),i.oncomplete=()=>r(),i.onerror=()=>s(i.error)})}async function Cf(t){try{const e=await FO();return await new Promise(n=>{const r=e.transaction(Tg,"readonly").objectStore(Tg).get(t);r.onsuccess=()=>n(r.result??null),r.onerror=()=>n(null)})}catch{return null}}function Af(t){return t.provider==="github"?Vie(t):Kie(t)}function Ov(t,e){const n=t.replace(/^\/+|\/+$/g,""),r=e.replace(/^\/+/,"");return n?`${n}/${r}`:r}const tj="---",Zie=/^(?:true|false|null|yes|no|on|off|~|y|n)$/i,Yie=/^[-+]?(?:\d[\d_]*)?(?:\.\d+)?(?:e[-+]?\d+)?$|^0x[0-9a-f]+$|^\.(?:inf|nan)$/i,eae=/^[\p{L}\p{N}][\p{L}\p{N} _.,!?()&'/+-]*$/u;function tae(t){return t.length>0&&t.trim()===t&&eae.test(t)&&!Zie.test(t)&&!Yie.test(t)&&!t.includes(": ")&&!t.includes(" #")}function nae(t){return typeof t=="string"?tae(t)?t:JSON.stringify(t):t===null?"null":JSON.stringify(t)}function nj(t,e){const n=[tj];for(const[r,s]of Object.entries(t))s!==void 0&&n.push(`${r}: ${nae(s)}`);return n.push(tj,""),n.join(`
|
|
3871
3871
|
`)+`
|
|
3872
3872
|
`+e}function Qy(t){const e=t.trim();if(e==="")return"";if(e.startsWith('"'))try{return JSON.parse(e)}catch{return e.replace(/^"|"$/g,"")}if(e.startsWith("'")&&e.endsWith("'")&&e.length>=2)return e.slice(1,-1).replace(/''/g,"'");if(e.startsWith("{")||e.startsWith("["))try{return JSON.parse(e)}catch{if(e.startsWith("[")&&e.endsWith("]")){const n=e.slice(1,-1).trim();return n?n.split(",").map(r=>Qy(r)):[]}return e}return/^(?:true|yes|on)$/i.test(e)?!0:/^(?:false|no|off)$/i.test(e)?!1:/^(?:null|~)$/i.test(e)?null:/^-?(?:0|[1-9]\d*)(?:\.\d+)?$/.test(e)?Number(e):e}function rj(t){let e=!1,n=!1;for(let r=0;r<t.length;r++){const s=t[r];if(s==="\\"&&n){r++;continue}if(s==="'"&&!n)e=!e;else if(s==='"'&&!e)n=!n;else if(s==="#"&&!e&&!n&&(r===0||/\s/.test(t[r-1])))return t.slice(0,r)}return t}function rae(t){const e={},n=t.split(/\r?\n/);for(let r=0;r<n.length;r++){const s=rj(n[r]).replace(/\s+$/,"");if(!s.trim()||/^\s/.test(s))continue;const i=s.indexOf(":");if(i===-1)continue;const a=s.slice(0,i).trim().replace(/^["']|["']$/g,""),o=s.slice(i+1).trim();if(o!==""){e[a]=Qy(o);continue}const l=[],c={};let h=null;for(;r+1<n.length;){const p=rj(n[r+1]).replace(/\s+$/,"");if(!p.trim()){r++;continue}if(!/^\s/.test(p))break;const m=p.trim();if(m.startsWith("- ")||m==="-")h=h??"list",l.push(Qy(m.slice(1)));else{const g=m.indexOf(":");g>0&&(h=h??"map",c[m.slice(0,g).trim()]=Qy(m.slice(g+1)))}r++}e[a]=h==="list"?l:h==="map"?c:null}return e}function sj(t){const e=t.replace(/^/,"");if(!/^---\r?\n/.test(e))return{data:{},body:e};const n=e.replace(/^---\r?\n/,""),r=/(?:^|\r?\n)---[ \t]*(?:\r?\n|$)/.exec(n);if(!r)return{data:{},body:e};const s=n.slice(0,r.index);let i=n.slice(r.index+r[0].length);return i=i.replace(/^\r?\n/,""),{data:rae(s),body:i}}const ij={post:"posts",page:"pages"},OO=["lastPublishedPath","lastPublishedHash","previousPublishedPaths","lastPublishedPathsByLocale"],zO=["createdAt","updatedAt","publishedAt"],aj=["id","type","title","slug","status"],sae=new Set(["apiKey","token","secretAccessKey","accessToken","password","sqliteToken"]),UO=/^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})?$/,eT={terms:"terms.json",media:"media.json",users:"users.json"},tT={settings:"settings",config:".cms/config"},zm=".cms/publish-state.json";function VS(t){return[...t].sort((e,n)=>e.id<n.id?-1:e.id>n.id?1:0)}function qS(t){return JSON.stringify(t,null,2)+`
|
|
3873
|
-
`}function ru(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function C0(t){const e={},n={};for(const[r,s]of Object.entries(t))if(sae.has(r)&&s!==""&&s!=null)n[r]=s;else if(ru(s)){const i=C0(s);e[r]=i.clean,i.secrets&&(n[r]=i.secrets)}else e[r]=s;return{clean:e,secrets:Object.keys(n).length?n:null}}function BO(t,e){const n={...t};for(const[r,s]of Object.entries(e))n[r]=ru(s)&&ru(n[r])?BO(n[r],s):s;return n}function $O(t,e){var n;for(const[r,s]of Object.entries(e)){const[i,a]=r.split("/"),o=(n=t[i])==null?void 0:n.get(a);o&&t[i].set(a,BO(o,s))}}function iae(t){return typeof t=="number"?new Date(t).toISOString():t}function aae(t){if(typeof t=="string"&&/^\d{4}-\d{2}-\d{2}/.test(t)){const e=Date.parse(t);if(!Number.isNaN(e))return e}return t}function oae(t,e){const n=new Map,r={},s={...t};delete s.contentMarkdown;for(const a of OO)delete s[a];const i={};if(ru(s.translations))for(const[a,o]of Object.entries(s.translations))if(UO.test(a)&&ru(o)&&typeof o.contentMarkdown=="string"){const{contentMarkdown:l,...c}=o;n.set(`${e}.${a}.md`,nj(c,l))}else i[a]=o;delete s.translations;for(const a of aj)a in s&&(r[a]=s[a]);for(const[a,o]of Object.entries(s))aj.includes(a)||(r[a]=zO.includes(a)?iae(o):o);return Object.keys(i).length&&(r.translations=i),n.set(`${e}.md`,nj(r,typeof t.contentMarkdown=="string"?t.contentMarkdown:"")),n}function oj(t){const e=t.type==="page"?ij.page:ij.post,n=typeof t.slug=="string"&&t.slug.trim()?t.slug.trim():"";return`${e}/${n||String(t.id).toLowerCase()}`}function lae(t,e){const n=new Map,r=new Set,s=[];for(const i of t){const a=oj(i),o=e.get(i.id),l=`${a}--${i.id.toLowerCase()}`;o&&(o===a||o===l)&&!r.has(o)?(n.set(i.id,o),r.add(o)):s.push(i)}for(const i of s){const a=oj(i),o=r.has(a)?`${a}--${i.id.toLowerCase()}`:a;n.set(i.id,o),r.add(o)}return n}function cae(t,e){const n=new Map,r={},s=VS(t.posts.values()),i=lae(s,e),a={};for(const o of s){for(const[c,h]of oae(o,i.get(o.id)))n.set(c,h);const l={};for(const c of OO)o[c]!==void 0&&(l[c]=o[c]);Object.keys(l).length&&(a[o.id]=l)}Object.keys(a).length&&n.set(zm,qS(a));for(const[o,l]of Object.entries(eT)){const c=VS(t[o].values());c.length&&n.set(l,qS(c))}for(const[o,l]of Object.entries(tT))for(const c of VS(t[o].values())){let h=c;if(o==="config"){const p=C0(c);h=p.clean,p.secrets&&(r[`${o}/${c.id}`]=p.secrets)}n.set(`${l}/${encodeURIComponent(c.id)}.json`,qS(h))}return{files:n,index:i,secrets:r}}function WS(t,e){try{return JSON.parse(t)}catch{return console.warn(`[docstore] ignoring malformed JSON: ${e}`),null}}function uae(t){const e=E0(),n=new Map,r=new Map,s=[];for(const[a,o]of t){const l=/^(posts|pages)\/(.+)\.md$/.exec(a);if(!l)continue;const c=l[2];if(c.includes("/"))continue;const h=c.split(".");if(h.length>=2&&UO.test(h[h.length-1])&&t.has(`${l[1]}/${h.slice(0,-1).join(".")}.md`)){s.push({base:`${l[1]}/${h.slice(0,-1).join(".")}`,lang:h[h.length-1],text:o});continue}const{data:p,body:m}=sj(o),g={};for(const[y,x]of Object.entries(p))g[y]=zO.includes(y)?aae(x):x;(typeof g.id!="string"||!g.id)&&(g.id=`${l[1]}-${c}`),g.type!=="post"&&g.type!=="page"&&(g.type=l[1]==="pages"?"page":"post"),typeof g.slug!="string"&&(g.slug=c),typeof g.title!="string"&&(g.title=String(g.title??c)),g.contentMarkdown=m,r.set(`${l[1]}/${c}`,g)}for(const{base:a,lang:o,text:l}of s){const c=r.get(a);if(!c)continue;const{data:h,body:p}=sj(l),m=ru(c.translations)?{...c.translations}:{};m[o]={...h,contentMarkdown:p},c.translations=m}const i=t.has(zm)?WS(t.get(zm),zm):null;for(const[a,o]of r){const l=o.id;if(e.posts.has(l)){console.warn(`[docstore] duplicate post id ${l} in ${a}.md — ignored`);continue}const c=i==null?void 0:i[l];e.posts.set(l,c?{...o,...c}:o),n.set(l,a)}for(const[a,o]of Object.entries(eT)){const l=t.has(o)?WS(t.get(o),o):null;if(Array.isArray(l))for(const c of l)ru(c)&&typeof c.id=="string"&&e[a].set(c.id,c)}for(const[a,o]of Object.entries(tT))for(const[l,c]of t){const h=new RegExp(`^${o.replace(/\./g,"\\.")}/([^/]+)\\.json$`).exec(l);if(!h)continue;const p=WS(c,l);if(!ru(p))continue;const m=typeof p.id=="string"?p.id:decodeURIComponent(h[1]);e[a].set(m,{...p,id:m})}return{snapshot:e,index:n}}function dae(t){return/^(posts|pages)\/[^/]+\.md$/.test(t)||Object.values(eT).includes(t)||t===zm||Object.values(tT).some(e=>new RegExp(`^${e.replace(/\./g,"\\.")}/[^/]+\\.json$`).test(t))}const Ig="content-folder",hae=3;function a1(t){return t.provider==="github"?`github:${t.owner}/${t.repo}`:t.provider==="gitlab"?`gitlab:${t.project}`:"local"}function HO(t){try{return window.localStorage.getItem(t)}catch{return null}}function VO(t,e){try{e===null?window.localStorage.removeItem(t):window.localStorage.setItem(t,e)}catch{}}function nT(t){return HO(`flexweg.gitToken:${a1(t)}`)}function rT(t,e){VO(`flexweg.gitToken:${a1(t)}`,(e==null?void 0:e.trim())||null)}function fae(t){try{return JSON.parse(HO(`flexweg.gitSecrets:${a1(t)}`)??"{}")}catch{return{}}}function pae(t,e){VO(`flexweg.gitSecrets:${a1(t)}`,JSON.stringify(e))}function mae(t){return[t.collection,t.op==="set"?t.doc.id:t.id]}function gae(t,e){const n=Object.fromEntries(Object.entries(t).map(([r,s])=>[r,new Map(s)]));for(const r of e)r.op==="set"?n[r.collection].set(r.doc.id,r.doc):n[r.collection].delete(r.id);return n}function bae(t){return typeof t.resetSession=="function"}function yae(t){const e=(t.contentDir??"").replace(/^\/+|\/+$/g,""),n=g=>e?g.slice(e.length+1):g,r=g=>!e||g.startsWith(e+"/");let s=null,i=null,a=null,o=!1;async function l(){if(s)return s;if(t.provider==="local"){const y=await Cf(Ig);return!y||!await _0(y,!1)?null:(s=DO(y),s)}const g=nT(t);return g?(s=t.provider==="github"?Af({provider:"github",owner:t.owner??"",repo:t.repo??"",branch:t.branch,token:g,apiBaseUrl:t.apiBaseUrl}):Af({provider:"gitlab",project:t.project??"",branch:t.branch,token:g,apiBaseUrl:t.apiBaseUrl}),s):null}async function c(){const g=await l();if(!g)throw new Error(jt.t("docstore.errors.notConnected"));return g}async function h(){const g=await c(),y=await g.listTree(),x=y.entries.filter(_=>r(_.path)&&dae(n(_.path))),v=await g.readTexts(x),k=new Map;for(const[_,P]of v)k.set(n(_),P);const{snapshot:C,index:N}=uae(k);return $O(C,fae(t)),{head:y.headSha,files:k,index:N,snapshot:C}}async function p(g,y,x,v){const k=await c();a||(a=await h());let C=x;for(let N=0;;N++){const{files:_,index:P,secrets:D}=cae(C,a.index);pae(t,D);const I=[];for(const[j,q]of _)a.files.get(j)!==q&&I.push({type:"put",path:Ov(e,j),content:q});for(const j of a.files.keys())_.has(j)||I.push({type:"delete",path:Ov(e,j)});if(I.length===0)return;try{a={head:await k.commit(I,{message:`${v} — Flexweg CMS`,expectedHeadSha:a.head}),files:_,index:P,snapshot:C};return}catch(j){if(!(j instanceof Hc)||N>=hae)throw j}const L=await h();for(const j of g){const[q,V]=mae(j),O=JSON.stringify(y[q].get(V)??null),$=JSON.stringify(L.snapshot[q].get(V)??null);if(O!==$)throw a=L,o=!0,new e_(jt.t("docstore.errors.conflict"),q,V)}a=L,o=!0,C=gae(L.snapshot,g)}}const m=GA({kind:"markdown-git",pollIntervalMs:t.provider==="local"?1e4:3e4,async load(){return a=await h(),o=!1,a.snapshot},persist:p,async poll(){const g=await l();return!g||!a||await g.headSha()===a.head&&!o?null:(a=await h(),o=!1,a.snapshot)},identity(){return i||(i=(async()=>{const g=await l();if(!g)return null;try{const y=await g.permissions();if(!y.canWrite)return null;const x=t.provider==="github"?`${y.login}@users.noreply.github.com`:t.provider==="gitlab"?`${y.login}@users.noreply.gitlab.com`:"local@localhost";return{uid:`${g.kind}:${y.login}`,email:x,displayName:y.login,role:y.isAdmin?"admin":"editor"}}catch{return null}})(),i.then(g=>{g||(i=null,s=null)})),i}});return Object.assign(m,{resetSession(){s=null,i=null,a=null,o=!1}})}function qO(t,e="kv"){const n=new Map;let r=null;function s(){return r||(r=new Promise(a=>{try{if(typeof indexedDB>"u")return a(null);const o=indexedDB.open(t,1);o.onupgradeneeded=()=>o.result.createObjectStore(e),o.onsuccess=()=>a(o.result),o.onerror=()=>a(null),o.onblocked=()=>a(null)}catch{a(null)}})),r}function i(a,o){return s().then(l=>new Promise((c,h)=>{if(!l)return c(void 0);const p=l.transaction(e,a),m=o(p.objectStore(e));p.oncomplete=()=>c(m?m.result:void 0),p.onerror=()=>h(p.error),p.onabort=()=>h(p.error)}))}return{async get(a){return await s()?i("readonly",o=>o.get(a)):n.get(a)},async set(a,o){if(!await s())return void n.set(a,o);await i("readwrite",l=>void l.put(o,a))},async delete(a){if(!await s())return void n.delete(a);await i("readwrite",o=>void o.delete(a))},async keys(){return await s()?(await i("readonly",a=>a.getAllKeys())??[]).map(String):[...n.keys()]},async entries(){if(!await s())return[...n.entries()];const a=[];return await i("readonly",o=>{const l=o.openCursor();l.onsuccess=()=>{const c=l.result;c&&(a.push([String(c.key),c.value]),c.continue())}}),a},async clear(){if(!await s())return void n.clear();await i("readwrite",a=>void a.clear())}}}const GS=qO("flexweg-local-data","docs"),lj=(t,e)=>`${t}/${e}`;function vae(){return GA({kind:"local",async load(){const t=E0();for(const[e,n]of await GS.entries()){const r=e.indexOf("/"),s=e.slice(0,r);t[s]&&t[s].set(n.id,n)}return t},async persist(t){for(const e of t)e.op==="set"?await GS.set(lj(e.collection,e.doc.id),e.doc):await GS.delete(lj(e.collection,e.id))},async identity(){return{uid:"local",email:"local@localhost",displayName:"Local admin",role:"admin"}}})}const xae="modulepreload",wae=function(t,e){return new URL(t,e).href},cj={},zv=function(e,n,r){let s=Promise.resolve();if(n&&n.length>0){let a=function(h){return Promise.all(h.map(p=>Promise.resolve(p).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};const o=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),c=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));s=a(n.map(h=>{if(h=wae(h,r),h in cj)return;cj[h]=!0;const p=h.endsWith(".css"),m=p?'[rel="stylesheet"]':"";if(!!r)for(let x=o.length-1;x>=0;x--){const v=o[x];if(v.href===h&&(!p||v.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${h}"]${m}`))return;const y=document.createElement("link");if(y.rel=p?"stylesheet":xae,p||(y.as="script"),y.crossOrigin="",y.href=h,c&&y.setAttribute("nonce",c),document.head.appendChild(y),p)return new Promise((x,v)=>{y.addEventListener("load",x),y.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${h}`)))})}))}function i(a){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=a,window.dispatchEvent(o),!o.defaultPrevented)throw a}return s.then(a=>{for(const o of a||[])o.status==="rejected"&&i(o.reason);return e().catch(i)})},Ro=new TextEncoder().encode("ACMSENC1"),Ng=Ro.length+4+16+12,kae=6e5;class Pg extends Error{constructor(e){super(e==="missing"?"This database is encrypted: enter its passphrase.":"Wrong passphrase for this database."),this.reason=e,this.name="SqlitePassphraseError"}}function WO(t){return!!t&&t.length>=Ng&&Ro.every((e,n)=>t[n]===e)}const KS=new Map;function Sae(t){return[...t].map(e=>e.toString(16).padStart(2,"0")).join("")}function GO(t,e,n){const r=`${n}:${Sae(e)}:${t}`;let s=KS.get(r);return s||(s=(async()=>{const i=await crypto.subtle.importKey("raw",new TextEncoder().encode(t.normalize("NFC")),"PBKDF2",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",hash:"SHA-256",salt:e,iterations:n},i,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])})(),s.catch(()=>KS.delete(r)),KS.set(r,s)),s}function KO(t){return{iterations:new DataView(t.buffer,t.byteOffset,t.byteLength).getUint32(Ro.length),salt:t.slice(Ro.length+4,Ro.length+20)}}async function Eae(t,e,n){if(!e)throw new Pg("missing");const r=(n==null?void 0:n.salt)??crypto.getRandomValues(new Uint8Array(16)),s=(n==null?void 0:n.iterations)??kae,i=crypto.getRandomValues(new Uint8Array(12)),a=await GO(e,r,s),o=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:i},a,t)),l=new Uint8Array(Ng+o.length);return l.set(Ro,0),new DataView(l.buffer).setUint32(Ro.length,s),l.set(r,Ro.length+4),l.set(i,Ro.length+20),l.set(o,Ng),l}async function _ae(t,e){if(!e)throw new Pg("missing");const{salt:n,iterations:r}=KO(t),s=t.slice(Ro.length+20,Ng),i=await GO(e,n,r);try{return new Uint8Array(await crypto.subtle.decrypt({name:"AES-GCM",iv:s},i,t.slice(Ng)))}catch{throw new Pg("wrong")}}function Uv(){const t="abcdefghjkmnpqrstuvwxyz23456789",n=[...crypto.getRandomValues(new Uint8Array(30))].map(r=>t[r%t.length]);return Array.from({length:6},(r,s)=>n.slice(s*5,s*5+5).join("")).join("-")}const JO=()=>rl(Xs(),ls.config,e1.storage);async function Cae(){const t=await Cu(JO());if(!t.exists())return null;const e=t.data();return e!=null&&e.connectorId?{connectorId:e.connectorId,settings:e.settings??{}}:null}async function Aae(t){await ro(JO(),{connectorId:t.connectorId,settings:t.settings??{}})}const Tae=Object.freeze(Object.defineProperty({__proto__:null,getStorageConfig:Cae,setStorageConfig:Aae},Symbol.toStringTag,{value:"Module"})),QO="storage";async function Iae(){const{rows:t}=await hs("SELECT value FROM config WHERE key = ?",[QO]);if(t.length===0)return null;let e;try{e=JSON.parse(t[0].value)}catch{return null}return e.connectorId?{connectorId:e.connectorId,settings:e.settings??{}}:null}async function Nae(t){const e=JSON.stringify({connectorId:t.connectorId,settings:t.settings??{}});await Kn(`INSERT INTO config (key, value) VALUES (?, ?)
|
|
3873
|
+
`}function ru(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function C0(t){const e={},n={};for(const[r,s]of Object.entries(t))if(sae.has(r)&&s!==""&&s!=null)n[r]=s;else if(ru(s)){const i=C0(s);e[r]=i.clean,i.secrets&&(n[r]=i.secrets)}else e[r]=s;return{clean:e,secrets:Object.keys(n).length?n:null}}function BO(t,e){const n={...t};for(const[r,s]of Object.entries(e))n[r]=ru(s)&&ru(n[r])?BO(n[r],s):s;return n}function $O(t,e){var n;for(const[r,s]of Object.entries(e)){const[i,a]=r.split("/"),o=(n=t[i])==null?void 0:n.get(a);o&&t[i].set(a,BO(o,s))}}function iae(t){return typeof t=="number"?new Date(t).toISOString():t}function aae(t){if(typeof t=="string"&&/^\d{4}-\d{2}-\d{2}/.test(t)){const e=Date.parse(t);if(!Number.isNaN(e))return e}return t}function oae(t,e){const n=new Map,r={},s={...t};delete s.contentMarkdown;for(const a of OO)delete s[a];const i={};if(ru(s.translations))for(const[a,o]of Object.entries(s.translations))if(UO.test(a)&&ru(o)&&typeof o.contentMarkdown=="string"){const{contentMarkdown:l,...c}=o;n.set(`${e}.${a}.md`,nj(c,l))}else i[a]=o;delete s.translations;for(const a of aj)a in s&&(r[a]=s[a]);for(const[a,o]of Object.entries(s))aj.includes(a)||(r[a]=zO.includes(a)?iae(o):o);return Object.keys(i).length&&(r.translations=i),n.set(`${e}.md`,nj(r,typeof t.contentMarkdown=="string"?t.contentMarkdown:"")),n}function oj(t){const e=t.type==="page"?ij.page:ij.post,n=typeof t.slug=="string"&&t.slug.trim()?t.slug.trim():"";return`${e}/${n||String(t.id).toLowerCase()}`}function lae(t,e){const n=new Map,r=new Set,s=[];for(const i of t){const a=oj(i),o=e.get(i.id),l=`${a}--${i.id.toLowerCase()}`;o&&(o===a||o===l)&&!r.has(o)?(n.set(i.id,o),r.add(o)):s.push(i)}for(const i of s){const a=oj(i),o=r.has(a)?`${a}--${i.id.toLowerCase()}`:a;n.set(i.id,o),r.add(o)}return n}function cae(t,e){const n=new Map,r={},s=VS(t.posts.values()),i=lae(s,e),a={};for(const o of s){for(const[c,h]of oae(o,i.get(o.id)))n.set(c,h);const l={};for(const c of OO)o[c]!==void 0&&(l[c]=o[c]);Object.keys(l).length&&(a[o.id]=l)}Object.keys(a).length&&n.set(zm,qS(a));for(const[o,l]of Object.entries(eT)){const c=VS(t[o].values());c.length&&n.set(l,qS(c))}for(const[o,l]of Object.entries(tT))for(const c of VS(t[o].values())){let h=c;if(o==="config"){const p=C0(c);h=p.clean,p.secrets&&(r[`${o}/${c.id}`]=p.secrets)}n.set(`${l}/${encodeURIComponent(c.id)}.json`,qS(h))}return{files:n,index:i,secrets:r}}function WS(t,e){try{return JSON.parse(t)}catch{return console.warn(`[docstore] ignoring malformed JSON: ${e}`),null}}function uae(t){const e=E0(),n=new Map,r=new Map,s=[];for(const[a,o]of t){const l=/^(posts|pages)\/(.+)\.md$/.exec(a);if(!l)continue;const c=l[2];if(c.includes("/"))continue;const h=c.split(".");if(h.length>=2&&UO.test(h[h.length-1])&&t.has(`${l[1]}/${h.slice(0,-1).join(".")}.md`)){s.push({base:`${l[1]}/${h.slice(0,-1).join(".")}`,lang:h[h.length-1],text:o});continue}const{data:p,body:m}=sj(o),g={};for(const[y,x]of Object.entries(p))g[y]=zO.includes(y)?aae(x):x;(typeof g.id!="string"||!g.id)&&(g.id=`${l[1]}-${c}`),g.type!=="post"&&g.type!=="page"&&(g.type=l[1]==="pages"?"page":"post"),typeof g.slug!="string"&&(g.slug=c),typeof g.title!="string"&&(g.title=String(g.title??c)),g.contentMarkdown=m,r.set(`${l[1]}/${c}`,g)}for(const{base:a,lang:o,text:l}of s){const c=r.get(a);if(!c)continue;const{data:h,body:p}=sj(l),m=ru(c.translations)?{...c.translations}:{};m[o]={...h,contentMarkdown:p},c.translations=m}const i=t.has(zm)?WS(t.get(zm),zm):null;for(const[a,o]of r){const l=o.id;if(e.posts.has(l)){console.warn(`[docstore] duplicate post id ${l} in ${a}.md — ignored`);continue}const c=i==null?void 0:i[l];e.posts.set(l,c?{...o,...c}:o),n.set(l,a)}for(const[a,o]of Object.entries(eT)){const l=t.has(o)?WS(t.get(o),o):null;if(Array.isArray(l))for(const c of l)ru(c)&&typeof c.id=="string"&&e[a].set(c.id,c)}for(const[a,o]of Object.entries(tT))for(const[l,c]of t){const h=new RegExp(`^${o.replace(/\./g,"\\.")}/([^/]+)\\.json$`).exec(l);if(!h)continue;const p=WS(c,l);if(!ru(p))continue;const m=typeof p.id=="string"?p.id:decodeURIComponent(h[1]);e[a].set(m,{...p,id:m})}return{snapshot:e,index:n}}function dae(t){return/^(posts|pages)\/[^/]+\.md$/.test(t)||Object.values(eT).includes(t)||t===zm||Object.values(tT).some(e=>new RegExp(`^${e.replace(/\./g,"\\.")}/[^/]+\\.json$`).test(t))}const Ig="content-folder",hae=3;function a1(t){return t.provider==="github"?`github:${t.owner}/${t.repo}`:t.provider==="gitlab"?`gitlab:${t.project}`:"local"}function HO(t){try{return window.localStorage.getItem(t)}catch{return null}}function VO(t,e){try{e===null?window.localStorage.removeItem(t):window.localStorage.setItem(t,e)}catch{}}function nT(t){return HO(`flexweg.gitToken:${a1(t)}`)}function rT(t,e){VO(`flexweg.gitToken:${a1(t)}`,(e==null?void 0:e.trim())||null)}function fae(t){try{return JSON.parse(HO(`flexweg.gitSecrets:${a1(t)}`)??"{}")}catch{return{}}}function pae(t,e){VO(`flexweg.gitSecrets:${a1(t)}`,JSON.stringify(e))}function mae(t){return[t.collection,t.op==="set"?t.doc.id:t.id]}function gae(t,e){const n=Object.fromEntries(Object.entries(t).map(([r,s])=>[r,new Map(s)]));for(const r of e)r.op==="set"?n[r.collection].set(r.doc.id,r.doc):n[r.collection].delete(r.id);return n}function bae(t){return typeof t.resetSession=="function"}function yae(t){const e=(t.contentDir??"").replace(/^\/+|\/+$/g,""),n=g=>e?g.slice(e.length+1):g,r=g=>!e||g.startsWith(e+"/");let s=null,i=null,a=null,o=!1;async function l(){if(s)return s;if(t.provider==="local"){const y=await Cf(Ig);return!y||!await _0(y,!1)?null:(s=DO(y),s)}const g=nT(t);return g?(s=t.provider==="github"?Af({provider:"github",owner:t.owner??"",repo:t.repo??"",branch:t.branch,token:g,apiBaseUrl:t.apiBaseUrl}):Af({provider:"gitlab",project:t.project??"",branch:t.branch,token:g,apiBaseUrl:t.apiBaseUrl}),s):null}async function c(){const g=await l();if(!g)throw new Error(jt.t("docstore.errors.notConnected"));return g}async function h(){const g=await c(),y=await g.listTree(),x=y.entries.filter(_=>r(_.path)&&dae(n(_.path))),v=await g.readTexts(x),k=new Map;for(const[_,P]of v)k.set(n(_),P);const{snapshot:C,index:N}=uae(k);return $O(C,fae(t)),{head:y.headSha,files:k,index:N,snapshot:C}}async function p(g,y,x,v){const k=await c();a||(a=await h());let C=x;for(let N=0;;N++){const{files:_,index:P,secrets:D}=cae(C,a.index);pae(t,D);const I=[];for(const[j,q]of _)a.files.get(j)!==q&&I.push({type:"put",path:Ov(e,j),content:q});for(const j of a.files.keys())_.has(j)||I.push({type:"delete",path:Ov(e,j)});if(I.length===0)return;try{a={head:await k.commit(I,{message:`${v} — AgentCMS`,expectedHeadSha:a.head}),files:_,index:P,snapshot:C};return}catch(j){if(!(j instanceof Hc)||N>=hae)throw j}const L=await h();for(const j of g){const[q,V]=mae(j),O=JSON.stringify(y[q].get(V)??null),$=JSON.stringify(L.snapshot[q].get(V)??null);if(O!==$)throw a=L,o=!0,new e_(jt.t("docstore.errors.conflict"),q,V)}a=L,o=!0,C=gae(L.snapshot,g)}}const m=GA({kind:"markdown-git",pollIntervalMs:t.provider==="local"?1e4:3e4,async load(){return a=await h(),o=!1,a.snapshot},persist:p,async poll(){const g=await l();return!g||!a||await g.headSha()===a.head&&!o?null:(a=await h(),o=!1,a.snapshot)},identity(){return i||(i=(async()=>{const g=await l();if(!g)return null;try{const y=await g.permissions();if(!y.canWrite)return null;const x=t.provider==="github"?`${y.login}@users.noreply.github.com`:t.provider==="gitlab"?`${y.login}@users.noreply.gitlab.com`:"local@localhost";return{uid:`${g.kind}:${y.login}`,email:x,displayName:y.login,role:y.isAdmin?"admin":"editor"}}catch{return null}})(),i.then(g=>{g||(i=null,s=null)})),i}});return Object.assign(m,{resetSession(){s=null,i=null,a=null,o=!1}})}function qO(t,e="kv"){const n=new Map;let r=null;function s(){return r||(r=new Promise(a=>{try{if(typeof indexedDB>"u")return a(null);const o=indexedDB.open(t,1);o.onupgradeneeded=()=>o.result.createObjectStore(e),o.onsuccess=()=>a(o.result),o.onerror=()=>a(null),o.onblocked=()=>a(null)}catch{a(null)}})),r}function i(a,o){return s().then(l=>new Promise((c,h)=>{if(!l)return c(void 0);const p=l.transaction(e,a),m=o(p.objectStore(e));p.oncomplete=()=>c(m?m.result:void 0),p.onerror=()=>h(p.error),p.onabort=()=>h(p.error)}))}return{async get(a){return await s()?i("readonly",o=>o.get(a)):n.get(a)},async set(a,o){if(!await s())return void n.set(a,o);await i("readwrite",l=>void l.put(o,a))},async delete(a){if(!await s())return void n.delete(a);await i("readwrite",o=>void o.delete(a))},async keys(){return await s()?(await i("readonly",a=>a.getAllKeys())??[]).map(String):[...n.keys()]},async entries(){if(!await s())return[...n.entries()];const a=[];return await i("readonly",o=>{const l=o.openCursor();l.onsuccess=()=>{const c=l.result;c&&(a.push([String(c.key),c.value]),c.continue())}}),a},async clear(){if(!await s())return void n.clear();await i("readwrite",a=>void a.clear())}}}const GS=qO("flexweg-local-data","docs"),lj=(t,e)=>`${t}/${e}`;function vae(){return GA({kind:"local",async load(){const t=E0();for(const[e,n]of await GS.entries()){const r=e.indexOf("/"),s=e.slice(0,r);t[s]&&t[s].set(n.id,n)}return t},async persist(t){for(const e of t)e.op==="set"?await GS.set(lj(e.collection,e.doc.id),e.doc):await GS.delete(lj(e.collection,e.id))},async identity(){return{uid:"local",email:"local@localhost",displayName:"Local admin",role:"admin"}}})}const xae="modulepreload",wae=function(t,e){return new URL(t,e).href},cj={},zv=function(e,n,r){let s=Promise.resolve();if(n&&n.length>0){let a=function(h){return Promise.all(h.map(p=>Promise.resolve(p).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};const o=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),c=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));s=a(n.map(h=>{if(h=wae(h,r),h in cj)return;cj[h]=!0;const p=h.endsWith(".css"),m=p?'[rel="stylesheet"]':"";if(!!r)for(let x=o.length-1;x>=0;x--){const v=o[x];if(v.href===h&&(!p||v.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${h}"]${m}`))return;const y=document.createElement("link");if(y.rel=p?"stylesheet":xae,p||(y.as="script"),y.crossOrigin="",y.href=h,c&&y.setAttribute("nonce",c),document.head.appendChild(y),p)return new Promise((x,v)=>{y.addEventListener("load",x),y.addEventListener("error",()=>v(new Error(`Unable to preload CSS for ${h}`)))})}))}function i(a){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=a,window.dispatchEvent(o),!o.defaultPrevented)throw a}return s.then(a=>{for(const o of a||[])o.status==="rejected"&&i(o.reason);return e().catch(i)})},Ro=new TextEncoder().encode("ACMSENC1"),Ng=Ro.length+4+16+12,kae=6e5;class Pg extends Error{constructor(e){super(e==="missing"?"This database is encrypted: enter its passphrase.":"Wrong passphrase for this database."),this.reason=e,this.name="SqlitePassphraseError"}}function WO(t){return!!t&&t.length>=Ng&&Ro.every((e,n)=>t[n]===e)}const KS=new Map;function Sae(t){return[...t].map(e=>e.toString(16).padStart(2,"0")).join("")}function GO(t,e,n){const r=`${n}:${Sae(e)}:${t}`;let s=KS.get(r);return s||(s=(async()=>{const i=await crypto.subtle.importKey("raw",new TextEncoder().encode(t.normalize("NFC")),"PBKDF2",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",hash:"SHA-256",salt:e,iterations:n},i,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])})(),s.catch(()=>KS.delete(r)),KS.set(r,s)),s}function KO(t){return{iterations:new DataView(t.buffer,t.byteOffset,t.byteLength).getUint32(Ro.length),salt:t.slice(Ro.length+4,Ro.length+20)}}async function Eae(t,e,n){if(!e)throw new Pg("missing");const r=(n==null?void 0:n.salt)??crypto.getRandomValues(new Uint8Array(16)),s=(n==null?void 0:n.iterations)??kae,i=crypto.getRandomValues(new Uint8Array(12)),a=await GO(e,r,s),o=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:i},a,t)),l=new Uint8Array(Ng+o.length);return l.set(Ro,0),new DataView(l.buffer).setUint32(Ro.length,s),l.set(r,Ro.length+4),l.set(i,Ro.length+20),l.set(o,Ng),l}async function _ae(t,e){if(!e)throw new Pg("missing");const{salt:n,iterations:r}=KO(t),s=t.slice(Ro.length+20,Ng),i=await GO(e,n,r);try{return new Uint8Array(await crypto.subtle.decrypt({name:"AES-GCM",iv:s},i,t.slice(Ng)))}catch{throw new Pg("wrong")}}function Uv(){const t="abcdefghjkmnpqrstuvwxyz23456789",n=[...crypto.getRandomValues(new Uint8Array(30))].map(r=>t[r%t.length]);return Array.from({length:6},(r,s)=>n.slice(s*5,s*5+5).join("")).join("-")}const JO=()=>rl(Xs(),ls.config,e1.storage);async function Cae(){const t=await Cu(JO());if(!t.exists())return null;const e=t.data();return e!=null&&e.connectorId?{connectorId:e.connectorId,settings:e.settings??{}}:null}async function Aae(t){await ro(JO(),{connectorId:t.connectorId,settings:t.settings??{}})}const Tae=Object.freeze(Object.defineProperty({__proto__:null,getStorageConfig:Cae,setStorageConfig:Aae},Symbol.toStringTag,{value:"Module"})),QO="storage";async function Iae(){const{rows:t}=await hs("SELECT value FROM config WHERE key = ?",[QO]);if(t.length===0)return null;let e;try{e=JSON.parse(t[0].value)}catch{return null}return e.connectorId?{connectorId:e.connectorId,settings:e.settings??{}}:null}async function Nae(t){const e=JSON.stringify({connectorId:t.connectorId,settings:t.settings??{}});await Kn(`INSERT INTO config (key, value) VALUES (?, ?)
|
|
3874
3874
|
ON CONFLICT(key) DO UPDATE SET value = excluded.value`,[QO,e])}const Pae=Object.freeze(Object.defineProperty({__proto__:null,getStorageConfig:Iae,setStorageConfig:Nae},Symbol.toStringTag,{value:"Module"})),XO="storage";async function Rae(){const t=Ct();await t.ready();const e=t.get("config",XO);return e!=null&&e.connectorId?{connectorId:e.connectorId,settings:{...e.settings??{}}}:null}async function jae(t){await Ct().write([{op:"set",collection:"config",doc:{id:XO,connectorId:t.connectorId,settings:t.settings??{}}}],{message:"Update publish storage settings"})}const Mae=Object.freeze(Object.defineProperty({__proto__:null,getStorageConfig:Rae,setStorageConfig:jae},Symbol.toStringTag,{value:"Module"}));let JS=null;function ZO(){if(!JS){const t=$r();JS=t==="flexweg-sqlite"?Pae:ao(t)?Mae:Tae}return JS}function sT(...t){return ZO().getStorageConfig(...t)}function uj(...t){return ZO().setStorageConfig(...t)}function ry(t){throw new Error('Could not dynamically require "'+t+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var QS={exports:{}};/*!
|
|
3875
3875
|
|
|
3876
3876
|
JSZip v3.10.1 - A JavaScript class for generating and reading zip files
|
|
@@ -3883,12 +3883,12 @@ JSZip uses the library pako released under the MIT license :
|
|
|
3883
3883
|
https://github.com/nodeca/pako/blob/main/LICENSE
|
|
3884
3884
|
*/var dj;function Lae(){return dj||(dj=1,(function(t,e){(function(n){t.exports=n()})(function(){return(function n(r,s,i){function a(c,h){if(!s[c]){if(!r[c]){var p=typeof ry=="function"&&ry;if(!h&&p)return p(c,!0);if(o)return o(c,!0);var m=new Error("Cannot find module '"+c+"'");throw m.code="MODULE_NOT_FOUND",m}var g=s[c]={exports:{}};r[c][0].call(g.exports,function(y){var x=r[c][1][y];return a(x||y)},g,g.exports,n,r,s,i)}return s[c].exports}for(var o=typeof ry=="function"&&ry,l=0;l<i.length;l++)a(i[l]);return a})({1:[function(n,r,s){var i=n("./utils"),a=n("./support"),o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";s.encode=function(l){for(var c,h,p,m,g,y,x,v=[],k=0,C=l.length,N=C,_=i.getTypeOf(l)!=="string";k<l.length;)N=C-k,p=_?(c=l[k++],h=k<C?l[k++]:0,k<C?l[k++]:0):(c=l.charCodeAt(k++),h=k<C?l.charCodeAt(k++):0,k<C?l.charCodeAt(k++):0),m=c>>2,g=(3&c)<<4|h>>4,y=1<N?(15&h)<<2|p>>6:64,x=2<N?63&p:64,v.push(o.charAt(m)+o.charAt(g)+o.charAt(y)+o.charAt(x));return v.join("")},s.decode=function(l){var c,h,p,m,g,y,x=0,v=0,k="data:";if(l.substr(0,k.length)===k)throw new Error("Invalid base64 input, it looks like a data url.");var C,N=3*(l=l.replace(/[^A-Za-z0-9+/=]/g,"")).length/4;if(l.charAt(l.length-1)===o.charAt(64)&&N--,l.charAt(l.length-2)===o.charAt(64)&&N--,N%1!=0)throw new Error("Invalid base64 input, bad content length.");for(C=a.uint8array?new Uint8Array(0|N):new Array(0|N);x<l.length;)c=o.indexOf(l.charAt(x++))<<2|(m=o.indexOf(l.charAt(x++)))>>4,h=(15&m)<<4|(g=o.indexOf(l.charAt(x++)))>>2,p=(3&g)<<6|(y=o.indexOf(l.charAt(x++))),C[v++]=c,g!==64&&(C[v++]=h),y!==64&&(C[v++]=p);return C}},{"./support":30,"./utils":32}],2:[function(n,r,s){var i=n("./external"),a=n("./stream/DataWorker"),o=n("./stream/Crc32Probe"),l=n("./stream/DataLengthProbe");function c(h,p,m,g,y){this.compressedSize=h,this.uncompressedSize=p,this.crc32=m,this.compression=g,this.compressedContent=y}c.prototype={getContentWorker:function(){var h=new a(i.Promise.resolve(this.compressedContent)).pipe(this.compression.uncompressWorker()).pipe(new l("data_length")),p=this;return h.on("end",function(){if(this.streamInfo.data_length!==p.uncompressedSize)throw new Error("Bug : uncompressed data size mismatch")}),h},getCompressedWorker:function(){return new a(i.Promise.resolve(this.compressedContent)).withStreamInfo("compressedSize",this.compressedSize).withStreamInfo("uncompressedSize",this.uncompressedSize).withStreamInfo("crc32",this.crc32).withStreamInfo("compression",this.compression)}},c.createWorkerFrom=function(h,p,m){return h.pipe(new o).pipe(new l("uncompressedSize")).pipe(p.compressWorker(m)).pipe(new l("compressedSize")).withStreamInfo("compression",p)},r.exports=c},{"./external":6,"./stream/Crc32Probe":25,"./stream/DataLengthProbe":26,"./stream/DataWorker":27}],3:[function(n,r,s){var i=n("./stream/GenericWorker");s.STORE={magic:"\0\0",compressWorker:function(){return new i("STORE compression")},uncompressWorker:function(){return new i("STORE decompression")}},s.DEFLATE=n("./flate")},{"./flate":7,"./stream/GenericWorker":28}],4:[function(n,r,s){var i=n("./utils"),a=(function(){for(var o,l=[],c=0;c<256;c++){o=c;for(var h=0;h<8;h++)o=1&o?3988292384^o>>>1:o>>>1;l[c]=o}return l})();r.exports=function(o,l){return o!==void 0&&o.length?i.getTypeOf(o)!=="string"?(function(c,h,p,m){var g=a,y=m+p;c^=-1;for(var x=m;x<y;x++)c=c>>>8^g[255&(c^h[x])];return-1^c})(0|l,o,o.length,0):(function(c,h,p,m){var g=a,y=m+p;c^=-1;for(var x=m;x<y;x++)c=c>>>8^g[255&(c^h.charCodeAt(x))];return-1^c})(0|l,o,o.length,0):0}},{"./utils":32}],5:[function(n,r,s){s.base64=!1,s.binary=!1,s.dir=!1,s.createFolders=!0,s.date=null,s.compression=null,s.compressionOptions=null,s.comment=null,s.unixPermissions=null,s.dosPermissions=null},{}],6:[function(n,r,s){var i=null;i=typeof Promise<"u"?Promise:n("lie"),r.exports={Promise:i}},{lie:37}],7:[function(n,r,s){var i=typeof Uint8Array<"u"&&typeof Uint16Array<"u"&&typeof Uint32Array<"u",a=n("pako"),o=n("./utils"),l=n("./stream/GenericWorker"),c=i?"uint8array":"array";function h(p,m){l.call(this,"FlateWorker/"+p),this._pako=null,this._pakoAction=p,this._pakoOptions=m,this.meta={}}s.magic="\b\0",o.inherits(h,l),h.prototype.processChunk=function(p){this.meta=p.meta,this._pako===null&&this._createPako(),this._pako.push(o.transformTo(c,p.data),!1)},h.prototype.flush=function(){l.prototype.flush.call(this),this._pako===null&&this._createPako(),this._pako.push([],!0)},h.prototype.cleanUp=function(){l.prototype.cleanUp.call(this),this._pako=null},h.prototype._createPako=function(){this._pako=new a[this._pakoAction]({raw:!0,level:this._pakoOptions.level||-1});var p=this;this._pako.onData=function(m){p.push({data:m,meta:p.meta})}},s.compressWorker=function(p){return new h("Deflate",p)},s.uncompressWorker=function(){return new h("Inflate",{})}},{"./stream/GenericWorker":28,"./utils":32,pako:38}],8:[function(n,r,s){function i(g,y){var x,v="";for(x=0;x<y;x++)v+=String.fromCharCode(255&g),g>>>=8;return v}function a(g,y,x,v,k,C){var N,_,P=g.file,D=g.compression,I=C!==c.utf8encode,L=o.transformTo("string",C(P.name)),j=o.transformTo("string",c.utf8encode(P.name)),q=P.comment,V=o.transformTo("string",C(q)),O=o.transformTo("string",c.utf8encode(q)),$=j.length!==P.name.length,B=O.length!==q.length,X="",fe="",ie="",ae=P.dir,ue=P.date,ve={crc32:0,compressedSize:0,uncompressedSize:0};y&&!x||(ve.crc32=g.crc32,ve.compressedSize=g.compressedSize,ve.uncompressedSize=g.uncompressedSize);var K=0;y&&(K|=8),I||!$&&!B||(K|=2048);var ee=0,xe=0;ae&&(ee|=16),k==="UNIX"?(xe=798,ee|=(function(ge,He){var Ye=ge;return ge||(Ye=He?16893:33204),(65535&Ye)<<16})(P.unixPermissions,ae)):(xe=20,ee|=(function(ge){return 63&(ge||0)})(P.dosPermissions)),N=ue.getUTCHours(),N<<=6,N|=ue.getUTCMinutes(),N<<=5,N|=ue.getUTCSeconds()/2,_=ue.getUTCFullYear()-1980,_<<=4,_|=ue.getUTCMonth()+1,_<<=5,_|=ue.getUTCDate(),$&&(fe=i(1,1)+i(h(L),4)+j,X+="up"+i(fe.length,2)+fe),B&&(ie=i(1,1)+i(h(V),4)+O,X+="uc"+i(ie.length,2)+ie);var _e="";return _e+=`
|
|
3885
3885
|
\0`,_e+=i(K,2),_e+=D.magic,_e+=i(N,2),_e+=i(_,2),_e+=i(ve.crc32,4),_e+=i(ve.compressedSize,4),_e+=i(ve.uncompressedSize,4),_e+=i(L.length,2),_e+=i(X.length,2),{fileRecord:p.LOCAL_FILE_HEADER+_e+L+X,dirRecord:p.CENTRAL_FILE_HEADER+i(xe,2)+_e+i(V.length,2)+"\0\0\0\0"+i(ee,4)+i(v,4)+L+X+V}}var o=n("../utils"),l=n("../stream/GenericWorker"),c=n("../utf8"),h=n("../crc32"),p=n("../signature");function m(g,y,x,v){l.call(this,"ZipFileWorker"),this.bytesWritten=0,this.zipComment=y,this.zipPlatform=x,this.encodeFileName=v,this.streamFiles=g,this.accumulate=!1,this.contentBuffer=[],this.dirRecords=[],this.currentSourceOffset=0,this.entriesCount=0,this.currentFile=null,this._sources=[]}o.inherits(m,l),m.prototype.push=function(g){var y=g.meta.percent||0,x=this.entriesCount,v=this._sources.length;this.accumulate?this.contentBuffer.push(g):(this.bytesWritten+=g.data.length,l.prototype.push.call(this,{data:g.data,meta:{currentFile:this.currentFile,percent:x?(y+100*(x-v-1))/x:100}}))},m.prototype.openedSource=function(g){this.currentSourceOffset=this.bytesWritten,this.currentFile=g.file.name;var y=this.streamFiles&&!g.file.dir;if(y){var x=a(g,y,!1,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);this.push({data:x.fileRecord,meta:{percent:0}})}else this.accumulate=!0},m.prototype.closedSource=function(g){this.accumulate=!1;var y=this.streamFiles&&!g.file.dir,x=a(g,y,!0,this.currentSourceOffset,this.zipPlatform,this.encodeFileName);if(this.dirRecords.push(x.dirRecord),y)this.push({data:(function(v){return p.DATA_DESCRIPTOR+i(v.crc32,4)+i(v.compressedSize,4)+i(v.uncompressedSize,4)})(g),meta:{percent:100}});else for(this.push({data:x.fileRecord,meta:{percent:0}});this.contentBuffer.length;)this.push(this.contentBuffer.shift());this.currentFile=null},m.prototype.flush=function(){for(var g=this.bytesWritten,y=0;y<this.dirRecords.length;y++)this.push({data:this.dirRecords[y],meta:{percent:100}});var x=this.bytesWritten-g,v=(function(k,C,N,_,P){var D=o.transformTo("string",P(_));return p.CENTRAL_DIRECTORY_END+"\0\0\0\0"+i(k,2)+i(k,2)+i(C,4)+i(N,4)+i(D.length,2)+D})(this.dirRecords.length,x,g,this.zipComment,this.encodeFileName);this.push({data:v,meta:{percent:100}})},m.prototype.prepareNextSource=function(){this.previous=this._sources.shift(),this.openedSource(this.previous.streamInfo),this.isPaused?this.previous.pause():this.previous.resume()},m.prototype.registerPrevious=function(g){this._sources.push(g);var y=this;return g.on("data",function(x){y.processChunk(x)}),g.on("end",function(){y.closedSource(y.previous.streamInfo),y._sources.length?y.prepareNextSource():y.end()}),g.on("error",function(x){y.error(x)}),this},m.prototype.resume=function(){return!!l.prototype.resume.call(this)&&(!this.previous&&this._sources.length?(this.prepareNextSource(),!0):this.previous||this._sources.length||this.generatedError?void 0:(this.end(),!0))},m.prototype.error=function(g){var y=this._sources;if(!l.prototype.error.call(this,g))return!1;for(var x=0;x<y.length;x++)try{y[x].error(g)}catch{}return!0},m.prototype.lock=function(){l.prototype.lock.call(this);for(var g=this._sources,y=0;y<g.length;y++)g[y].lock()},r.exports=m},{"../crc32":4,"../signature":23,"../stream/GenericWorker":28,"../utf8":31,"../utils":32}],9:[function(n,r,s){var i=n("../compressions"),a=n("./ZipFileWorker");s.generateWorker=function(o,l,c){var h=new a(l.streamFiles,c,l.platform,l.encodeFileName),p=0;try{o.forEach(function(m,g){p++;var y=(function(C,N){var _=C||N,P=i[_];if(!P)throw new Error(_+" is not a valid compression method !");return P})(g.options.compression,l.compression),x=g.options.compressionOptions||l.compressionOptions||{},v=g.dir,k=g.date;g._compressWorker(y,x).withStreamInfo("file",{name:m,dir:v,date:k,comment:g.comment||"",unixPermissions:g.unixPermissions,dosPermissions:g.dosPermissions}).pipe(h)}),h.entriesCount=p}catch(m){h.error(m)}return h}},{"../compressions":3,"./ZipFileWorker":8}],10:[function(n,r,s){function i(){if(!(this instanceof i))return new i;if(arguments.length)throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide.");this.files=Object.create(null),this.comment=null,this.root="",this.clone=function(){var a=new i;for(var o in this)typeof this[o]!="function"&&(a[o]=this[o]);return a}}(i.prototype=n("./object")).loadAsync=n("./load"),i.support=n("./support"),i.defaults=n("./defaults"),i.version="3.10.1",i.loadAsync=function(a,o){return new i().loadAsync(a,o)},i.external=n("./external"),r.exports=i},{"./defaults":5,"./external":6,"./load":11,"./object":15,"./support":30}],11:[function(n,r,s){var i=n("./utils"),a=n("./external"),o=n("./utf8"),l=n("./zipEntries"),c=n("./stream/Crc32Probe"),h=n("./nodejsUtils");function p(m){return new a.Promise(function(g,y){var x=m.decompressed.getContentWorker().pipe(new c);x.on("error",function(v){y(v)}).on("end",function(){x.streamInfo.crc32!==m.decompressed.crc32?y(new Error("Corrupted zip : CRC32 mismatch")):g()}).resume()})}r.exports=function(m,g){var y=this;return g=i.extend(g||{},{base64:!1,checkCRC32:!1,optimizedBinaryString:!1,createFolders:!1,decodeFileName:o.utf8decode}),h.isNode&&h.isStream(m)?a.Promise.reject(new Error("JSZip can't accept a stream when loading a zip file.")):i.prepareContent("the loaded zip file",m,!0,g.optimizedBinaryString,g.base64).then(function(x){var v=new l(g);return v.load(x),v}).then(function(x){var v=[a.Promise.resolve(x)],k=x.files;if(g.checkCRC32)for(var C=0;C<k.length;C++)v.push(p(k[C]));return a.Promise.all(v)}).then(function(x){for(var v=x.shift(),k=v.files,C=0;C<k.length;C++){var N=k[C],_=N.fileNameStr,P=i.resolve(N.fileNameStr);y.file(P,N.decompressed,{binary:!0,optimizedBinaryString:!0,date:N.date,dir:N.dir,comment:N.fileCommentStr.length?N.fileCommentStr:null,unixPermissions:N.unixPermissions,dosPermissions:N.dosPermissions,createFolders:g.createFolders}),N.dir||(y.file(P).unsafeOriginalName=_)}return v.zipComment.length&&(y.comment=v.zipComment),y})}},{"./external":6,"./nodejsUtils":14,"./stream/Crc32Probe":25,"./utf8":31,"./utils":32,"./zipEntries":33}],12:[function(n,r,s){var i=n("../utils"),a=n("../stream/GenericWorker");function o(l,c){a.call(this,"Nodejs stream input adapter for "+l),this._upstreamEnded=!1,this._bindStream(c)}i.inherits(o,a),o.prototype._bindStream=function(l){var c=this;(this._stream=l).pause(),l.on("data",function(h){c.push({data:h,meta:{percent:0}})}).on("error",function(h){c.isPaused?this.generatedError=h:c.error(h)}).on("end",function(){c.isPaused?c._upstreamEnded=!0:c.end()})},o.prototype.pause=function(){return!!a.prototype.pause.call(this)&&(this._stream.pause(),!0)},o.prototype.resume=function(){return!!a.prototype.resume.call(this)&&(this._upstreamEnded?this.end():this._stream.resume(),!0)},r.exports=o},{"../stream/GenericWorker":28,"../utils":32}],13:[function(n,r,s){var i=n("readable-stream").Readable;function a(o,l,c){i.call(this,l),this._helper=o;var h=this;o.on("data",function(p,m){h.push(p)||h._helper.pause(),c&&c(m)}).on("error",function(p){h.emit("error",p)}).on("end",function(){h.push(null)})}n("../utils").inherits(a,i),a.prototype._read=function(){this._helper.resume()},r.exports=a},{"../utils":32,"readable-stream":16}],14:[function(n,r,s){r.exports={isNode:typeof Buffer<"u",newBufferFrom:function(i,a){if(Buffer.from&&Buffer.from!==Uint8Array.from)return Buffer.from(i,a);if(typeof i=="number")throw new Error('The "data" argument must not be a number');return new Buffer(i,a)},allocBuffer:function(i){if(Buffer.alloc)return Buffer.alloc(i);var a=new Buffer(i);return a.fill(0),a},isBuffer:function(i){return Buffer.isBuffer(i)},isStream:function(i){return i&&typeof i.on=="function"&&typeof i.pause=="function"&&typeof i.resume=="function"}}},{}],15:[function(n,r,s){function i(P,D,I){var L,j=o.getTypeOf(D),q=o.extend(I||{},h);q.date=q.date||new Date,q.compression!==null&&(q.compression=q.compression.toUpperCase()),typeof q.unixPermissions=="string"&&(q.unixPermissions=parseInt(q.unixPermissions,8)),q.unixPermissions&&16384&q.unixPermissions&&(q.dir=!0),q.dosPermissions&&16&q.dosPermissions&&(q.dir=!0),q.dir&&(P=k(P)),q.createFolders&&(L=v(P))&&C.call(this,L,!0);var V=j==="string"&&q.binary===!1&&q.base64===!1;I&&I.binary!==void 0||(q.binary=!V),(D instanceof p&&D.uncompressedSize===0||q.dir||!D||D.length===0)&&(q.base64=!1,q.binary=!0,D="",q.compression="STORE",j="string");var O=null;O=D instanceof p||D instanceof l?D:y.isNode&&y.isStream(D)?new x(P,D):o.prepareContent(P,D,q.binary,q.optimizedBinaryString,q.base64);var $=new m(P,O,q);this.files[P]=$}var a=n("./utf8"),o=n("./utils"),l=n("./stream/GenericWorker"),c=n("./stream/StreamHelper"),h=n("./defaults"),p=n("./compressedObject"),m=n("./zipObject"),g=n("./generate"),y=n("./nodejsUtils"),x=n("./nodejs/NodejsStreamInputAdapter"),v=function(P){P.slice(-1)==="/"&&(P=P.substring(0,P.length-1));var D=P.lastIndexOf("/");return 0<D?P.substring(0,D):""},k=function(P){return P.slice(-1)!=="/"&&(P+="/"),P},C=function(P,D){return D=D!==void 0?D:h.createFolders,P=k(P),this.files[P]||i.call(this,P,null,{dir:!0,createFolders:D}),this.files[P]};function N(P){return Object.prototype.toString.call(P)==="[object RegExp]"}var _={load:function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},forEach:function(P){var D,I,L;for(D in this.files)L=this.files[D],(I=D.slice(this.root.length,D.length))&&D.slice(0,this.root.length)===this.root&&P(I,L)},filter:function(P){var D=[];return this.forEach(function(I,L){P(I,L)&&D.push(L)}),D},file:function(P,D,I){if(arguments.length!==1)return P=this.root+P,i.call(this,P,D,I),this;if(N(P)){var L=P;return this.filter(function(q,V){return!V.dir&&L.test(q)})}var j=this.files[this.root+P];return j&&!j.dir?j:null},folder:function(P){if(!P)return this;if(N(P))return this.filter(function(j,q){return q.dir&&P.test(j)});var D=this.root+P,I=C.call(this,D),L=this.clone();return L.root=I.name,L},remove:function(P){P=this.root+P;var D=this.files[P];if(D||(P.slice(-1)!=="/"&&(P+="/"),D=this.files[P]),D&&!D.dir)delete this.files[P];else for(var I=this.filter(function(j,q){return q.name.slice(0,P.length)===P}),L=0;L<I.length;L++)delete this.files[I[L].name];return this},generate:function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},generateInternalStream:function(P){var D,I={};try{if((I=o.extend(P||{},{streamFiles:!1,compression:"STORE",compressionOptions:null,type:"",platform:"DOS",comment:null,mimeType:"application/zip",encodeFileName:a.utf8encode})).type=I.type.toLowerCase(),I.compression=I.compression.toUpperCase(),I.type==="binarystring"&&(I.type="string"),!I.type)throw new Error("No output type specified.");o.checkSupport(I.type),I.platform!=="darwin"&&I.platform!=="freebsd"&&I.platform!=="linux"&&I.platform!=="sunos"||(I.platform="UNIX"),I.platform==="win32"&&(I.platform="DOS");var L=I.comment||this.comment||"";D=g.generateWorker(this,I,L)}catch(j){(D=new l("error")).error(j)}return new c(D,I.type||"string",I.mimeType)},generateAsync:function(P,D){return this.generateInternalStream(P).accumulate(D)},generateNodeStream:function(P,D){return(P=P||{}).type||(P.type="nodebuffer"),this.generateInternalStream(P).toNodejsStream(D)}};r.exports=_},{"./compressedObject":2,"./defaults":5,"./generate":9,"./nodejs/NodejsStreamInputAdapter":12,"./nodejsUtils":14,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31,"./utils":32,"./zipObject":35}],16:[function(n,r,s){r.exports=n("stream")},{stream:void 0}],17:[function(n,r,s){var i=n("./DataReader");function a(o){i.call(this,o);for(var l=0;l<this.data.length;l++)o[l]=255&o[l]}n("../utils").inherits(a,i),a.prototype.byteAt=function(o){return this.data[this.zero+o]},a.prototype.lastIndexOfSignature=function(o){for(var l=o.charCodeAt(0),c=o.charCodeAt(1),h=o.charCodeAt(2),p=o.charCodeAt(3),m=this.length-4;0<=m;--m)if(this.data[m]===l&&this.data[m+1]===c&&this.data[m+2]===h&&this.data[m+3]===p)return m-this.zero;return-1},a.prototype.readAndCheckSignature=function(o){var l=o.charCodeAt(0),c=o.charCodeAt(1),h=o.charCodeAt(2),p=o.charCodeAt(3),m=this.readData(4);return l===m[0]&&c===m[1]&&h===m[2]&&p===m[3]},a.prototype.readData=function(o){if(this.checkOffset(o),o===0)return[];var l=this.data.slice(this.zero+this.index,this.zero+this.index+o);return this.index+=o,l},r.exports=a},{"../utils":32,"./DataReader":18}],18:[function(n,r,s){var i=n("../utils");function a(o){this.data=o,this.length=o.length,this.index=0,this.zero=0}a.prototype={checkOffset:function(o){this.checkIndex(this.index+o)},checkIndex:function(o){if(this.length<this.zero+o||o<0)throw new Error("End of data reached (data length = "+this.length+", asked index = "+o+"). Corrupted zip ?")},setIndex:function(o){this.checkIndex(o),this.index=o},skip:function(o){this.setIndex(this.index+o)},byteAt:function(){},readInt:function(o){var l,c=0;for(this.checkOffset(o),l=this.index+o-1;l>=this.index;l--)c=(c<<8)+this.byteAt(l);return this.index+=o,c},readString:function(o){return i.transformTo("string",this.readData(o))},readData:function(){},lastIndexOfSignature:function(){},readAndCheckSignature:function(){},readDate:function(){var o=this.readInt(4);return new Date(Date.UTC(1980+(o>>25&127),(o>>21&15)-1,o>>16&31,o>>11&31,o>>5&63,(31&o)<<1))}},r.exports=a},{"../utils":32}],19:[function(n,r,s){var i=n("./Uint8ArrayReader");function a(o){i.call(this,o)}n("../utils").inherits(a,i),a.prototype.readData=function(o){this.checkOffset(o);var l=this.data.slice(this.zero+this.index,this.zero+this.index+o);return this.index+=o,l},r.exports=a},{"../utils":32,"./Uint8ArrayReader":21}],20:[function(n,r,s){var i=n("./DataReader");function a(o){i.call(this,o)}n("../utils").inherits(a,i),a.prototype.byteAt=function(o){return this.data.charCodeAt(this.zero+o)},a.prototype.lastIndexOfSignature=function(o){return this.data.lastIndexOf(o)-this.zero},a.prototype.readAndCheckSignature=function(o){return o===this.readData(4)},a.prototype.readData=function(o){this.checkOffset(o);var l=this.data.slice(this.zero+this.index,this.zero+this.index+o);return this.index+=o,l},r.exports=a},{"../utils":32,"./DataReader":18}],21:[function(n,r,s){var i=n("./ArrayReader");function a(o){i.call(this,o)}n("../utils").inherits(a,i),a.prototype.readData=function(o){if(this.checkOffset(o),o===0)return new Uint8Array(0);var l=this.data.subarray(this.zero+this.index,this.zero+this.index+o);return this.index+=o,l},r.exports=a},{"../utils":32,"./ArrayReader":17}],22:[function(n,r,s){var i=n("../utils"),a=n("../support"),o=n("./ArrayReader"),l=n("./StringReader"),c=n("./NodeBufferReader"),h=n("./Uint8ArrayReader");r.exports=function(p){var m=i.getTypeOf(p);return i.checkSupport(m),m!=="string"||a.uint8array?m==="nodebuffer"?new c(p):a.uint8array?new h(i.transformTo("uint8array",p)):new o(i.transformTo("array",p)):new l(p)}},{"../support":30,"../utils":32,"./ArrayReader":17,"./NodeBufferReader":19,"./StringReader":20,"./Uint8ArrayReader":21}],23:[function(n,r,s){s.LOCAL_FILE_HEADER="PK",s.CENTRAL_FILE_HEADER="PK",s.CENTRAL_DIRECTORY_END="PK",s.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK\x07",s.ZIP64_CENTRAL_DIRECTORY_END="PK",s.DATA_DESCRIPTOR="PK\x07\b"},{}],24:[function(n,r,s){var i=n("./GenericWorker"),a=n("../utils");function o(l){i.call(this,"ConvertWorker to "+l),this.destType=l}a.inherits(o,i),o.prototype.processChunk=function(l){this.push({data:a.transformTo(this.destType,l.data),meta:l.meta})},r.exports=o},{"../utils":32,"./GenericWorker":28}],25:[function(n,r,s){var i=n("./GenericWorker"),a=n("../crc32");function o(){i.call(this,"Crc32Probe"),this.withStreamInfo("crc32",0)}n("../utils").inherits(o,i),o.prototype.processChunk=function(l){this.streamInfo.crc32=a(l.data,this.streamInfo.crc32||0),this.push(l)},r.exports=o},{"../crc32":4,"../utils":32,"./GenericWorker":28}],26:[function(n,r,s){var i=n("../utils"),a=n("./GenericWorker");function o(l){a.call(this,"DataLengthProbe for "+l),this.propName=l,this.withStreamInfo(l,0)}i.inherits(o,a),o.prototype.processChunk=function(l){if(l){var c=this.streamInfo[this.propName]||0;this.streamInfo[this.propName]=c+l.data.length}a.prototype.processChunk.call(this,l)},r.exports=o},{"../utils":32,"./GenericWorker":28}],27:[function(n,r,s){var i=n("../utils"),a=n("./GenericWorker");function o(l){a.call(this,"DataWorker");var c=this;this.dataIsReady=!1,this.index=0,this.max=0,this.data=null,this.type="",this._tickScheduled=!1,l.then(function(h){c.dataIsReady=!0,c.data=h,c.max=h&&h.length||0,c.type=i.getTypeOf(h),c.isPaused||c._tickAndRepeat()},function(h){c.error(h)})}i.inherits(o,a),o.prototype.cleanUp=function(){a.prototype.cleanUp.call(this),this.data=null},o.prototype.resume=function(){return!!a.prototype.resume.call(this)&&(!this._tickScheduled&&this.dataIsReady&&(this._tickScheduled=!0,i.delay(this._tickAndRepeat,[],this)),!0)},o.prototype._tickAndRepeat=function(){this._tickScheduled=!1,this.isPaused||this.isFinished||(this._tick(),this.isFinished||(i.delay(this._tickAndRepeat,[],this),this._tickScheduled=!0))},o.prototype._tick=function(){if(this.isPaused||this.isFinished)return!1;var l=null,c=Math.min(this.max,this.index+16384);if(this.index>=this.max)return this.end();switch(this.type){case"string":l=this.data.substring(this.index,c);break;case"uint8array":l=this.data.subarray(this.index,c);break;case"array":case"nodebuffer":l=this.data.slice(this.index,c)}return this.index=c,this.push({data:l,meta:{percent:this.max?this.index/this.max*100:0}})},r.exports=o},{"../utils":32,"./GenericWorker":28}],28:[function(n,r,s){function i(a){this.name=a||"default",this.streamInfo={},this.generatedError=null,this.extraStreamInfo={},this.isPaused=!0,this.isFinished=!1,this.isLocked=!1,this._listeners={data:[],end:[],error:[]},this.previous=null}i.prototype={push:function(a){this.emit("data",a)},end:function(){if(this.isFinished)return!1;this.flush();try{this.emit("end"),this.cleanUp(),this.isFinished=!0}catch(a){this.emit("error",a)}return!0},error:function(a){return!this.isFinished&&(this.isPaused?this.generatedError=a:(this.isFinished=!0,this.emit("error",a),this.previous&&this.previous.error(a),this.cleanUp()),!0)},on:function(a,o){return this._listeners[a].push(o),this},cleanUp:function(){this.streamInfo=this.generatedError=this.extraStreamInfo=null,this._listeners=[]},emit:function(a,o){if(this._listeners[a])for(var l=0;l<this._listeners[a].length;l++)this._listeners[a][l].call(this,o)},pipe:function(a){return a.registerPrevious(this)},registerPrevious:function(a){if(this.isLocked)throw new Error("The stream '"+this+"' has already been used.");this.streamInfo=a.streamInfo,this.mergeStreamInfo(),this.previous=a;var o=this;return a.on("data",function(l){o.processChunk(l)}),a.on("end",function(){o.end()}),a.on("error",function(l){o.error(l)}),this},pause:function(){return!this.isPaused&&!this.isFinished&&(this.isPaused=!0,this.previous&&this.previous.pause(),!0)},resume:function(){if(!this.isPaused||this.isFinished)return!1;var a=this.isPaused=!1;return this.generatedError&&(this.error(this.generatedError),a=!0),this.previous&&this.previous.resume(),!a},flush:function(){},processChunk:function(a){this.push(a)},withStreamInfo:function(a,o){return this.extraStreamInfo[a]=o,this.mergeStreamInfo(),this},mergeStreamInfo:function(){for(var a in this.extraStreamInfo)Object.prototype.hasOwnProperty.call(this.extraStreamInfo,a)&&(this.streamInfo[a]=this.extraStreamInfo[a])},lock:function(){if(this.isLocked)throw new Error("The stream '"+this+"' has already been used.");this.isLocked=!0,this.previous&&this.previous.lock()},toString:function(){var a="Worker "+this.name;return this.previous?this.previous+" -> "+a:a}},r.exports=i},{}],29:[function(n,r,s){var i=n("../utils"),a=n("./ConvertWorker"),o=n("./GenericWorker"),l=n("../base64"),c=n("../support"),h=n("../external"),p=null;if(c.nodestream)try{p=n("../nodejs/NodejsStreamOutputAdapter")}catch{}function m(y,x){return new h.Promise(function(v,k){var C=[],N=y._internalType,_=y._outputType,P=y._mimeType;y.on("data",function(D,I){C.push(D),x&&x(I)}).on("error",function(D){C=[],k(D)}).on("end",function(){try{var D=(function(I,L,j){switch(I){case"blob":return i.newBlob(i.transformTo("arraybuffer",L),j);case"base64":return l.encode(L);default:return i.transformTo(I,L)}})(_,(function(I,L){var j,q=0,V=null,O=0;for(j=0;j<L.length;j++)O+=L[j].length;switch(I){case"string":return L.join("");case"array":return Array.prototype.concat.apply([],L);case"uint8array":for(V=new Uint8Array(O),j=0;j<L.length;j++)V.set(L[j],q),q+=L[j].length;return V;case"nodebuffer":return Buffer.concat(L);default:throw new Error("concat : unsupported type '"+I+"'")}})(N,C),P);v(D)}catch(I){k(I)}C=[]}).resume()})}function g(y,x,v){var k=x;switch(x){case"blob":case"arraybuffer":k="uint8array";break;case"base64":k="string"}try{this._internalType=k,this._outputType=x,this._mimeType=v,i.checkSupport(k),this._worker=y.pipe(new a(k)),y.lock()}catch(C){this._worker=new o("error"),this._worker.error(C)}}g.prototype={accumulate:function(y){return m(this,y)},on:function(y,x){var v=this;return y==="data"?this._worker.on(y,function(k){x.call(v,k.data,k.meta)}):this._worker.on(y,function(){i.delay(x,arguments,v)}),this},resume:function(){return i.delay(this._worker.resume,[],this._worker),this},pause:function(){return this._worker.pause(),this},toNodejsStream:function(y){if(i.checkSupport("nodestream"),this._outputType!=="nodebuffer")throw new Error(this._outputType+" is not supported by this method");return new p(this,{objectMode:this._outputType!=="nodebuffer"},y)}},r.exports=g},{"../base64":1,"../external":6,"../nodejs/NodejsStreamOutputAdapter":13,"../support":30,"../utils":32,"./ConvertWorker":24,"./GenericWorker":28}],30:[function(n,r,s){if(s.base64=!0,s.array=!0,s.string=!0,s.arraybuffer=typeof ArrayBuffer<"u"&&typeof Uint8Array<"u",s.nodebuffer=typeof Buffer<"u",s.uint8array=typeof Uint8Array<"u",typeof ArrayBuffer>"u")s.blob=!1;else{var i=new ArrayBuffer(0);try{s.blob=new Blob([i],{type:"application/zip"}).size===0}catch{try{var a=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);a.append(i),s.blob=a.getBlob("application/zip").size===0}catch{s.blob=!1}}}try{s.nodestream=!!n("readable-stream").Readable}catch{s.nodestream=!1}},{"readable-stream":16}],31:[function(n,r,s){for(var i=n("./utils"),a=n("./support"),o=n("./nodejsUtils"),l=n("./stream/GenericWorker"),c=new Array(256),h=0;h<256;h++)c[h]=252<=h?6:248<=h?5:240<=h?4:224<=h?3:192<=h?2:1;c[254]=c[254]=1;function p(){l.call(this,"utf-8 decode"),this.leftOver=null}function m(){l.call(this,"utf-8 encode")}s.utf8encode=function(g){return a.nodebuffer?o.newBufferFrom(g,"utf-8"):(function(y){var x,v,k,C,N,_=y.length,P=0;for(C=0;C<_;C++)(64512&(v=y.charCodeAt(C)))==55296&&C+1<_&&(64512&(k=y.charCodeAt(C+1)))==56320&&(v=65536+(v-55296<<10)+(k-56320),C++),P+=v<128?1:v<2048?2:v<65536?3:4;for(x=a.uint8array?new Uint8Array(P):new Array(P),C=N=0;N<P;C++)(64512&(v=y.charCodeAt(C)))==55296&&C+1<_&&(64512&(k=y.charCodeAt(C+1)))==56320&&(v=65536+(v-55296<<10)+(k-56320),C++),v<128?x[N++]=v:(v<2048?x[N++]=192|v>>>6:(v<65536?x[N++]=224|v>>>12:(x[N++]=240|v>>>18,x[N++]=128|v>>>12&63),x[N++]=128|v>>>6&63),x[N++]=128|63&v);return x})(g)},s.utf8decode=function(g){return a.nodebuffer?i.transformTo("nodebuffer",g).toString("utf-8"):(function(y){var x,v,k,C,N=y.length,_=new Array(2*N);for(x=v=0;x<N;)if((k=y[x++])<128)_[v++]=k;else if(4<(C=c[k]))_[v++]=65533,x+=C-1;else{for(k&=C===2?31:C===3?15:7;1<C&&x<N;)k=k<<6|63&y[x++],C--;1<C?_[v++]=65533:k<65536?_[v++]=k:(k-=65536,_[v++]=55296|k>>10&1023,_[v++]=56320|1023&k)}return _.length!==v&&(_.subarray?_=_.subarray(0,v):_.length=v),i.applyFromCharCode(_)})(g=i.transformTo(a.uint8array?"uint8array":"array",g))},i.inherits(p,l),p.prototype.processChunk=function(g){var y=i.transformTo(a.uint8array?"uint8array":"array",g.data);if(this.leftOver&&this.leftOver.length){if(a.uint8array){var x=y;(y=new Uint8Array(x.length+this.leftOver.length)).set(this.leftOver,0),y.set(x,this.leftOver.length)}else y=this.leftOver.concat(y);this.leftOver=null}var v=(function(C,N){var _;for((N=N||C.length)>C.length&&(N=C.length),_=N-1;0<=_&&(192&C[_])==128;)_--;return _<0||_===0?N:_+c[C[_]]>N?_:N})(y),k=y;v!==y.length&&(a.uint8array?(k=y.subarray(0,v),this.leftOver=y.subarray(v,y.length)):(k=y.slice(0,v),this.leftOver=y.slice(v,y.length))),this.push({data:s.utf8decode(k),meta:g.meta})},p.prototype.flush=function(){this.leftOver&&this.leftOver.length&&(this.push({data:s.utf8decode(this.leftOver),meta:{}}),this.leftOver=null)},s.Utf8DecodeWorker=p,i.inherits(m,l),m.prototype.processChunk=function(g){this.push({data:s.utf8encode(g.data),meta:g.meta})},s.Utf8EncodeWorker=m},{"./nodejsUtils":14,"./stream/GenericWorker":28,"./support":30,"./utils":32}],32:[function(n,r,s){var i=n("./support"),a=n("./base64"),o=n("./nodejsUtils"),l=n("./external");function c(x){return x}function h(x,v){for(var k=0;k<x.length;++k)v[k]=255&x.charCodeAt(k);return v}n("setimmediate"),s.newBlob=function(x,v){s.checkSupport("blob");try{return new Blob([x],{type:v})}catch{try{var k=new(self.BlobBuilder||self.WebKitBlobBuilder||self.MozBlobBuilder||self.MSBlobBuilder);return k.append(x),k.getBlob(v)}catch{throw new Error("Bug : can't construct the Blob.")}}};var p={stringifyByChunk:function(x,v,k){var C=[],N=0,_=x.length;if(_<=k)return String.fromCharCode.apply(null,x);for(;N<_;)v==="array"||v==="nodebuffer"?C.push(String.fromCharCode.apply(null,x.slice(N,Math.min(N+k,_)))):C.push(String.fromCharCode.apply(null,x.subarray(N,Math.min(N+k,_)))),N+=k;return C.join("")},stringifyByChar:function(x){for(var v="",k=0;k<x.length;k++)v+=String.fromCharCode(x[k]);return v},applyCanBeUsed:{uint8array:(function(){try{return i.uint8array&&String.fromCharCode.apply(null,new Uint8Array(1)).length===1}catch{return!1}})(),nodebuffer:(function(){try{return i.nodebuffer&&String.fromCharCode.apply(null,o.allocBuffer(1)).length===1}catch{return!1}})()}};function m(x){var v=65536,k=s.getTypeOf(x),C=!0;if(k==="uint8array"?C=p.applyCanBeUsed.uint8array:k==="nodebuffer"&&(C=p.applyCanBeUsed.nodebuffer),C)for(;1<v;)try{return p.stringifyByChunk(x,k,v)}catch{v=Math.floor(v/2)}return p.stringifyByChar(x)}function g(x,v){for(var k=0;k<x.length;k++)v[k]=x[k];return v}s.applyFromCharCode=m;var y={};y.string={string:c,array:function(x){return h(x,new Array(x.length))},arraybuffer:function(x){return y.string.uint8array(x).buffer},uint8array:function(x){return h(x,new Uint8Array(x.length))},nodebuffer:function(x){return h(x,o.allocBuffer(x.length))}},y.array={string:m,array:c,arraybuffer:function(x){return new Uint8Array(x).buffer},uint8array:function(x){return new Uint8Array(x)},nodebuffer:function(x){return o.newBufferFrom(x)}},y.arraybuffer={string:function(x){return m(new Uint8Array(x))},array:function(x){return g(new Uint8Array(x),new Array(x.byteLength))},arraybuffer:c,uint8array:function(x){return new Uint8Array(x)},nodebuffer:function(x){return o.newBufferFrom(new Uint8Array(x))}},y.uint8array={string:m,array:function(x){return g(x,new Array(x.length))},arraybuffer:function(x){return x.buffer},uint8array:c,nodebuffer:function(x){return o.newBufferFrom(x)}},y.nodebuffer={string:m,array:function(x){return g(x,new Array(x.length))},arraybuffer:function(x){return y.nodebuffer.uint8array(x).buffer},uint8array:function(x){return g(x,new Uint8Array(x.length))},nodebuffer:c},s.transformTo=function(x,v){if(v=v||"",!x)return v;s.checkSupport(x);var k=s.getTypeOf(v);return y[k][x](v)},s.resolve=function(x){for(var v=x.split("/"),k=[],C=0;C<v.length;C++){var N=v[C];N==="."||N===""&&C!==0&&C!==v.length-1||(N===".."?k.pop():k.push(N))}return k.join("/")},s.getTypeOf=function(x){return typeof x=="string"?"string":Object.prototype.toString.call(x)==="[object Array]"?"array":i.nodebuffer&&o.isBuffer(x)?"nodebuffer":i.uint8array&&x instanceof Uint8Array?"uint8array":i.arraybuffer&&x instanceof ArrayBuffer?"arraybuffer":void 0},s.checkSupport=function(x){if(!i[x.toLowerCase()])throw new Error(x+" is not supported by this platform")},s.MAX_VALUE_16BITS=65535,s.MAX_VALUE_32BITS=-1,s.pretty=function(x){var v,k,C="";for(k=0;k<(x||"").length;k++)C+="\\x"+((v=x.charCodeAt(k))<16?"0":"")+v.toString(16).toUpperCase();return C},s.delay=function(x,v,k){setImmediate(function(){x.apply(k||null,v||[])})},s.inherits=function(x,v){function k(){}k.prototype=v.prototype,x.prototype=new k},s.extend=function(){var x,v,k={};for(x=0;x<arguments.length;x++)for(v in arguments[x])Object.prototype.hasOwnProperty.call(arguments[x],v)&&k[v]===void 0&&(k[v]=arguments[x][v]);return k},s.prepareContent=function(x,v,k,C,N){return l.Promise.resolve(v).then(function(_){return i.blob&&(_ instanceof Blob||["[object File]","[object Blob]"].indexOf(Object.prototype.toString.call(_))!==-1)&&typeof FileReader<"u"?new l.Promise(function(P,D){var I=new FileReader;I.onload=function(L){P(L.target.result)},I.onerror=function(L){D(L.target.error)},I.readAsArrayBuffer(_)}):_}).then(function(_){var P=s.getTypeOf(_);return P?(P==="arraybuffer"?_=s.transformTo("uint8array",_):P==="string"&&(N?_=a.decode(_):k&&C!==!0&&(_=(function(D){return h(D,i.uint8array?new Uint8Array(D.length):new Array(D.length))})(_))),_):l.Promise.reject(new Error("Can't read the data of '"+x+"'. Is it in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?"))})}},{"./base64":1,"./external":6,"./nodejsUtils":14,"./support":30,setimmediate:54}],33:[function(n,r,s){var i=n("./reader/readerFor"),a=n("./utils"),o=n("./signature"),l=n("./zipEntry"),c=n("./support");function h(p){this.files=[],this.loadOptions=p}h.prototype={checkSignature:function(p){if(!this.reader.readAndCheckSignature(p)){this.reader.index-=4;var m=this.reader.readString(4);throw new Error("Corrupted zip or bug: unexpected signature ("+a.pretty(m)+", expected "+a.pretty(p)+")")}},isSignature:function(p,m){var g=this.reader.index;this.reader.setIndex(p);var y=this.reader.readString(4)===m;return this.reader.setIndex(g),y},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2);var p=this.reader.readData(this.zipCommentLength),m=c.uint8array?"uint8array":"array",g=a.transformTo(m,p);this.zipComment=this.loadOptions.decodeFileName(g)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.reader.skip(4),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var p,m,g,y=this.zip64EndOfCentralSize-44;0<y;)p=this.reader.readInt(2),m=this.reader.readInt(4),g=this.reader.readData(m),this.zip64ExtensibleData[p]={id:p,length:m,value:g}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),1<this.disksCount)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var p,m;for(p=0;p<this.files.length;p++)m=this.files[p],this.reader.setIndex(m.localHeaderOffset),this.checkSignature(o.LOCAL_FILE_HEADER),m.readLocalPart(this.reader),m.handleUTF8(),m.processAttributes()},readCentralDir:function(){var p;for(this.reader.setIndex(this.centralDirOffset);this.reader.readAndCheckSignature(o.CENTRAL_FILE_HEADER);)(p=new l({zip64:this.zip64},this.loadOptions)).readCentralPart(this.reader),this.files.push(p);if(this.centralDirRecords!==this.files.length&&this.centralDirRecords!==0&&this.files.length===0)throw new Error("Corrupted zip or bug: expected "+this.centralDirRecords+" records in central dir, got "+this.files.length)},readEndOfCentral:function(){var p=this.reader.lastIndexOfSignature(o.CENTRAL_DIRECTORY_END);if(p<0)throw this.isSignature(0,o.LOCAL_FILE_HEADER)?new Error("Corrupted zip: can't find end of central directory"):new Error("Can't find end of central directory : is this a zip file ? If it is, see https://stuk.github.io/jszip/documentation/howto/read_zip.html");this.reader.setIndex(p);var m=p;if(this.checkSignature(o.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===a.MAX_VALUE_16BITS||this.diskWithCentralDirStart===a.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===a.MAX_VALUE_16BITS||this.centralDirRecords===a.MAX_VALUE_16BITS||this.centralDirSize===a.MAX_VALUE_32BITS||this.centralDirOffset===a.MAX_VALUE_32BITS){if(this.zip64=!0,(p=this.reader.lastIndexOfSignature(o.ZIP64_CENTRAL_DIRECTORY_LOCATOR))<0)throw new Error("Corrupted zip: can't find the ZIP64 end of central directory locator");if(this.reader.setIndex(p),this.checkSignature(o.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),!this.isSignature(this.relativeOffsetEndOfZip64CentralDir,o.ZIP64_CENTRAL_DIRECTORY_END)&&(this.relativeOffsetEndOfZip64CentralDir=this.reader.lastIndexOfSignature(o.ZIP64_CENTRAL_DIRECTORY_END),this.relativeOffsetEndOfZip64CentralDir<0))throw new Error("Corrupted zip: can't find the ZIP64 end of central directory");this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(o.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}var g=this.centralDirOffset+this.centralDirSize;this.zip64&&(g+=20,g+=12+this.zip64EndOfCentralSize);var y=m-g;if(0<y)this.isSignature(m,o.CENTRAL_FILE_HEADER)||(this.reader.zero=y);else if(y<0)throw new Error("Corrupted zip: missing "+Math.abs(y)+" bytes.")},prepareReader:function(p){this.reader=i(p)},load:function(p){this.prepareReader(p),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},r.exports=h},{"./reader/readerFor":22,"./signature":23,"./support":30,"./utils":32,"./zipEntry":34}],34:[function(n,r,s){var i=n("./reader/readerFor"),a=n("./utils"),o=n("./compressedObject"),l=n("./crc32"),c=n("./utf8"),h=n("./compressions"),p=n("./support");function m(g,y){this.options=g,this.loadOptions=y}m.prototype={isEncrypted:function(){return(1&this.bitFlag)==1},useUTF8:function(){return(2048&this.bitFlag)==2048},readLocalPart:function(g){var y,x;if(g.skip(22),this.fileNameLength=g.readInt(2),x=g.readInt(2),this.fileName=g.readData(this.fileNameLength),g.skip(x),this.compressedSize===-1||this.uncompressedSize===-1)throw new Error("Bug or corrupted zip : didn't get enough information from the central directory (compressedSize === -1 || uncompressedSize === -1)");if((y=(function(v){for(var k in h)if(Object.prototype.hasOwnProperty.call(h,k)&&h[k].magic===v)return h[k];return null})(this.compressionMethod))===null)throw new Error("Corrupted zip : compression "+a.pretty(this.compressionMethod)+" unknown (inner file : "+a.transformTo("string",this.fileName)+")");this.decompressed=new o(this.compressedSize,this.uncompressedSize,this.crc32,y,g.readData(this.compressedSize))},readCentralPart:function(g){this.versionMadeBy=g.readInt(2),g.skip(2),this.bitFlag=g.readInt(2),this.compressionMethod=g.readString(2),this.date=g.readDate(),this.crc32=g.readInt(4),this.compressedSize=g.readInt(4),this.uncompressedSize=g.readInt(4);var y=g.readInt(2);if(this.extraFieldsLength=g.readInt(2),this.fileCommentLength=g.readInt(2),this.diskNumberStart=g.readInt(2),this.internalFileAttributes=g.readInt(2),this.externalFileAttributes=g.readInt(4),this.localHeaderOffset=g.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");g.skip(y),this.readExtraFields(g),this.parseZIP64ExtraField(g),this.fileComment=g.readData(this.fileCommentLength)},processAttributes:function(){this.unixPermissions=null,this.dosPermissions=null;var g=this.versionMadeBy>>8;this.dir=!!(16&this.externalFileAttributes),g==0&&(this.dosPermissions=63&this.externalFileAttributes),g==3&&(this.unixPermissions=this.externalFileAttributes>>16&65535),this.dir||this.fileNameStr.slice(-1)!=="/"||(this.dir=!0)},parseZIP64ExtraField:function(){if(this.extraFields[1]){var g=i(this.extraFields[1].value);this.uncompressedSize===a.MAX_VALUE_32BITS&&(this.uncompressedSize=g.readInt(8)),this.compressedSize===a.MAX_VALUE_32BITS&&(this.compressedSize=g.readInt(8)),this.localHeaderOffset===a.MAX_VALUE_32BITS&&(this.localHeaderOffset=g.readInt(8)),this.diskNumberStart===a.MAX_VALUE_32BITS&&(this.diskNumberStart=g.readInt(4))}},readExtraFields:function(g){var y,x,v,k=g.index+this.extraFieldsLength;for(this.extraFields||(this.extraFields={});g.index+4<k;)y=g.readInt(2),x=g.readInt(2),v=g.readData(x),this.extraFields[y]={id:y,length:x,value:v};g.setIndex(k)},handleUTF8:function(){var g=p.uint8array?"uint8array":"array";if(this.useUTF8())this.fileNameStr=c.utf8decode(this.fileName),this.fileCommentStr=c.utf8decode(this.fileComment);else{var y=this.findExtraFieldUnicodePath();if(y!==null)this.fileNameStr=y;else{var x=a.transformTo(g,this.fileName);this.fileNameStr=this.loadOptions.decodeFileName(x)}var v=this.findExtraFieldUnicodeComment();if(v!==null)this.fileCommentStr=v;else{var k=a.transformTo(g,this.fileComment);this.fileCommentStr=this.loadOptions.decodeFileName(k)}}},findExtraFieldUnicodePath:function(){var g=this.extraFields[28789];if(g){var y=i(g.value);return y.readInt(1)!==1||l(this.fileName)!==y.readInt(4)?null:c.utf8decode(y.readData(g.length-5))}return null},findExtraFieldUnicodeComment:function(){var g=this.extraFields[25461];if(g){var y=i(g.value);return y.readInt(1)!==1||l(this.fileComment)!==y.readInt(4)?null:c.utf8decode(y.readData(g.length-5))}return null}},r.exports=m},{"./compressedObject":2,"./compressions":3,"./crc32":4,"./reader/readerFor":22,"./support":30,"./utf8":31,"./utils":32}],35:[function(n,r,s){function i(y,x,v){this.name=y,this.dir=v.dir,this.date=v.date,this.comment=v.comment,this.unixPermissions=v.unixPermissions,this.dosPermissions=v.dosPermissions,this._data=x,this._dataBinary=v.binary,this.options={compression:v.compression,compressionOptions:v.compressionOptions}}var a=n("./stream/StreamHelper"),o=n("./stream/DataWorker"),l=n("./utf8"),c=n("./compressedObject"),h=n("./stream/GenericWorker");i.prototype={internalStream:function(y){var x=null,v="string";try{if(!y)throw new Error("No output type specified.");var k=(v=y.toLowerCase())==="string"||v==="text";v!=="binarystring"&&v!=="text"||(v="string"),x=this._decompressWorker();var C=!this._dataBinary;C&&!k&&(x=x.pipe(new l.Utf8EncodeWorker)),!C&&k&&(x=x.pipe(new l.Utf8DecodeWorker))}catch(N){(x=new h("error")).error(N)}return new a(x,v,"")},async:function(y,x){return this.internalStream(y).accumulate(x)},nodeStream:function(y,x){return this.internalStream(y||"nodebuffer").toNodejsStream(x)},_compressWorker:function(y,x){if(this._data instanceof c&&this._data.compression.magic===y.magic)return this._data.getCompressedWorker();var v=this._decompressWorker();return this._dataBinary||(v=v.pipe(new l.Utf8EncodeWorker)),c.createWorkerFrom(v,y,x)},_decompressWorker:function(){return this._data instanceof c?this._data.getContentWorker():this._data instanceof h?this._data:new o(this._data)}};for(var p=["asText","asBinary","asNodeBuffer","asUint8Array","asArrayBuffer"],m=function(){throw new Error("This method has been removed in JSZip 3.0, please check the upgrade guide.")},g=0;g<p.length;g++)i.prototype[p[g]]=m;r.exports=i},{"./compressedObject":2,"./stream/DataWorker":27,"./stream/GenericWorker":28,"./stream/StreamHelper":29,"./utf8":31}],36:[function(n,r,s){(function(i){var a,o,l=i.MutationObserver||i.WebKitMutationObserver;if(l){var c=0,h=new l(y),p=i.document.createTextNode("");h.observe(p,{characterData:!0}),a=function(){p.data=c=++c%2}}else if(i.setImmediate||i.MessageChannel===void 0)a="document"in i&&"onreadystatechange"in i.document.createElement("script")?function(){var x=i.document.createElement("script");x.onreadystatechange=function(){y(),x.onreadystatechange=null,x.parentNode.removeChild(x),x=null},i.document.documentElement.appendChild(x)}:function(){setTimeout(y,0)};else{var m=new i.MessageChannel;m.port1.onmessage=y,a=function(){m.port2.postMessage(0)}}var g=[];function y(){var x,v;o=!0;for(var k=g.length;k;){for(v=g,g=[],x=-1;++x<k;)v[x]();k=g.length}o=!1}r.exports=function(x){g.push(x)!==1||o||a()}}).call(this,typeof Vb<"u"?Vb:typeof self<"u"?self:typeof window<"u"?window:{})},{}],37:[function(n,r,s){var i=n("immediate");function a(){}var o={},l=["REJECTED"],c=["FULFILLED"],h=["PENDING"];function p(k){if(typeof k!="function")throw new TypeError("resolver must be a function");this.state=h,this.queue=[],this.outcome=void 0,k!==a&&x(this,k)}function m(k,C,N){this.promise=k,typeof C=="function"&&(this.onFulfilled=C,this.callFulfilled=this.otherCallFulfilled),typeof N=="function"&&(this.onRejected=N,this.callRejected=this.otherCallRejected)}function g(k,C,N){i(function(){var _;try{_=C(N)}catch(P){return o.reject(k,P)}_===k?o.reject(k,new TypeError("Cannot resolve promise with itself")):o.resolve(k,_)})}function y(k){var C=k&&k.then;if(k&&(typeof k=="object"||typeof k=="function")&&typeof C=="function")return function(){C.apply(k,arguments)}}function x(k,C){var N=!1;function _(I){N||(N=!0,o.reject(k,I))}function P(I){N||(N=!0,o.resolve(k,I))}var D=v(function(){C(P,_)});D.status==="error"&&_(D.value)}function v(k,C){var N={};try{N.value=k(C),N.status="success"}catch(_){N.status="error",N.value=_}return N}(r.exports=p).prototype.finally=function(k){if(typeof k!="function")return this;var C=this.constructor;return this.then(function(N){return C.resolve(k()).then(function(){return N})},function(N){return C.resolve(k()).then(function(){throw N})})},p.prototype.catch=function(k){return this.then(null,k)},p.prototype.then=function(k,C){if(typeof k!="function"&&this.state===c||typeof C!="function"&&this.state===l)return this;var N=new this.constructor(a);return this.state!==h?g(N,this.state===c?k:C,this.outcome):this.queue.push(new m(N,k,C)),N},m.prototype.callFulfilled=function(k){o.resolve(this.promise,k)},m.prototype.otherCallFulfilled=function(k){g(this.promise,this.onFulfilled,k)},m.prototype.callRejected=function(k){o.reject(this.promise,k)},m.prototype.otherCallRejected=function(k){g(this.promise,this.onRejected,k)},o.resolve=function(k,C){var N=v(y,C);if(N.status==="error")return o.reject(k,N.value);var _=N.value;if(_)x(k,_);else{k.state=c,k.outcome=C;for(var P=-1,D=k.queue.length;++P<D;)k.queue[P].callFulfilled(C)}return k},o.reject=function(k,C){k.state=l,k.outcome=C;for(var N=-1,_=k.queue.length;++N<_;)k.queue[N].callRejected(C);return k},p.resolve=function(k){return k instanceof this?k:o.resolve(new this(a),k)},p.reject=function(k){var C=new this(a);return o.reject(C,k)},p.all=function(k){var C=this;if(Object.prototype.toString.call(k)!=="[object Array]")return this.reject(new TypeError("must be an array"));var N=k.length,_=!1;if(!N)return this.resolve([]);for(var P=new Array(N),D=0,I=-1,L=new this(a);++I<N;)j(k[I],I);return L;function j(q,V){C.resolve(q).then(function(O){P[V]=O,++D!==N||_||(_=!0,o.resolve(L,P))},function(O){_||(_=!0,o.reject(L,O))})}},p.race=function(k){var C=this;if(Object.prototype.toString.call(k)!=="[object Array]")return this.reject(new TypeError("must be an array"));var N=k.length,_=!1;if(!N)return this.resolve([]);for(var P=-1,D=new this(a);++P<N;)I=k[P],C.resolve(I).then(function(L){_||(_=!0,o.resolve(D,L))},function(L){_||(_=!0,o.reject(D,L))});var I;return D}},{immediate:36}],38:[function(n,r,s){var i={};(0,n("./lib/utils/common").assign)(i,n("./lib/deflate"),n("./lib/inflate"),n("./lib/zlib/constants")),r.exports=i},{"./lib/deflate":39,"./lib/inflate":40,"./lib/utils/common":41,"./lib/zlib/constants":44}],39:[function(n,r,s){var i=n("./zlib/deflate"),a=n("./utils/common"),o=n("./utils/strings"),l=n("./zlib/messages"),c=n("./zlib/zstream"),h=Object.prototype.toString,p=0,m=-1,g=0,y=8;function x(k){if(!(this instanceof x))return new x(k);this.options=a.assign({level:m,method:y,chunkSize:16384,windowBits:15,memLevel:8,strategy:g,to:""},k||{});var C=this.options;C.raw&&0<C.windowBits?C.windowBits=-C.windowBits:C.gzip&&0<C.windowBits&&C.windowBits<16&&(C.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new c,this.strm.avail_out=0;var N=i.deflateInit2(this.strm,C.level,C.method,C.windowBits,C.memLevel,C.strategy);if(N!==p)throw new Error(l[N]);if(C.header&&i.deflateSetHeader(this.strm,C.header),C.dictionary){var _;if(_=typeof C.dictionary=="string"?o.string2buf(C.dictionary):h.call(C.dictionary)==="[object ArrayBuffer]"?new Uint8Array(C.dictionary):C.dictionary,(N=i.deflateSetDictionary(this.strm,_))!==p)throw new Error(l[N]);this._dict_set=!0}}function v(k,C){var N=new x(C);if(N.push(k,!0),N.err)throw N.msg||l[N.err];return N.result}x.prototype.push=function(k,C){var N,_,P=this.strm,D=this.options.chunkSize;if(this.ended)return!1;_=C===~~C?C:C===!0?4:0,typeof k=="string"?P.input=o.string2buf(k):h.call(k)==="[object ArrayBuffer]"?P.input=new Uint8Array(k):P.input=k,P.next_in=0,P.avail_in=P.input.length;do{if(P.avail_out===0&&(P.output=new a.Buf8(D),P.next_out=0,P.avail_out=D),(N=i.deflate(P,_))!==1&&N!==p)return this.onEnd(N),!(this.ended=!0);P.avail_out!==0&&(P.avail_in!==0||_!==4&&_!==2)||(this.options.to==="string"?this.onData(o.buf2binstring(a.shrinkBuf(P.output,P.next_out))):this.onData(a.shrinkBuf(P.output,P.next_out)))}while((0<P.avail_in||P.avail_out===0)&&N!==1);return _===4?(N=i.deflateEnd(this.strm),this.onEnd(N),this.ended=!0,N===p):_!==2||(this.onEnd(p),!(P.avail_out=0))},x.prototype.onData=function(k){this.chunks.push(k)},x.prototype.onEnd=function(k){k===p&&(this.options.to==="string"?this.result=this.chunks.join(""):this.result=a.flattenChunks(this.chunks)),this.chunks=[],this.err=k,this.msg=this.strm.msg},s.Deflate=x,s.deflate=v,s.deflateRaw=function(k,C){return(C=C||{}).raw=!0,v(k,C)},s.gzip=function(k,C){return(C=C||{}).gzip=!0,v(k,C)}},{"./utils/common":41,"./utils/strings":42,"./zlib/deflate":46,"./zlib/messages":51,"./zlib/zstream":53}],40:[function(n,r,s){var i=n("./zlib/inflate"),a=n("./utils/common"),o=n("./utils/strings"),l=n("./zlib/constants"),c=n("./zlib/messages"),h=n("./zlib/zstream"),p=n("./zlib/gzheader"),m=Object.prototype.toString;function g(x){if(!(this instanceof g))return new g(x);this.options=a.assign({chunkSize:16384,windowBits:0,to:""},x||{});var v=this.options;v.raw&&0<=v.windowBits&&v.windowBits<16&&(v.windowBits=-v.windowBits,v.windowBits===0&&(v.windowBits=-15)),!(0<=v.windowBits&&v.windowBits<16)||x&&x.windowBits||(v.windowBits+=32),15<v.windowBits&&v.windowBits<48&&(15&v.windowBits)==0&&(v.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new h,this.strm.avail_out=0;var k=i.inflateInit2(this.strm,v.windowBits);if(k!==l.Z_OK)throw new Error(c[k]);this.header=new p,i.inflateGetHeader(this.strm,this.header)}function y(x,v){var k=new g(v);if(k.push(x,!0),k.err)throw k.msg||c[k.err];return k.result}g.prototype.push=function(x,v){var k,C,N,_,P,D,I=this.strm,L=this.options.chunkSize,j=this.options.dictionary,q=!1;if(this.ended)return!1;C=v===~~v?v:v===!0?l.Z_FINISH:l.Z_NO_FLUSH,typeof x=="string"?I.input=o.binstring2buf(x):m.call(x)==="[object ArrayBuffer]"?I.input=new Uint8Array(x):I.input=x,I.next_in=0,I.avail_in=I.input.length;do{if(I.avail_out===0&&(I.output=new a.Buf8(L),I.next_out=0,I.avail_out=L),(k=i.inflate(I,l.Z_NO_FLUSH))===l.Z_NEED_DICT&&j&&(D=typeof j=="string"?o.string2buf(j):m.call(j)==="[object ArrayBuffer]"?new Uint8Array(j):j,k=i.inflateSetDictionary(this.strm,D)),k===l.Z_BUF_ERROR&&q===!0&&(k=l.Z_OK,q=!1),k!==l.Z_STREAM_END&&k!==l.Z_OK)return this.onEnd(k),!(this.ended=!0);I.next_out&&(I.avail_out!==0&&k!==l.Z_STREAM_END&&(I.avail_in!==0||C!==l.Z_FINISH&&C!==l.Z_SYNC_FLUSH)||(this.options.to==="string"?(N=o.utf8border(I.output,I.next_out),_=I.next_out-N,P=o.buf2string(I.output,N),I.next_out=_,I.avail_out=L-_,_&&a.arraySet(I.output,I.output,N,_,0),this.onData(P)):this.onData(a.shrinkBuf(I.output,I.next_out)))),I.avail_in===0&&I.avail_out===0&&(q=!0)}while((0<I.avail_in||I.avail_out===0)&&k!==l.Z_STREAM_END);return k===l.Z_STREAM_END&&(C=l.Z_FINISH),C===l.Z_FINISH?(k=i.inflateEnd(this.strm),this.onEnd(k),this.ended=!0,k===l.Z_OK):C!==l.Z_SYNC_FLUSH||(this.onEnd(l.Z_OK),!(I.avail_out=0))},g.prototype.onData=function(x){this.chunks.push(x)},g.prototype.onEnd=function(x){x===l.Z_OK&&(this.options.to==="string"?this.result=this.chunks.join(""):this.result=a.flattenChunks(this.chunks)),this.chunks=[],this.err=x,this.msg=this.strm.msg},s.Inflate=g,s.inflate=y,s.inflateRaw=function(x,v){return(v=v||{}).raw=!0,y(x,v)},s.ungzip=y},{"./utils/common":41,"./utils/strings":42,"./zlib/constants":44,"./zlib/gzheader":47,"./zlib/inflate":49,"./zlib/messages":51,"./zlib/zstream":53}],41:[function(n,r,s){var i=typeof Uint8Array<"u"&&typeof Uint16Array<"u"&&typeof Int32Array<"u";s.assign=function(l){for(var c=Array.prototype.slice.call(arguments,1);c.length;){var h=c.shift();if(h){if(typeof h!="object")throw new TypeError(h+"must be non-object");for(var p in h)h.hasOwnProperty(p)&&(l[p]=h[p])}}return l},s.shrinkBuf=function(l,c){return l.length===c?l:l.subarray?l.subarray(0,c):(l.length=c,l)};var a={arraySet:function(l,c,h,p,m){if(c.subarray&&l.subarray)l.set(c.subarray(h,h+p),m);else for(var g=0;g<p;g++)l[m+g]=c[h+g]},flattenChunks:function(l){var c,h,p,m,g,y;for(c=p=0,h=l.length;c<h;c++)p+=l[c].length;for(y=new Uint8Array(p),c=m=0,h=l.length;c<h;c++)g=l[c],y.set(g,m),m+=g.length;return y}},o={arraySet:function(l,c,h,p,m){for(var g=0;g<p;g++)l[m+g]=c[h+g]},flattenChunks:function(l){return[].concat.apply([],l)}};s.setTyped=function(l){l?(s.Buf8=Uint8Array,s.Buf16=Uint16Array,s.Buf32=Int32Array,s.assign(s,a)):(s.Buf8=Array,s.Buf16=Array,s.Buf32=Array,s.assign(s,o))},s.setTyped(i)},{}],42:[function(n,r,s){var i=n("./common"),a=!0,o=!0;try{String.fromCharCode.apply(null,[0])}catch{a=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch{o=!1}for(var l=new i.Buf8(256),c=0;c<256;c++)l[c]=252<=c?6:248<=c?5:240<=c?4:224<=c?3:192<=c?2:1;function h(p,m){if(m<65537&&(p.subarray&&o||!p.subarray&&a))return String.fromCharCode.apply(null,i.shrinkBuf(p,m));for(var g="",y=0;y<m;y++)g+=String.fromCharCode(p[y]);return g}l[254]=l[254]=1,s.string2buf=function(p){var m,g,y,x,v,k=p.length,C=0;for(x=0;x<k;x++)(64512&(g=p.charCodeAt(x)))==55296&&x+1<k&&(64512&(y=p.charCodeAt(x+1)))==56320&&(g=65536+(g-55296<<10)+(y-56320),x++),C+=g<128?1:g<2048?2:g<65536?3:4;for(m=new i.Buf8(C),x=v=0;v<C;x++)(64512&(g=p.charCodeAt(x)))==55296&&x+1<k&&(64512&(y=p.charCodeAt(x+1)))==56320&&(g=65536+(g-55296<<10)+(y-56320),x++),g<128?m[v++]=g:(g<2048?m[v++]=192|g>>>6:(g<65536?m[v++]=224|g>>>12:(m[v++]=240|g>>>18,m[v++]=128|g>>>12&63),m[v++]=128|g>>>6&63),m[v++]=128|63&g);return m},s.buf2binstring=function(p){return h(p,p.length)},s.binstring2buf=function(p){for(var m=new i.Buf8(p.length),g=0,y=m.length;g<y;g++)m[g]=p.charCodeAt(g);return m},s.buf2string=function(p,m){var g,y,x,v,k=m||p.length,C=new Array(2*k);for(g=y=0;g<k;)if((x=p[g++])<128)C[y++]=x;else if(4<(v=l[x]))C[y++]=65533,g+=v-1;else{for(x&=v===2?31:v===3?15:7;1<v&&g<k;)x=x<<6|63&p[g++],v--;1<v?C[y++]=65533:x<65536?C[y++]=x:(x-=65536,C[y++]=55296|x>>10&1023,C[y++]=56320|1023&x)}return h(C,y)},s.utf8border=function(p,m){var g;for((m=m||p.length)>p.length&&(m=p.length),g=m-1;0<=g&&(192&p[g])==128;)g--;return g<0||g===0?m:g+l[p[g]]>m?g:m}},{"./common":41}],43:[function(n,r,s){r.exports=function(i,a,o,l){for(var c=65535&i|0,h=i>>>16&65535|0,p=0;o!==0;){for(o-=p=2e3<o?2e3:o;h=h+(c=c+a[l++]|0)|0,--p;);c%=65521,h%=65521}return c|h<<16|0}},{}],44:[function(n,r,s){r.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],45:[function(n,r,s){var i=(function(){for(var a,o=[],l=0;l<256;l++){a=l;for(var c=0;c<8;c++)a=1&a?3988292384^a>>>1:a>>>1;o[l]=a}return o})();r.exports=function(a,o,l,c){var h=i,p=c+l;a^=-1;for(var m=c;m<p;m++)a=a>>>8^h[255&(a^o[m])];return-1^a}},{}],46:[function(n,r,s){var i,a=n("../utils/common"),o=n("./trees"),l=n("./adler32"),c=n("./crc32"),h=n("./messages"),p=0,m=4,g=0,y=-2,x=-1,v=4,k=2,C=8,N=9,_=286,P=30,D=19,I=2*_+1,L=15,j=3,q=258,V=q+j+1,O=42,$=113,B=1,X=2,fe=3,ie=4;function ae(z,ce){return z.msg=h[ce],ce}function ue(z){return(z<<1)-(4<z?9:0)}function ve(z){for(var ce=z.length;0<=--ce;)z[ce]=0}function K(z){var ce=z.state,le=ce.pending;le>z.avail_out&&(le=z.avail_out),le!==0&&(a.arraySet(z.output,ce.pending_buf,ce.pending_out,le,z.next_out),z.next_out+=le,ce.pending_out+=le,z.total_out+=le,z.avail_out-=le,ce.pending-=le,ce.pending===0&&(ce.pending_out=0))}function ee(z,ce){o._tr_flush_block(z,0<=z.block_start?z.block_start:-1,z.strstart-z.block_start,ce),z.block_start=z.strstart,K(z.strm)}function xe(z,ce){z.pending_buf[z.pending++]=ce}function _e(z,ce){z.pending_buf[z.pending++]=ce>>>8&255,z.pending_buf[z.pending++]=255&ce}function ge(z,ce){var le,Y,Z=z.max_chain_length,re=z.strstart,be=z.prev_length,Te=z.nice_match,he=z.strstart>z.w_size-V?z.strstart-(z.w_size-V):0,Me=z.window,$e=z.w_mask,Re=z.prev,Be=z.strstart+q,st=Me[re+be-1],ot=Me[re+be];z.prev_length>=z.good_match&&(Z>>=2),Te>z.lookahead&&(Te=z.lookahead);do if(Me[(le=ce)+be]===ot&&Me[le+be-1]===st&&Me[le]===Me[re]&&Me[++le]===Me[re+1]){re+=2,le++;do;while(Me[++re]===Me[++le]&&Me[++re]===Me[++le]&&Me[++re]===Me[++le]&&Me[++re]===Me[++le]&&Me[++re]===Me[++le]&&Me[++re]===Me[++le]&&Me[++re]===Me[++le]&&Me[++re]===Me[++le]&&re<Be);if(Y=q-(Be-re),re=Be-q,be<Y){if(z.match_start=ce,Te<=(be=Y))break;st=Me[re+be-1],ot=Me[re+be]}}while((ce=Re[ce&$e])>he&&--Z!=0);return be<=z.lookahead?be:z.lookahead}function He(z){var ce,le,Y,Z,re,be,Te,he,Me,$e,Re=z.w_size;do{if(Z=z.window_size-z.lookahead-z.strstart,z.strstart>=Re+(Re-V)){for(a.arraySet(z.window,z.window,Re,Re,0),z.match_start-=Re,z.strstart-=Re,z.block_start-=Re,ce=le=z.hash_size;Y=z.head[--ce],z.head[ce]=Re<=Y?Y-Re:0,--le;);for(ce=le=Re;Y=z.prev[--ce],z.prev[ce]=Re<=Y?Y-Re:0,--le;);Z+=Re}if(z.strm.avail_in===0)break;if(be=z.strm,Te=z.window,he=z.strstart+z.lookahead,Me=Z,$e=void 0,$e=be.avail_in,Me<$e&&($e=Me),le=$e===0?0:(be.avail_in-=$e,a.arraySet(Te,be.input,be.next_in,$e,he),be.state.wrap===1?be.adler=l(be.adler,Te,$e,he):be.state.wrap===2&&(be.adler=c(be.adler,Te,$e,he)),be.next_in+=$e,be.total_in+=$e,$e),z.lookahead+=le,z.lookahead+z.insert>=j)for(re=z.strstart-z.insert,z.ins_h=z.window[re],z.ins_h=(z.ins_h<<z.hash_shift^z.window[re+1])&z.hash_mask;z.insert&&(z.ins_h=(z.ins_h<<z.hash_shift^z.window[re+j-1])&z.hash_mask,z.prev[re&z.w_mask]=z.head[z.ins_h],z.head[z.ins_h]=re,re++,z.insert--,!(z.lookahead+z.insert<j)););}while(z.lookahead<V&&z.strm.avail_in!==0)}function Ye(z,ce){for(var le,Y;;){if(z.lookahead<V){if(He(z),z.lookahead<V&&ce===p)return B;if(z.lookahead===0)break}if(le=0,z.lookahead>=j&&(z.ins_h=(z.ins_h<<z.hash_shift^z.window[z.strstart+j-1])&z.hash_mask,le=z.prev[z.strstart&z.w_mask]=z.head[z.ins_h],z.head[z.ins_h]=z.strstart),le!==0&&z.strstart-le<=z.w_size-V&&(z.match_length=ge(z,le)),z.match_length>=j)if(Y=o._tr_tally(z,z.strstart-z.match_start,z.match_length-j),z.lookahead-=z.match_length,z.match_length<=z.max_lazy_match&&z.lookahead>=j){for(z.match_length--;z.strstart++,z.ins_h=(z.ins_h<<z.hash_shift^z.window[z.strstart+j-1])&z.hash_mask,le=z.prev[z.strstart&z.w_mask]=z.head[z.ins_h],z.head[z.ins_h]=z.strstart,--z.match_length!=0;);z.strstart++}else z.strstart+=z.match_length,z.match_length=0,z.ins_h=z.window[z.strstart],z.ins_h=(z.ins_h<<z.hash_shift^z.window[z.strstart+1])&z.hash_mask;else Y=o._tr_tally(z,0,z.window[z.strstart]),z.lookahead--,z.strstart++;if(Y&&(ee(z,!1),z.strm.avail_out===0))return B}return z.insert=z.strstart<j-1?z.strstart:j-1,ce===m?(ee(z,!0),z.strm.avail_out===0?fe:ie):z.last_lit&&(ee(z,!1),z.strm.avail_out===0)?B:X}function Se(z,ce){for(var le,Y,Z;;){if(z.lookahead<V){if(He(z),z.lookahead<V&&ce===p)return B;if(z.lookahead===0)break}if(le=0,z.lookahead>=j&&(z.ins_h=(z.ins_h<<z.hash_shift^z.window[z.strstart+j-1])&z.hash_mask,le=z.prev[z.strstart&z.w_mask]=z.head[z.ins_h],z.head[z.ins_h]=z.strstart),z.prev_length=z.match_length,z.prev_match=z.match_start,z.match_length=j-1,le!==0&&z.prev_length<z.max_lazy_match&&z.strstart-le<=z.w_size-V&&(z.match_length=ge(z,le),z.match_length<=5&&(z.strategy===1||z.match_length===j&&4096<z.strstart-z.match_start)&&(z.match_length=j-1)),z.prev_length>=j&&z.match_length<=z.prev_length){for(Z=z.strstart+z.lookahead-j,Y=o._tr_tally(z,z.strstart-1-z.prev_match,z.prev_length-j),z.lookahead-=z.prev_length-1,z.prev_length-=2;++z.strstart<=Z&&(z.ins_h=(z.ins_h<<z.hash_shift^z.window[z.strstart+j-1])&z.hash_mask,le=z.prev[z.strstart&z.w_mask]=z.head[z.ins_h],z.head[z.ins_h]=z.strstart),--z.prev_length!=0;);if(z.match_available=0,z.match_length=j-1,z.strstart++,Y&&(ee(z,!1),z.strm.avail_out===0))return B}else if(z.match_available){if((Y=o._tr_tally(z,0,z.window[z.strstart-1]))&&ee(z,!1),z.strstart++,z.lookahead--,z.strm.avail_out===0)return B}else z.match_available=1,z.strstart++,z.lookahead--}return z.match_available&&(Y=o._tr_tally(z,0,z.window[z.strstart-1]),z.match_available=0),z.insert=z.strstart<j-1?z.strstart:j-1,ce===m?(ee(z,!0),z.strm.avail_out===0?fe:ie):z.last_lit&&(ee(z,!1),z.strm.avail_out===0)?B:X}function we(z,ce,le,Y,Z){this.good_length=z,this.max_lazy=ce,this.nice_length=le,this.max_chain=Y,this.func=Z}function rt(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=C,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new a.Buf16(2*I),this.dyn_dtree=new a.Buf16(2*(2*P+1)),this.bl_tree=new a.Buf16(2*(2*D+1)),ve(this.dyn_ltree),ve(this.dyn_dtree),ve(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new a.Buf16(L+1),this.heap=new a.Buf16(2*_+1),ve(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new a.Buf16(2*_+1),ve(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function lt(z){var ce;return z&&z.state?(z.total_in=z.total_out=0,z.data_type=k,(ce=z.state).pending=0,ce.pending_out=0,ce.wrap<0&&(ce.wrap=-ce.wrap),ce.status=ce.wrap?O:$,z.adler=ce.wrap===2?0:1,ce.last_flush=p,o._tr_init(ce),g):ae(z,y)}function Dt(z){var ce=lt(z);return ce===g&&(function(le){le.window_size=2*le.w_size,ve(le.head),le.max_lazy_match=i[le.level].max_lazy,le.good_match=i[le.level].good_length,le.nice_match=i[le.level].nice_length,le.max_chain_length=i[le.level].max_chain,le.strstart=0,le.block_start=0,le.lookahead=0,le.insert=0,le.match_length=le.prev_length=j-1,le.match_available=0,le.ins_h=0})(z.state),ce}function je(z,ce,le,Y,Z,re){if(!z)return y;var be=1;if(ce===x&&(ce=6),Y<0?(be=0,Y=-Y):15<Y&&(be=2,Y-=16),Z<1||N<Z||le!==C||Y<8||15<Y||ce<0||9<ce||re<0||v<re)return ae(z,y);Y===8&&(Y=9);var Te=new rt;return(z.state=Te).strm=z,Te.wrap=be,Te.gzhead=null,Te.w_bits=Y,Te.w_size=1<<Te.w_bits,Te.w_mask=Te.w_size-1,Te.hash_bits=Z+7,Te.hash_size=1<<Te.hash_bits,Te.hash_mask=Te.hash_size-1,Te.hash_shift=~~((Te.hash_bits+j-1)/j),Te.window=new a.Buf8(2*Te.w_size),Te.head=new a.Buf16(Te.hash_size),Te.prev=new a.Buf16(Te.w_size),Te.lit_bufsize=1<<Z+6,Te.pending_buf_size=4*Te.lit_bufsize,Te.pending_buf=new a.Buf8(Te.pending_buf_size),Te.d_buf=1*Te.lit_bufsize,Te.l_buf=3*Te.lit_bufsize,Te.level=ce,Te.strategy=re,Te.method=le,Dt(z)}i=[new we(0,0,0,0,function(z,ce){var le=65535;for(le>z.pending_buf_size-5&&(le=z.pending_buf_size-5);;){if(z.lookahead<=1){if(He(z),z.lookahead===0&&ce===p)return B;if(z.lookahead===0)break}z.strstart+=z.lookahead,z.lookahead=0;var Y=z.block_start+le;if((z.strstart===0||z.strstart>=Y)&&(z.lookahead=z.strstart-Y,z.strstart=Y,ee(z,!1),z.strm.avail_out===0)||z.strstart-z.block_start>=z.w_size-V&&(ee(z,!1),z.strm.avail_out===0))return B}return z.insert=0,ce===m?(ee(z,!0),z.strm.avail_out===0?fe:ie):(z.strstart>z.block_start&&(ee(z,!1),z.strm.avail_out),B)}),new we(4,4,8,4,Ye),new we(4,5,16,8,Ye),new we(4,6,32,32,Ye),new we(4,4,16,16,Se),new we(8,16,32,32,Se),new we(8,16,128,128,Se),new we(8,32,128,256,Se),new we(32,128,258,1024,Se),new we(32,258,258,4096,Se)],s.deflateInit=function(z,ce){return je(z,ce,C,15,8,0)},s.deflateInit2=je,s.deflateReset=Dt,s.deflateResetKeep=lt,s.deflateSetHeader=function(z,ce){return z&&z.state?z.state.wrap!==2?y:(z.state.gzhead=ce,g):y},s.deflate=function(z,ce){var le,Y,Z,re;if(!z||!z.state||5<ce||ce<0)return z?ae(z,y):y;if(Y=z.state,!z.output||!z.input&&z.avail_in!==0||Y.status===666&&ce!==m)return ae(z,z.avail_out===0?-5:y);if(Y.strm=z,le=Y.last_flush,Y.last_flush=ce,Y.status===O)if(Y.wrap===2)z.adler=0,xe(Y,31),xe(Y,139),xe(Y,8),Y.gzhead?(xe(Y,(Y.gzhead.text?1:0)+(Y.gzhead.hcrc?2:0)+(Y.gzhead.extra?4:0)+(Y.gzhead.name?8:0)+(Y.gzhead.comment?16:0)),xe(Y,255&Y.gzhead.time),xe(Y,Y.gzhead.time>>8&255),xe(Y,Y.gzhead.time>>16&255),xe(Y,Y.gzhead.time>>24&255),xe(Y,Y.level===9?2:2<=Y.strategy||Y.level<2?4:0),xe(Y,255&Y.gzhead.os),Y.gzhead.extra&&Y.gzhead.extra.length&&(xe(Y,255&Y.gzhead.extra.length),xe(Y,Y.gzhead.extra.length>>8&255)),Y.gzhead.hcrc&&(z.adler=c(z.adler,Y.pending_buf,Y.pending,0)),Y.gzindex=0,Y.status=69):(xe(Y,0),xe(Y,0),xe(Y,0),xe(Y,0),xe(Y,0),xe(Y,Y.level===9?2:2<=Y.strategy||Y.level<2?4:0),xe(Y,3),Y.status=$);else{var be=C+(Y.w_bits-8<<4)<<8;be|=(2<=Y.strategy||Y.level<2?0:Y.level<6?1:Y.level===6?2:3)<<6,Y.strstart!==0&&(be|=32),be+=31-be%31,Y.status=$,_e(Y,be),Y.strstart!==0&&(_e(Y,z.adler>>>16),_e(Y,65535&z.adler)),z.adler=1}if(Y.status===69)if(Y.gzhead.extra){for(Z=Y.pending;Y.gzindex<(65535&Y.gzhead.extra.length)&&(Y.pending!==Y.pending_buf_size||(Y.gzhead.hcrc&&Y.pending>Z&&(z.adler=c(z.adler,Y.pending_buf,Y.pending-Z,Z)),K(z),Z=Y.pending,Y.pending!==Y.pending_buf_size));)xe(Y,255&Y.gzhead.extra[Y.gzindex]),Y.gzindex++;Y.gzhead.hcrc&&Y.pending>Z&&(z.adler=c(z.adler,Y.pending_buf,Y.pending-Z,Z)),Y.gzindex===Y.gzhead.extra.length&&(Y.gzindex=0,Y.status=73)}else Y.status=73;if(Y.status===73)if(Y.gzhead.name){Z=Y.pending;do{if(Y.pending===Y.pending_buf_size&&(Y.gzhead.hcrc&&Y.pending>Z&&(z.adler=c(z.adler,Y.pending_buf,Y.pending-Z,Z)),K(z),Z=Y.pending,Y.pending===Y.pending_buf_size)){re=1;break}re=Y.gzindex<Y.gzhead.name.length?255&Y.gzhead.name.charCodeAt(Y.gzindex++):0,xe(Y,re)}while(re!==0);Y.gzhead.hcrc&&Y.pending>Z&&(z.adler=c(z.adler,Y.pending_buf,Y.pending-Z,Z)),re===0&&(Y.gzindex=0,Y.status=91)}else Y.status=91;if(Y.status===91)if(Y.gzhead.comment){Z=Y.pending;do{if(Y.pending===Y.pending_buf_size&&(Y.gzhead.hcrc&&Y.pending>Z&&(z.adler=c(z.adler,Y.pending_buf,Y.pending-Z,Z)),K(z),Z=Y.pending,Y.pending===Y.pending_buf_size)){re=1;break}re=Y.gzindex<Y.gzhead.comment.length?255&Y.gzhead.comment.charCodeAt(Y.gzindex++):0,xe(Y,re)}while(re!==0);Y.gzhead.hcrc&&Y.pending>Z&&(z.adler=c(z.adler,Y.pending_buf,Y.pending-Z,Z)),re===0&&(Y.status=103)}else Y.status=103;if(Y.status===103&&(Y.gzhead.hcrc?(Y.pending+2>Y.pending_buf_size&&K(z),Y.pending+2<=Y.pending_buf_size&&(xe(Y,255&z.adler),xe(Y,z.adler>>8&255),z.adler=0,Y.status=$)):Y.status=$),Y.pending!==0){if(K(z),z.avail_out===0)return Y.last_flush=-1,g}else if(z.avail_in===0&&ue(ce)<=ue(le)&&ce!==m)return ae(z,-5);if(Y.status===666&&z.avail_in!==0)return ae(z,-5);if(z.avail_in!==0||Y.lookahead!==0||ce!==p&&Y.status!==666){var Te=Y.strategy===2?(function(he,Me){for(var $e;;){if(he.lookahead===0&&(He(he),he.lookahead===0)){if(Me===p)return B;break}if(he.match_length=0,$e=o._tr_tally(he,0,he.window[he.strstart]),he.lookahead--,he.strstart++,$e&&(ee(he,!1),he.strm.avail_out===0))return B}return he.insert=0,Me===m?(ee(he,!0),he.strm.avail_out===0?fe:ie):he.last_lit&&(ee(he,!1),he.strm.avail_out===0)?B:X})(Y,ce):Y.strategy===3?(function(he,Me){for(var $e,Re,Be,st,ot=he.window;;){if(he.lookahead<=q){if(He(he),he.lookahead<=q&&Me===p)return B;if(he.lookahead===0)break}if(he.match_length=0,he.lookahead>=j&&0<he.strstart&&(Re=ot[Be=he.strstart-1])===ot[++Be]&&Re===ot[++Be]&&Re===ot[++Be]){st=he.strstart+q;do;while(Re===ot[++Be]&&Re===ot[++Be]&&Re===ot[++Be]&&Re===ot[++Be]&&Re===ot[++Be]&&Re===ot[++Be]&&Re===ot[++Be]&&Re===ot[++Be]&&Be<st);he.match_length=q-(st-Be),he.match_length>he.lookahead&&(he.match_length=he.lookahead)}if(he.match_length>=j?($e=o._tr_tally(he,1,he.match_length-j),he.lookahead-=he.match_length,he.strstart+=he.match_length,he.match_length=0):($e=o._tr_tally(he,0,he.window[he.strstart]),he.lookahead--,he.strstart++),$e&&(ee(he,!1),he.strm.avail_out===0))return B}return he.insert=0,Me===m?(ee(he,!0),he.strm.avail_out===0?fe:ie):he.last_lit&&(ee(he,!1),he.strm.avail_out===0)?B:X})(Y,ce):i[Y.level].func(Y,ce);if(Te!==fe&&Te!==ie||(Y.status=666),Te===B||Te===fe)return z.avail_out===0&&(Y.last_flush=-1),g;if(Te===X&&(ce===1?o._tr_align(Y):ce!==5&&(o._tr_stored_block(Y,0,0,!1),ce===3&&(ve(Y.head),Y.lookahead===0&&(Y.strstart=0,Y.block_start=0,Y.insert=0))),K(z),z.avail_out===0))return Y.last_flush=-1,g}return ce!==m?g:Y.wrap<=0?1:(Y.wrap===2?(xe(Y,255&z.adler),xe(Y,z.adler>>8&255),xe(Y,z.adler>>16&255),xe(Y,z.adler>>24&255),xe(Y,255&z.total_in),xe(Y,z.total_in>>8&255),xe(Y,z.total_in>>16&255),xe(Y,z.total_in>>24&255)):(_e(Y,z.adler>>>16),_e(Y,65535&z.adler)),K(z),0<Y.wrap&&(Y.wrap=-Y.wrap),Y.pending!==0?g:1)},s.deflateEnd=function(z){var ce;return z&&z.state?(ce=z.state.status)!==O&&ce!==69&&ce!==73&&ce!==91&&ce!==103&&ce!==$&&ce!==666?ae(z,y):(z.state=null,ce===$?ae(z,-3):g):y},s.deflateSetDictionary=function(z,ce){var le,Y,Z,re,be,Te,he,Me,$e=ce.length;if(!z||!z.state||(re=(le=z.state).wrap)===2||re===1&&le.status!==O||le.lookahead)return y;for(re===1&&(z.adler=l(z.adler,ce,$e,0)),le.wrap=0,$e>=le.w_size&&(re===0&&(ve(le.head),le.strstart=0,le.block_start=0,le.insert=0),Me=new a.Buf8(le.w_size),a.arraySet(Me,ce,$e-le.w_size,le.w_size,0),ce=Me,$e=le.w_size),be=z.avail_in,Te=z.next_in,he=z.input,z.avail_in=$e,z.next_in=0,z.input=ce,He(le);le.lookahead>=j;){for(Y=le.strstart,Z=le.lookahead-(j-1);le.ins_h=(le.ins_h<<le.hash_shift^le.window[Y+j-1])&le.hash_mask,le.prev[Y&le.w_mask]=le.head[le.ins_h],le.head[le.ins_h]=Y,Y++,--Z;);le.strstart=Y,le.lookahead=j-1,He(le)}return le.strstart+=le.lookahead,le.block_start=le.strstart,le.insert=le.lookahead,le.lookahead=0,le.match_length=le.prev_length=j-1,le.match_available=0,z.next_in=Te,z.input=he,z.avail_in=be,le.wrap=re,g},s.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":41,"./adler32":43,"./crc32":45,"./messages":51,"./trees":52}],47:[function(n,r,s){r.exports=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}},{}],48:[function(n,r,s){r.exports=function(i,a){var o,l,c,h,p,m,g,y,x,v,k,C,N,_,P,D,I,L,j,q,V,O,$,B,X;o=i.state,l=i.next_in,B=i.input,c=l+(i.avail_in-5),h=i.next_out,X=i.output,p=h-(a-i.avail_out),m=h+(i.avail_out-257),g=o.dmax,y=o.wsize,x=o.whave,v=o.wnext,k=o.window,C=o.hold,N=o.bits,_=o.lencode,P=o.distcode,D=(1<<o.lenbits)-1,I=(1<<o.distbits)-1;e:do{N<15&&(C+=B[l++]<<N,N+=8,C+=B[l++]<<N,N+=8),L=_[C&D];t:for(;;){if(C>>>=j=L>>>24,N-=j,(j=L>>>16&255)===0)X[h++]=65535&L;else{if(!(16&j)){if((64&j)==0){L=_[(65535&L)+(C&(1<<j)-1)];continue t}if(32&j){o.mode=12;break e}i.msg="invalid literal/length code",o.mode=30;break e}q=65535&L,(j&=15)&&(N<j&&(C+=B[l++]<<N,N+=8),q+=C&(1<<j)-1,C>>>=j,N-=j),N<15&&(C+=B[l++]<<N,N+=8,C+=B[l++]<<N,N+=8),L=P[C&I];n:for(;;){if(C>>>=j=L>>>24,N-=j,!(16&(j=L>>>16&255))){if((64&j)==0){L=P[(65535&L)+(C&(1<<j)-1)];continue n}i.msg="invalid distance code",o.mode=30;break e}if(V=65535&L,N<(j&=15)&&(C+=B[l++]<<N,(N+=8)<j&&(C+=B[l++]<<N,N+=8)),g<(V+=C&(1<<j)-1)){i.msg="invalid distance too far back",o.mode=30;break e}if(C>>>=j,N-=j,(j=h-p)<V){if(x<(j=V-j)&&o.sane){i.msg="invalid distance too far back",o.mode=30;break e}if($=k,(O=0)===v){if(O+=y-j,j<q){for(q-=j;X[h++]=k[O++],--j;);O=h-V,$=X}}else if(v<j){if(O+=y+v-j,(j-=v)<q){for(q-=j;X[h++]=k[O++],--j;);if(O=0,v<q){for(q-=j=v;X[h++]=k[O++],--j;);O=h-V,$=X}}}else if(O+=v-j,j<q){for(q-=j;X[h++]=k[O++],--j;);O=h-V,$=X}for(;2<q;)X[h++]=$[O++],X[h++]=$[O++],X[h++]=$[O++],q-=3;q&&(X[h++]=$[O++],1<q&&(X[h++]=$[O++]))}else{for(O=h-V;X[h++]=X[O++],X[h++]=X[O++],X[h++]=X[O++],2<(q-=3););q&&(X[h++]=X[O++],1<q&&(X[h++]=X[O++]))}break}}break}}while(l<c&&h<m);l-=q=N>>3,C&=(1<<(N-=q<<3))-1,i.next_in=l,i.next_out=h,i.avail_in=l<c?c-l+5:5-(l-c),i.avail_out=h<m?m-h+257:257-(h-m),o.hold=C,o.bits=N}},{}],49:[function(n,r,s){var i=n("../utils/common"),a=n("./adler32"),o=n("./crc32"),l=n("./inffast"),c=n("./inftrees"),h=1,p=2,m=0,g=-2,y=1,x=852,v=592;function k(O){return(O>>>24&255)+(O>>>8&65280)+((65280&O)<<8)+((255&O)<<24)}function C(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new i.Buf16(320),this.work=new i.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function N(O){var $;return O&&O.state?($=O.state,O.total_in=O.total_out=$.total=0,O.msg="",$.wrap&&(O.adler=1&$.wrap),$.mode=y,$.last=0,$.havedict=0,$.dmax=32768,$.head=null,$.hold=0,$.bits=0,$.lencode=$.lendyn=new i.Buf32(x),$.distcode=$.distdyn=new i.Buf32(v),$.sane=1,$.back=-1,m):g}function _(O){var $;return O&&O.state?(($=O.state).wsize=0,$.whave=0,$.wnext=0,N(O)):g}function P(O,$){var B,X;return O&&O.state?(X=O.state,$<0?(B=0,$=-$):(B=1+($>>4),$<48&&($&=15)),$&&($<8||15<$)?g:(X.window!==null&&X.wbits!==$&&(X.window=null),X.wrap=B,X.wbits=$,_(O))):g}function D(O,$){var B,X;return O?(X=new C,(O.state=X).window=null,(B=P(O,$))!==m&&(O.state=null),B):g}var I,L,j=!0;function q(O){if(j){var $;for(I=new i.Buf32(512),L=new i.Buf32(32),$=0;$<144;)O.lens[$++]=8;for(;$<256;)O.lens[$++]=9;for(;$<280;)O.lens[$++]=7;for(;$<288;)O.lens[$++]=8;for(c(h,O.lens,0,288,I,0,O.work,{bits:9}),$=0;$<32;)O.lens[$++]=5;c(p,O.lens,0,32,L,0,O.work,{bits:5}),j=!1}O.lencode=I,O.lenbits=9,O.distcode=L,O.distbits=5}function V(O,$,B,X){var fe,ie=O.state;return ie.window===null&&(ie.wsize=1<<ie.wbits,ie.wnext=0,ie.whave=0,ie.window=new i.Buf8(ie.wsize)),X>=ie.wsize?(i.arraySet(ie.window,$,B-ie.wsize,ie.wsize,0),ie.wnext=0,ie.whave=ie.wsize):(X<(fe=ie.wsize-ie.wnext)&&(fe=X),i.arraySet(ie.window,$,B-X,fe,ie.wnext),(X-=fe)?(i.arraySet(ie.window,$,B-X,X,0),ie.wnext=X,ie.whave=ie.wsize):(ie.wnext+=fe,ie.wnext===ie.wsize&&(ie.wnext=0),ie.whave<ie.wsize&&(ie.whave+=fe))),0}s.inflateReset=_,s.inflateReset2=P,s.inflateResetKeep=N,s.inflateInit=function(O){return D(O,15)},s.inflateInit2=D,s.inflate=function(O,$){var B,X,fe,ie,ae,ue,ve,K,ee,xe,_e,ge,He,Ye,Se,we,rt,lt,Dt,je,z,ce,le,Y,Z=0,re=new i.Buf8(4),be=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!O||!O.state||!O.output||!O.input&&O.avail_in!==0)return g;(B=O.state).mode===12&&(B.mode=13),ae=O.next_out,fe=O.output,ve=O.avail_out,ie=O.next_in,X=O.input,ue=O.avail_in,K=B.hold,ee=B.bits,xe=ue,_e=ve,ce=m;e:for(;;)switch(B.mode){case y:if(B.wrap===0){B.mode=13;break}for(;ee<16;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if(2&B.wrap&&K===35615){re[B.check=0]=255&K,re[1]=K>>>8&255,B.check=o(B.check,re,2,0),ee=K=0,B.mode=2;break}if(B.flags=0,B.head&&(B.head.done=!1),!(1&B.wrap)||(((255&K)<<8)+(K>>8))%31){O.msg="incorrect header check",B.mode=30;break}if((15&K)!=8){O.msg="unknown compression method",B.mode=30;break}if(ee-=4,z=8+(15&(K>>>=4)),B.wbits===0)B.wbits=z;else if(z>B.wbits){O.msg="invalid window size",B.mode=30;break}B.dmax=1<<z,O.adler=B.check=1,B.mode=512&K?10:12,ee=K=0;break;case 2:for(;ee<16;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if(B.flags=K,(255&B.flags)!=8){O.msg="unknown compression method",B.mode=30;break}if(57344&B.flags){O.msg="unknown header flags set",B.mode=30;break}B.head&&(B.head.text=K>>8&1),512&B.flags&&(re[0]=255&K,re[1]=K>>>8&255,B.check=o(B.check,re,2,0)),ee=K=0,B.mode=3;case 3:for(;ee<32;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}B.head&&(B.head.time=K),512&B.flags&&(re[0]=255&K,re[1]=K>>>8&255,re[2]=K>>>16&255,re[3]=K>>>24&255,B.check=o(B.check,re,4,0)),ee=K=0,B.mode=4;case 4:for(;ee<16;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}B.head&&(B.head.xflags=255&K,B.head.os=K>>8),512&B.flags&&(re[0]=255&K,re[1]=K>>>8&255,B.check=o(B.check,re,2,0)),ee=K=0,B.mode=5;case 5:if(1024&B.flags){for(;ee<16;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}B.length=K,B.head&&(B.head.extra_len=K),512&B.flags&&(re[0]=255&K,re[1]=K>>>8&255,B.check=o(B.check,re,2,0)),ee=K=0}else B.head&&(B.head.extra=null);B.mode=6;case 6:if(1024&B.flags&&(ue<(ge=B.length)&&(ge=ue),ge&&(B.head&&(z=B.head.extra_len-B.length,B.head.extra||(B.head.extra=new Array(B.head.extra_len)),i.arraySet(B.head.extra,X,ie,ge,z)),512&B.flags&&(B.check=o(B.check,X,ge,ie)),ue-=ge,ie+=ge,B.length-=ge),B.length))break e;B.length=0,B.mode=7;case 7:if(2048&B.flags){if(ue===0)break e;for(ge=0;z=X[ie+ge++],B.head&&z&&B.length<65536&&(B.head.name+=String.fromCharCode(z)),z&&ge<ue;);if(512&B.flags&&(B.check=o(B.check,X,ge,ie)),ue-=ge,ie+=ge,z)break e}else B.head&&(B.head.name=null);B.length=0,B.mode=8;case 8:if(4096&B.flags){if(ue===0)break e;for(ge=0;z=X[ie+ge++],B.head&&z&&B.length<65536&&(B.head.comment+=String.fromCharCode(z)),z&&ge<ue;);if(512&B.flags&&(B.check=o(B.check,X,ge,ie)),ue-=ge,ie+=ge,z)break e}else B.head&&(B.head.comment=null);B.mode=9;case 9:if(512&B.flags){for(;ee<16;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if(K!==(65535&B.check)){O.msg="header crc mismatch",B.mode=30;break}ee=K=0}B.head&&(B.head.hcrc=B.flags>>9&1,B.head.done=!0),O.adler=B.check=0,B.mode=12;break;case 10:for(;ee<32;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}O.adler=B.check=k(K),ee=K=0,B.mode=11;case 11:if(B.havedict===0)return O.next_out=ae,O.avail_out=ve,O.next_in=ie,O.avail_in=ue,B.hold=K,B.bits=ee,2;O.adler=B.check=1,B.mode=12;case 12:if($===5||$===6)break e;case 13:if(B.last){K>>>=7&ee,ee-=7&ee,B.mode=27;break}for(;ee<3;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}switch(B.last=1&K,ee-=1,3&(K>>>=1)){case 0:B.mode=14;break;case 1:if(q(B),B.mode=20,$!==6)break;K>>>=2,ee-=2;break e;case 2:B.mode=17;break;case 3:O.msg="invalid block type",B.mode=30}K>>>=2,ee-=2;break;case 14:for(K>>>=7&ee,ee-=7ⅇee<32;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if((65535&K)!=(K>>>16^65535)){O.msg="invalid stored block lengths",B.mode=30;break}if(B.length=65535&K,ee=K=0,B.mode=15,$===6)break e;case 15:B.mode=16;case 16:if(ge=B.length){if(ue<ge&&(ge=ue),ve<ge&&(ge=ve),ge===0)break e;i.arraySet(fe,X,ie,ge,ae),ue-=ge,ie+=ge,ve-=ge,ae+=ge,B.length-=ge;break}B.mode=12;break;case 17:for(;ee<14;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if(B.nlen=257+(31&K),K>>>=5,ee-=5,B.ndist=1+(31&K),K>>>=5,ee-=5,B.ncode=4+(15&K),K>>>=4,ee-=4,286<B.nlen||30<B.ndist){O.msg="too many length or distance symbols",B.mode=30;break}B.have=0,B.mode=18;case 18:for(;B.have<B.ncode;){for(;ee<3;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}B.lens[be[B.have++]]=7&K,K>>>=3,ee-=3}for(;B.have<19;)B.lens[be[B.have++]]=0;if(B.lencode=B.lendyn,B.lenbits=7,le={bits:B.lenbits},ce=c(0,B.lens,0,19,B.lencode,0,B.work,le),B.lenbits=le.bits,ce){O.msg="invalid code lengths set",B.mode=30;break}B.have=0,B.mode=19;case 19:for(;B.have<B.nlen+B.ndist;){for(;we=(Z=B.lencode[K&(1<<B.lenbits)-1])>>>16&255,rt=65535&Z,!((Se=Z>>>24)<=ee);){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if(rt<16)K>>>=Se,ee-=Se,B.lens[B.have++]=rt;else{if(rt===16){for(Y=Se+2;ee<Y;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if(K>>>=Se,ee-=Se,B.have===0){O.msg="invalid bit length repeat",B.mode=30;break}z=B.lens[B.have-1],ge=3+(3&K),K>>>=2,ee-=2}else if(rt===17){for(Y=Se+3;ee<Y;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}ee-=Se,z=0,ge=3+(7&(K>>>=Se)),K>>>=3,ee-=3}else{for(Y=Se+7;ee<Y;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}ee-=Se,z=0,ge=11+(127&(K>>>=Se)),K>>>=7,ee-=7}if(B.have+ge>B.nlen+B.ndist){O.msg="invalid bit length repeat",B.mode=30;break}for(;ge--;)B.lens[B.have++]=z}}if(B.mode===30)break;if(B.lens[256]===0){O.msg="invalid code -- missing end-of-block",B.mode=30;break}if(B.lenbits=9,le={bits:B.lenbits},ce=c(h,B.lens,0,B.nlen,B.lencode,0,B.work,le),B.lenbits=le.bits,ce){O.msg="invalid literal/lengths set",B.mode=30;break}if(B.distbits=6,B.distcode=B.distdyn,le={bits:B.distbits},ce=c(p,B.lens,B.nlen,B.ndist,B.distcode,0,B.work,le),B.distbits=le.bits,ce){O.msg="invalid distances set",B.mode=30;break}if(B.mode=20,$===6)break e;case 20:B.mode=21;case 21:if(6<=ue&&258<=ve){O.next_out=ae,O.avail_out=ve,O.next_in=ie,O.avail_in=ue,B.hold=K,B.bits=ee,l(O,_e),ae=O.next_out,fe=O.output,ve=O.avail_out,ie=O.next_in,X=O.input,ue=O.avail_in,K=B.hold,ee=B.bits,B.mode===12&&(B.back=-1);break}for(B.back=0;we=(Z=B.lencode[K&(1<<B.lenbits)-1])>>>16&255,rt=65535&Z,!((Se=Z>>>24)<=ee);){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if(we&&(240&we)==0){for(lt=Se,Dt=we,je=rt;we=(Z=B.lencode[je+((K&(1<<lt+Dt)-1)>>lt)])>>>16&255,rt=65535&Z,!(lt+(Se=Z>>>24)<=ee);){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}K>>>=lt,ee-=lt,B.back+=lt}if(K>>>=Se,ee-=Se,B.back+=Se,B.length=rt,we===0){B.mode=26;break}if(32&we){B.back=-1,B.mode=12;break}if(64&we){O.msg="invalid literal/length code",B.mode=30;break}B.extra=15&we,B.mode=22;case 22:if(B.extra){for(Y=B.extra;ee<Y;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}B.length+=K&(1<<B.extra)-1,K>>>=B.extra,ee-=B.extra,B.back+=B.extra}B.was=B.length,B.mode=23;case 23:for(;we=(Z=B.distcode[K&(1<<B.distbits)-1])>>>16&255,rt=65535&Z,!((Se=Z>>>24)<=ee);){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if((240&we)==0){for(lt=Se,Dt=we,je=rt;we=(Z=B.distcode[je+((K&(1<<lt+Dt)-1)>>lt)])>>>16&255,rt=65535&Z,!(lt+(Se=Z>>>24)<=ee);){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}K>>>=lt,ee-=lt,B.back+=lt}if(K>>>=Se,ee-=Se,B.back+=Se,64&we){O.msg="invalid distance code",B.mode=30;break}B.offset=rt,B.extra=15&we,B.mode=24;case 24:if(B.extra){for(Y=B.extra;ee<Y;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}B.offset+=K&(1<<B.extra)-1,K>>>=B.extra,ee-=B.extra,B.back+=B.extra}if(B.offset>B.dmax){O.msg="invalid distance too far back",B.mode=30;break}B.mode=25;case 25:if(ve===0)break e;if(ge=_e-ve,B.offset>ge){if((ge=B.offset-ge)>B.whave&&B.sane){O.msg="invalid distance too far back",B.mode=30;break}He=ge>B.wnext?(ge-=B.wnext,B.wsize-ge):B.wnext-ge,ge>B.length&&(ge=B.length),Ye=B.window}else Ye=fe,He=ae-B.offset,ge=B.length;for(ve<ge&&(ge=ve),ve-=ge,B.length-=ge;fe[ae++]=Ye[He++],--ge;);B.length===0&&(B.mode=21);break;case 26:if(ve===0)break e;fe[ae++]=B.length,ve--,B.mode=21;break;case 27:if(B.wrap){for(;ee<32;){if(ue===0)break e;ue--,K|=X[ie++]<<ee,ee+=8}if(_e-=ve,O.total_out+=_e,B.total+=_e,_e&&(O.adler=B.check=B.flags?o(B.check,fe,_e,ae-_e):a(B.check,fe,_e,ae-_e)),_e=ve,(B.flags?K:k(K))!==B.check){O.msg="incorrect data check",B.mode=30;break}ee=K=0}B.mode=28;case 28:if(B.wrap&&B.flags){for(;ee<32;){if(ue===0)break e;ue--,K+=X[ie++]<<ee,ee+=8}if(K!==(4294967295&B.total)){O.msg="incorrect length check",B.mode=30;break}ee=K=0}B.mode=29;case 29:ce=1;break e;case 30:ce=-3;break e;case 31:return-4;case 32:default:return g}return O.next_out=ae,O.avail_out=ve,O.next_in=ie,O.avail_in=ue,B.hold=K,B.bits=ee,(B.wsize||_e!==O.avail_out&&B.mode<30&&(B.mode<27||$!==4))&&V(O,O.output,O.next_out,_e-O.avail_out)?(B.mode=31,-4):(xe-=O.avail_in,_e-=O.avail_out,O.total_in+=xe,O.total_out+=_e,B.total+=_e,B.wrap&&_e&&(O.adler=B.check=B.flags?o(B.check,fe,_e,O.next_out-_e):a(B.check,fe,_e,O.next_out-_e)),O.data_type=B.bits+(B.last?64:0)+(B.mode===12?128:0)+(B.mode===20||B.mode===15?256:0),(xe==0&&_e===0||$===4)&&ce===m&&(ce=-5),ce)},s.inflateEnd=function(O){if(!O||!O.state)return g;var $=O.state;return $.window&&($.window=null),O.state=null,m},s.inflateGetHeader=function(O,$){var B;return O&&O.state?(2&(B=O.state).wrap)==0?g:((B.head=$).done=!1,m):g},s.inflateSetDictionary=function(O,$){var B,X=$.length;return O&&O.state?(B=O.state).wrap!==0&&B.mode!==11?g:B.mode===11&&a(1,$,X,0)!==B.check?-3:V(O,$,X,X)?(B.mode=31,-4):(B.havedict=1,m):g},s.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":41,"./adler32":43,"./crc32":45,"./inffast":48,"./inftrees":50}],50:[function(n,r,s){var i=n("../utils/common"),a=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],o=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],l=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],c=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];r.exports=function(h,p,m,g,y,x,v,k){var C,N,_,P,D,I,L,j,q,V=k.bits,O=0,$=0,B=0,X=0,fe=0,ie=0,ae=0,ue=0,ve=0,K=0,ee=null,xe=0,_e=new i.Buf16(16),ge=new i.Buf16(16),He=null,Ye=0;for(O=0;O<=15;O++)_e[O]=0;for($=0;$<g;$++)_e[p[m+$]]++;for(fe=V,X=15;1<=X&&_e[X]===0;X--);if(X<fe&&(fe=X),X===0)return y[x++]=20971520,y[x++]=20971520,k.bits=1,0;for(B=1;B<X&&_e[B]===0;B++);for(fe<B&&(fe=B),O=ue=1;O<=15;O++)if(ue<<=1,(ue-=_e[O])<0)return-1;if(0<ue&&(h===0||X!==1))return-1;for(ge[1]=0,O=1;O<15;O++)ge[O+1]=ge[O]+_e[O];for($=0;$<g;$++)p[m+$]!==0&&(v[ge[p[m+$]]++]=$);if(I=h===0?(ee=He=v,19):h===1?(ee=a,xe-=257,He=o,Ye-=257,256):(ee=l,He=c,-1),O=B,D=x,ae=$=K=0,_=-1,P=(ve=1<<(ie=fe))-1,h===1&&852<ve||h===2&&592<ve)return 1;for(;;){for(L=O-ae,q=v[$]<I?(j=0,v[$]):v[$]>I?(j=He[Ye+v[$]],ee[xe+v[$]]):(j=96,0),C=1<<O-ae,B=N=1<<ie;y[D+(K>>ae)+(N-=C)]=L<<24|j<<16|q|0,N!==0;);for(C=1<<O-1;K&C;)C>>=1;if(C!==0?(K&=C-1,K+=C):K=0,$++,--_e[O]==0){if(O===X)break;O=p[m+v[$]]}if(fe<O&&(K&P)!==_){for(ae===0&&(ae=fe),D+=B,ue=1<<(ie=O-ae);ie+ae<X&&!((ue-=_e[ie+ae])<=0);)ie++,ue<<=1;if(ve+=1<<ie,h===1&&852<ve||h===2&&592<ve)return 1;y[_=K&P]=fe<<24|ie<<16|D-x|0}}return K!==0&&(y[D+K]=O-ae<<24|64<<16|0),k.bits=fe,0}},{"../utils/common":41}],51:[function(n,r,s){r.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],52:[function(n,r,s){var i=n("../utils/common"),a=0,o=1;function l(Z){for(var re=Z.length;0<=--re;)Z[re]=0}var c=0,h=29,p=256,m=p+1+h,g=30,y=19,x=2*m+1,v=15,k=16,C=7,N=256,_=16,P=17,D=18,I=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],L=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],j=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],q=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],V=new Array(2*(m+2));l(V);var O=new Array(2*g);l(O);var $=new Array(512);l($);var B=new Array(256);l(B);var X=new Array(h);l(X);var fe,ie,ae,ue=new Array(g);function ve(Z,re,be,Te,he){this.static_tree=Z,this.extra_bits=re,this.extra_base=be,this.elems=Te,this.max_length=he,this.has_stree=Z&&Z.length}function K(Z,re){this.dyn_tree=Z,this.max_code=0,this.stat_desc=re}function ee(Z){return Z<256?$[Z]:$[256+(Z>>>7)]}function xe(Z,re){Z.pending_buf[Z.pending++]=255&re,Z.pending_buf[Z.pending++]=re>>>8&255}function _e(Z,re,be){Z.bi_valid>k-be?(Z.bi_buf|=re<<Z.bi_valid&65535,xe(Z,Z.bi_buf),Z.bi_buf=re>>k-Z.bi_valid,Z.bi_valid+=be-k):(Z.bi_buf|=re<<Z.bi_valid&65535,Z.bi_valid+=be)}function ge(Z,re,be){_e(Z,be[2*re],be[2*re+1])}function He(Z,re){for(var be=0;be|=1&Z,Z>>>=1,be<<=1,0<--re;);return be>>>1}function Ye(Z,re,be){var Te,he,Me=new Array(v+1),$e=0;for(Te=1;Te<=v;Te++)Me[Te]=$e=$e+be[Te-1]<<1;for(he=0;he<=re;he++){var Re=Z[2*he+1];Re!==0&&(Z[2*he]=He(Me[Re]++,Re))}}function Se(Z){var re;for(re=0;re<m;re++)Z.dyn_ltree[2*re]=0;for(re=0;re<g;re++)Z.dyn_dtree[2*re]=0;for(re=0;re<y;re++)Z.bl_tree[2*re]=0;Z.dyn_ltree[2*N]=1,Z.opt_len=Z.static_len=0,Z.last_lit=Z.matches=0}function we(Z){8<Z.bi_valid?xe(Z,Z.bi_buf):0<Z.bi_valid&&(Z.pending_buf[Z.pending++]=Z.bi_buf),Z.bi_buf=0,Z.bi_valid=0}function rt(Z,re,be,Te){var he=2*re,Me=2*be;return Z[he]<Z[Me]||Z[he]===Z[Me]&&Te[re]<=Te[be]}function lt(Z,re,be){for(var Te=Z.heap[be],he=be<<1;he<=Z.heap_len&&(he<Z.heap_len&&rt(re,Z.heap[he+1],Z.heap[he],Z.depth)&&he++,!rt(re,Te,Z.heap[he],Z.depth));)Z.heap[be]=Z.heap[he],be=he,he<<=1;Z.heap[be]=Te}function Dt(Z,re,be){var Te,he,Me,$e,Re=0;if(Z.last_lit!==0)for(;Te=Z.pending_buf[Z.d_buf+2*Re]<<8|Z.pending_buf[Z.d_buf+2*Re+1],he=Z.pending_buf[Z.l_buf+Re],Re++,Te===0?ge(Z,he,re):(ge(Z,(Me=B[he])+p+1,re),($e=I[Me])!==0&&_e(Z,he-=X[Me],$e),ge(Z,Me=ee(--Te),be),($e=L[Me])!==0&&_e(Z,Te-=ue[Me],$e)),Re<Z.last_lit;);ge(Z,N,re)}function je(Z,re){var be,Te,he,Me=re.dyn_tree,$e=re.stat_desc.static_tree,Re=re.stat_desc.has_stree,Be=re.stat_desc.elems,st=-1;for(Z.heap_len=0,Z.heap_max=x,be=0;be<Be;be++)Me[2*be]!==0?(Z.heap[++Z.heap_len]=st=be,Z.depth[be]=0):Me[2*be+1]=0;for(;Z.heap_len<2;)Me[2*(he=Z.heap[++Z.heap_len]=st<2?++st:0)]=1,Z.depth[he]=0,Z.opt_len--,Re&&(Z.static_len-=$e[2*he+1]);for(re.max_code=st,be=Z.heap_len>>1;1<=be;be--)lt(Z,Me,be);for(he=Be;be=Z.heap[1],Z.heap[1]=Z.heap[Z.heap_len--],lt(Z,Me,1),Te=Z.heap[1],Z.heap[--Z.heap_max]=be,Z.heap[--Z.heap_max]=Te,Me[2*he]=Me[2*be]+Me[2*Te],Z.depth[he]=(Z.depth[be]>=Z.depth[Te]?Z.depth[be]:Z.depth[Te])+1,Me[2*be+1]=Me[2*Te+1]=he,Z.heap[1]=he++,lt(Z,Me,1),2<=Z.heap_len;);Z.heap[--Z.heap_max]=Z.heap[1],(function(ot,dn){var Rn,_n,Dn,Ht,Ne,Xe,it=dn.dyn_tree,Mt=dn.max_code,At=dn.stat_desc.static_tree,Gt=dn.stat_desc.has_stree,hn=dn.stat_desc.extra_bits,cn=dn.stat_desc.extra_base,It=dn.stat_desc.max_length,tn=0;for(Ht=0;Ht<=v;Ht++)ot.bl_count[Ht]=0;for(it[2*ot.heap[ot.heap_max]+1]=0,Rn=ot.heap_max+1;Rn<x;Rn++)It<(Ht=it[2*it[2*(_n=ot.heap[Rn])+1]+1]+1)&&(Ht=It,tn++),it[2*_n+1]=Ht,Mt<_n||(ot.bl_count[Ht]++,Ne=0,cn<=_n&&(Ne=hn[_n-cn]),Xe=it[2*_n],ot.opt_len+=Xe*(Ht+Ne),Gt&&(ot.static_len+=Xe*(At[2*_n+1]+Ne)));if(tn!==0){do{for(Ht=It-1;ot.bl_count[Ht]===0;)Ht--;ot.bl_count[Ht]--,ot.bl_count[Ht+1]+=2,ot.bl_count[It]--,tn-=2}while(0<tn);for(Ht=It;Ht!==0;Ht--)for(_n=ot.bl_count[Ht];_n!==0;)Mt<(Dn=ot.heap[--Rn])||(it[2*Dn+1]!==Ht&&(ot.opt_len+=(Ht-it[2*Dn+1])*it[2*Dn],it[2*Dn+1]=Ht),_n--)}})(Z,re),Ye(Me,st,Z.bl_count)}function z(Z,re,be){var Te,he,Me=-1,$e=re[1],Re=0,Be=7,st=4;for($e===0&&(Be=138,st=3),re[2*(be+1)+1]=65535,Te=0;Te<=be;Te++)he=$e,$e=re[2*(Te+1)+1],++Re<Be&&he===$e||(Re<st?Z.bl_tree[2*he]+=Re:he!==0?(he!==Me&&Z.bl_tree[2*he]++,Z.bl_tree[2*_]++):Re<=10?Z.bl_tree[2*P]++:Z.bl_tree[2*D]++,Me=he,st=(Re=0)===$e?(Be=138,3):he===$e?(Be=6,3):(Be=7,4))}function ce(Z,re,be){var Te,he,Me=-1,$e=re[1],Re=0,Be=7,st=4;for($e===0&&(Be=138,st=3),Te=0;Te<=be;Te++)if(he=$e,$e=re[2*(Te+1)+1],!(++Re<Be&&he===$e)){if(Re<st)for(;ge(Z,he,Z.bl_tree),--Re!=0;);else he!==0?(he!==Me&&(ge(Z,he,Z.bl_tree),Re--),ge(Z,_,Z.bl_tree),_e(Z,Re-3,2)):Re<=10?(ge(Z,P,Z.bl_tree),_e(Z,Re-3,3)):(ge(Z,D,Z.bl_tree),_e(Z,Re-11,7));Me=he,st=(Re=0)===$e?(Be=138,3):he===$e?(Be=6,3):(Be=7,4)}}l(ue);var le=!1;function Y(Z,re,be,Te){_e(Z,(c<<1)+(Te?1:0),3),(function(he,Me,$e,Re){we(he),xe(he,$e),xe(he,~$e),i.arraySet(he.pending_buf,he.window,Me,$e,he.pending),he.pending+=$e})(Z,re,be)}s._tr_init=function(Z){le||((function(){var re,be,Te,he,Me,$e=new Array(v+1);for(he=Te=0;he<h-1;he++)for(X[he]=Te,re=0;re<1<<I[he];re++)B[Te++]=he;for(B[Te-1]=he,he=Me=0;he<16;he++)for(ue[he]=Me,re=0;re<1<<L[he];re++)$[Me++]=he;for(Me>>=7;he<g;he++)for(ue[he]=Me<<7,re=0;re<1<<L[he]-7;re++)$[256+Me++]=he;for(be=0;be<=v;be++)$e[be]=0;for(re=0;re<=143;)V[2*re+1]=8,re++,$e[8]++;for(;re<=255;)V[2*re+1]=9,re++,$e[9]++;for(;re<=279;)V[2*re+1]=7,re++,$e[7]++;for(;re<=287;)V[2*re+1]=8,re++,$e[8]++;for(Ye(V,m+1,$e),re=0;re<g;re++)O[2*re+1]=5,O[2*re]=He(re,5);fe=new ve(V,I,p+1,m,v),ie=new ve(O,L,0,g,v),ae=new ve(new Array(0),j,0,y,C)})(),le=!0),Z.l_desc=new K(Z.dyn_ltree,fe),Z.d_desc=new K(Z.dyn_dtree,ie),Z.bl_desc=new K(Z.bl_tree,ae),Z.bi_buf=0,Z.bi_valid=0,Se(Z)},s._tr_stored_block=Y,s._tr_flush_block=function(Z,re,be,Te){var he,Me,$e=0;0<Z.level?(Z.strm.data_type===2&&(Z.strm.data_type=(function(Re){var Be,st=4093624447;for(Be=0;Be<=31;Be++,st>>>=1)if(1&st&&Re.dyn_ltree[2*Be]!==0)return a;if(Re.dyn_ltree[18]!==0||Re.dyn_ltree[20]!==0||Re.dyn_ltree[26]!==0)return o;for(Be=32;Be<p;Be++)if(Re.dyn_ltree[2*Be]!==0)return o;return a})(Z)),je(Z,Z.l_desc),je(Z,Z.d_desc),$e=(function(Re){var Be;for(z(Re,Re.dyn_ltree,Re.l_desc.max_code),z(Re,Re.dyn_dtree,Re.d_desc.max_code),je(Re,Re.bl_desc),Be=y-1;3<=Be&&Re.bl_tree[2*q[Be]+1]===0;Be--);return Re.opt_len+=3*(Be+1)+5+5+4,Be})(Z),he=Z.opt_len+3+7>>>3,(Me=Z.static_len+3+7>>>3)<=he&&(he=Me)):he=Me=be+5,be+4<=he&&re!==-1?Y(Z,re,be,Te):Z.strategy===4||Me===he?(_e(Z,2+(Te?1:0),3),Dt(Z,V,O)):(_e(Z,4+(Te?1:0),3),(function(Re,Be,st,ot){var dn;for(_e(Re,Be-257,5),_e(Re,st-1,5),_e(Re,ot-4,4),dn=0;dn<ot;dn++)_e(Re,Re.bl_tree[2*q[dn]+1],3);ce(Re,Re.dyn_ltree,Be-1),ce(Re,Re.dyn_dtree,st-1)})(Z,Z.l_desc.max_code+1,Z.d_desc.max_code+1,$e+1),Dt(Z,Z.dyn_ltree,Z.dyn_dtree)),Se(Z),Te&&we(Z)},s._tr_tally=function(Z,re,be){return Z.pending_buf[Z.d_buf+2*Z.last_lit]=re>>>8&255,Z.pending_buf[Z.d_buf+2*Z.last_lit+1]=255&re,Z.pending_buf[Z.l_buf+Z.last_lit]=255&be,Z.last_lit++,re===0?Z.dyn_ltree[2*be]++:(Z.matches++,re--,Z.dyn_ltree[2*(B[be]+p+1)]++,Z.dyn_dtree[2*ee(re)]++),Z.last_lit===Z.lit_bufsize-1},s._tr_align=function(Z){_e(Z,2,3),ge(Z,N,V),(function(re){re.bi_valid===16?(xe(re,re.bi_buf),re.bi_buf=0,re.bi_valid=0):8<=re.bi_valid&&(re.pending_buf[re.pending++]=255&re.bi_buf,re.bi_buf>>=8,re.bi_valid-=8)})(Z)}},{"../utils/common":41}],53:[function(n,r,s){r.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],54:[function(n,r,s){(function(i){(function(a,o){if(!a.setImmediate){var l,c,h,p,m=1,g={},y=!1,x=a.document,v=Object.getPrototypeOf&&Object.getPrototypeOf(a);v=v&&v.setTimeout?v:a,l={}.toString.call(a.process)==="[object process]"?function(_){process.nextTick(function(){C(_)})}:(function(){if(a.postMessage&&!a.importScripts){var _=!0,P=a.onmessage;return a.onmessage=function(){_=!1},a.postMessage("","*"),a.onmessage=P,_}})()?(p="setImmediate$"+Math.random()+"$",a.addEventListener?a.addEventListener("message",N,!1):a.attachEvent("onmessage",N),function(_){a.postMessage(p+_,"*")}):a.MessageChannel?((h=new MessageChannel).port1.onmessage=function(_){C(_.data)},function(_){h.port2.postMessage(_)}):x&&"onreadystatechange"in x.createElement("script")?(c=x.documentElement,function(_){var P=x.createElement("script");P.onreadystatechange=function(){C(_),P.onreadystatechange=null,c.removeChild(P),P=null},c.appendChild(P)}):function(_){setTimeout(C,0,_)},v.setImmediate=function(_){typeof _!="function"&&(_=new Function(""+_));for(var P=new Array(arguments.length-1),D=0;D<P.length;D++)P[D]=arguments[D+1];var I={callback:_,args:P};return g[m]=I,l(m),m++},v.clearImmediate=k}function k(_){delete g[_]}function C(_){if(y)setTimeout(C,0,_);else{var P=g[_];if(P){y=!0;try{(function(D){var I=D.callback,L=D.args;switch(L.length){case 0:I();break;case 1:I(L[0]);break;case 2:I(L[0],L[1]);break;case 3:I(L[0],L[1],L[2]);break;default:I.apply(o,L)}})(P)}finally{k(_),y=!1}}}}function N(_){_.source===a&&typeof _.data=="string"&&_.data.indexOf(p)===0&&C(+_.data.slice(p.length))}})(typeof self>"u"?i===void 0?this:i:self)}).call(this,typeof Vb<"u"?Vb:typeof self<"u"?self:typeof window<"u"?window:{})},{}]},{},[10])(10)})})(QS)),QS.exports}var Dae=Lae();const YO=qd(Dae),Nl=qO("flexweg-site-mirror","files");async function Fae(){const t=new YO;for(const[e,n]of await Nl.entries())t.file(e,n.encoding==="base64"?rp(n.content):n.content);return t.generateAsync({type:"blob",compression:"DEFLATE"})}async function Oae(){return(await Nl.keys()).length}function zae(t){const e=(t.siteUrl??"").replace(/\/+$/,""),n=r=>r.replace(/^\/+/,"");return{id:"browser-mirror",model:"files",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0,storageLimits:!1},async put(r){await Nl.set(n(r.path),{content:r.content,encoding:r.encoding==="base64"?"base64":"utf-8",updatedAt:Date.now()})},async get(r){const s=await Nl.get(n(r));if(!s)throw new Ns(`File not found: ${r}`,404);return s.encoding==="base64"?LO(s.content):s.content},async getBytes(r){const s=await Nl.get(n(r));return s?s.encoding==="base64"?rp(s.content):new TextEncoder().encode(s.content):null},delete:r=>Nl.delete(n(r)),async deletePrefix(r){const s=n(r).replace(/\/+$/,"")+"/";for(const i of await Nl.keys())i.startsWith(s)&&await Nl.delete(i)},async list(r,s){const i=(await Nl.keys()).sort().map(a=>({path:a,type:"file",url:e?`${e}/${a}`:`/${a}`}));return{items:i.slice((r-1)*s,r*s),page:r,per_page:s,total:i.length}},async publicUrl(r){return e?`${e}/${n(r)}`:`/${n(r)}`}}}const Uae={id:"browser-mirror",create:zae},io="https://www.flexweg.com/api/v1",e8=()=>rl(Xs(),ls.config,e1.flexweg);function Bv(t){return t.replace(/\/+$/,"")}async function Bae(){const t=await Cu(e8());if(!t.exists())return null;const e=t.data();return!(e!=null&&e.apiKey)||!(e!=null&&e.siteUrl)?null:{apiKey:e.apiKey,siteUrl:Bv(e.siteUrl),apiBaseUrl:Bv(e.apiBaseUrl??io)}}async function $ae(t){await ro(e8(),{apiKey:t.apiKey,siteUrl:Bv(t.siteUrl),apiBaseUrl:Bv(t.apiBaseUrl||io)})}const Hae=Object.freeze(Object.defineProperty({__proto__:null,DEFAULT_FLEXWEG_API_BASE_URL:io,getFlexwegConfig:Bae,setFlexwegConfig:$ae},Symbol.toStringTag,{value:"Module"})),iT="https://www.flexweg.com/api/v1",t8="flexweg";function $v(t){return t.replace(/\/+$/,"")}async function Vae(){const{rows:t}=await hs("SELECT value FROM config WHERE key = ?",[t8]);if(t.length===0)return null;let e;try{e=JSON.parse(t[0].value)}catch{return null}return!e.apiKey||!e.siteUrl?null:{apiKey:e.apiKey,siteUrl:$v(e.siteUrl),apiBaseUrl:$v(e.apiBaseUrl??iT)}}async function qae(t){const e=JSON.stringify({apiKey:t.apiKey,siteUrl:$v(t.siteUrl),apiBaseUrl:$v(t.apiBaseUrl||iT)});await Kn(`INSERT INTO config (key, value) VALUES (?, ?)
|
|
3886
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value`,[t8,e])}const Wae=Object.freeze(Object.defineProperty({__proto__:null,DEFAULT_FLEXWEG_API_BASE_URL:iT,getFlexwegConfig:Vae,setFlexwegConfig:qae},Symbol.toStringTag,{value:"Module"})),aT="https://www.flexweg.com/api/v1",n8="flexweg";function Hv(t){return t.replace(/\/+$/,"")}async function Gae(){const t=Ct();await t.ready();const e=t.get("config",n8);return!(e!=null&&e.apiKey)||!(e!=null&&e.siteUrl)?null:{apiKey:e.apiKey,siteUrl:Hv(e.siteUrl),apiBaseUrl:Hv(e.apiBaseUrl??aT)}}async function Kae(t){await Ct().write([{op:"set",collection:"config",doc:{id:n8,apiKey:t.apiKey,siteUrl:Hv(t.siteUrl),apiBaseUrl:Hv(t.apiBaseUrl||aT)}}],{message:"Update Flexweg API settings"})}const Jae=Object.freeze(Object.defineProperty({__proto__:null,DEFAULT_FLEXWEG_API_BASE_URL:aT,getFlexwegConfig:Gae,setFlexwegConfig:Kae},Symbol.toStringTag,{value:"Module"}));let XS=null;function r8(){if(!XS){const t=$r();XS=t==="flexweg-sqlite"?Wae:ao(t)?Jae:Hae}return XS}function oT(...t){return r8().getFlexwegConfig(...t)}function Qae(...t){return r8().setFlexwegConfig(...t)}function sy(t){return{"X-API-Key":t.apiKey,"Content-Type":"application/json"}}function hj(t){return t.split("/").map(encodeURIComponent).join("/")}function s8(t,e){async function n(){const r=await e();if(!r){const s=jt.t("flexweg.errors.configMissing");throw at.error(s),new Error(s)}return r}return{id:t,model:"files",capabilities:{list:!0,rename:!0,renameFolder:!0,folders:!0,deletePrefix:!0,storageLimits:!0},async put(r,s){const i=await n(),a={path:r.path,content:r.content};r.encoding&&(a.encoding=r.encoding),await Hs("upload",()=>fetch(`${i.apiBaseUrl}/files/upload`,{method:"POST",headers:sy(i),body:JSON.stringify(a),signal:s}))},async get(r){const s=await n(),i=`${s.apiBaseUrl}/files/get?${new URLSearchParams({path:r,_t:String(Date.now())})}`;return(await Hs("get",()=>fetch(i,{method:"GET",headers:{"X-API-Key":s.apiKey},cache:"no-store"}))).text()},async getBytes(r){const s=await n(),i=`${s.apiBaseUrl}/files/get?${new URLSearchParams({path:r,_t:String(Date.now())})}`,a=await fetch(i,{method:"GET",headers:{"X-API-Key":s.apiKey},cache:"no-store"}).catch(l=>Hs("get",()=>Promise.reject(l)));if(a.status===404)return null;const o=a.ok?a:await Hs("get",async()=>a);return new Uint8Array(await o.arrayBuffer())},async delete(r,s){const i=await n(),a=`${i.apiBaseUrl}/files/delete?path=${hj(r)}`;try{await Hs("delete",()=>fetch(a,{method:"DELETE",headers:{"X-API-Key":i.apiKey},signal:s}))}catch(o){if(o instanceof Ns&&o.status===404)return;throw o}},async deletePrefix(r){const s=await n(),i=`${s.apiBaseUrl}/files/delete-folder?path=${hj(r)}`;try{await Hs("deleteFolder",()=>fetch(i,{method:"DELETE",headers:{"X-API-Key":s.apiKey}}))}catch(a){if(a instanceof Ns&&a.status===404)return;throw a}},async rename(r,s){const i=await n();await Hs("rename",()=>fetch(`${i.apiBaseUrl}/files/rename`,{method:"POST",headers:sy(i),body:JSON.stringify({old_path:r,new_path:s})}))},async renameFolder(r,s){const i=await n();await Hs("renameFolder",()=>fetch(`${i.apiBaseUrl}/files/rename-folder`,{method:"POST",headers:sy(i),body:JSON.stringify({old_path:r,new_path:s})}))},async createFolder(r){const s=await n();await Hs("createFolder",()=>fetch(`${s.apiBaseUrl}/files/create-folder`,{method:"POST",headers:sy(s),body:JSON.stringify({path:r})}))},async list(r,s){const i=await n(),a=`${i.apiBaseUrl}/files/list?${new URLSearchParams({page:String(r),per_page:String(s)})}`;return await(await Hs("list",()=>fetch(a,{method:"GET",headers:{"X-API-Key":i.apiKey}}))).json()},async storageLimits(){const r=await n();return await(await Hs("storageLimits",()=>fetch(`${r.apiBaseUrl}/files/storage-limits`,{method:"GET",headers:{"X-API-Key":r.apiKey}}))).json()},async publicUrl(r){const s=await n(),i=r.replace(/^\/+/,"");try{return`${new URL(s.siteUrl).origin.replace(/\/+$/,"")}/${i}`}catch{return`${s.siteUrl.replace(/\/+$/,"")}/${i}`}}}}const i8=s8("flexweg",oT);function Xae(t,e){return["# Generated by
|
|
3887
|
-
`)}function lT(t){if(t.token)return t.token;const e=ra();return(e==null?void 0:e.backend)==="markdown-git"&&e.git.provider===t.provider?nT(e.git)??"":""}const fj=new Map;function Zae(t,e,n){const r=`${t.owner}/${t.repo}`;let s=fj.get(r);return s||(s=Yae(t,e,n,r),fj.set(r,s)),s}async function Yae(t,e,n,r){const i=`${(t.apiBaseUrl||"https://api.github.com").replace(/\/+$/,"")}/repos/${encodeURIComponent(t.owner??"")}/${encodeURIComponent(t.repo??"")}/pages`,a={Authorization:`Bearer ${e}`,Accept:"application/vnd.github+json"};try{if((await fetch(i,{headers:a,cache:"no-store"})).ok)return;if((await fetch(i,{method:"POST",headers:{...a,"Content-Type":"application/json"},body:JSON.stringify({source:{branch:t.branch,path:n==="docs"?"/docs":"/"}})})).ok){at.success(jt.t("connectors.pages.enabled"));return}}catch{}at.info(jt.t("connectors.pages.enableHint",{repo:r,branch:t.branch,folder:n==="docs"?"/docs":"/ (root)"}))}function eoe(t){const e=lT(t);let n=String(t.dir??"").replace(/^\/+|\/+$/g,"");t.host==="gitlab-pages"&&!n&&(n="public");const r=Af(t.provider==="github"?{provider:"github",owner:t.owner??"",repo:t.repo??"",branch:t.branch,token:e,apiBaseUrl:t.apiBaseUrl}:{provider:"gitlab",project:t.project??"",branch:t.branch,token:e,apiBaseUrl:t.apiBaseUrl}),s=(t.siteUrl??"").replace(/\/+$/,""),i=m=>Ov(n,m),a=m=>n?m.slice(n.length+1):m,o=m=>!n||m.startsWith(n+"/");let l=null;async function c(){const m=await r.headSha();if(l&&l.head===m)return l;const g=await r.listTree();return l={head:g.headSha,files:new Map(g.entries.map(y=>[y.path,y]))},l}function h(m){if(t.host==="github-pages"){const g=i(".nojekyll");return m.has(g)?[]:[{type:"put",path:g,content:""}]}return t.host==="gitlab-pages"?m.has(".gitlab-ci.yml")?[]:[{type:"put",path:".gitlab-ci.yml",content:Xae(n,t.branch)}]:[]}async function p(m){const{files:g}=await c(),y=[];let x=0;for(const C of m)if(C.type==="deletePrefix"){const N=i(C.path)+"/";for(const _ of g.keys())_.startsWith(N)&&y.push({type:"delete",path:_})}else C.type==="delete"?g.has(i(C.path))&&y.push({type:"delete",path:i(C.path)}):(y.push({type:"put",path:i(C.path),content:C.content,encoding:C.encoding}),x++);y.push(...h(g));const v=y.filter(C=>C.type==="delete").length,k=[x&&`${x} updated`,v&&`${v} removed`].filter(Boolean).join(", ");await r.commit(y,{message:`Publish site${k?` (${k})`:""} —
|
|
3886
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`,[t8,e])}const Wae=Object.freeze(Object.defineProperty({__proto__:null,DEFAULT_FLEXWEG_API_BASE_URL:iT,getFlexwegConfig:Vae,setFlexwegConfig:qae},Symbol.toStringTag,{value:"Module"})),aT="https://www.flexweg.com/api/v1",n8="flexweg";function Hv(t){return t.replace(/\/+$/,"")}async function Gae(){const t=Ct();await t.ready();const e=t.get("config",n8);return!(e!=null&&e.apiKey)||!(e!=null&&e.siteUrl)?null:{apiKey:e.apiKey,siteUrl:Hv(e.siteUrl),apiBaseUrl:Hv(e.apiBaseUrl??aT)}}async function Kae(t){await Ct().write([{op:"set",collection:"config",doc:{id:n8,apiKey:t.apiKey,siteUrl:Hv(t.siteUrl),apiBaseUrl:Hv(t.apiBaseUrl||aT)}}],{message:"Update Flexweg API settings"})}const Jae=Object.freeze(Object.defineProperty({__proto__:null,DEFAULT_FLEXWEG_API_BASE_URL:aT,getFlexwegConfig:Gae,setFlexwegConfig:Kae},Symbol.toStringTag,{value:"Module"}));let XS=null;function r8(){if(!XS){const t=$r();XS=t==="flexweg-sqlite"?Wae:ao(t)?Jae:Hae}return XS}function oT(...t){return r8().getFlexwegConfig(...t)}function Qae(...t){return r8().setFlexwegConfig(...t)}function sy(t){return{"X-API-Key":t.apiKey,"Content-Type":"application/json"}}function hj(t){return t.split("/").map(encodeURIComponent).join("/")}function s8(t,e){async function n(){const r=await e();if(!r){const s=jt.t("flexweg.errors.configMissing");throw at.error(s),new Error(s)}return r}return{id:t,model:"files",capabilities:{list:!0,rename:!0,renameFolder:!0,folders:!0,deletePrefix:!0,storageLimits:!0},async put(r,s){const i=await n(),a={path:r.path,content:r.content};r.encoding&&(a.encoding=r.encoding),await Hs("upload",()=>fetch(`${i.apiBaseUrl}/files/upload`,{method:"POST",headers:sy(i),body:JSON.stringify(a),signal:s}))},async get(r){const s=await n(),i=`${s.apiBaseUrl}/files/get?${new URLSearchParams({path:r,_t:String(Date.now())})}`;return(await Hs("get",()=>fetch(i,{method:"GET",headers:{"X-API-Key":s.apiKey},cache:"no-store"}))).text()},async getBytes(r){const s=await n(),i=`${s.apiBaseUrl}/files/get?${new URLSearchParams({path:r,_t:String(Date.now())})}`,a=await fetch(i,{method:"GET",headers:{"X-API-Key":s.apiKey},cache:"no-store"}).catch(l=>Hs("get",()=>Promise.reject(l)));if(a.status===404)return null;const o=a.ok?a:await Hs("get",async()=>a);return new Uint8Array(await o.arrayBuffer())},async delete(r,s){const i=await n(),a=`${i.apiBaseUrl}/files/delete?path=${hj(r)}`;try{await Hs("delete",()=>fetch(a,{method:"DELETE",headers:{"X-API-Key":i.apiKey},signal:s}))}catch(o){if(o instanceof Ns&&o.status===404)return;throw o}},async deletePrefix(r){const s=await n(),i=`${s.apiBaseUrl}/files/delete-folder?path=${hj(r)}`;try{await Hs("deleteFolder",()=>fetch(i,{method:"DELETE",headers:{"X-API-Key":s.apiKey}}))}catch(a){if(a instanceof Ns&&a.status===404)return;throw a}},async rename(r,s){const i=await n();await Hs("rename",()=>fetch(`${i.apiBaseUrl}/files/rename`,{method:"POST",headers:sy(i),body:JSON.stringify({old_path:r,new_path:s})}))},async renameFolder(r,s){const i=await n();await Hs("renameFolder",()=>fetch(`${i.apiBaseUrl}/files/rename-folder`,{method:"POST",headers:sy(i),body:JSON.stringify({old_path:r,new_path:s})}))},async createFolder(r){const s=await n();await Hs("createFolder",()=>fetch(`${s.apiBaseUrl}/files/create-folder`,{method:"POST",headers:sy(s),body:JSON.stringify({path:r})}))},async list(r,s){const i=await n(),a=`${i.apiBaseUrl}/files/list?${new URLSearchParams({page:String(r),per_page:String(s)})}`;return await(await Hs("list",()=>fetch(a,{method:"GET",headers:{"X-API-Key":i.apiKey}}))).json()},async storageLimits(){const r=await n();return await(await Hs("storageLimits",()=>fetch(`${r.apiBaseUrl}/files/storage-limits`,{method:"GET",headers:{"X-API-Key":r.apiKey}}))).json()},async publicUrl(r){const s=await n(),i=r.replace(/^\/+/,"");try{return`${new URL(s.siteUrl).origin.replace(/\/+$/,"")}/${i}`}catch{return`${s.siteUrl.replace(/\/+$/,"")}/${i}`}}}}const i8=s8("flexweg",oT);function Xae(t,e){return["# Generated by AgentCMS — publishes the static site with GitLab Pages.","# Safe to edit: the CMS only creates this file when the repo has none.","pages:"," stage: deploy"," script:",t==="public"?' - echo "Publishing public/"':` - rm -rf public && cp -r ${t} public`," artifacts:"," paths:"," - public"," rules:",` - if: $CI_COMMIT_BRANCH == "${e}"`,""].join(`
|
|
3887
|
+
`)}function lT(t){if(t.token)return t.token;const e=ra();return(e==null?void 0:e.backend)==="markdown-git"&&e.git.provider===t.provider?nT(e.git)??"":""}const fj=new Map;function Zae(t,e,n){const r=`${t.owner}/${t.repo}`;let s=fj.get(r);return s||(s=Yae(t,e,n,r),fj.set(r,s)),s}async function Yae(t,e,n,r){const i=`${(t.apiBaseUrl||"https://api.github.com").replace(/\/+$/,"")}/repos/${encodeURIComponent(t.owner??"")}/${encodeURIComponent(t.repo??"")}/pages`,a={Authorization:`Bearer ${e}`,Accept:"application/vnd.github+json"};try{if((await fetch(i,{headers:a,cache:"no-store"})).ok)return;if((await fetch(i,{method:"POST",headers:{...a,"Content-Type":"application/json"},body:JSON.stringify({source:{branch:t.branch,path:n==="docs"?"/docs":"/"}})})).ok){at.success(jt.t("connectors.pages.enabled"));return}}catch{}at.info(jt.t("connectors.pages.enableHint",{repo:r,branch:t.branch,folder:n==="docs"?"/docs":"/ (root)"}))}function eoe(t){const e=lT(t);let n=String(t.dir??"").replace(/^\/+|\/+$/g,"");t.host==="gitlab-pages"&&!n&&(n="public");const r=Af(t.provider==="github"?{provider:"github",owner:t.owner??"",repo:t.repo??"",branch:t.branch,token:e,apiBaseUrl:t.apiBaseUrl}:{provider:"gitlab",project:t.project??"",branch:t.branch,token:e,apiBaseUrl:t.apiBaseUrl}),s=(t.siteUrl??"").replace(/\/+$/,""),i=m=>Ov(n,m),a=m=>n?m.slice(n.length+1):m,o=m=>!n||m.startsWith(n+"/");let l=null;async function c(){const m=await r.headSha();if(l&&l.head===m)return l;const g=await r.listTree();return l={head:g.headSha,files:new Map(g.entries.map(y=>[y.path,y]))},l}function h(m){if(t.host==="github-pages"){const g=i(".nojekyll");return m.has(g)?[]:[{type:"put",path:g,content:""}]}return t.host==="gitlab-pages"?m.has(".gitlab-ci.yml")?[]:[{type:"put",path:".gitlab-ci.yml",content:Xae(n,t.branch)}]:[]}async function p(m){const{files:g}=await c(),y=[];let x=0;for(const C of m)if(C.type==="deletePrefix"){const N=i(C.path)+"/";for(const _ of g.keys())_.startsWith(N)&&y.push({type:"delete",path:_})}else C.type==="delete"?g.has(i(C.path))&&y.push({type:"delete",path:i(C.path)}):(y.push({type:"put",path:i(C.path),content:C.content,encoding:C.encoding}),x++);y.push(...h(g));const v=y.filter(C=>C.type==="delete").length,k=[x&&`${x} updated`,v&&`${v} removed`].filter(Boolean).join(", ");await r.commit(y,{message:`Publish site${k?` (${k})`:""} — AgentCMS`}),l=null,t.host==="github-pages"&&t.provider==="github"&&Zae(t,e,n)}return{id:"git-pages",model:"commit",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0,storageLimits:!1},put:m=>p([{type:"put",...m}]),delete:m=>p([{type:"delete",path:m}]),deletePrefix:m=>p([{type:"deletePrefix",path:m}]),commitBatch:p,async get(m){const{files:g}=await c(),y=g.get(i(m));if(!y)throw new Ns(`File not found: ${m}`,404);const v=(await r.readTexts([y])).get(y.path);if(v===void 0)throw new Ns(`File not found: ${m}`,404);return v},async getBytes(m){const{files:g}=await c(),y=g.get(i(m));return y?r.readBytes(y):null},async list(m,g){const{files:y}=await c(),x=[...y.values()].filter(v=>o(v.path)).map(v=>({path:a(v.path),type:"file",size:v.size,url:`${s}/${a(v.path)}`})).sort((v,k)=>v.path<k.path?-1:1);return{items:x.slice((m-1)*g,m*g),page:m,per_page:g,total:x.length}},async publicUrl(m){return`${s}/${m.replace(/^\/+/,"")}`}}}const toe={id:"git-pages",create:eoe},Xy="publish-target";function noe(t){const e=(t.siteUrl??"").replace(/\/+$/,"");let n=null;async function r(){if(n)return n;const i=await Cf(Xy);if(!i||!await _0(i,!1)){const a=jt.t("flexweg.errors.folderAccess");throw at.error(a),new Ns(a,403)}return n=DO(i),n}async function s(i){return(await(await r()).listTree()).entries.find(o=>o.path===i.replace(/^\/+/,""))}return{id:"local-folder",model:"files",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0,storageLimits:!1},async put(i){await(await r()).commit([{type:"put",...i,path:i.path.replace(/^\/+/,"")}],{message:""})},async get(i){const a=await s(i),o=a?(await(await r()).readTexts([a])).get(a.path):void 0;if(o===void 0)throw new Ns(`File not found: ${i}`,404);return o},async getBytes(i){const a=await s(i);return a?(await r()).readBytes(a):null},async delete(i){await(await r()).commit([{type:"delete",path:i.replace(/^\/+/,"")}],{message:""})},async deletePrefix(i){const a=await r(),o=i.replace(/^\/+|\/+$/g,"")+"/",l=(await a.listTree()).entries.filter(c=>c.path.startsWith(o));await a.commit(l.map(c=>({type:"delete",path:c.path})),{message:""})},async list(i,a){const o=(await(await r()).listTree()).entries.map(l=>({path:l.path,type:"file",size:l.size,url:e?`${e}/${l.path}`:`/${l.path}`}));return{items:o.slice((i-1)*a,i*a),page:i,per_page:a,total:o.length}},async publicUrl(i){const a=i.replace(/^\/+/,"");return e?`${e}/${a}`:`/${a}`}}}const roe={id:"local-folder",create:noe},soe={id:"php-bridge",create(t){const e={apiKey:t.apiKey??"",siteUrl:(t.siteUrl??"").replace(/\/+$/,""),apiBaseUrl:(t.apiBaseUrl??"").replace(/\/+$/,"")},n=s8("php-bridge",async()=>e.apiKey&&e.apiBaseUrl?e:null);return{...n,capabilities:{...n.capabilities,storageLimits:!1},storageLimits:void 0}}},ioe={html:"text/html; charset=utf-8",htm:"text/html; charset=utf-8",css:"text/css; charset=utf-8",js:"text/javascript; charset=utf-8",mjs:"text/javascript; charset=utf-8",json:"application/json; charset=utf-8",webmanifest:"application/manifest+json; charset=utf-8",xml:"application/xml; charset=utf-8",xsl:"application/xslt+xml; charset=utf-8",txt:"text/plain; charset=utf-8",md:"text/markdown; charset=utf-8",svg:"image/svg+xml",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",avif:"image/avif",ico:"image/x-icon",pdf:"application/pdf",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",mp4:"video/mp4",webm:"video/webm",mp3:"audio/mpeg",zip:"application/zip"};function aoe(t){var n;const e=((n=t.split(".").pop())==null?void 0:n.toLowerCase())??"";return ioe[e]??"application/octet-stream"}function ooe(t){return/\.(html?|json|xml|xsl|txt|css|js|mjs|webmanifest)$/i.test(t)?"no-cache":"public, max-age=86400"}const cT=new TextEncoder;function a8(t){return[...new Uint8Array(t)].map(e=>e.toString(16).padStart(2,"0")).join("")}async function loe(t){return a8(await crypto.subtle.digest("SHA-256",cT.encode(t)))}async function Qp(t,e){const n=await crypto.subtle.importKey("raw",t,{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return crypto.subtle.sign("HMAC",n,cT.encode(e))}function Vv(t){return encodeURIComponent(t).replace(/[!'()*]/g,e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`)}function coe(t){const e=t.toISOString().replace(/[:-]|\.\d{3}/g,"");return{amzDate:e,dateStamp:e.slice(0,8)}}async function pj(t){const e=new URL(t.url),{amzDate:n,dateStamp:r}=coe(t.date??new Date),s={...t.headers,"x-amz-date":n},i={host:e.host};for(const[N,_]of Object.entries(s))i[N.toLowerCase()]=String(_).trim().replace(/\s+/g," ");const a=Object.keys(i).sort(),o=a.map(N=>`${N}:${i[N]}
|
|
3888
3888
|
`).join(""),l=a.join(";"),c=[...e.searchParams.entries()].map(([N,_])=>[Vv(N),Vv(_)]).sort(([N,_],[P,D])=>N<P?-1:N>P?1:_<D?-1:_>D?1:0).map(([N,_])=>`${N}=${_}`).join("&"),h=[t.method.toUpperCase(),e.pathname||"/",c,o,l,t.payloadHash].join(`
|
|
3889
3889
|
`),{accessKeyId:p,secretAccessKey:m,region:g,service:y}=t.credentials,x=`${r}/${g}/${y}/aws4_request`,v=["AWS4-HMAC-SHA256",n,x,await loe(h)].join(`
|
|
3890
|
-
`);let k=await Qp(cT.encode(`AWS4${m}`),r);k=await Qp(k,g),k=await Qp(k,y),k=await Qp(k,"aws4_request");const C=a8(await Qp(k,v));return{...s,Authorization:`AWS4-HMAC-SHA256 Credential=${p}/${x}, SignedHeaders=${l}, Signature=${C}`}}const iy="UNSIGNED-PAYLOAD";function ay(t){return t.split("/").map(Vv).join("/")}function mj(t){return t.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}function uoe(t){const e=(t.endpoint||`https://s3.${t.region}.amazonaws.com`).replace(/\/+$/,"");let n;try{n=new URL(e)}catch{throw new Ns(`Invalid S3 endpoint: ${e}`,400)}const s=t.forcePathStyle??!n.hostname.endsWith("amazonaws.com")?`${e}/${Vv(t.bucket)}`:`${n.protocol}//${t.bucket}.${n.host}`,i=(t.prefix??"").replace(/^\/+|\/+$/g,""),a=(t.siteUrl??"").replace(/\/+$/,""),o={accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey,region:t.region||"us-east-1",service:"s3"},l=g=>i?`${i}/${g.replace(/^\/+/,"")}`:g.replace(/^\/+/,""),c=g=>i?g.slice(i.length+1):g;async function h(g,y,x,v={}){const k=await pj({method:y,url:x,headers:{"x-amz-content-sha256":iy,...v.headers??{}},payloadHash:iy,credentials:o});return Hs(g,()=>fetch(x,{method:y,headers:k,body:v.body,signal:v.signal,cache:v.cache}))}async function p(g){var v,k,C;const y=[];let x;do{const N=new URLSearchParams({"list-type":"2","max-keys":"1000"});g&&N.set("prefix",g),x&&N.set("continuation-token",x);const P=await(await h("list","GET",`${s}/?${N}`,{cache:"no-store"})).text();for(const I of P.match(/<Contents>[\s\S]*?<\/Contents>/g)??[]){const L=(v=I.match(/<Key>([\s\S]*?)<\/Key>/))==null?void 0:v[1],j=Number(((k=I.match(/<Size>(\d+)<\/Size>/))==null?void 0:k[1])??0);L&&y.push({key:mj(L),size:j})}x=/<IsTruncated>true<\/IsTruncated>/.test(P)?mj(((C=P.match(/<NextContinuationToken>([\s\S]*?)<\/NextContinuationToken>/))==null?void 0:C[1])??""):void 0}while(x);return y}async function m(g,y){try{await h("delete","DELETE",`${s}/${ay(g)}`,{signal:y})}catch(x){if(x instanceof Ns&&x.status===404)return;throw x}}return{id:"s3",model:"files",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0,storageLimits:!1},async put(g,y){const x=g.encoding==="base64"?rp(g.content):g.content;await h("upload","PUT",`${s}/${ay(l(g.path))}`,{headers:{"content-type":aoe(g.path),"cache-control":ooe(g.path),...t.publicRead?{"x-amz-acl":"public-read"}:{}},body:x,signal:y})},async get(g){return(await h("get","GET",`${s}/${ay(l(g))}`,{cache:"no-store"})).text()},async getBytes(g){const y=`${s}/${ay(l(g))}`,x=await pj({method:"GET",url:y,headers:{"x-amz-content-sha256":iy},payloadHash:iy,credentials:o}),v=await fetch(y,{headers:x,cache:"no-store"}).catch(C=>Hs("get",()=>Promise.reject(C)));if(v.status===404||v.status===403)return null;const k=v.ok?v:await Hs("get",async()=>v);return new Uint8Array(await k.arrayBuffer())},delete:(g,y)=>m(l(g),y),async deletePrefix(g){const y=await p(l(g).replace(/\/+$/,"")+"/");await XA(y,6,x=>m(x.key))},async list(g,y){const x=(await p(i?`${i}/`:"")).map(v=>({path:c(v.key),type:"file",size:v.size,url:`${a}/${c(v.key)}`}));return{items:x.slice((g-1)*y,g*y),page:g,per_page:y,total:x.length}},async publicUrl(g){return`${a}/${g.replace(/^\/+/,"")}`}}}const doe={id:"s3",create:uoe},hoe=i8.id,o8=new Map([i8,toe,doe,soe,Uae,roe].map(t=>[t.id,t]));function foe(t){return typeof t.create=="function"}function poe(t){o8.set(t.id,t),oi&&oi.id===t.id&&(oi=null)}function l8(){return ao($r())?"browser-mirror":hoe}function o1(t,e){const n=o8.get(t);if(!n)throw new Ns(jt.t("flexweg.errors.unknownConnector",{connector:t}),501);return foe(n)?n.create(e):n}let oi=null;async function moe(){let t=null;try{t=await sT()}catch(n){console.warn("[storage] could not read storage config, defaulting to Flexweg:",n)}const e=(t==null?void 0:t.connectorId)??l8();try{return o1(e,(t==null?void 0:t.settings)??{})}catch(n){throw at.error(n.message),n}}async function sl(){if(!oi){const t=moe();oi={id:"",connector:t},t.then(e=>{(oi==null?void 0:oi.connector)===t&&(oi.id=e.id)},()=>{(oi==null?void 0:oi.connector)===t&&(oi=null)})}return oi.connector}function goe(){oi=null}const boe=/^index\.[a-z0-9]+$/i;function A0(){if(typeof window>"u")return"";const e=window.location.pathname.split("/").filter(Boolean),n=e[e.length-1];return n&&boe.test(n)&&e.pop(),e.join("/")}function yoe(){if(typeof window>"u")return!1;const t=window.location.hostname;return t==="localhost"||t==="127.0.0.1"||t==="[::1]"||t==="::1"||t==="0.0.0.0"||t.endsWith(".localhost")}function voe(){return yoe()?!1:A0()===""}function c8(t){const e=A0(),n=t.replace(/^\/+/,"");return e?`${e}/${n}`:n}function u8(t){return t.replace(/\/+$/,"")}class uT extends Error{constructor(e,n){super(e),this.status=n,this.name="SetupApiError"}}async function d8(t,e){const n=u8(t.apiBaseUrl),r=await fetch(`${n}/files/storage-limits`,{method:"GET",headers:{"X-API-Key":t.apiKey},signal:e});if(!r.ok){const s=await r.text().catch(()=>"");throw new uT(s.length>0?s.slice(0,240):`HTTP ${r.status}`,r.status)}}async function xoe(t,e,n){const r=u8(t.apiBaseUrl),s=await fetch(`${r}/files/upload`,{method:"POST",headers:{"X-API-Key":t.apiKey,"Content-Type":"application/json"},body:JSON.stringify({path:c8("config.js"),content:e,encoding:"utf-8"}),signal:n});if(!s.ok){const i=await s.text().catch(()=>"");throw new uT(i.length>0?i.slice(0,240):`HTTP ${s.status}`,s.status)}}const ZS=".flexweg-cms-probe.txt",YS={flexweg:()=>["apiKey","siteUrl"],"git-pages":t=>[...t.provider==="gitlab"?["project"]:["owner","repo"],"branch","siteUrl"],s3:()=>["bucket","accessKeyId","secretAccessKey","siteUrl"],"php-bridge":()=>["apiBaseUrl","apiKey","siteUrl"]};function h8(t,e,n=[]){var s;return(((s=YS[t])==null?void 0:s.call(YS,e))??[]).filter(i=>!n.includes(i)).filter(i=>typeof e[i]!="string"||!e[i].trim())}async function l1(t,e,n={}){const r=h8(t,e,n.ignore);if(r.length)return{ok:!1,detail:`missing: ${r.join(", ")}`};try{if(t==="flexweg"){const a={apiKey:String(e.apiKey??"").trim(),siteUrl:String(e.siteUrl??"").trim(),apiBaseUrl:String(e.apiBaseUrl??"").trim()||"https://www.flexweg.com/api/v1"};return await d8(a),{ok:!0,detail:a.siteUrl}}if(t==="git-pages"){const a=e,o=lT(a),l=Af(a.provider==="github"?{provider:"github",owner:a.owner??"",repo:a.repo??"",branch:a.branch,token:o,apiBaseUrl:a.apiBaseUrl}:{provider:"gitlab",project:a.project??"",branch:a.branch,token:o,apiBaseUrl:a.apiBaseUrl}),c=await l.permissions();return c.canWrite?{ok:!0,detail:`${c.login} → ${l.label}`}:{ok:!1,detail:`${c.login}: read-only access`}}const s=o1(t,e);if(t==="browser-mirror")return{ok:!0,detail:"browser"};await s.put({path:ZS,content:`
|
|
3891
|
-
`});const i=await s.get(ZS).catch(()=>null);return await s.delete(ZS),i===null?{ok:!1,detail:"write succeeded but read-back failed"}:{ok:!0,detail:await s.publicUrl("")}}catch(s){const i=s instanceof Ns?` (${s.status})`:"";return{ok:!1,detail:`${s.message}${i}`}}}const woe="1",koe=3,f8="flexweg.sqliteConnectorSecrets",gj="flexweg.sqliteDocSecrets",a_="flexweg.sqlitePassphrase";function p8(t,e){try{const n=window.localStorage.getItem(t);return n?JSON.parse(n):e}catch{return e}}function m8(t,e){try{window.localStorage.setItem(t,JSON.stringify(e))}catch{}}function g8(t){const{clean:e,secrets:n}=C0(t);return{publicSettings:e,secrets:n??{}}}function dT(t){m8(f8,t)}function wm(){try{return window.localStorage.getItem(a_)}catch{return null}}function qv(t){try{t?window.localStorage.setItem(a_,t):window.localStorage.removeItem(a_)}catch{}}async function b8(t,e){return WO(t)?{plain:await _ae(t,e),params:KO(t)}:{plain:t,params:null}}function o_(t){return{...t.settings,...p8(f8,{})}}let oy=null;function y8(){return oy||(oy=(async()=>{const{default:t}=await zv(async()=>{const{default:r}=await import("./sql-wasm-CYl3LXH_.js").then(s=>s.s);return{default:r}},[],import.meta.url);if(!(typeof window<"u"&&typeof document<"u"))return t(void 0);const{default:n}=await zv(async()=>{const{default:r}=await import("./sql-wasm-V5jTDcrT.js");return{default:r}},[],import.meta.url);return t({locateFile:()=>n})})().catch(t=>{throw oy=null,t})),oy}async function Soe(t){var r,s;const e=await y8(),n=new e.Database(t);try{const i=E0(),a=new Set((((r=n.exec("SELECT name FROM sqlite_master WHERE type = 'table'")[0])==null?void 0:r.values)??[]).map(o=>String(o[0])));for(const o of Tu)if(a.has(o))for(const[l,c]of((s=n.exec(`SELECT id, data FROM "${o}"`)[0])==null?void 0:s.values)??[])try{i[o].set(String(l),{...JSON.parse(String(c)),id:String(l)})}catch{console.warn(`[sqlite-file] skipping malformed row ${o}/${l}`)}return i}finally{n.close()}}async function Eoe(t){const e=await y8(),n=new e.Database;try{n.run("CREATE TABLE meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)"),n.run("INSERT INTO meta VALUES ('format', 'flexweg-cms'), ('version', ?), ('savedAt', ?)",[woe,new Date().toISOString()]),n.run("BEGIN");for(const r of Tu){n.run(`CREATE TABLE "${r}" (id TEXT PRIMARY KEY, data TEXT NOT NULL)`);const s=n.prepare(`INSERT INTO "${r}" (id, data) VALUES (?, ?)`);for(const i of t[r].values())s.run([i.id,JSON.stringify(i)]);s.free()}return n.run("COMMIT"),n.export()}finally{n.close()}}async function bj(t){if(!t)return"missing";const e=await crypto.subtle.digest("SHA-256",t);return[...new Uint8Array(e)].map(n=>n.toString(16).padStart(2,"0")).join("")}function _oe(t){const e=Object.fromEntries(Tu.map(r=>[r,new Map(t[r])])),n={};for(const r of t.config.values()){const s=C0(r);s.secrets&&(n[`config/${r.id}`]=s.secrets,e.config.set(r.id,s.clean))}return{clean:e,secrets:n}}function Coe(t,e){const n=Object.fromEntries(Tu.map(r=>[r,new Map(t[r])]));for(const r of e)r.op==="set"?n[r.collection].set(r.doc.id,r.doc):n[r.collection].delete(r.id);return n}function Aoe(t){let e=null,n=null,r=null,s=null,i=!!t.encrypted,a=!1;function o(){return n||(n=o1(t.connectorId,o_(t))),n}async function l(){const p=o();if(!p.getBytes)throw new Ns(jt.t("docstore.errors.sqliteUnsupported",{connector:t.connectorId}),501);const m=await p.getBytes(t.path);let g=E0();if(m){const y=await b8(m,wm());y.params&&(r=y.params),g=await Soe(y.plain)}return $O(g,p8(gj,{})),{snapshot:g,hash:await bj(m)}}async function c(p){const{clean:m,secrets:g}=_oe(p);m8(gj,g);const y=await Eoe(m),v=i||r!==null?await Eae(y,wm()??"",r??void 0):y;await o().put({path:t.path,content:JA(v),encoding:"base64"}),e=await bj(v)}const h=GA({kind:"sqlite-file",pollIntervalMs:6e4,async load(){const p=await l();return e=p.hash,a=!1,p.snapshot},async persist(p,m,g){let y=g;for(let x=0;;x++){const v=await l();if(e===null||v.hash===e){await c(y);return}for(const k of p){const C=k.op==="set"?k.doc.id:k.id,N=JSON.stringify(m[k.collection].get(C)??null),_=JSON.stringify(v.snapshot[k.collection].get(C)??null);if(N!==_)throw e=v.hash,a=!0,new e_(jt.t("docstore.errors.conflict"),k.collection,C)}if(x>=koe)throw new e_(jt.t("docstore.errors.conflict"),p[0].collection,"");e=v.hash,a=!0,y=Coe(v.snapshot,p)}},async poll(){const p=await l();return p.hash===e&&!a?null:(e=p.hash,a=!1,p.snapshot)},async identity(){if(h8(t.connectorId,o_(t),["siteUrl"]).length>0)return null;if(i&&!wm())return s="missing",null;try{await h.ready(),s=null}catch(p){if(p instanceof Pg)return s=p.reason,null}return{uid:"admin",email:"admin@localhost",displayName:"Admin",role:"admin"}}});return Object.assign(h,{passphraseProblem:()=>s,isEncrypted:()=>i||r!==null,async rekey(p){if(p.trim().length<12)throw new Error("The passphrase must be at least 12 characters long.");await h.ready();const m=await l(),g=wm();qv(p.trim());const y=r;r=null;try{i=!0,await c(m.snapshot),await l()}catch(x){throw qv(g),r=y,i=!!t.encrypted,x}},resetSession(){n=null,r=null,s=null,e=null,a=!1}})}let Ih=null;function Ct(){if(Ih)return Ih;const t=ra();if((t==null?void 0:t.backend)==="markdown-git")Ih=yae(t.git);else if((t==null?void 0:t.backend)==="sqlite-file")Ih=Aoe(t.sqlite);else if((t==null?void 0:t.backend)==="local")Ih=vae();else throw new Error("No document store for the active backend.");return Ih}function v8(t){if(t!=null){if(typeof t=="number")return t;if(t instanceof en)return t.toMillis();if(t instanceof Date)return t.getTime();if(typeof t=="string"){const e=Date.parse(t);return Number.isNaN(e)?void 0:e}return Date.now()}}function bd(t){const e=v8(t);return e===void 0?void 0:en.fromMillis(e)}function hT(){const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";return[...crypto.getRandomValues(new Uint8Array(20))].map(n=>t[n%t.length]).join("")}const Pd="terms";function x8(t){if(!t||typeof t!="object")return!1;const e=t;return!!(e.title||e.description||e.ogImage)}function Toe(t){const e={id:t.id,type:t.type,name:t.name??"",slug:t.slug??"",createdAt:bd(t.createdAt??0),updatedAt:bd(t.updatedAt??t.createdAt??0)};return t.description&&(e.description=t.description),t.parentId&&(e.parentId=t.parentId),t.lastPublishedPath&&(e.lastPublishedPath=t.lastPublishedPath),t.translations&&typeof t.translations=="object"&&Object.keys(t.translations).length>0&&(e.translations=JSON.parse(JSON.stringify(t.translations))),x8(t.seo)&&(e.seo={...t.seo}),e}function Ioe(t,e){return t.name<e.name?-1:t.name>e.name?1:0}function w8(){return Ct().list(Pd).map(Toe).sort(Ioe)}function fT(t){return`${t.type==="tag"?"tag":"category"}: ${t.name||t.id}`}function Noe(t,e){let n=!1,r=null;const s=()=>{try{t(w8())}catch(i){e==null||e(i)}};try{const i=Ct();i.ready().then(()=>{n||(r=i.subscribe(a=>{a.has(Pd)&&s()}),s())},a=>{n||e==null||e(a)})}catch(i){e==null||e(i)}return()=>{n=!0,r==null||r()}}async function Poe(){return await Ct().ready(),w8()}async function Roe(t){const e=hT(),n=Date.now(),r={id:e,type:t.type,name:t.name,slug:t.slug,createdAt:n,updatedAt:n};t.description&&(r.description=t.description),t.parentId&&(r.parentId=t.parentId);const s=Ct();return await s.ready(),await s.write([{op:"set",collection:Pd,doc:r}],{message:`Create ${fT(r)}`}),e}async function joe(t,e){const n=Ct();await n.ready();const r=n.get(Pd,t);if(!r)throw new Error(`Term not found: ${t}`);const s={...r},i=(a,o,l)=>{o!==void 0&&(o===null||!l?delete s[a]:s[a]=o)};i("name",e.name,!0),i("slug",e.slug,!0),i("description",e.description,!!e.description),i("parentId",e.parentId,!!e.parentId),i("translations",e.translations,!!e.translations&&Object.keys(e.translations).length>0),i("seo",e.seo,x8(e.seo)),s.updatedAt=Date.now(),await n.write([{op:"set",collection:Pd,doc:s}],{message:`Update ${fT(s)}`})}async function Moe(t){const e=Ct();await e.ready();const n=e.get(Pd,t);n&&await e.write([{op:"delete",collection:Pd,id:t}],{message:`Delete ${fT(n)}`})}const Loe=Object.freeze(Object.defineProperty({__proto__:null,createTerm:Roe,deleteTerm:Moe,fetchAllTerms:Poe,subscribeToTerms:Noe,updateTerm:joe},Symbol.toStringTag,{value:"Module"}));let e2=null;function T0(){if(!e2){const t=$r();e2=t==="flexweg-sqlite"?jte:ao(t)?Loe:bte}return e2}function Doe(...t){return T0().subscribeToTerms(...t)}function pT(...t){return T0().fetchAllTerms(...t)}function Wv(...t){return T0().createTerm(...t)}function c1(...t){return T0().updateTerm(...t)}function k8(...t){return T0().deleteTerm(...t)}let km=null;function Foe(t){return t.replace(/^\/+|\/+$/g,"")}function S8(t,e){return t===e||t.startsWith(e+"/")}function mT(){return km}function Ooe(t,e){t.files.set(e.path,{type:"put",...e})}function zoe(t,e){t.files.set(e,{type:"delete",path:e})}function Uoe(t,e){const n=Foe(e);for(const r of[...t.files.keys()])S8(r,n)&&t.files.delete(r);t.prefixes.add(n)}function Boe(t,e){const n=t.files.get(e);if((n==null?void 0:n.type)==="put"){if(n.encoding!=="base64")return{kind:"content",content:n.content};const r=Uint8Array.from(atob(n.content),s=>s.charCodeAt(0));return{kind:"content",content:new TextDecoder().decode(r)}}if((n==null?void 0:n.type)==="delete")return{kind:"deleted"};for(const r of t.prefixes)if(S8(e,r))return{kind:"deleted"};return null}function E8(t){const e=[];for(const n of t.prefixes)e.push({type:"deletePrefix",path:n});for(const n of t.files.values())e.push(n);return e}const $oe=1500;let Ti=null;function Hoe(){Ti&&(Ti.timer&&clearTimeout(Ti.timer),Ti.timer=setTimeout(()=>void gT(),$oe))}function Voe(t){return(!Ti||Ti.connector!==t)&&(Ti={connector:t,depth:0,files:new Map,prefixes:new Set,timer:null,flushing:null}),Hoe(),Ti}function qoe(){return Ti}async function gT(){const t=Ti;if(!t)return;t.timer&&clearTimeout(t.timer),Ti=null;const e=E8(t);if(e.length!==0)try{await t.connector.commitBatch(e)}catch(n){console.error("[storage] deferred commit failed:",n)}}typeof window<"u"&&typeof window.addEventListener=="function"&&window.addEventListener("beforeunload",t=>{Ti&&(Ti.files.size>0||Ti.prefixes.size>0)&&(gT(),t.preventDefault())});async function ja(t){const e=await sl();if(!e.commitBatch)return t();await gT(),km||(km={connector:e,depth:0,files:new Map,prefixes:new Set});const n=km;n.depth++;let r=!1,s,i;try{i=await t()}catch(a){r=!0,s=a}if(n.depth--,n.depth===0){km=null;const a=E8(n);if(a.length>0)try{await n.connector.commitBatch(a)}catch(o){if(!r)throw o;console.error("[storage] batch commit failed after an earlier error:",o)}}if(r)throw s;return i}const Woe=/\.(webp|png|jpe?g|gif|avif|svg|ico)$/i,Goe={webp:"image/webp",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",avif:"image/avif",svg:"image/svg+xml",ico:"image/x-icon"},Gv=new Map;function Koe(t){return t.replace(/^\/+/,"")}function Joe(t,e){if(typeof URL>"u"||typeof URL.createObjectURL!="function")return;const n=Koe(t);if(Woe.test(n))try{const r=atob(e),s=new Uint8Array(r.length);for(let o=0;o<r.length;o++)s[o]=r.charCodeAt(o);const i=n.split(".").pop().toLowerCase(),a=Gv.get(n);a&&URL.revokeObjectURL(a),Gv.set(n,URL.createObjectURL(new Blob([s],{type:Goe[i]??"application/octet-stream"})))}catch{}}function Qoe(t){if(!t||Gv.size===0)return null;let e=t;try{e=new URL(t,"http://x").pathname}catch{}e=decodeURIComponent(e);for(const[n,r]of Gv)if(e===`/${n}`||e.endsWith(`/${n}`))return r;return null}async function _8(){const t=await sl();return{...t.capabilities,connectorId:t.id,model:t.model}}async function bT(){const t=mT();if(t)return{batch:t,connector:null};const e=await sl();return{batch:e.commitBatch?Voe(e):null,connector:e}}async function bn(t){const e={path:t.path,content:t.content,encoding:t.encoding};t.encoding==="base64"&&Joe(t.path,t.content);const{batch:n,connector:r}=await bT();if(n){Ooe(n,e);return}await r.put(e,t.signal)}function Xoe(t){return new Promise((e,n)=>{const r=new FileReader;r.onload=()=>{const s=r.result;if(typeof s!="string"){n(new Error("Unexpected FileReader result type"));return}const i=s.indexOf(",");e(i>=0?s.slice(i+1):s)},r.onerror=()=>n(r.error??new Error("Failed to read file")),r.readAsDataURL(t)})}async function il(t,e){const{batch:n,connector:r}=await bT();if(n){zoe(n,t);return}await r.delete(t,e)}async function Kv(t){for(const n of[mT(),qoe()]){if(!n)continue;const r=Boe(n,t);if((r==null?void 0:r.kind)==="content")return r.content;if((r==null?void 0:r.kind)==="deleted")throw new Ns(`File not found: ${t}`,404)}return(await sl()).get(t)}async function Zy(t,e){const n=await sl();if(n.rename&&!mT()){await n.rename(t,e);return}const r=await Kv(t);await bn({path:e,content:r}),await il(t)}async function C8(t=1,e=100){const n=await sl();if(!n.list)throw i1("list",n.id);return n.list(t,e)}async function Zoe(t){const e=await sl();!e.capabilities.folders||!e.createFolder||await e.createFolder(t)}async function Yoe(t,e){const n=await sl();if(!n.renameFolder)throw i1("renameFolder",n.id);await n.renameFolder(t,e)}async function A8(){const t=await sl();if(!t.storageLimits)throw i1("storageLimits",t.id);return t.storageLimits()}async function rh(t){const{batch:e,connector:n}=await bT();if(e){Uoe(e,t);return}const r=n;if(r.deletePrefix){await r.deletePrefix(t);return}if(!r.list)throw i1("deleteFolder",r.id);const s=t.replace(/^\/+|\/+$/g,"")+"/",i=100,a=[];for(let o=1;;o++){const l=await r.list(o,i);for(const c of l.items)c.type==="file"&&c.path.replace(/^\/+/,"").startsWith(s)&&a.push(c.path);if(l.items.length<i||l.total!==void 0&&o*i>=l.total)break}for(const o of a)await r.delete(o)}async function I0(t){return(await sl()).publicUrl(t)}const yT={"admin-thumb":{width:240,height:240,fit:"cover"},"admin-preview":{width:800,height:800,fit:"contain"},"admin-original":{width:2e3,height:2e3,fit:"contain",quality:90}},vT="admin-thumb",T8="admin-preview";function xT(t,e){const n=t.toLowerCase(),r=n.lastIndexOf("."),s=r>=0?n.slice(r):"",i=e.map(a=>a.startsWith(".")?a.toLowerCase():`.${a.toLowerCase()}`);return i.includes(s)?null:`Unsupported file type "${s}". Accepted: ${i.join(", ")}.`}function ele(t,e,n){const r=n.fit??"cover",s=n.width,i=n.height,a=t/e,o=s/i;if(r==="cover"){let p=t,m=e,g=0,y=0;return a>o?(p=e*o,g=(t-p)/2):(m=t/o,y=(e-m)/2),{canvasWidth:s,canvasHeight:i,srcX:g,srcY:y,srcWidth:p,srcHeight:m,drawWidth:s,drawHeight:i}}const l=Math.min(s/t,i/e,1),c=Math.round(t*l),h=Math.round(e*l);return{canvasWidth:c,canvasHeight:h,srcX:0,srcY:0,srcWidth:t,srcHeight:e,drawWidth:c,drawHeight:h}}function yj(t){return Number.isFinite(t)?Math.max(0,Math.min(1,t>1?t/100:t)):.8}async function wT(t,e){var r;const n=await createImageBitmap(t);try{const s=yj(e.quality),i=[];for(const[a,o]of Object.entries(e.formats)){const l=ele(n.width,n.height,o),c=tle(l.canvasWidth,l.canvasHeight),h=c.getContext("2d");if(!h)throw new Error("2D canvas context unavailable.");h.imageSmoothingEnabled=!0,h.imageSmoothingQuality="high",h.drawImage(n,l.srcX,l.srcY,l.srcWidth,l.srcHeight,0,0,l.drawWidth,l.drawHeight);const p=o.quality!==void 0?yj(o.quality):s,m=await nle(c,e.outputMime,p);if(!m)throw new Error(`Failed to encode variant "${a}".`);i.push({name:a,blob:m,width:l.canvasWidth,height:l.canvasHeight,bytes:m.size})}return i}finally{(r=n.close)==null||r.call(n)}}function tle(t,e){if(typeof OffscreenCanvas<"u")return new OffscreenCanvas(t,e);const n=document.createElement("canvas");return n.width=t,n.height=e,n}function nle(t,e,n){return"convertToBlob"in t?t.convertToBlob({type:e,quality:n}):new Promise(r=>t.toBlob(s=>r(s),e,n))}function kT(t){return new Promise((e,n)=>{const r=new FileReader;r.onload=()=>{const s=r.result;if(typeof s!="string"){n(new Error("Unexpected FileReader result type"));return}const i=s.indexOf(",");e(i>=0?s.slice(i+1):s)},r.onerror=()=>n(r.error??new Error("Failed to read blob")),r.readAsDataURL(t)})}function ST(t){switch(t){case"image/webp":return"webp";case"image/jpeg":return"jpg";case"image/png":return"png";default:return"bin"}}function ET(t,e){const n=(e==null?void 0:e.formats)??{},r={...t,...n},s=(e==null?void 0:e.outputFormat)??"webp",i=`image/${s==="jpeg"?"jpeg":s}`,a=(e==null?void 0:e.quality)??80,o=(e==null?void 0:e.defaultFormat)??(n.medium?"medium":Object.keys(n)[0]??"admin-preview");return{formats:r,outputMime:i,quality:a,defaultFormat:o}}function _i(t){return t.normalize("NFD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,96)}function Rd(t){return/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(t)}function Tr({post:t,primaryTerm:e}){const n=t.slug.trim();if(!n)throw new Error("Post slug is required to build its URL.");if(t.type==="page")return`${n}.html`;if(e&&e.type==="category"){const r=e.slug.trim();if(!r)throw new Error("Primary category slug is required to build the post URL.");return`${r}/${n}.html`}return`${n}.html`}function vj(t){var r,s;const n=[t.firstName,t.lastName].filter(Boolean).join(" ").trim()||((r=t.displayName)==null?void 0:r.trim())||((s=t.email)==null?void 0:s.split("@")[0])||t.id;return _i(n)||t.id.slice(0,8)}function _T(t,e){const n=vj(t);return`author/${e.some(i=>i.id!==t.id&&vj(i)===n)?`${n}-${t.id.slice(0,6)}`:n}.html`}function sa(t){const e=t.slug.trim();if(!e)throw new Error("Term slug is required to build its URL.");if(t.type!=="category")throw new Error("Only categories produce a public archive URL.");return`${e}/index.html`}const sp="index.html",I8="404.html";function N8(t,e){const n=t.replace(/\/+$/,""),r=e.replace(/^\/+/,"");return`${n}/${r}`}function P8(t){return t.replace(/(^|\/)index\.html$/i,(e,n)=>n)}function R8(t,e){if(!t)return"";const n=t.replace(/\/+$/,""),r=P8(e.replace(/^\/+/,""));return`${n}/${r}`}function u1(t,e){if(t||(t="untitled"),!e(t))return t;for(let n=2;n<1e3;n++){const r=`${t}-${n}`;if(!e(r))return r}return`${t}-${Date.now()}`}function Yy(t,e,n,r,s){for(const i of e){if(i.id===s)continue;const a=i.primaryTermId?r.find(l=>l.id===i.primaryTermId):void 0;let o;try{o=Tr({post:i,primaryTerm:a})}catch{continue}if(o===t)return{kind:"post",id:i.id,label:i.title||i.slug,path:o}}for(const i of n){if(i.id===s)continue;let a;try{a=Tr({post:i})}catch{continue}if(a===t)return{kind:"page",id:i.id,label:i.title||i.slug,path:a}}for(const i of r){if(i.id===s||i.type!=="category")continue;let a;try{a=sa(i)}catch{continue}if(a===t)return{kind:"category",id:i.id,label:i.name||i.slug,path:a}}return null}function Um(t,e,n){for(const r of e)if(r.id!==n&&r.type===t.type&&r.slug===t.slug)return{kind:"category",id:r.id,label:r.name||r.slug,path:r.slug};return null}function d1(t){const e=t.lastIndexOf("."),n=e>0?t.slice(0,e):t;return`${_i(n)||"media"}-${rle(6)}`}function rle(t){if(typeof crypto<"u"&&typeof crypto.getRandomValues=="function"){const e=new Uint8Array(Math.ceil(t/2));return crypto.getRandomValues(e),Array.from(e).map(n=>n.toString(16).padStart(2,"0")).join("").slice(0,t)}return Math.random().toString(16).slice(2,2+t)}function sle({site:t}){const{settings:e}=t,n=t.homePath??"/index.html";return d.jsxs(d.Fragment,{children:[d.jsx("header",{className:"site-header",children:d.jsxs("div",{className:"container site-header__inner",children:[d.jsx("button",{type:"button",className:"burger-toggle","aria-controls":"burger-menu","aria-expanded":"false","aria-label":"Open menu",children:d.jsx(ile,{})}),d.jsx("a",{className:"site-brand",href:n,"data-cms-brand":!0,children:e.title}),d.jsx("div",{className:"site-langswitch","data-cms-langswitch":"header","aria-hidden":"true"})]})}),d.jsx("nav",{id:"burger-menu",className:"burger-menu","data-cms-menu":"header","aria-label":"Primary",children:d.jsx("ul",{})})]})}function ile(){return d.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[d.jsx("line",{x1:"3",y1:"6",x2:"21",y2:"6"}),d.jsx("line",{x1:"3",y1:"12",x2:"21",y2:"12"}),d.jsx("line",{x1:"3",y1:"18",x2:"21",y2:"18"})]})}function ale({site:t}){const{settings:e}=t,n=new Date().getFullYear();return d.jsx("footer",{className:"site-footer",children:d.jsxs("div",{className:"container site-footer__inner",children:[d.jsx("p",{className:"site-footer__brand",children:e.title}),d.jsx("nav",{className:"site-footer__nav","data-cms-menu":"footer","aria-label":"Footer",children:d.jsx("ul",{})}),d.jsxs("p",{className:"site-footer__copy",children:["© ",n," ",e.title]}),d.jsx("div",{className:"site-footer__langswitch","data-cms-langswitch":"footer","aria-hidden":"true"})]})})}function ole({site:t,pageTitle:e,pageDescription:n,ogImage:r,currentPath:s,currentLocale:i,children:a}){var y;const o=(y=t.themeConfig)==null?void 0:y.cssUpdatedAt,l=o?`/${t.themeCssPath}?v=${o}`:`/${t.themeCssPath}`,c=t.themeCssPath.replace(/^theme-assets\//,"").replace(/\.css$/,""),h=`/theme-assets/${c}-menu.js`,p=`/theme-assets/${c}-posts.js`,m=t.settings.baseUrl&&s?R8(t.settings.baseUrl,s):void 0,g=e?`${e} — ${t.settings.title}`:t.settings.title;return d.jsxs("html",{lang:i||t.settings.language||"en",children:[d.jsxs("head",{children:[d.jsx("meta",{charSet:"UTF-8"}),d.jsx("meta",{name:"viewport",content:"width=device-width, initial-scale=1"}),d.jsx("title",{children:g}),n&&d.jsx("meta",{name:"description",content:n}),m&&d.jsx("link",{rel:"canonical",href:m}),d.jsx("link",{rel:"preconnect",href:"https://fonts.googleapis.com"}),d.jsx("link",{rel:"preconnect",href:"https://fonts.gstatic.com",crossOrigin:""}),d.jsx("link",{rel:"stylesheet",href:l}),d.jsx("meta",{property:"og:title",content:g}),n&&d.jsx("meta",{property:"og:description",content:n}),r&&d.jsx("meta",{property:"og:image",content:r}),m&&d.jsx("meta",{property:"og:url",content:m}),d.jsx("meta",{property:"og:type",content:"website"}),d.jsx("meta",{name:"x-cms-head-extra"})]}),d.jsxs("body",{children:[d.jsx(sle,{site:t}),d.jsx("main",{className:"site-main",children:a}),d.jsx(ale,{site:t}),d.jsx("script",{src:h,defer:!0}),d.jsx("script",{src:p,defer:!0}),d.jsx("script",{type:"application/x-cms-body-end"})]})]})}function lle({staticPage:t,archivesLink:e,heroHtml:n,listHtml:r}){return t?d.jsxs("article",{className:"page-static container",children:[d.jsx("h1",{className:"page-title",children:t.post.title}),d.jsx("div",{className:"page-body",dangerouslySetInnerHTML:{__html:t.bodyHtml}})]}):n&&n.length>0||r&&r.length>0?d.jsxs(d.Fragment,{children:[n&&d.jsx("div",{className:"container",dangerouslySetInnerHTML:{__html:n}}),r&&d.jsx("div",{className:"container",dangerouslySetInnerHTML:{__html:r}}),e&&d.jsx("div",{className:"container",children:d.jsx("p",{className:"archives-link",children:d.jsx("a",{href:e.href,children:e.label})})})]}):d.jsx("div",{className:"page-home container",children:d.jsx("p",{className:"empty-state",children:"No posts yet."})})}function Js(t,e){if(!t)return"";const n=t.formats;if(e&&n[e])return n[e].url;if(t.default&&n[t.default])return n[t.default].url;const r=Object.values(n).reduce((s,i)=>{const a=(i.width||0)*(i.height||0);return!s||a>s.area?{url:i.url,area:a}:s},null);return(r==null?void 0:r.url)??""}function ia(t){if(t){if(t.formats&&Object.keys(t.formats).length>0)return{alt:t.alt,caption:t.caption,default:t.defaultFormat??Object.keys(t.formats)[0],formats:Object.fromEntries(Object.entries(t.formats).map(([e,n])=>[e,{url:n.url,width:n.width,height:n.height}]))};if(t.url)return{alt:t.alt,caption:t.caption,default:"legacy",formats:{legacy:{url:t.url,width:0,height:0}}}}}function jd(t,e){return Js(ia(t),e)}function cle(t){if(!t)return"?";const e=t.trim().split(/\s+/);if(e.length===1)return e[0].slice(0,2).toUpperCase();const n=e[0][0]??"",r=e[e.length-1][0]??"";return(n+r).toUpperCase()}function j8({name:t,avatar:e,size:n="default"}){const r=["author-avatar"];if(n==="lg"&&r.push("author-avatar--lg"),n==="xl"&&r.push("author-avatar--xl"),e){const i=Js(e,n==="xl"?"large":n==="lg"?"medium":"small");if(i)return r.push("author-avatar--image"),d.jsx("img",{className:r.join(" "),src:i,alt:e.alt??t,loading:"lazy"})}return d.jsx("span",{className:r.join(" "),"aria-hidden":"true",children:cle(t)})}function ule({items:t}){return t.length===0?null:d.jsx("nav",{className:"breadcrumb","aria-label":"Breadcrumb",children:d.jsx("ol",{className:"breadcrumb",children:t.map((e,n)=>{const r=n===t.length-1;return d.jsxs("li",{"aria-current":r?"page":void 0,children:[e.href&&!r?d.jsx("a",{href:e.href,children:e.label}):d.jsx("span",{className:"breadcrumb__current",children:e.label}),!r&&d.jsx("span",{className:"breadcrumb__sep","aria-hidden":"true",children:"/"})]},`${e.label}-${n}`)})})})}function dle({post:t,bodyHtml:e,author:n,hero:r,primaryTerm:s,tags:i,site:a}){var p,m,g,y,x,v;if(t.type==="page")return d.jsx("div",{className:"page-static container",children:d.jsx("div",{className:"page-body",dangerouslySetInnerHTML:{__html:e}})});const o=jt.getFixedT(nh(a.settings.language),"theme-default"),l=[{label:o("breadcrumb.home",{defaultValue:"Home"}),href:a.homePath??"/index.html"}];s&&s.type==="category"&&l.push({label:s.name,href:`/${sa(s)}`}),l.push({label:t.title});const c=((m=(p=t.publishedAt)==null?void 0:p.toMillis)==null?void 0:m.call(p))??((y=(g=t.updatedAt)==null?void 0:g.toMillis)==null?void 0:y.call(g))??((v=(x=t.createdAt)==null?void 0:x.toMillis)==null?void 0:v.call(x));let h;if(c)try{h=new Intl.DateTimeFormat(a.settings.language||"en",{month:"long",day:"numeric",year:"numeric"}).format(new Date(c))}catch{h=new Date(c).toDateString()}return d.jsxs("div",{className:"page-single container",children:[d.jsxs("article",{className:"page-single__main",children:[d.jsx(ule,{items:l}),d.jsxs("header",{children:[d.jsx("h1",{className:"page-single__title",children:t.title}),r&&d.jsxs("figure",{className:"page-single__hero",children:[d.jsx("img",{src:Js(r,"large"),alt:r.alt??"",fetchPriority:"high"}),r.caption&&d.jsx("figcaption",{children:r.caption})]}),t.excerpt&&d.jsx("p",{className:"page-single__lede",children:t.excerpt}),d.jsxs("div",{className:"page-single__meta-strip",children:[s&&d.jsx("span",{className:"label-caps",children:s.name}),s&&h&&d.jsx("span",{className:"page-single__meta-dot","aria-hidden":"true"}),h&&d.jsx("span",{className:"label-caps",children:h})]}),n&&d.jsxs("div",{className:"page-single__author-strip",children:[d.jsx(j8,{name:n.displayName,avatar:n.avatar}),d.jsx("div",{children:d.jsx("p",{className:"page-single__author-name",children:n.displayName})})]})]}),d.jsx("div",{className:"page-body",dangerouslySetInnerHTML:{__html:e}}),i.length>0&&d.jsx("ul",{className:"page-single__tags",children:i.map(k=>d.jsxs("li",{children:["#",k.name]},k.id))})]}),d.jsxs("aside",{className:"page-single__sidebar",children:[t.authorId&&d.jsx("section",{className:"author-bio","data-cms-author-bio":!0,"data-cms-author-id":t.authorId,"data-cms-eyebrow":o("publicBaked.authorBioEyebrow"),hidden:!0}),d.jsx("section",{className:"related-posts","data-cms-related":!0,"data-cms-current-id":t.id,"data-cms-term-id":t.primaryTermId??"","data-cms-limit":"3","data-cms-label":o("publicBaked.relatedPostsLabel"),"data-cms-fallback-label":o("publicBaked.relatedPostsFallbackLabel")})]})]})}function M8({post:t}){var n;const e=t.hero?Js(t.hero,"medium"):"";return d.jsx("article",{className:"card-post",children:d.jsxs("a",{className:"card-post__link",href:`/${t.url}`,children:[e&&d.jsx("div",{className:"card-post__media",children:d.jsx("img",{src:e,alt:((n=t.hero)==null?void 0:n.alt)??"",loading:"lazy"})}),d.jsxs("div",{className:"card-post__body",children:[t.category&&d.jsx("p",{className:"card-post__eyebrow",children:t.category.name}),d.jsx("h3",{className:"card-post__title",children:t.title}),t.excerpt&&d.jsx("p",{className:"card-post__excerpt",children:t.excerpt}),t.dateLabel&&d.jsx("p",{className:"card-post__meta",children:t.dateLabel})]})]})})}function hle({term:t,posts:e,categoryRssUrl:n,archivesLink:r}){return d.jsxs("div",{className:"page-archive container",children:[d.jsxs("header",{className:"page-archive__header",children:[d.jsxs("div",{className:"page-archive__head",children:[d.jsx("p",{className:"page-archive__eyebrow",children:"Section"}),d.jsx("h1",{className:"page-archive__title",children:t.name}),t.description&&d.jsx("p",{className:"page-archive__desc",children:t.description})]}),n&&d.jsxs("a",{className:"page-archive__rss",href:n,"aria-label":`RSS feed for ${t.name}`,children:[d.jsx(fle,{}),"Follow"]})]}),e.length===0?d.jsx("p",{className:"empty-state",children:"No posts in this category yet."}):d.jsx("ul",{className:"post-grid",children:e.map(s=>d.jsx("li",{children:d.jsx(M8,{post:s})},s.id))}),r&&d.jsx("p",{className:"archives-link",children:d.jsx("a",{href:r.href,children:r.label})})]})}function fle(){return d.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[d.jsx("path",{d:"M4 11a9 9 0 0 1 9 9"}),d.jsx("path",{d:"M4 4a16 16 0 0 1 16 16"}),d.jsx("circle",{cx:"5",cy:"19",r:"1.5",fill:"currentColor"})]})}const ple={twitter:"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z",linkedin:"M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z",instagram:"M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z",mastodon:"M23.193 7.88c0-5.207-3.411-6.733-3.411-6.733C18.062.357 15.108.025 12.041 0h-.076c-3.068.025-6.02.357-7.74 1.147 0 0-3.412 1.526-3.412 6.733 0 1.193-.023 2.619.015 4.13.124 5.092.934 10.11 5.641 11.355 2.17.574 4.034.695 5.535.612 2.722-.151 4.25-.972 4.25-.972l-.09-1.975s-1.945.613-4.129.539c-2.165-.074-4.449-.233-4.799-2.891a5.499 5.499 0 0 1-.048-.745s2.125.52 4.817.643c1.646.075 3.19-.097 4.758-.283 3.007-.359 5.625-2.212 5.954-3.905.52-2.667.477-6.508.477-6.508zm-4.024 6.709h-2.497V8.469c0-1.29-.543-1.944-1.628-1.944-1.2 0-1.802.776-1.802 2.312v3.349h-2.484v-3.35c0-1.536-.601-2.312-1.802-2.312-1.085 0-1.628.655-1.628 1.945v6.119H4.831V8.285c0-1.29.328-2.313.987-3.07.68-.756 1.57-1.144 2.674-1.144 1.278 0 2.246.491 2.886 1.474L12 6.585l.622-1.04c.64-.983 1.608-1.474 2.886-1.474 1.104 0 1.994.388 2.674 1.144.658.757.986 1.78.986 3.07v6.304z",bluesky:"M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.137-.02.275-.039.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.952 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 0 1-.415-.056c.14.017.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8Z",github:"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12",website:"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95a15.65 15.65 0 0 0-1.38-3.56A8.03 8.03 0 0 1 18.92 8zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56A7.987 7.987 0 0 1 5.08 16zm2.95-8H5.08a7.987 7.987 0 0 1 4.33-3.56A15.65 15.65 0 0 0 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95a8.03 8.03 0 0 1-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"},mle={twitter:"Twitter / X",linkedin:"LinkedIn",instagram:"Instagram",mastodon:"Mastodon",bluesky:"Bluesky",github:"GitHub",website:"Website"};function L8({network:t,className:e,size:n=18}){const r=ple[t];return d.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:n,height:n,fill:"currentColor","aria-hidden":"true",className:e,children:d.jsx("path",{d:r})})}function l_(t){return mle[t]}function gle({author:t,posts:e}){return d.jsxs("div",{className:"page-author container",children:[d.jsxs("header",{className:"page-author__hero",children:[d.jsx("div",{className:"page-author__portrait",children:d.jsx(j8,{name:t.displayName,avatar:t.avatar,size:"xl"})}),d.jsxs("div",{className:"page-author__body",children:[d.jsx("p",{className:"page-author__eyebrow",children:"Author"}),d.jsx("h1",{className:"page-author__title",children:t.displayName}),t.title&&d.jsx("p",{className:"page-author__role",children:t.title}),t.bio&&d.jsx("p",{className:"page-author__bio",children:t.bio}),t.socials&&t.socials.length>0&&d.jsx("div",{className:"page-author__socials",children:t.socials.map(n=>d.jsx("a",{className:"page-author__social-link",href:n.url,target:"_blank",rel:"noopener noreferrer","aria-label":l_(n.network),title:l_(n.network),children:d.jsx(L8,{network:n.network})},n.network))})]})]}),e.length===0?d.jsx("p",{className:"empty-state",children:"No posts by this author yet."}):d.jsx("ul",{className:"post-grid",children:e.map(n=>d.jsx("li",{children:d.jsx(M8,{post:n})},n.id))})]})}function ble({message:t}){return d.jsxs("div",{className:"page-not-found container",children:[d.jsx("h1",{children:"404"}),d.jsx("p",{children:t??"The page you are looking for does not exist."}),d.jsx("a",{href:"/index.html",children:"Back to home"})]})}const xj='@charset "UTF-8";@import"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Newsreader:ital,wght@0,300;0,400;0,500;0,600;0,700;1,400;1,700&display=swap";:root{--color-bg: #fbf9f9;--color-surface: #ffffff;--color-surface-low: #f5f3f3;--color-surface-mid: #efeded;--color-surface-high: #e9e8e7;--color-surface-highest: #e3e2e2;--color-on-surface: #1b1c1c;--color-on-surface-variant: #444748;--color-on-surface-muted: #868382;--color-outline: #747878;--color-outline-variant: #c4c7c7;--color-primary: #000000;--color-on-primary: #ffffff;--color-secondary: #476558;--color-secondary-container: #c9ead9;--color-on-secondary-container: #4d6b5d;--font-serif: "Newsreader", Georgia, "Times New Roman", serif;--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--weight-display: 600;--weight-heading: 500;--weight-body: 400;--weight-meta: 600;--weight-emphasis: 700;--weight-lede: 300;--container-max: 1120px;--gutter: 24px;--section-gap: 80px;--radius-sm: .125rem;--radius: .25rem;--radius-lg: .5rem;--radius-xl: .75rem}*,*:before,*:after{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;font-family:var(--font-sans);font-size:16px;line-height:1.6;color:var(--color-on-surface);background:var(--color-bg);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}::-moz-selection{background:var(--color-secondary-container)}::selection{background:var(--color-secondary-container)}img,picture,video,svg{display:block;max-width:100%}button{font-family:inherit;cursor:pointer;background:none;border:none;padding:0;color:inherit}a{color:inherit}h1,h2,h3,h4,h5,h6{font-family:var(--font-serif);margin:0;color:var(--color-on-surface)}p,ul,ol{margin:0}.container{width:100%;max-width:var(--container-max);margin:0 auto;padding:0 20px}@media(min-width:768px){.container{padding:0 40px}}.label-caps{font-family:var(--font-sans);font-size:12px;line-height:1;font-weight:var(--weight-meta);letter-spacing:.05em;text-transform:uppercase;color:var(--color-on-surface-muted)}.site-header{position:sticky;top:0;z-index:50;background:#fbf9f9d9;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border-bottom:1px solid var(--color-surface-highest)}.site-header__inner{position:relative;display:flex;align-items:center;justify-content:space-between;height:64px}.site-brand{font-family:var(--font-serif);font-style:italic;font-size:22px;font-weight:var(--weight-emphasis);letter-spacing:-.02em;text-decoration:none;color:var(--color-on-surface);position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);white-space:nowrap;display:inline-flex;align-items:center}.site-brand__logo{display:block;height:36px;width:auto;max-width:min(240px,60vw);-o-object-fit:contain;object-fit:contain}.burger-toggle{display:inline-flex;align-items:center;justify-content:center;padding:8px;margin-left:-8px;border-radius:var(--radius);transition:opacity .2s ease}.burger-toggle:hover{opacity:.7}.burger-toggle svg{width:24px;height:24px}.burger-menu{position:fixed;inset:0 auto 0 0;width:min(360px,88vw);background:var(--color-bg);z-index:60;padding:64px 32px 32px;transform:translate(-100%);transition:transform .3s ease;overflow-y:auto;box-shadow:4px 0 24px #00000014}.burger-menu.is-open{transform:translate(0)}.burger-menu ul{list-style:none;padding:0;display:flex;flex-direction:column;gap:24px;margin-top:24px}.burger-menu li{margin:0}.burger-menu a{display:block;font-family:var(--font-serif);font-size:22px;font-weight:var(--weight-body);color:var(--color-on-surface-muted);text-decoration:none;padding-left:16px;border-left:4px solid transparent;transition:color .2s ease,border-color .2s ease}.burger-menu a:hover{color:var(--color-on-surface)}.burger-menu a[aria-current=page]{color:var(--color-on-surface);font-weight:var(--weight-meta);border-left-color:var(--color-on-surface)}.burger-close{position:absolute;top:16px;right:16px;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--radius);color:var(--color-on-surface);transition:opacity .2s ease}.burger-close:hover{opacity:.7}.burger-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#0006;z-index:55;opacity:0;pointer-events:none;transition:opacity .3s ease}.burger-backdrop.is-open{opacity:1;pointer-events:auto}body.burger-open{overflow:hidden}.site-footer{margin-top:var(--section-gap);border-top:1px solid var(--color-surface-highest);background:var(--color-surface-low);padding:56px 0}.site-footer__inner{display:flex;flex-direction:column;align-items:center;text-align:center;gap:24px}@media(min-width:768px){.site-footer__inner{flex-direction:row;justify-content:space-between;text-align:left}}.site-footer__brand{font-family:var(--font-serif);font-style:italic;font-size:18px;font-weight:var(--weight-emphasis);letter-spacing:-.02em;margin:0}.site-footer__nav ul{list-style:none;padding:0;display:flex;flex-wrap:wrap;gap:24px;justify-content:center}.site-footer__nav a{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);text-decoration:none;transition:color .2s ease}.site-footer__nav a:hover{color:var(--color-on-surface)}.site-footer__copy{font-family:var(--font-sans);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:0}.site-main{display:block;min-height:60vh;padding-bottom:var(--section-gap)}.card-post{display:flex;flex-direction:column;background:var(--color-surface-low);border:1px solid var(--color-outline-variant);overflow:hidden;height:100%}.card-post__link{display:flex;flex-direction:column;flex:1;text-decoration:none;color:inherit}.card-post__media{aspect-ratio:16/9;background:var(--color-surface-high);overflow:hidden}.card-post__media img{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;transition:transform .5s ease}.card-post:hover .card-post__media img{transform:scale(1.03)}.card-post__body{display:flex;flex-direction:column;flex:1;padding:20px}.card-post__eyebrow{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 12px}.card-post__title{font-family:var(--font-serif);font-size:22px;line-height:1.3;font-weight:var(--weight-heading);margin:0 0 12px;transition:color .2s ease}.card-post:hover .card-post__title{color:var(--color-secondary)}.card-post__excerpt{font-size:15px;line-height:1.6;color:var(--color-on-surface-variant);margin:0 0 16px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.card-post__meta{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:auto 0 0}.hero-featured{margin-top:48px}@media(min-width:768px){.hero-featured{margin-top:80px}}.hero-featured__link{text-decoration:none;color:inherit;display:block}.hero-featured__media{aspect-ratio:21/9;background:var(--color-surface-high);overflow:hidden;border-radius:var(--radius)}.hero-featured__media img{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;transition:transform .7s ease}.hero-featured__link:hover .hero-featured__media img{transform:scale(1.03)}.hero-featured__body{margin-top:32px;max-width:720px}.hero-featured__pill{display:inline-block;background:var(--color-secondary-container);color:var(--color-on-secondary-container);padding:6px 12px;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;border-radius:var(--radius);margin-bottom:16px}.hero-featured__title{font-family:var(--font-serif);font-size:clamp(32px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 16px}.hero-featured__excerpt{font-size:18px;line-height:1.7;color:var(--color-on-surface-variant);margin:0 0 24px;max-width:600px}.hero-featured__date{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted)}.page-home__title-row{display:flex;align-items:center;justify-content:space-between;margin-top:var(--section-gap);margin-bottom:32px;padding-bottom:16px;border-bottom:1px solid var(--color-surface-highest)}.page-home__title{font-family:var(--font-serif);font-size:22px;font-weight:var(--weight-heading);letter-spacing:.04em;text-transform:uppercase;margin:0}.post-grid{list-style:none;padding:0;display:grid;grid-template-columns:1fr;gap:48px 32px}@media(min-width:768px){.post-grid{grid-template-columns:repeat(2,1fr)}}@media(min-width:1024px){.post-grid{grid-template-columns:repeat(3,1fr)}}.post-grid li{list-style:none}.page-single{padding-top:48px;display:grid;grid-template-columns:minmax(0,1fr);gap:64px}@media(min-width:1024px){.page-single{padding-top:80px;grid-template-columns:minmax(0,8fr) minmax(0,4fr);-moz-column-gap:64px;column-gap:64px}}.page-static{padding-top:48px;padding-bottom:96px}@media(min-width:1024px){.page-static{padding-top:80px}}.page-single__main{min-width:0}.page-single__meta-strip{display:flex;align-items:center;flex-wrap:wrap;gap:12px 16px;margin-bottom:40px}.page-single__meta-strip .label-caps{color:var(--color-secondary)}.page-single__meta-dot{width:4px;height:4px;border-radius:50%;background:var(--color-outline-variant);flex-shrink:0}.page-single__title{font-family:var(--font-serif);font-size:clamp(32px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 32px}.page-single__lede{font-family:var(--font-serif);font-style:italic;font-size:clamp(20px,2.5vw,24px);line-height:1.5;font-weight:var(--weight-lede);color:var(--color-on-surface-variant);margin:0 0 40px}.page-single__author-strip{display:flex;align-items:center;gap:16px;padding-bottom:32px;margin-bottom:48px;border-bottom:1px solid var(--color-surface-highest)}.page-single__author-name{font-family:var(--font-sans);font-size:14px;font-weight:var(--weight-emphasis);margin:0;color:var(--color-on-surface)}.page-single__author-meta{font-family:var(--font-sans);font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:4px 0 0}.page-single__hero{margin:0 0 48px;border-radius:var(--radius-lg);overflow:hidden;background:var(--color-surface-high)}.page-single__hero img{aspect-ratio:16/9;width:100%;height:auto;-o-object-fit:cover;object-fit:cover}.page-single__hero figcaption{font-family:var(--font-sans);font-size:12px;color:var(--color-on-surface-muted);padding:8px 16px}.page-single__tags{list-style:none;margin:64px 0 0;padding:32px 0 0;border-top:1px solid var(--color-surface-highest);display:flex;flex-wrap:wrap;gap:8px}.page-single__tags li{background:var(--color-surface-low);color:var(--color-on-surface-muted);padding:8px 16px;border-radius:999px;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.05em;text-transform:uppercase}.page-single__sidebar{display:flex;flex-direction:column;gap:48px}.page-body{font-family:var(--font-serif);font-size:18px;line-height:1.8;color:var(--color-on-surface)}.page-body>p:first-of-type:first-letter{float:left;font-size:5rem;line-height:4rem;padding-right:12px;padding-top:4px;font-family:var(--font-serif);font-weight:var(--weight-emphasis)}.page-body p{margin:0 0 28px}.page-body strong,.page-body b{font-weight:var(--weight-emphasis)}.page-body h2{font-size:32px;margin:56px 0 16px;font-weight:var(--weight-display);letter-spacing:-.01em}.page-body h3{font-size:24px;margin:40px 0 12px;font-weight:var(--weight-heading)}.page-body blockquote{border-left:2px solid var(--color-primary);padding-left:24px;margin:48px 0;font-family:var(--font-serif);font-style:italic;font-size:clamp(22px,2.5vw,28px);font-weight:var(--weight-lede);line-height:1.5;color:var(--color-on-surface-variant)}.page-body blockquote p{margin:0 0 12px}.page-body img{width:100%;border-radius:var(--radius)}.page-body a{color:var(--color-secondary);text-decoration:underline;text-underline-offset:.2em}.page-body code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,monospace;background:var(--color-surface-mid);padding:.1em .4em;border-radius:3px;font-size:.85em}.page-body pre{background:var(--color-surface-mid);border-radius:var(--radius);padding:16px 20px;overflow-x:auto;margin:32px 0;font-size:14px;line-height:1.6}.page-body pre code{background:transparent;padding:0;font-size:inherit}.page-body ul,.page-body ol{padding-left:28px;margin:0 0 28px}.page-body li{margin:8px 0}.page-body hr{border:none;border-top:1px solid var(--color-surface-highest);margin:48px 0}.author-bio{background:var(--color-surface-low);padding:32px;border-radius:var(--radius-lg);border:1px solid var(--color-surface-highest)}.author-bio__eyebrow{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface);margin:0 0 24px}.author-bio__head{display:flex;align-items:flex-start;gap:16px}.author-bio__name{font-family:var(--font-serif);font-size:20px;font-weight:var(--weight-emphasis);margin:0;color:var(--color-on-surface);text-decoration:none;display:inline-block}a.author-bio__name:hover{color:var(--color-secondary);text-decoration:underline;text-underline-offset:.2em}.author-bio__role{font-family:var(--font-sans);font-size:13px;font-style:italic;color:var(--color-on-surface-muted);margin:4px 0 0}.author-bio__bio{font-family:var(--font-sans);font-size:14px;line-height:1.6;color:var(--color-on-surface-variant);margin:24px 0 0}.author-bio__socials{display:flex;gap:12px;margin:16px 0 0}.author-bio__social-link{display:inline-flex;align-items:center;justify-content:center;color:var(--color-on-surface-variant);line-height:0;transition:color .15s ease}.author-bio__social-link:hover{color:var(--color-primary)}.author-bio__social-link svg{width:18px;height:18px}.author-avatar{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;background:var(--color-on-surface);color:var(--color-bg);font-family:var(--font-sans);font-size:13px;font-weight:var(--weight-emphasis);letter-spacing:.02em;text-transform:uppercase}.author-avatar--lg{width:56px;height:56px;font-size:16px}.author-avatar--xl{width:100%;max-width:280px;aspect-ratio:3/4;height:auto;border-radius:var(--radius-lg);font-size:clamp(48px,8vw,72px);font-weight:var(--weight-display)}.author-avatar--image{background:var(--color-surface-high);-o-object-fit:cover;object-fit:cover;display:block;color:transparent}.related-posts__title{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface);margin:0 0 24px;padding-bottom:16px;border-bottom:1px solid var(--color-surface-highest)}.related-posts__list{list-style:none;padding:0;display:flex;flex-direction:column;gap:28px}.related-posts__item a{display:block;color:inherit;text-decoration:none}.related-posts__eyebrow{font-family:var(--font-sans);font-size:10px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 6px}.related-posts__title-line{font-family:var(--font-serif);font-size:17px;font-weight:var(--weight-emphasis);line-height:1.3;margin:0 0 6px;transition:color .2s ease}.related-posts__item a:hover .related-posts__title-line{color:var(--color-secondary)}.related-posts__date{font-family:var(--font-sans);font-size:10px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:0}.page-archive{padding-top:64px}.page-archive__header{display:flex;flex-direction:column;gap:32px;padding-bottom:48px;border-bottom:1px solid var(--color-surface-highest);margin-bottom:64px}@media(min-width:768px){.page-archive__header{flex-direction:row;align-items:flex-end;justify-content:space-between}}.page-archive__head{max-width:720px}.page-archive__eyebrow{font-family:var(--font-sans);font-size:12px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 16px}.page-archive__title{font-family:var(--font-serif);font-size:clamp(36px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 16px}.page-archive__desc{font-size:18px;line-height:1.7;color:var(--color-on-surface-variant);margin:0;max-width:56ch}.page-archive__rss{display:inline-flex;align-items:center;gap:8px;padding:10px 24px;border:1px solid var(--color-primary);background:transparent;color:var(--color-on-surface);font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;border-radius:var(--radius);text-decoration:none;transition:background .2s ease,color .2s ease;align-self:flex-start}.page-archive__rss:hover{background:var(--color-primary);color:var(--color-on-primary)}.page-archive__rss svg{width:16px;height:16px}.page-author{padding-top:64px}.page-author__hero{display:flex;flex-direction:column;gap:48px;padding-bottom:64px;border-bottom:1px solid var(--color-surface-highest);margin-bottom:64px}@media(min-width:768px){.page-author__hero{flex-direction:row;align-items:center;gap:96px}}.page-author__portrait{flex-shrink:0;width:100%;max-width:280px}.page-author__body{display:flex;flex-direction:column;justify-content:center}.page-author__eyebrow{font-family:var(--font-sans);font-size:12px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 16px}.page-author__title{font-family:var(--font-serif);font-size:clamp(36px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 12px}.page-author__role{font-family:var(--font-sans);font-size:13px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 16px}.page-author__bio{font-size:18px;line-height:1.7;color:var(--color-on-surface-variant);margin:0}.page-author__socials{display:flex;gap:16px;margin:24px 0 0}.page-author__social-link{display:inline-flex;align-items:center;justify-content:center;color:var(--color-on-surface-variant);line-height:0;transition:color .15s ease}.page-author__social-link:hover{color:var(--color-primary)}.page-author__social-link svg{width:20px;height:20px}.empty-state{text-align:center;padding:80px 0;color:var(--color-on-surface-muted);font-style:italic}.page-static{padding-top:64px}.page-static .page-title,.page-title{font-family:var(--font-serif);font-size:clamp(36px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 32px}.breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:0 0 32px;padding:0;list-style:none}.breadcrumb li{display:inline-flex;align-items:center;gap:8px}.breadcrumb a{color:var(--color-on-surface-muted);text-decoration:none;transition:color .2s ease}.breadcrumb a:hover{color:var(--color-on-surface)}.breadcrumb__sep{color:var(--color-outline-variant)}.breadcrumb__current{color:var(--color-on-surface);display:inline-block;max-width:min(420px,60vw);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.pagination{display:flex;align-items:center;justify-content:space-between;margin-top:var(--section-gap);padding-top:48px;border-top:1px solid var(--color-surface-highest)}.pagination__pages{display:none;gap:12px}@media(min-width:768px){.pagination__pages{display:flex}}.pagination a,.pagination span{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);text-decoration:none;transition:color .2s ease}.pagination a:hover{color:var(--color-on-surface)}.pagination__pages a,.pagination__pages span{width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;border-radius:50%}.pagination__pages a.is-active{background:var(--color-primary);color:var(--color-on-primary)}.page-not-found{display:flex;flex-direction:column;align-items:center;text-align:center;padding:120px 20px}.page-not-found h1{font-family:var(--font-serif);font-size:clamp(72px,12vw,120px);font-weight:var(--weight-display);margin:0 0 24px;letter-spacing:-.04em;line-height:1}.page-not-found p{font-size:18px;color:var(--color-on-surface-variant);max-width:420px;margin:0 0 32px}.page-not-found a{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface);border-bottom:2px solid var(--color-primary);text-decoration:none;padding-bottom:4px;transition:color .2s ease,border-color .2s ease}.page-not-found a:hover{color:var(--color-secondary);border-color:var(--color-secondary)}.cms-hero a,.cms-card a,.cms-cta a,.cms-categories a,.cms-list-block a,.cms-list-header a,.card-post a{text-decoration:none}.cms-hero{position:relative;display:flex;overflow:hidden;width:100%;margin:32px 0;background:var(--color-bg)}.cms-hero .cms-hero-image-wrap{background:var(--color-surface-mid);overflow:hidden}.cms-hero .cms-hero-image-wrap a{display:block;width:100%;height:100%}.cms-hero .cms-hero-image{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;display:block}.cms-hero .cms-hero-content{padding:32px;flex:1;display:flex;flex-direction:column;justify-content:center;min-width:0}.cms-hero .cms-hero-category{display:inline-block;align-self:flex-start;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;background:var(--color-secondary-container);color:var(--color-on-surface);padding:4px 10px;margin:0 0 16px;text-decoration:none;transition:opacity .2s ease}.cms-hero .cms-hero-category:hover{opacity:.85}.cms-hero .cms-hero-title{font-family:var(--font-serif);font-size:clamp(26px,4.5vw,40px);font-weight:var(--weight-display);line-height:1.15;letter-spacing:-.02em;margin:0 0 20px}.cms-hero .cms-hero-title a{color:inherit;text-decoration:none;transition:color .2s ease}.cms-hero .cms-hero-title a:hover{color:var(--color-secondary)}.cms-hero .cms-hero-excerpt{font-family:var(--font-sans);font-size:16px;line-height:1.6;color:var(--color-on-surface-variant);margin:0 0 20px;max-width:60ch}.cms-hero-image-overlay{min-height:320px;align-items:flex-end}.cms-hero-image-overlay .cms-hero-image-wrap{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1}.cms-hero-image-overlay:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to top,#000000d9,#0003 60%,#0000);z-index:2;pointer-events:none}.cms-hero-image-overlay .cms-hero-content{position:relative;z-index:3;width:100%;color:#fff;padding:32px}.cms-hero-image-overlay .cms-hero-title a{color:#fff}.cms-hero-image-overlay .cms-hero-title a:hover{color:var(--color-secondary-container)}.cms-hero-image-overlay .cms-hero-excerpt{color:#ffffffd9}@media(min-width:768px){.cms-hero-image-overlay{min-height:480px}.cms-hero-image-overlay .cms-hero-content{padding:48px}}.cms-hero-split-left,.cms-hero-split-right{background:var(--color-surface-low);border:1px solid var(--color-outline-variant);flex-direction:column}.cms-hero-split-left .cms-hero-image-wrap,.cms-hero-split-right .cms-hero-image-wrap{width:100%;height:240px;flex-shrink:0}@media(min-width:768px){.cms-hero-split-left,.cms-hero-split-right{flex-direction:row;min-height:360px}.cms-hero-split-left .cms-hero-image-wrap,.cms-hero-split-right .cms-hero-image-wrap{flex:0 0 50%;height:auto}.cms-hero-split-right{flex-direction:row-reverse}}.cms-hero-minimal{flex-direction:column;text-align:center;align-items:center;padding:48px 16px;border-bottom:2px solid var(--color-on-surface)}.cms-hero-minimal .cms-hero-content{max-width:720px;align-items:center;padding:0}.cms-hero-minimal .cms-hero-category{align-self:center}.cms-hero-minimal .cms-hero-title{font-size:clamp(32px,6vw,56px)}@media(min-width:768px){.cms-hero-minimal{padding:80px 24px}}.cms-list-block{margin:48px 0}.cms-list-header{display:flex;align-items:center;justify-content:space-between;gap:16px;border-bottom:1px solid var(--color-outline-variant);padding-bottom:12px;margin-bottom:24px}.cms-list-title{font-family:var(--font-serif);font-size:20px;font-weight:var(--weight-heading);text-transform:uppercase;letter-spacing:.05em;margin:0}.cms-list-see-more{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-variant);text-decoration:none}.cms-list-see-more:hover{color:var(--color-primary)}.cms-list-cards{display:grid;grid-template-columns:1fr;gap:32px}@media(min-width:768px){.cms-list-cards.cms-list-cols-2{grid-template-columns:repeat(2,1fr)}.cms-list-cards.cms-list-cols-3{grid-template-columns:repeat(3,1fr)}.cms-list-cards.cms-list-cols-4{grid-template-columns:repeat(4,1fr)}}.cms-list-list{display:flex;flex-direction:column;gap:24px}.cms-list-compact{display:flex;flex-direction:column;gap:8px}.cms-list-numbered{display:flex;flex-direction:column;gap:16px}.cms-list-slider{display:flex;gap:16px;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:8px;-webkit-overflow-scrolling:touch;scrollbar-width:thin}.cms-list-slider>.cms-card{scroll-snap-align:start;flex:0 0 240px}@media(min-width:768px){.cms-list-slider>.cms-card{flex:0 0 280px}}.cms-card-slider{position:relative;display:block;overflow:hidden;aspect-ratio:4/5;background:var(--color-on-surface);color:#fff;text-decoration:none}.cms-card-slider-image-wrap{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1}.cms-card-slider-image{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;display:block;transition:transform .5s ease}.cms-card-slider:hover .cms-card-slider-image{transform:scale(1.05)}.cms-card-slider:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to top,#000000d9,#0000004d 55%,#0000);z-index:2;pointer-events:none}.cms-card-slider-no-image:after{display:none}.cms-card-slider-overlay{position:absolute;inset:auto 0 0 0;z-index:3;padding:16px;display:flex;flex-direction:column;gap:6px}.cms-card-slider-overlay .cms-card-category{align-self:flex-start;margin:0}.cms-card-slider-overlay .cms-card-title{color:#fff;font-size:16px;line-height:1.25;margin:0}.cms-card-slider-overlay .cms-card-meta{color:#ffffffd9}.cms-card{display:block;text-decoration:none;color:inherit}.cms-card-image-wrap{aspect-ratio:16/9;background:var(--color-surface-mid);overflow:hidden}.cms-card-image{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;display:block;transition:transform .4s ease}.cms-card:hover .cms-card-image{transform:scale(1.03)}.cms-card-category{display:inline-block;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin-bottom:6px}.cms-card-title{font-family:var(--font-serif);font-size:20px;font-weight:var(--weight-display);line-height:1.3;margin:0 0 8px;color:var(--color-on-surface);transition:color .2s ease}.cms-card:hover .cms-card-title{color:var(--color-secondary)}.cms-card-excerpt{font-family:var(--font-sans);font-size:15px;line-height:1.6;color:var(--color-on-surface-variant);margin:0 0 8px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.cms-card-meta{display:inline-block;font-family:var(--font-sans);font-size:11px;letter-spacing:.05em;color:var(--color-on-surface-muted)}.cms-card-default{display:flex;flex-direction:column;background:var(--color-surface-low);border:1px solid var(--color-outline-variant);overflow:hidden;height:100%}.cms-card-body{display:flex;flex-direction:column;flex:1;padding:20px}.cms-card-body .cms-card-meta{margin-top:auto;padding-top:8px}.cms-card-compact{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding:8px 0;border-bottom:1px solid var(--color-outline-variant)}.cms-card-compact .cms-card-title{font-size:16px;font-weight:var(--weight-display);margin:0;flex:1;font-family:var(--font-sans)}.cms-card-numbered{display:grid;grid-template-columns:auto 1fr;-moz-column-gap:16px;column-gap:16px;row-gap:2px;align-items:start}.cms-card-number{font-family:var(--font-serif);font-style:italic;font-size:32px;font-weight:700;color:var(--color-outline-variant);line-height:1}.cms-card-numbered .cms-card-title{font-size:16px;font-family:var(--font-sans);font-weight:var(--weight-display);line-height:1.3;margin:0}.cms-card-numbered .cms-card-meta{grid-column:2;display:block}.cms-card-list{display:block;padding-bottom:24px;border-bottom:1px solid var(--color-outline-variant)}.cms-card-list:last-child{border-bottom:none}.cms-card-list-with-image{display:flex;gap:16px;align-items:flex-start}.cms-card-list-with-image .cms-card-list-image-wrap{flex:0 0 120px;aspect-ratio:1;background:var(--color-surface-mid);overflow:hidden}.cms-card-list-with-image .cms-card-list-image{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;display:block;transition:transform .4s ease}.cms-card-list-with-image:hover .cms-card-list-image{transform:scale(1.03)}.cms-card-list-with-image .cms-card-list-body{flex:1;min-width:0;display:flex;flex-direction:column}@media(max-width:480px){.cms-card-list-with-image{gap:12px}.cms-card-list-with-image .cms-card-list-image-wrap{flex:0 0 84px}}.cms-card-list .cms-card-title,.cms-card-list .cms-card-excerpt{margin-bottom:2px}.cms-cta{display:flex;flex-direction:column;gap:16px;padding:32px;margin:32px 0}.cms-cta-light{background:var(--color-surface-mid);color:var(--color-on-surface)}.cms-cta-dark{background:var(--color-primary);color:var(--color-on-primary)}.cms-cta-title{font-family:var(--font-serif);font-size:24px;font-weight:var(--weight-heading);line-height:1.3;margin:0}.cms-cta-description{font-family:var(--font-sans);font-size:15px;line-height:1.6;margin:0;opacity:.85}.cms-cta-button{display:inline-block;align-self:flex-start;font-family:var(--font-sans);font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;border-bottom:2px solid currentColor;padding-bottom:4px;text-decoration:none;color:inherit;margin-top:8px;transition:opacity .2s ease}.cms-cta-button:hover{opacity:.7}@media(min-width:768px){.cms-cta{padding:40px}}.cms-categories{margin:32px 0}.cms-categories-title{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;border-bottom:1px solid var(--color-outline-variant);padding-bottom:12px;margin:0 0 16px}.cms-categories-items{display:flex;flex-wrap:wrap;gap:8px}.cms-categories-pill{display:inline-block;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;padding:8px 16px;border:1px solid var(--color-outline-variant);border-radius:9999px;text-decoration:none;color:var(--color-on-surface);transition:background .2s ease,color .2s ease}.cms-categories-pill:hover{background:var(--color-primary);color:var(--color-on-primary)}.cms-categories-list .cms-categories-items{flex-direction:column;gap:4px}.cms-categories-list .cms-categories-pill{border:none;border-radius:0;padding:4px 0;text-transform:none;letter-spacing:0;font-size:14px}.cms-spacer{display:block}.cms-spacer-sm{height:24px}.cms-spacer-md{height:48px}.cms-spacer-lg{height:96px}.cms-spacer-divider{position:relative}.cms-spacer-divider:before{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:64px;height:1px;background:var(--color-outline-variant)}.archives{max-width:var(--container-max);margin:0 auto;padding:var(--section-gap, 4rem) var(--gutter, 1rem)}.archives__header{margin-bottom:2.5rem}.archives__back{margin:0 0 .75rem;font-size:.875rem}.archives__back a{color:var(--color-on-surface-variant);text-decoration:none}.archives__back a:hover{color:var(--color-on-surface);text-decoration:underline}.archives__title{font-family:var(--font-serif);font-weight:var(--weight-display);font-size:clamp(2rem,4vw,3rem);line-height:1.1;margin:0 0 .5rem;color:var(--color-on-surface)}.archives__subtitle{margin:0;color:var(--color-on-surface-variant);font-size:1rem}.archives__empty{color:var(--color-on-surface-muted);font-style:italic}.archives__years{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2rem}.archives__year{border-top:1px solid var(--color-outline-variant);padding-top:1.5rem}.archives__year:first-child{border-top:0;padding-top:0}.archives__year-heading{font-family:var(--font-serif);font-weight:var(--weight-heading);font-size:1.75rem;margin:0 0 .75rem;display:flex;align-items:baseline;gap:.5rem}.archives__year-link,.archives__group-link,.archives__drilldown-link,.archives__item-link{color:var(--color-on-surface);text-decoration:none;border-bottom:1px solid transparent;transition:border-color .15s}.archives__year-link:hover,.archives__group-link:hover,.archives__drilldown-link:hover,.archives__item-link:hover{border-bottom-color:currentColor}.archives__count{color:var(--color-on-surface-muted);font-size:.875rem;font-weight:400}.archives__drilldown{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:.5rem 1rem}.archives__drilldown-item{display:inline-flex;align-items:baseline;gap:.35rem;font-size:.95rem}.archives__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}.archives__item{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;padding:.5rem 0;border-bottom:1px solid var(--color-outline-variant)}.archives__item:last-child{border-bottom:0}.archives__item-link{flex:1;font-size:1rem}.archives__item-date{color:var(--color-on-surface-muted);font-size:.85rem;white-space:nowrap}.archives__groups{display:flex;flex-direction:column;gap:2.5rem}.archives__group-heading{font-family:var(--font-serif);font-weight:var(--weight-heading);font-size:1.25rem;margin:0 0 .75rem;display:flex;align-items:baseline;gap:.5rem}.archives-link{margin:3rem 0 0;text-align:right;font-size:.95rem}.archives-link a{color:var(--color-secondary);text-decoration:none;border-bottom:1px solid currentColor;padding-bottom:.1rem}.archives-link a:hover{color:var(--color-on-surface)}',yle=`/**
|
|
3890
|
+
`);let k=await Qp(cT.encode(`AWS4${m}`),r);k=await Qp(k,g),k=await Qp(k,y),k=await Qp(k,"aws4_request");const C=a8(await Qp(k,v));return{...s,Authorization:`AWS4-HMAC-SHA256 Credential=${p}/${x}, SignedHeaders=${l}, Signature=${C}`}}const iy="UNSIGNED-PAYLOAD";function ay(t){return t.split("/").map(Vv).join("/")}function mj(t){return t.replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&")}function uoe(t){const e=(t.endpoint||`https://s3.${t.region}.amazonaws.com`).replace(/\/+$/,"");let n;try{n=new URL(e)}catch{throw new Ns(`Invalid S3 endpoint: ${e}`,400)}const s=t.forcePathStyle??!n.hostname.endsWith("amazonaws.com")?`${e}/${Vv(t.bucket)}`:`${n.protocol}//${t.bucket}.${n.host}`,i=(t.prefix??"").replace(/^\/+|\/+$/g,""),a=(t.siteUrl??"").replace(/\/+$/,""),o={accessKeyId:t.accessKeyId,secretAccessKey:t.secretAccessKey,region:t.region||"us-east-1",service:"s3"},l=g=>i?`${i}/${g.replace(/^\/+/,"")}`:g.replace(/^\/+/,""),c=g=>i?g.slice(i.length+1):g;async function h(g,y,x,v={}){const k=await pj({method:y,url:x,headers:{"x-amz-content-sha256":iy,...v.headers??{}},payloadHash:iy,credentials:o});return Hs(g,()=>fetch(x,{method:y,headers:k,body:v.body,signal:v.signal,cache:v.cache}))}async function p(g){var v,k,C;const y=[];let x;do{const N=new URLSearchParams({"list-type":"2","max-keys":"1000"});g&&N.set("prefix",g),x&&N.set("continuation-token",x);const P=await(await h("list","GET",`${s}/?${N}`,{cache:"no-store"})).text();for(const I of P.match(/<Contents>[\s\S]*?<\/Contents>/g)??[]){const L=(v=I.match(/<Key>([\s\S]*?)<\/Key>/))==null?void 0:v[1],j=Number(((k=I.match(/<Size>(\d+)<\/Size>/))==null?void 0:k[1])??0);L&&y.push({key:mj(L),size:j})}x=/<IsTruncated>true<\/IsTruncated>/.test(P)?mj(((C=P.match(/<NextContinuationToken>([\s\S]*?)<\/NextContinuationToken>/))==null?void 0:C[1])??""):void 0}while(x);return y}async function m(g,y){try{await h("delete","DELETE",`${s}/${ay(g)}`,{signal:y})}catch(x){if(x instanceof Ns&&x.status===404)return;throw x}}return{id:"s3",model:"files",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0,storageLimits:!1},async put(g,y){const x=g.encoding==="base64"?rp(g.content):g.content;await h("upload","PUT",`${s}/${ay(l(g.path))}`,{headers:{"content-type":aoe(g.path),"cache-control":ooe(g.path),...t.publicRead?{"x-amz-acl":"public-read"}:{}},body:x,signal:y})},async get(g){return(await h("get","GET",`${s}/${ay(l(g))}`,{cache:"no-store"})).text()},async getBytes(g){const y=`${s}/${ay(l(g))}`,x=await pj({method:"GET",url:y,headers:{"x-amz-content-sha256":iy},payloadHash:iy,credentials:o}),v=await fetch(y,{headers:x,cache:"no-store"}).catch(C=>Hs("get",()=>Promise.reject(C)));if(v.status===404||v.status===403)return null;const k=v.ok?v:await Hs("get",async()=>v);return new Uint8Array(await k.arrayBuffer())},delete:(g,y)=>m(l(g),y),async deletePrefix(g){const y=await p(l(g).replace(/\/+$/,"")+"/");await XA(y,6,x=>m(x.key))},async list(g,y){const x=(await p(i?`${i}/`:"")).map(v=>({path:c(v.key),type:"file",size:v.size,url:`${a}/${c(v.key)}`}));return{items:x.slice((g-1)*y,g*y),page:g,per_page:y,total:x.length}},async publicUrl(g){return`${a}/${g.replace(/^\/+/,"")}`}}}const doe={id:"s3",create:uoe},hoe=i8.id,o8=new Map([i8,toe,doe,soe,Uae,roe].map(t=>[t.id,t]));function foe(t){return typeof t.create=="function"}function poe(t){o8.set(t.id,t),oi&&oi.id===t.id&&(oi=null)}function l8(){return ao($r())?"browser-mirror":hoe}function o1(t,e){const n=o8.get(t);if(!n)throw new Ns(jt.t("flexweg.errors.unknownConnector",{connector:t}),501);return foe(n)?n.create(e):n}let oi=null;async function moe(){let t=null;try{t=await sT()}catch(n){console.warn("[storage] could not read storage config, defaulting to Flexweg:",n)}const e=(t==null?void 0:t.connectorId)??l8();try{return o1(e,(t==null?void 0:t.settings)??{})}catch(n){throw at.error(n.message),n}}async function sl(){if(!oi){const t=moe();oi={id:"",connector:t},t.then(e=>{(oi==null?void 0:oi.connector)===t&&(oi.id=e.id)},()=>{(oi==null?void 0:oi.connector)===t&&(oi=null)})}return oi.connector}function goe(){oi=null}const boe=/^index\.[a-z0-9]+$/i;function A0(){if(typeof window>"u")return"";const e=window.location.pathname.split("/").filter(Boolean),n=e[e.length-1];return n&&boe.test(n)&&e.pop(),e.join("/")}function yoe(){if(typeof window>"u")return!1;const t=window.location.hostname;return t==="localhost"||t==="127.0.0.1"||t==="[::1]"||t==="::1"||t==="0.0.0.0"||t.endsWith(".localhost")}function voe(){return yoe()?!1:A0()===""}function c8(t){const e=A0(),n=t.replace(/^\/+/,"");return e?`${e}/${n}`:n}function u8(t){return t.replace(/\/+$/,"")}class uT extends Error{constructor(e,n){super(e),this.status=n,this.name="SetupApiError"}}async function d8(t,e){const n=u8(t.apiBaseUrl),r=await fetch(`${n}/files/storage-limits`,{method:"GET",headers:{"X-API-Key":t.apiKey},signal:e});if(!r.ok){const s=await r.text().catch(()=>"");throw new uT(s.length>0?s.slice(0,240):`HTTP ${r.status}`,r.status)}}async function xoe(t,e,n){const r=u8(t.apiBaseUrl),s=await fetch(`${r}/files/upload`,{method:"POST",headers:{"X-API-Key":t.apiKey,"Content-Type":"application/json"},body:JSON.stringify({path:c8("config.js"),content:e,encoding:"utf-8"}),signal:n});if(!s.ok){const i=await s.text().catch(()=>"");throw new uT(i.length>0?i.slice(0,240):`HTTP ${s.status}`,s.status)}}const ZS=".flexweg-cms-probe.txt",YS={flexweg:()=>["apiKey","siteUrl"],"git-pages":t=>[...t.provider==="gitlab"?["project"]:["owner","repo"],"branch","siteUrl"],s3:()=>["bucket","accessKeyId","secretAccessKey","siteUrl"],"php-bridge":()=>["apiBaseUrl","apiKey","siteUrl"]};function h8(t,e,n=[]){var s;return(((s=YS[t])==null?void 0:s.call(YS,e))??[]).filter(i=>!n.includes(i)).filter(i=>typeof e[i]!="string"||!e[i].trim())}async function l1(t,e,n={}){const r=h8(t,e,n.ignore);if(r.length)return{ok:!1,detail:`missing: ${r.join(", ")}`};try{if(t==="flexweg"){const a={apiKey:String(e.apiKey??"").trim(),siteUrl:String(e.siteUrl??"").trim(),apiBaseUrl:String(e.apiBaseUrl??"").trim()||"https://www.flexweg.com/api/v1"};return await d8(a),{ok:!0,detail:a.siteUrl}}if(t==="git-pages"){const a=e,o=lT(a),l=Af(a.provider==="github"?{provider:"github",owner:a.owner??"",repo:a.repo??"",branch:a.branch,token:o,apiBaseUrl:a.apiBaseUrl}:{provider:"gitlab",project:a.project??"",branch:a.branch,token:o,apiBaseUrl:a.apiBaseUrl}),c=await l.permissions();return c.canWrite?{ok:!0,detail:`${c.login} → ${l.label}`}:{ok:!1,detail:`${c.login}: read-only access`}}const s=o1(t,e);if(t==="browser-mirror")return{ok:!0,detail:"browser"};await s.put({path:ZS,content:`AgentCMS connection test ${new Date().toISOString()}
|
|
3891
|
+
`});const i=await s.get(ZS).catch(()=>null);return await s.delete(ZS),i===null?{ok:!1,detail:"write succeeded but read-back failed"}:{ok:!0,detail:await s.publicUrl("")}}catch(s){const i=s instanceof Ns?` (${s.status})`:"";return{ok:!1,detail:`${s.message}${i}`}}}const woe="1",koe=3,f8="flexweg.sqliteConnectorSecrets",gj="flexweg.sqliteDocSecrets",a_="flexweg.sqlitePassphrase";function p8(t,e){try{const n=window.localStorage.getItem(t);return n?JSON.parse(n):e}catch{return e}}function m8(t,e){try{window.localStorage.setItem(t,JSON.stringify(e))}catch{}}function g8(t){const{clean:e,secrets:n}=C0(t);return{publicSettings:e,secrets:n??{}}}function dT(t){m8(f8,t)}function wm(){try{return window.localStorage.getItem(a_)}catch{return null}}function qv(t){try{t?window.localStorage.setItem(a_,t):window.localStorage.removeItem(a_)}catch{}}async function b8(t,e){return WO(t)?{plain:await _ae(t,e),params:KO(t)}:{plain:t,params:null}}function o_(t){return{...t.settings,...p8(f8,{})}}let oy=null;function y8(){return oy||(oy=(async()=>{const{default:t}=await zv(async()=>{const{default:r}=await import("./sql-wasm-Bfkbn6Oa.js").then(s=>s.s);return{default:r}},[],import.meta.url);if(!(typeof window<"u"&&typeof document<"u"))return t(void 0);const{default:n}=await zv(async()=>{const{default:r}=await import("./sql-wasm-V5jTDcrT.js");return{default:r}},[],import.meta.url);return t({locateFile:()=>n})})().catch(t=>{throw oy=null,t})),oy}async function Soe(t){var r,s;const e=await y8(),n=new e.Database(t);try{const i=E0(),a=new Set((((r=n.exec("SELECT name FROM sqlite_master WHERE type = 'table'")[0])==null?void 0:r.values)??[]).map(o=>String(o[0])));for(const o of Tu)if(a.has(o))for(const[l,c]of((s=n.exec(`SELECT id, data FROM "${o}"`)[0])==null?void 0:s.values)??[])try{i[o].set(String(l),{...JSON.parse(String(c)),id:String(l)})}catch{console.warn(`[sqlite-file] skipping malformed row ${o}/${l}`)}return i}finally{n.close()}}async function Eoe(t){const e=await y8(),n=new e.Database;try{n.run("CREATE TABLE meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)"),n.run("INSERT INTO meta VALUES ('format', 'flexweg-cms'), ('version', ?), ('savedAt', ?)",[woe,new Date().toISOString()]),n.run("BEGIN");for(const r of Tu){n.run(`CREATE TABLE "${r}" (id TEXT PRIMARY KEY, data TEXT NOT NULL)`);const s=n.prepare(`INSERT INTO "${r}" (id, data) VALUES (?, ?)`);for(const i of t[r].values())s.run([i.id,JSON.stringify(i)]);s.free()}return n.run("COMMIT"),n.export()}finally{n.close()}}async function bj(t){if(!t)return"missing";const e=await crypto.subtle.digest("SHA-256",t);return[...new Uint8Array(e)].map(n=>n.toString(16).padStart(2,"0")).join("")}function _oe(t){const e=Object.fromEntries(Tu.map(r=>[r,new Map(t[r])])),n={};for(const r of t.config.values()){const s=C0(r);s.secrets&&(n[`config/${r.id}`]=s.secrets,e.config.set(r.id,s.clean))}return{clean:e,secrets:n}}function Coe(t,e){const n=Object.fromEntries(Tu.map(r=>[r,new Map(t[r])]));for(const r of e)r.op==="set"?n[r.collection].set(r.doc.id,r.doc):n[r.collection].delete(r.id);return n}function Aoe(t){let e=null,n=null,r=null,s=null,i=!!t.encrypted,a=!1;function o(){return n||(n=o1(t.connectorId,o_(t))),n}async function l(){const p=o();if(!p.getBytes)throw new Ns(jt.t("docstore.errors.sqliteUnsupported",{connector:t.connectorId}),501);const m=await p.getBytes(t.path);let g=E0();if(m){const y=await b8(m,wm());y.params&&(r=y.params),g=await Soe(y.plain)}return $O(g,p8(gj,{})),{snapshot:g,hash:await bj(m)}}async function c(p){const{clean:m,secrets:g}=_oe(p);m8(gj,g);const y=await Eoe(m),v=i||r!==null?await Eae(y,wm()??"",r??void 0):y;await o().put({path:t.path,content:JA(v),encoding:"base64"}),e=await bj(v)}const h=GA({kind:"sqlite-file",pollIntervalMs:6e4,async load(){const p=await l();return e=p.hash,a=!1,p.snapshot},async persist(p,m,g){let y=g;for(let x=0;;x++){const v=await l();if(e===null||v.hash===e){await c(y);return}for(const k of p){const C=k.op==="set"?k.doc.id:k.id,N=JSON.stringify(m[k.collection].get(C)??null),_=JSON.stringify(v.snapshot[k.collection].get(C)??null);if(N!==_)throw e=v.hash,a=!0,new e_(jt.t("docstore.errors.conflict"),k.collection,C)}if(x>=koe)throw new e_(jt.t("docstore.errors.conflict"),p[0].collection,"");e=v.hash,a=!0,y=Coe(v.snapshot,p)}},async poll(){const p=await l();return p.hash===e&&!a?null:(e=p.hash,a=!1,p.snapshot)},async identity(){if(h8(t.connectorId,o_(t),["siteUrl"]).length>0)return null;if(i&&!wm())return s="missing",null;try{await h.ready(),s=null}catch(p){if(p instanceof Pg)return s=p.reason,null}return{uid:"admin",email:"admin@localhost",displayName:"Admin",role:"admin"}}});return Object.assign(h,{passphraseProblem:()=>s,isEncrypted:()=>i||r!==null,async rekey(p){if(p.trim().length<12)throw new Error("The passphrase must be at least 12 characters long.");await h.ready();const m=await l(),g=wm();qv(p.trim());const y=r;r=null;try{i=!0,await c(m.snapshot),await l()}catch(x){throw qv(g),r=y,i=!!t.encrypted,x}},resetSession(){n=null,r=null,s=null,e=null,a=!1}})}let Ih=null;function Ct(){if(Ih)return Ih;const t=ra();if((t==null?void 0:t.backend)==="markdown-git")Ih=yae(t.git);else if((t==null?void 0:t.backend)==="sqlite-file")Ih=Aoe(t.sqlite);else if((t==null?void 0:t.backend)==="local")Ih=vae();else throw new Error("No document store for the active backend.");return Ih}function v8(t){if(t!=null){if(typeof t=="number")return t;if(t instanceof en)return t.toMillis();if(t instanceof Date)return t.getTime();if(typeof t=="string"){const e=Date.parse(t);return Number.isNaN(e)?void 0:e}return Date.now()}}function bd(t){const e=v8(t);return e===void 0?void 0:en.fromMillis(e)}function hT(){const t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";return[...crypto.getRandomValues(new Uint8Array(20))].map(n=>t[n%t.length]).join("")}const Pd="terms";function x8(t){if(!t||typeof t!="object")return!1;const e=t;return!!(e.title||e.description||e.ogImage)}function Toe(t){const e={id:t.id,type:t.type,name:t.name??"",slug:t.slug??"",createdAt:bd(t.createdAt??0),updatedAt:bd(t.updatedAt??t.createdAt??0)};return t.description&&(e.description=t.description),t.parentId&&(e.parentId=t.parentId),t.lastPublishedPath&&(e.lastPublishedPath=t.lastPublishedPath),t.translations&&typeof t.translations=="object"&&Object.keys(t.translations).length>0&&(e.translations=JSON.parse(JSON.stringify(t.translations))),x8(t.seo)&&(e.seo={...t.seo}),e}function Ioe(t,e){return t.name<e.name?-1:t.name>e.name?1:0}function w8(){return Ct().list(Pd).map(Toe).sort(Ioe)}function fT(t){return`${t.type==="tag"?"tag":"category"}: ${t.name||t.id}`}function Noe(t,e){let n=!1,r=null;const s=()=>{try{t(w8())}catch(i){e==null||e(i)}};try{const i=Ct();i.ready().then(()=>{n||(r=i.subscribe(a=>{a.has(Pd)&&s()}),s())},a=>{n||e==null||e(a)})}catch(i){e==null||e(i)}return()=>{n=!0,r==null||r()}}async function Poe(){return await Ct().ready(),w8()}async function Roe(t){const e=hT(),n=Date.now(),r={id:e,type:t.type,name:t.name,slug:t.slug,createdAt:n,updatedAt:n};t.description&&(r.description=t.description),t.parentId&&(r.parentId=t.parentId);const s=Ct();return await s.ready(),await s.write([{op:"set",collection:Pd,doc:r}],{message:`Create ${fT(r)}`}),e}async function joe(t,e){const n=Ct();await n.ready();const r=n.get(Pd,t);if(!r)throw new Error(`Term not found: ${t}`);const s={...r},i=(a,o,l)=>{o!==void 0&&(o===null||!l?delete s[a]:s[a]=o)};i("name",e.name,!0),i("slug",e.slug,!0),i("description",e.description,!!e.description),i("parentId",e.parentId,!!e.parentId),i("translations",e.translations,!!e.translations&&Object.keys(e.translations).length>0),i("seo",e.seo,x8(e.seo)),s.updatedAt=Date.now(),await n.write([{op:"set",collection:Pd,doc:s}],{message:`Update ${fT(s)}`})}async function Moe(t){const e=Ct();await e.ready();const n=e.get(Pd,t);n&&await e.write([{op:"delete",collection:Pd,id:t}],{message:`Delete ${fT(n)}`})}const Loe=Object.freeze(Object.defineProperty({__proto__:null,createTerm:Roe,deleteTerm:Moe,fetchAllTerms:Poe,subscribeToTerms:Noe,updateTerm:joe},Symbol.toStringTag,{value:"Module"}));let e2=null;function T0(){if(!e2){const t=$r();e2=t==="flexweg-sqlite"?jte:ao(t)?Loe:bte}return e2}function Doe(...t){return T0().subscribeToTerms(...t)}function pT(...t){return T0().fetchAllTerms(...t)}function Wv(...t){return T0().createTerm(...t)}function c1(...t){return T0().updateTerm(...t)}function k8(...t){return T0().deleteTerm(...t)}let km=null;function Foe(t){return t.replace(/^\/+|\/+$/g,"")}function S8(t,e){return t===e||t.startsWith(e+"/")}function mT(){return km}function Ooe(t,e){t.files.set(e.path,{type:"put",...e})}function zoe(t,e){t.files.set(e,{type:"delete",path:e})}function Uoe(t,e){const n=Foe(e);for(const r of[...t.files.keys()])S8(r,n)&&t.files.delete(r);t.prefixes.add(n)}function Boe(t,e){const n=t.files.get(e);if((n==null?void 0:n.type)==="put"){if(n.encoding!=="base64")return{kind:"content",content:n.content};const r=Uint8Array.from(atob(n.content),s=>s.charCodeAt(0));return{kind:"content",content:new TextDecoder().decode(r)}}if((n==null?void 0:n.type)==="delete")return{kind:"deleted"};for(const r of t.prefixes)if(S8(e,r))return{kind:"deleted"};return null}function E8(t){const e=[];for(const n of t.prefixes)e.push({type:"deletePrefix",path:n});for(const n of t.files.values())e.push(n);return e}const $oe=1500;let Ti=null;function Hoe(){Ti&&(Ti.timer&&clearTimeout(Ti.timer),Ti.timer=setTimeout(()=>void gT(),$oe))}function Voe(t){return(!Ti||Ti.connector!==t)&&(Ti={connector:t,depth:0,files:new Map,prefixes:new Set,timer:null,flushing:null}),Hoe(),Ti}function qoe(){return Ti}async function gT(){const t=Ti;if(!t)return;t.timer&&clearTimeout(t.timer),Ti=null;const e=E8(t);if(e.length!==0)try{await t.connector.commitBatch(e)}catch(n){console.error("[storage] deferred commit failed:",n)}}typeof window<"u"&&typeof window.addEventListener=="function"&&window.addEventListener("beforeunload",t=>{Ti&&(Ti.files.size>0||Ti.prefixes.size>0)&&(gT(),t.preventDefault())});async function ja(t){const e=await sl();if(!e.commitBatch)return t();await gT(),km||(km={connector:e,depth:0,files:new Map,prefixes:new Set});const n=km;n.depth++;let r=!1,s,i;try{i=await t()}catch(a){r=!0,s=a}if(n.depth--,n.depth===0){km=null;const a=E8(n);if(a.length>0)try{await n.connector.commitBatch(a)}catch(o){if(!r)throw o;console.error("[storage] batch commit failed after an earlier error:",o)}}if(r)throw s;return i}const Woe=/\.(webp|png|jpe?g|gif|avif|svg|ico)$/i,Goe={webp:"image/webp",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",avif:"image/avif",svg:"image/svg+xml",ico:"image/x-icon"},Gv=new Map;function Koe(t){return t.replace(/^\/+/,"")}function Joe(t,e){if(typeof URL>"u"||typeof URL.createObjectURL!="function")return;const n=Koe(t);if(Woe.test(n))try{const r=atob(e),s=new Uint8Array(r.length);for(let o=0;o<r.length;o++)s[o]=r.charCodeAt(o);const i=n.split(".").pop().toLowerCase(),a=Gv.get(n);a&&URL.revokeObjectURL(a),Gv.set(n,URL.createObjectURL(new Blob([s],{type:Goe[i]??"application/octet-stream"})))}catch{}}function Qoe(t){if(!t||Gv.size===0)return null;let e=t;try{e=new URL(t,"http://x").pathname}catch{}e=decodeURIComponent(e);for(const[n,r]of Gv)if(e===`/${n}`||e.endsWith(`/${n}`))return r;return null}async function _8(){const t=await sl();return{...t.capabilities,connectorId:t.id,model:t.model}}async function bT(){const t=mT();if(t)return{batch:t,connector:null};const e=await sl();return{batch:e.commitBatch?Voe(e):null,connector:e}}async function bn(t){const e={path:t.path,content:t.content,encoding:t.encoding};t.encoding==="base64"&&Joe(t.path,t.content);const{batch:n,connector:r}=await bT();if(n){Ooe(n,e);return}await r.put(e,t.signal)}function Xoe(t){return new Promise((e,n)=>{const r=new FileReader;r.onload=()=>{const s=r.result;if(typeof s!="string"){n(new Error("Unexpected FileReader result type"));return}const i=s.indexOf(",");e(i>=0?s.slice(i+1):s)},r.onerror=()=>n(r.error??new Error("Failed to read file")),r.readAsDataURL(t)})}async function il(t,e){const{batch:n,connector:r}=await bT();if(n){zoe(n,t);return}await r.delete(t,e)}async function Kv(t){for(const n of[mT(),qoe()]){if(!n)continue;const r=Boe(n,t);if((r==null?void 0:r.kind)==="content")return r.content;if((r==null?void 0:r.kind)==="deleted")throw new Ns(`File not found: ${t}`,404)}return(await sl()).get(t)}async function Zy(t,e){const n=await sl();if(n.rename&&!mT()){await n.rename(t,e);return}const r=await Kv(t);await bn({path:e,content:r}),await il(t)}async function C8(t=1,e=100){const n=await sl();if(!n.list)throw i1("list",n.id);return n.list(t,e)}async function Zoe(t){const e=await sl();!e.capabilities.folders||!e.createFolder||await e.createFolder(t)}async function Yoe(t,e){const n=await sl();if(!n.renameFolder)throw i1("renameFolder",n.id);await n.renameFolder(t,e)}async function A8(){const t=await sl();if(!t.storageLimits)throw i1("storageLimits",t.id);return t.storageLimits()}async function rh(t){const{batch:e,connector:n}=await bT();if(e){Uoe(e,t);return}const r=n;if(r.deletePrefix){await r.deletePrefix(t);return}if(!r.list)throw i1("deleteFolder",r.id);const s=t.replace(/^\/+|\/+$/g,"")+"/",i=100,a=[];for(let o=1;;o++){const l=await r.list(o,i);for(const c of l.items)c.type==="file"&&c.path.replace(/^\/+/,"").startsWith(s)&&a.push(c.path);if(l.items.length<i||l.total!==void 0&&o*i>=l.total)break}for(const o of a)await r.delete(o)}async function I0(t){return(await sl()).publicUrl(t)}const yT={"admin-thumb":{width:240,height:240,fit:"cover"},"admin-preview":{width:800,height:800,fit:"contain"},"admin-original":{width:2e3,height:2e3,fit:"contain",quality:90}},vT="admin-thumb",T8="admin-preview";function xT(t,e){const n=t.toLowerCase(),r=n.lastIndexOf("."),s=r>=0?n.slice(r):"",i=e.map(a=>a.startsWith(".")?a.toLowerCase():`.${a.toLowerCase()}`);return i.includes(s)?null:`Unsupported file type "${s}". Accepted: ${i.join(", ")}.`}function ele(t,e,n){const r=n.fit??"cover",s=n.width,i=n.height,a=t/e,o=s/i;if(r==="cover"){let p=t,m=e,g=0,y=0;return a>o?(p=e*o,g=(t-p)/2):(m=t/o,y=(e-m)/2),{canvasWidth:s,canvasHeight:i,srcX:g,srcY:y,srcWidth:p,srcHeight:m,drawWidth:s,drawHeight:i}}const l=Math.min(s/t,i/e,1),c=Math.round(t*l),h=Math.round(e*l);return{canvasWidth:c,canvasHeight:h,srcX:0,srcY:0,srcWidth:t,srcHeight:e,drawWidth:c,drawHeight:h}}function yj(t){return Number.isFinite(t)?Math.max(0,Math.min(1,t>1?t/100:t)):.8}async function wT(t,e){var r;const n=await createImageBitmap(t);try{const s=yj(e.quality),i=[];for(const[a,o]of Object.entries(e.formats)){const l=ele(n.width,n.height,o),c=tle(l.canvasWidth,l.canvasHeight),h=c.getContext("2d");if(!h)throw new Error("2D canvas context unavailable.");h.imageSmoothingEnabled=!0,h.imageSmoothingQuality="high",h.drawImage(n,l.srcX,l.srcY,l.srcWidth,l.srcHeight,0,0,l.drawWidth,l.drawHeight);const p=o.quality!==void 0?yj(o.quality):s,m=await nle(c,e.outputMime,p);if(!m)throw new Error(`Failed to encode variant "${a}".`);i.push({name:a,blob:m,width:l.canvasWidth,height:l.canvasHeight,bytes:m.size})}return i}finally{(r=n.close)==null||r.call(n)}}function tle(t,e){if(typeof OffscreenCanvas<"u")return new OffscreenCanvas(t,e);const n=document.createElement("canvas");return n.width=t,n.height=e,n}function nle(t,e,n){return"convertToBlob"in t?t.convertToBlob({type:e,quality:n}):new Promise(r=>t.toBlob(s=>r(s),e,n))}function kT(t){return new Promise((e,n)=>{const r=new FileReader;r.onload=()=>{const s=r.result;if(typeof s!="string"){n(new Error("Unexpected FileReader result type"));return}const i=s.indexOf(",");e(i>=0?s.slice(i+1):s)},r.onerror=()=>n(r.error??new Error("Failed to read blob")),r.readAsDataURL(t)})}function ST(t){switch(t){case"image/webp":return"webp";case"image/jpeg":return"jpg";case"image/png":return"png";default:return"bin"}}function ET(t,e){const n=(e==null?void 0:e.formats)??{},r={...t,...n},s=(e==null?void 0:e.outputFormat)??"webp",i=`image/${s==="jpeg"?"jpeg":s}`,a=(e==null?void 0:e.quality)??80,o=(e==null?void 0:e.defaultFormat)??(n.medium?"medium":Object.keys(n)[0]??"admin-preview");return{formats:r,outputMime:i,quality:a,defaultFormat:o}}function _i(t){return t.normalize("NFD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,96)}function Rd(t){return/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(t)}function Tr({post:t,primaryTerm:e}){const n=t.slug.trim();if(!n)throw new Error("Post slug is required to build its URL.");if(t.type==="page")return`${n}.html`;if(e&&e.type==="category"){const r=e.slug.trim();if(!r)throw new Error("Primary category slug is required to build the post URL.");return`${r}/${n}.html`}return`${n}.html`}function vj(t){var r,s;const n=[t.firstName,t.lastName].filter(Boolean).join(" ").trim()||((r=t.displayName)==null?void 0:r.trim())||((s=t.email)==null?void 0:s.split("@")[0])||t.id;return _i(n)||t.id.slice(0,8)}function _T(t,e){const n=vj(t);return`author/${e.some(i=>i.id!==t.id&&vj(i)===n)?`${n}-${t.id.slice(0,6)}`:n}.html`}function sa(t){const e=t.slug.trim();if(!e)throw new Error("Term slug is required to build its URL.");if(t.type!=="category")throw new Error("Only categories produce a public archive URL.");return`${e}/index.html`}const sp="index.html",I8="404.html";function N8(t,e){const n=t.replace(/\/+$/,""),r=e.replace(/^\/+/,"");return`${n}/${r}`}function P8(t){return t.replace(/(^|\/)index\.html$/i,(e,n)=>n)}function R8(t,e){if(!t)return"";const n=t.replace(/\/+$/,""),r=P8(e.replace(/^\/+/,""));return`${n}/${r}`}function u1(t,e){if(t||(t="untitled"),!e(t))return t;for(let n=2;n<1e3;n++){const r=`${t}-${n}`;if(!e(r))return r}return`${t}-${Date.now()}`}function Yy(t,e,n,r,s){for(const i of e){if(i.id===s)continue;const a=i.primaryTermId?r.find(l=>l.id===i.primaryTermId):void 0;let o;try{o=Tr({post:i,primaryTerm:a})}catch{continue}if(o===t)return{kind:"post",id:i.id,label:i.title||i.slug,path:o}}for(const i of n){if(i.id===s)continue;let a;try{a=Tr({post:i})}catch{continue}if(a===t)return{kind:"page",id:i.id,label:i.title||i.slug,path:a}}for(const i of r){if(i.id===s||i.type!=="category")continue;let a;try{a=sa(i)}catch{continue}if(a===t)return{kind:"category",id:i.id,label:i.name||i.slug,path:a}}return null}function Um(t,e,n){for(const r of e)if(r.id!==n&&r.type===t.type&&r.slug===t.slug)return{kind:"category",id:r.id,label:r.name||r.slug,path:r.slug};return null}function d1(t){const e=t.lastIndexOf("."),n=e>0?t.slice(0,e):t;return`${_i(n)||"media"}-${rle(6)}`}function rle(t){if(typeof crypto<"u"&&typeof crypto.getRandomValues=="function"){const e=new Uint8Array(Math.ceil(t/2));return crypto.getRandomValues(e),Array.from(e).map(n=>n.toString(16).padStart(2,"0")).join("").slice(0,t)}return Math.random().toString(16).slice(2,2+t)}function sle({site:t}){const{settings:e}=t,n=t.homePath??"/index.html";return d.jsxs(d.Fragment,{children:[d.jsx("header",{className:"site-header",children:d.jsxs("div",{className:"container site-header__inner",children:[d.jsx("button",{type:"button",className:"burger-toggle","aria-controls":"burger-menu","aria-expanded":"false","aria-label":"Open menu",children:d.jsx(ile,{})}),d.jsx("a",{className:"site-brand",href:n,"data-cms-brand":!0,children:e.title}),d.jsx("div",{className:"site-langswitch","data-cms-langswitch":"header","aria-hidden":"true"})]})}),d.jsx("nav",{id:"burger-menu",className:"burger-menu","data-cms-menu":"header","aria-label":"Primary",children:d.jsx("ul",{})})]})}function ile(){return d.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[d.jsx("line",{x1:"3",y1:"6",x2:"21",y2:"6"}),d.jsx("line",{x1:"3",y1:"12",x2:"21",y2:"12"}),d.jsx("line",{x1:"3",y1:"18",x2:"21",y2:"18"})]})}function ale({site:t}){const{settings:e}=t,n=new Date().getFullYear();return d.jsx("footer",{className:"site-footer",children:d.jsxs("div",{className:"container site-footer__inner",children:[d.jsx("p",{className:"site-footer__brand",children:e.title}),d.jsx("nav",{className:"site-footer__nav","data-cms-menu":"footer","aria-label":"Footer",children:d.jsx("ul",{})}),d.jsxs("p",{className:"site-footer__copy",children:["© ",n," ",e.title]}),d.jsx("div",{className:"site-footer__langswitch","data-cms-langswitch":"footer","aria-hidden":"true"})]})})}function ole({site:t,pageTitle:e,pageDescription:n,ogImage:r,currentPath:s,currentLocale:i,children:a}){var y;const o=(y=t.themeConfig)==null?void 0:y.cssUpdatedAt,l=o?`/${t.themeCssPath}?v=${o}`:`/${t.themeCssPath}`,c=t.themeCssPath.replace(/^theme-assets\//,"").replace(/\.css$/,""),h=`/theme-assets/${c}-menu.js`,p=`/theme-assets/${c}-posts.js`,m=t.settings.baseUrl&&s?R8(t.settings.baseUrl,s):void 0,g=e?`${e} — ${t.settings.title}`:t.settings.title;return d.jsxs("html",{lang:i||t.settings.language||"en",children:[d.jsxs("head",{children:[d.jsx("meta",{charSet:"UTF-8"}),d.jsx("meta",{name:"viewport",content:"width=device-width, initial-scale=1"}),d.jsx("title",{children:g}),n&&d.jsx("meta",{name:"description",content:n}),m&&d.jsx("link",{rel:"canonical",href:m}),d.jsx("link",{rel:"preconnect",href:"https://fonts.googleapis.com"}),d.jsx("link",{rel:"preconnect",href:"https://fonts.gstatic.com",crossOrigin:""}),d.jsx("link",{rel:"stylesheet",href:l}),d.jsx("meta",{property:"og:title",content:g}),n&&d.jsx("meta",{property:"og:description",content:n}),r&&d.jsx("meta",{property:"og:image",content:r}),m&&d.jsx("meta",{property:"og:url",content:m}),d.jsx("meta",{property:"og:type",content:"website"}),d.jsx("meta",{name:"x-cms-head-extra"})]}),d.jsxs("body",{children:[d.jsx(sle,{site:t}),d.jsx("main",{className:"site-main",children:a}),d.jsx(ale,{site:t}),d.jsx("script",{src:h,defer:!0}),d.jsx("script",{src:p,defer:!0}),d.jsx("script",{type:"application/x-cms-body-end"})]})]})}function lle({staticPage:t,archivesLink:e,heroHtml:n,listHtml:r}){return t?d.jsxs("article",{className:"page-static container",children:[d.jsx("h1",{className:"page-title",children:t.post.title}),d.jsx("div",{className:"page-body",dangerouslySetInnerHTML:{__html:t.bodyHtml}})]}):n&&n.length>0||r&&r.length>0?d.jsxs(d.Fragment,{children:[n&&d.jsx("div",{className:"container",dangerouslySetInnerHTML:{__html:n}}),r&&d.jsx("div",{className:"container",dangerouslySetInnerHTML:{__html:r}}),e&&d.jsx("div",{className:"container",children:d.jsx("p",{className:"archives-link",children:d.jsx("a",{href:e.href,children:e.label})})})]}):d.jsx("div",{className:"page-home container",children:d.jsx("p",{className:"empty-state",children:"No posts yet."})})}function Js(t,e){if(!t)return"";const n=t.formats;if(e&&n[e])return n[e].url;if(t.default&&n[t.default])return n[t.default].url;const r=Object.values(n).reduce((s,i)=>{const a=(i.width||0)*(i.height||0);return!s||a>s.area?{url:i.url,area:a}:s},null);return(r==null?void 0:r.url)??""}function ia(t){if(t){if(t.formats&&Object.keys(t.formats).length>0)return{alt:t.alt,caption:t.caption,default:t.defaultFormat??Object.keys(t.formats)[0],formats:Object.fromEntries(Object.entries(t.formats).map(([e,n])=>[e,{url:n.url,width:n.width,height:n.height}]))};if(t.url)return{alt:t.alt,caption:t.caption,default:"legacy",formats:{legacy:{url:t.url,width:0,height:0}}}}}function jd(t,e){return Js(ia(t),e)}function cle(t){if(!t)return"?";const e=t.trim().split(/\s+/);if(e.length===1)return e[0].slice(0,2).toUpperCase();const n=e[0][0]??"",r=e[e.length-1][0]??"";return(n+r).toUpperCase()}function j8({name:t,avatar:e,size:n="default"}){const r=["author-avatar"];if(n==="lg"&&r.push("author-avatar--lg"),n==="xl"&&r.push("author-avatar--xl"),e){const i=Js(e,n==="xl"?"large":n==="lg"?"medium":"small");if(i)return r.push("author-avatar--image"),d.jsx("img",{className:r.join(" "),src:i,alt:e.alt??t,loading:"lazy"})}return d.jsx("span",{className:r.join(" "),"aria-hidden":"true",children:cle(t)})}function ule({items:t}){return t.length===0?null:d.jsx("nav",{className:"breadcrumb","aria-label":"Breadcrumb",children:d.jsx("ol",{className:"breadcrumb",children:t.map((e,n)=>{const r=n===t.length-1;return d.jsxs("li",{"aria-current":r?"page":void 0,children:[e.href&&!r?d.jsx("a",{href:e.href,children:e.label}):d.jsx("span",{className:"breadcrumb__current",children:e.label}),!r&&d.jsx("span",{className:"breadcrumb__sep","aria-hidden":"true",children:"/"})]},`${e.label}-${n}`)})})})}function dle({post:t,bodyHtml:e,author:n,hero:r,primaryTerm:s,tags:i,site:a}){var p,m,g,y,x,v;if(t.type==="page")return d.jsx("div",{className:"page-static container",children:d.jsx("div",{className:"page-body",dangerouslySetInnerHTML:{__html:e}})});const o=jt.getFixedT(nh(a.settings.language),"theme-default"),l=[{label:o("breadcrumb.home",{defaultValue:"Home"}),href:a.homePath??"/index.html"}];s&&s.type==="category"&&l.push({label:s.name,href:`/${sa(s)}`}),l.push({label:t.title});const c=((m=(p=t.publishedAt)==null?void 0:p.toMillis)==null?void 0:m.call(p))??((y=(g=t.updatedAt)==null?void 0:g.toMillis)==null?void 0:y.call(g))??((v=(x=t.createdAt)==null?void 0:x.toMillis)==null?void 0:v.call(x));let h;if(c)try{h=new Intl.DateTimeFormat(a.settings.language||"en",{month:"long",day:"numeric",year:"numeric"}).format(new Date(c))}catch{h=new Date(c).toDateString()}return d.jsxs("div",{className:"page-single container",children:[d.jsxs("article",{className:"page-single__main",children:[d.jsx(ule,{items:l}),d.jsxs("header",{children:[d.jsx("h1",{className:"page-single__title",children:t.title}),r&&d.jsxs("figure",{className:"page-single__hero",children:[d.jsx("img",{src:Js(r,"large"),alt:r.alt??"",fetchPriority:"high"}),r.caption&&d.jsx("figcaption",{children:r.caption})]}),t.excerpt&&d.jsx("p",{className:"page-single__lede",children:t.excerpt}),d.jsxs("div",{className:"page-single__meta-strip",children:[s&&d.jsx("span",{className:"label-caps",children:s.name}),s&&h&&d.jsx("span",{className:"page-single__meta-dot","aria-hidden":"true"}),h&&d.jsx("span",{className:"label-caps",children:h})]}),n&&d.jsxs("div",{className:"page-single__author-strip",children:[d.jsx(j8,{name:n.displayName,avatar:n.avatar}),d.jsx("div",{children:d.jsx("p",{className:"page-single__author-name",children:n.displayName})})]})]}),d.jsx("div",{className:"page-body",dangerouslySetInnerHTML:{__html:e}}),i.length>0&&d.jsx("ul",{className:"page-single__tags",children:i.map(k=>d.jsxs("li",{children:["#",k.name]},k.id))})]}),d.jsxs("aside",{className:"page-single__sidebar",children:[t.authorId&&d.jsx("section",{className:"author-bio","data-cms-author-bio":!0,"data-cms-author-id":t.authorId,"data-cms-eyebrow":o("publicBaked.authorBioEyebrow"),hidden:!0}),d.jsx("section",{className:"related-posts","data-cms-related":!0,"data-cms-current-id":t.id,"data-cms-term-id":t.primaryTermId??"","data-cms-limit":"3","data-cms-label":o("publicBaked.relatedPostsLabel"),"data-cms-fallback-label":o("publicBaked.relatedPostsFallbackLabel")})]})]})}function M8({post:t}){var n;const e=t.hero?Js(t.hero,"medium"):"";return d.jsx("article",{className:"card-post",children:d.jsxs("a",{className:"card-post__link",href:`/${t.url}`,children:[e&&d.jsx("div",{className:"card-post__media",children:d.jsx("img",{src:e,alt:((n=t.hero)==null?void 0:n.alt)??"",loading:"lazy"})}),d.jsxs("div",{className:"card-post__body",children:[t.category&&d.jsx("p",{className:"card-post__eyebrow",children:t.category.name}),d.jsx("h3",{className:"card-post__title",children:t.title}),t.excerpt&&d.jsx("p",{className:"card-post__excerpt",children:t.excerpt}),t.dateLabel&&d.jsx("p",{className:"card-post__meta",children:t.dateLabel})]})]})})}function hle({term:t,posts:e,categoryRssUrl:n,archivesLink:r}){return d.jsxs("div",{className:"page-archive container",children:[d.jsxs("header",{className:"page-archive__header",children:[d.jsxs("div",{className:"page-archive__head",children:[d.jsx("p",{className:"page-archive__eyebrow",children:"Section"}),d.jsx("h1",{className:"page-archive__title",children:t.name}),t.description&&d.jsx("p",{className:"page-archive__desc",children:t.description})]}),n&&d.jsxs("a",{className:"page-archive__rss",href:n,"aria-label":`RSS feed for ${t.name}`,children:[d.jsx(fle,{}),"Follow"]})]}),e.length===0?d.jsx("p",{className:"empty-state",children:"No posts in this category yet."}):d.jsx("ul",{className:"post-grid",children:e.map(s=>d.jsx("li",{children:d.jsx(M8,{post:s})},s.id))}),r&&d.jsx("p",{className:"archives-link",children:d.jsx("a",{href:r.href,children:r.label})})]})}function fle(){return d.jsxs("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[d.jsx("path",{d:"M4 11a9 9 0 0 1 9 9"}),d.jsx("path",{d:"M4 4a16 16 0 0 1 16 16"}),d.jsx("circle",{cx:"5",cy:"19",r:"1.5",fill:"currentColor"})]})}const ple={twitter:"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z",linkedin:"M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z",instagram:"M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z",mastodon:"M23.193 7.88c0-5.207-3.411-6.733-3.411-6.733C18.062.357 15.108.025 12.041 0h-.076c-3.068.025-6.02.357-7.74 1.147 0 0-3.412 1.526-3.412 6.733 0 1.193-.023 2.619.015 4.13.124 5.092.934 10.11 5.641 11.355 2.17.574 4.034.695 5.535.612 2.722-.151 4.25-.972 4.25-.972l-.09-1.975s-1.945.613-4.129.539c-2.165-.074-4.449-.233-4.799-2.891a5.499 5.499 0 0 1-.048-.745s2.125.52 4.817.643c1.646.075 3.19-.097 4.758-.283 3.007-.359 5.625-2.212 5.954-3.905.52-2.667.477-6.508.477-6.508zm-4.024 6.709h-2.497V8.469c0-1.29-.543-1.944-1.628-1.944-1.2 0-1.802.776-1.802 2.312v3.349h-2.484v-3.35c0-1.536-.601-2.312-1.802-2.312-1.085 0-1.628.655-1.628 1.945v6.119H4.831V8.285c0-1.29.328-2.313.987-3.07.68-.756 1.57-1.144 2.674-1.144 1.278 0 2.246.491 2.886 1.474L12 6.585l.622-1.04c.64-.983 1.608-1.474 2.886-1.474 1.104 0 1.994.388 2.674 1.144.658.757.986 1.78.986 3.07v6.304z",bluesky:"M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479.815 2.736 3.713 3.66 6.383 3.364.137-.02.275-.039.415-.056-.138.022-.276.04-.415.056-3.912.58-7.387 2.005-2.83 7.078 5.013 5.19 6.87-1.113 7.823-4.308.952 3.195 2.05 9.271 7.733 4.308 4.267-4.308 1.172-6.498-2.74-7.078a8.741 8.741 0 0 1-.415-.056c.14.017.279.036.415.056 2.67.297 5.568-.628 6.383-3.364.246-.828.624-5.79.624-6.478 0-.69-.139-1.861-.902-2.206-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8Z",github:"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12",website:"M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95a15.65 15.65 0 0 0-1.38-3.56A8.03 8.03 0 0 1 18.92 8zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56A7.987 7.987 0 0 1 5.08 16zm2.95-8H5.08a7.987 7.987 0 0 1 4.33-3.56A15.65 15.65 0 0 0 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95a8.03 8.03 0 0 1-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"},mle={twitter:"Twitter / X",linkedin:"LinkedIn",instagram:"Instagram",mastodon:"Mastodon",bluesky:"Bluesky",github:"GitHub",website:"Website"};function L8({network:t,className:e,size:n=18}){const r=ple[t];return d.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:n,height:n,fill:"currentColor","aria-hidden":"true",className:e,children:d.jsx("path",{d:r})})}function l_(t){return mle[t]}function gle({author:t,posts:e}){return d.jsxs("div",{className:"page-author container",children:[d.jsxs("header",{className:"page-author__hero",children:[d.jsx("div",{className:"page-author__portrait",children:d.jsx(j8,{name:t.displayName,avatar:t.avatar,size:"xl"})}),d.jsxs("div",{className:"page-author__body",children:[d.jsx("p",{className:"page-author__eyebrow",children:"Author"}),d.jsx("h1",{className:"page-author__title",children:t.displayName}),t.title&&d.jsx("p",{className:"page-author__role",children:t.title}),t.bio&&d.jsx("p",{className:"page-author__bio",children:t.bio}),t.socials&&t.socials.length>0&&d.jsx("div",{className:"page-author__socials",children:t.socials.map(n=>d.jsx("a",{className:"page-author__social-link",href:n.url,target:"_blank",rel:"noopener noreferrer","aria-label":l_(n.network),title:l_(n.network),children:d.jsx(L8,{network:n.network})},n.network))})]})]}),e.length===0?d.jsx("p",{className:"empty-state",children:"No posts by this author yet."}):d.jsx("ul",{className:"post-grid",children:e.map(n=>d.jsx("li",{children:d.jsx(M8,{post:n})},n.id))})]})}function ble({message:t}){return d.jsxs("div",{className:"page-not-found container",children:[d.jsx("h1",{children:"404"}),d.jsx("p",{children:t??"The page you are looking for does not exist."}),d.jsx("a",{href:"/index.html",children:"Back to home"})]})}const xj='@charset "UTF-8";@import"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Newsreader:ital,wght@0,300;0,400;0,500;0,600;0,700;1,400;1,700&display=swap";:root{--color-bg: #fbf9f9;--color-surface: #ffffff;--color-surface-low: #f5f3f3;--color-surface-mid: #efeded;--color-surface-high: #e9e8e7;--color-surface-highest: #e3e2e2;--color-on-surface: #1b1c1c;--color-on-surface-variant: #444748;--color-on-surface-muted: #868382;--color-outline: #747878;--color-outline-variant: #c4c7c7;--color-primary: #000000;--color-on-primary: #ffffff;--color-secondary: #476558;--color-secondary-container: #c9ead9;--color-on-secondary-container: #4d6b5d;--font-serif: "Newsreader", Georgia, "Times New Roman", serif;--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--weight-display: 600;--weight-heading: 500;--weight-body: 400;--weight-meta: 600;--weight-emphasis: 700;--weight-lede: 300;--container-max: 1120px;--gutter: 24px;--section-gap: 80px;--radius-sm: .125rem;--radius: .25rem;--radius-lg: .5rem;--radius-xl: .75rem}*,*:before,*:after{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;font-family:var(--font-sans);font-size:16px;line-height:1.6;color:var(--color-on-surface);background:var(--color-bg);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}::-moz-selection{background:var(--color-secondary-container)}::selection{background:var(--color-secondary-container)}img,picture,video,svg{display:block;max-width:100%}button{font-family:inherit;cursor:pointer;background:none;border:none;padding:0;color:inherit}a{color:inherit}h1,h2,h3,h4,h5,h6{font-family:var(--font-serif);margin:0;color:var(--color-on-surface)}p,ul,ol{margin:0}.container{width:100%;max-width:var(--container-max);margin:0 auto;padding:0 20px}@media(min-width:768px){.container{padding:0 40px}}.label-caps{font-family:var(--font-sans);font-size:12px;line-height:1;font-weight:var(--weight-meta);letter-spacing:.05em;text-transform:uppercase;color:var(--color-on-surface-muted)}.site-header{position:sticky;top:0;z-index:50;background:#fbf9f9d9;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border-bottom:1px solid var(--color-surface-highest)}.site-header__inner{position:relative;display:flex;align-items:center;justify-content:space-between;height:64px}.site-brand{font-family:var(--font-serif);font-style:italic;font-size:22px;font-weight:var(--weight-emphasis);letter-spacing:-.02em;text-decoration:none;color:var(--color-on-surface);position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);white-space:nowrap;display:inline-flex;align-items:center}.site-brand__logo{display:block;height:36px;width:auto;max-width:min(240px,60vw);-o-object-fit:contain;object-fit:contain}.burger-toggle{display:inline-flex;align-items:center;justify-content:center;padding:8px;margin-left:-8px;border-radius:var(--radius);transition:opacity .2s ease}.burger-toggle:hover{opacity:.7}.burger-toggle svg{width:24px;height:24px}.burger-menu{position:fixed;inset:0 auto 0 0;width:min(360px,88vw);background:var(--color-bg);z-index:60;padding:64px 32px 32px;transform:translate(-100%);transition:transform .3s ease;overflow-y:auto;box-shadow:4px 0 24px #00000014}.burger-menu.is-open{transform:translate(0)}.burger-menu ul{list-style:none;padding:0;display:flex;flex-direction:column;gap:24px;margin-top:24px}.burger-menu li{margin:0}.burger-menu a{display:block;font-family:var(--font-serif);font-size:22px;font-weight:var(--weight-body);color:var(--color-on-surface-muted);text-decoration:none;padding-left:16px;border-left:4px solid transparent;transition:color .2s ease,border-color .2s ease}.burger-menu a:hover{color:var(--color-on-surface)}.burger-menu a[aria-current=page]{color:var(--color-on-surface);font-weight:var(--weight-meta);border-left-color:var(--color-on-surface)}.burger-close{position:absolute;top:16px;right:16px;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--radius);color:var(--color-on-surface);transition:opacity .2s ease}.burger-close:hover{opacity:.7}.burger-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#0006;z-index:55;opacity:0;pointer-events:none;transition:opacity .3s ease}.burger-backdrop.is-open{opacity:1;pointer-events:auto}body.burger-open{overflow:hidden}.site-footer{margin-top:var(--section-gap);border-top:1px solid var(--color-surface-highest);background:var(--color-surface-low);padding:56px 0}.site-footer__inner{display:flex;flex-direction:column;align-items:center;text-align:center;gap:24px}@media(min-width:768px){.site-footer__inner{flex-direction:row;justify-content:space-between;text-align:left}}.site-footer__brand{font-family:var(--font-serif);font-style:italic;font-size:18px;font-weight:var(--weight-emphasis);letter-spacing:-.02em;margin:0}.site-footer__nav ul{list-style:none;padding:0;display:flex;flex-wrap:wrap;gap:24px;justify-content:center}.site-footer__nav a{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);text-decoration:none;transition:color .2s ease}.site-footer__nav a:hover{color:var(--color-on-surface)}.site-footer__copy{font-family:var(--font-sans);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:0}.site-main{display:block;min-height:60vh;padding-bottom:var(--section-gap)}.card-post{display:flex;flex-direction:column;background:var(--color-surface-low);border:1px solid var(--color-outline-variant);overflow:hidden;height:100%}.card-post__link{display:flex;flex-direction:column;flex:1;text-decoration:none;color:inherit}.card-post__media{aspect-ratio:16/9;background:var(--color-surface-high);overflow:hidden}.card-post__media img{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;transition:transform .5s ease}.card-post:hover .card-post__media img{transform:scale(1.03)}.card-post__body{display:flex;flex-direction:column;flex:1;padding:20px}.card-post__eyebrow{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 12px}.card-post__title{font-family:var(--font-serif);font-size:22px;line-height:1.3;font-weight:var(--weight-heading);margin:0 0 12px;transition:color .2s ease}.card-post:hover .card-post__title{color:var(--color-secondary)}.card-post__excerpt{font-size:15px;line-height:1.6;color:var(--color-on-surface-variant);margin:0 0 16px;display:-webkit-box;-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.card-post__meta{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:auto 0 0}.hero-featured{margin-top:48px}@media(min-width:768px){.hero-featured{margin-top:80px}}.hero-featured__link{text-decoration:none;color:inherit;display:block}.hero-featured__media{aspect-ratio:21/9;background:var(--color-surface-high);overflow:hidden;border-radius:var(--radius)}.hero-featured__media img{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;transition:transform .7s ease}.hero-featured__link:hover .hero-featured__media img{transform:scale(1.03)}.hero-featured__body{margin-top:32px;max-width:720px}.hero-featured__pill{display:inline-block;background:var(--color-secondary-container);color:var(--color-on-secondary-container);padding:6px 12px;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;border-radius:var(--radius);margin-bottom:16px}.hero-featured__title{font-family:var(--font-serif);font-size:clamp(32px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 16px}.hero-featured__excerpt{font-size:18px;line-height:1.7;color:var(--color-on-surface-variant);margin:0 0 24px;max-width:600px}.hero-featured__date{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted)}.page-home__title-row{display:flex;align-items:center;justify-content:space-between;margin-top:var(--section-gap);margin-bottom:32px;padding-bottom:16px;border-bottom:1px solid var(--color-surface-highest)}.page-home__title{font-family:var(--font-serif);font-size:22px;font-weight:var(--weight-heading);letter-spacing:.04em;text-transform:uppercase;margin:0}.post-grid{list-style:none;padding:0;display:grid;grid-template-columns:1fr;gap:48px 32px}@media(min-width:768px){.post-grid{grid-template-columns:repeat(2,1fr)}}@media(min-width:1024px){.post-grid{grid-template-columns:repeat(3,1fr)}}.post-grid li{list-style:none}.page-single{padding-top:48px;display:grid;grid-template-columns:minmax(0,1fr);gap:64px}@media(min-width:1024px){.page-single{padding-top:80px;grid-template-columns:minmax(0,8fr) minmax(0,4fr);-moz-column-gap:64px;column-gap:64px}}.page-static{padding-top:48px;padding-bottom:96px}@media(min-width:1024px){.page-static{padding-top:80px}}.page-single__main{min-width:0}.page-single__meta-strip{display:flex;align-items:center;flex-wrap:wrap;gap:12px 16px;margin-bottom:40px}.page-single__meta-strip .label-caps{color:var(--color-secondary)}.page-single__meta-dot{width:4px;height:4px;border-radius:50%;background:var(--color-outline-variant);flex-shrink:0}.page-single__title{font-family:var(--font-serif);font-size:clamp(32px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 32px}.page-single__lede{font-family:var(--font-serif);font-style:italic;font-size:clamp(20px,2.5vw,24px);line-height:1.5;font-weight:var(--weight-lede);color:var(--color-on-surface-variant);margin:0 0 40px}.page-single__author-strip{display:flex;align-items:center;gap:16px;padding-bottom:32px;margin-bottom:48px;border-bottom:1px solid var(--color-surface-highest)}.page-single__author-name{font-family:var(--font-sans);font-size:14px;font-weight:var(--weight-emphasis);margin:0;color:var(--color-on-surface)}.page-single__author-meta{font-family:var(--font-sans);font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:4px 0 0}.page-single__hero{margin:0 0 48px;border-radius:var(--radius-lg);overflow:hidden;background:var(--color-surface-high)}.page-single__hero img{aspect-ratio:16/9;width:100%;height:auto;-o-object-fit:cover;object-fit:cover}.page-single__hero figcaption{font-family:var(--font-sans);font-size:12px;color:var(--color-on-surface-muted);padding:8px 16px}.page-single__tags{list-style:none;margin:64px 0 0;padding:32px 0 0;border-top:1px solid var(--color-surface-highest);display:flex;flex-wrap:wrap;gap:8px}.page-single__tags li{background:var(--color-surface-low);color:var(--color-on-surface-muted);padding:8px 16px;border-radius:999px;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.05em;text-transform:uppercase}.page-single__sidebar{display:flex;flex-direction:column;gap:48px}.page-body{font-family:var(--font-serif);font-size:18px;line-height:1.8;color:var(--color-on-surface)}.page-body>p:first-of-type:first-letter{float:left;font-size:5rem;line-height:4rem;padding-right:12px;padding-top:4px;font-family:var(--font-serif);font-weight:var(--weight-emphasis)}.page-body p{margin:0 0 28px}.page-body strong,.page-body b{font-weight:var(--weight-emphasis)}.page-body h2{font-size:32px;margin:56px 0 16px;font-weight:var(--weight-display);letter-spacing:-.01em}.page-body h3{font-size:24px;margin:40px 0 12px;font-weight:var(--weight-heading)}.page-body blockquote{border-left:2px solid var(--color-primary);padding-left:24px;margin:48px 0;font-family:var(--font-serif);font-style:italic;font-size:clamp(22px,2.5vw,28px);font-weight:var(--weight-lede);line-height:1.5;color:var(--color-on-surface-variant)}.page-body blockquote p{margin:0 0 12px}.page-body img{width:100%;border-radius:var(--radius)}.page-body a{color:var(--color-secondary);text-decoration:underline;text-underline-offset:.2em}.page-body code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,monospace;background:var(--color-surface-mid);padding:.1em .4em;border-radius:3px;font-size:.85em}.page-body pre{background:var(--color-surface-mid);border-radius:var(--radius);padding:16px 20px;overflow-x:auto;margin:32px 0;font-size:14px;line-height:1.6}.page-body pre code{background:transparent;padding:0;font-size:inherit}.page-body ul,.page-body ol{padding-left:28px;margin:0 0 28px}.page-body li{margin:8px 0}.page-body hr{border:none;border-top:1px solid var(--color-surface-highest);margin:48px 0}.author-bio{background:var(--color-surface-low);padding:32px;border-radius:var(--radius-lg);border:1px solid var(--color-surface-highest)}.author-bio__eyebrow{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface);margin:0 0 24px}.author-bio__head{display:flex;align-items:flex-start;gap:16px}.author-bio__name{font-family:var(--font-serif);font-size:20px;font-weight:var(--weight-emphasis);margin:0;color:var(--color-on-surface);text-decoration:none;display:inline-block}a.author-bio__name:hover{color:var(--color-secondary);text-decoration:underline;text-underline-offset:.2em}.author-bio__role{font-family:var(--font-sans);font-size:13px;font-style:italic;color:var(--color-on-surface-muted);margin:4px 0 0}.author-bio__bio{font-family:var(--font-sans);font-size:14px;line-height:1.6;color:var(--color-on-surface-variant);margin:24px 0 0}.author-bio__socials{display:flex;gap:12px;margin:16px 0 0}.author-bio__social-link{display:inline-flex;align-items:center;justify-content:center;color:var(--color-on-surface-variant);line-height:0;transition:color .15s ease}.author-bio__social-link:hover{color:var(--color-primary)}.author-bio__social-link svg{width:18px;height:18px}.author-avatar{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;background:var(--color-on-surface);color:var(--color-bg);font-family:var(--font-sans);font-size:13px;font-weight:var(--weight-emphasis);letter-spacing:.02em;text-transform:uppercase}.author-avatar--lg{width:56px;height:56px;font-size:16px}.author-avatar--xl{width:100%;max-width:280px;aspect-ratio:3/4;height:auto;border-radius:var(--radius-lg);font-size:clamp(48px,8vw,72px);font-weight:var(--weight-display)}.author-avatar--image{background:var(--color-surface-high);-o-object-fit:cover;object-fit:cover;display:block;color:transparent}.related-posts__title{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface);margin:0 0 24px;padding-bottom:16px;border-bottom:1px solid var(--color-surface-highest)}.related-posts__list{list-style:none;padding:0;display:flex;flex-direction:column;gap:28px}.related-posts__item a{display:block;color:inherit;text-decoration:none}.related-posts__eyebrow{font-family:var(--font-sans);font-size:10px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 6px}.related-posts__title-line{font-family:var(--font-serif);font-size:17px;font-weight:var(--weight-emphasis);line-height:1.3;margin:0 0 6px;transition:color .2s ease}.related-posts__item a:hover .related-posts__title-line{color:var(--color-secondary)}.related-posts__date{font-family:var(--font-sans);font-size:10px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:0}.page-archive{padding-top:64px}.page-archive__header{display:flex;flex-direction:column;gap:32px;padding-bottom:48px;border-bottom:1px solid var(--color-surface-highest);margin-bottom:64px}@media(min-width:768px){.page-archive__header{flex-direction:row;align-items:flex-end;justify-content:space-between}}.page-archive__head{max-width:720px}.page-archive__eyebrow{font-family:var(--font-sans);font-size:12px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 16px}.page-archive__title{font-family:var(--font-serif);font-size:clamp(36px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 16px}.page-archive__desc{font-size:18px;line-height:1.7;color:var(--color-on-surface-variant);margin:0;max-width:56ch}.page-archive__rss{display:inline-flex;align-items:center;gap:8px;padding:10px 24px;border:1px solid var(--color-primary);background:transparent;color:var(--color-on-surface);font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;border-radius:var(--radius);text-decoration:none;transition:background .2s ease,color .2s ease;align-self:flex-start}.page-archive__rss:hover{background:var(--color-primary);color:var(--color-on-primary)}.page-archive__rss svg{width:16px;height:16px}.page-author{padding-top:64px}.page-author__hero{display:flex;flex-direction:column;gap:48px;padding-bottom:64px;border-bottom:1px solid var(--color-surface-highest);margin-bottom:64px}@media(min-width:768px){.page-author__hero{flex-direction:row;align-items:center;gap:96px}}.page-author__portrait{flex-shrink:0;width:100%;max-width:280px}.page-author__body{display:flex;flex-direction:column;justify-content:center}.page-author__eyebrow{font-family:var(--font-sans);font-size:12px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 16px}.page-author__title{font-family:var(--font-serif);font-size:clamp(36px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 12px}.page-author__role{font-family:var(--font-sans);font-size:13px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-secondary);margin:0 0 16px}.page-author__bio{font-size:18px;line-height:1.7;color:var(--color-on-surface-variant);margin:0}.page-author__socials{display:flex;gap:16px;margin:24px 0 0}.page-author__social-link{display:inline-flex;align-items:center;justify-content:center;color:var(--color-on-surface-variant);line-height:0;transition:color .15s ease}.page-author__social-link:hover{color:var(--color-primary)}.page-author__social-link svg{width:20px;height:20px}.empty-state{text-align:center;padding:80px 0;color:var(--color-on-surface-muted);font-style:italic}.page-static{padding-top:64px}.page-static .page-title,.page-title{font-family:var(--font-serif);font-size:clamp(36px,5vw,48px);line-height:1.1;letter-spacing:-.02em;font-weight:var(--weight-display);margin:0 0 32px}.breadcrumb{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin:0 0 32px;padding:0;list-style:none}.breadcrumb li{display:inline-flex;align-items:center;gap:8px}.breadcrumb a{color:var(--color-on-surface-muted);text-decoration:none;transition:color .2s ease}.breadcrumb a:hover{color:var(--color-on-surface)}.breadcrumb__sep{color:var(--color-outline-variant)}.breadcrumb__current{color:var(--color-on-surface);display:inline-block;max-width:min(420px,60vw);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:bottom}.pagination{display:flex;align-items:center;justify-content:space-between;margin-top:var(--section-gap);padding-top:48px;border-top:1px solid var(--color-surface-highest)}.pagination__pages{display:none;gap:12px}@media(min-width:768px){.pagination__pages{display:flex}}.pagination a,.pagination span{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);text-decoration:none;transition:color .2s ease}.pagination a:hover{color:var(--color-on-surface)}.pagination__pages a,.pagination__pages span{width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;border-radius:50%}.pagination__pages a.is-active{background:var(--color-primary);color:var(--color-on-primary)}.page-not-found{display:flex;flex-direction:column;align-items:center;text-align:center;padding:120px 20px}.page-not-found h1{font-family:var(--font-serif);font-size:clamp(72px,12vw,120px);font-weight:var(--weight-display);margin:0 0 24px;letter-spacing:-.04em;line-height:1}.page-not-found p{font-size:18px;color:var(--color-on-surface-variant);max-width:420px;margin:0 0 32px}.page-not-found a{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface);border-bottom:2px solid var(--color-primary);text-decoration:none;padding-bottom:4px;transition:color .2s ease,border-color .2s ease}.page-not-found a:hover{color:var(--color-secondary);border-color:var(--color-secondary)}.cms-hero a,.cms-card a,.cms-cta a,.cms-categories a,.cms-list-block a,.cms-list-header a,.card-post a{text-decoration:none}.cms-hero{position:relative;display:flex;overflow:hidden;width:100%;margin:32px 0;background:var(--color-bg)}.cms-hero .cms-hero-image-wrap{background:var(--color-surface-mid);overflow:hidden}.cms-hero .cms-hero-image-wrap a{display:block;width:100%;height:100%}.cms-hero .cms-hero-image{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;display:block}.cms-hero .cms-hero-content{padding:32px;flex:1;display:flex;flex-direction:column;justify-content:center;min-width:0}.cms-hero .cms-hero-category{display:inline-block;align-self:flex-start;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;background:var(--color-secondary-container);color:var(--color-on-surface);padding:4px 10px;margin:0 0 16px;text-decoration:none;transition:opacity .2s ease}.cms-hero .cms-hero-category:hover{opacity:.85}.cms-hero .cms-hero-title{font-family:var(--font-serif);font-size:clamp(26px,4.5vw,40px);font-weight:var(--weight-display);line-height:1.15;letter-spacing:-.02em;margin:0 0 20px}.cms-hero .cms-hero-title a{color:inherit;text-decoration:none;transition:color .2s ease}.cms-hero .cms-hero-title a:hover{color:var(--color-secondary)}.cms-hero .cms-hero-excerpt{font-family:var(--font-sans);font-size:16px;line-height:1.6;color:var(--color-on-surface-variant);margin:0 0 20px;max-width:60ch}.cms-hero-image-overlay{min-height:320px;align-items:flex-end}.cms-hero-image-overlay .cms-hero-image-wrap{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1}.cms-hero-image-overlay:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to top,#000000d9,#0003 60%,#0000);z-index:2;pointer-events:none}.cms-hero-image-overlay .cms-hero-content{position:relative;z-index:3;width:100%;color:#fff;padding:32px}.cms-hero-image-overlay .cms-hero-title a{color:#fff}.cms-hero-image-overlay .cms-hero-title a:hover{color:var(--color-secondary-container)}.cms-hero-image-overlay .cms-hero-excerpt{color:#ffffffd9}@media(min-width:768px){.cms-hero-image-overlay{min-height:480px}.cms-hero-image-overlay .cms-hero-content{padding:48px}}.cms-hero-split-left,.cms-hero-split-right{background:var(--color-surface-low);border:1px solid var(--color-outline-variant);flex-direction:column}.cms-hero-split-left .cms-hero-image-wrap,.cms-hero-split-right .cms-hero-image-wrap{width:100%;height:240px;flex-shrink:0}@media(min-width:768px){.cms-hero-split-left,.cms-hero-split-right{flex-direction:row;min-height:360px}.cms-hero-split-left .cms-hero-image-wrap,.cms-hero-split-right .cms-hero-image-wrap{flex:0 0 50%;height:auto}.cms-hero-split-right{flex-direction:row-reverse}}.cms-hero-minimal{flex-direction:column;text-align:center;align-items:center;padding:48px 16px;border-bottom:2px solid var(--color-on-surface)}.cms-hero-minimal .cms-hero-content{max-width:720px;align-items:center;padding:0}.cms-hero-minimal .cms-hero-category{align-self:center}.cms-hero-minimal .cms-hero-title{font-size:clamp(32px,6vw,56px)}@media(min-width:768px){.cms-hero-minimal{padding:80px 24px}}.cms-list-block{margin:48px 0}.cms-list-header{display:flex;align-items:center;justify-content:space-between;gap:16px;border-bottom:1px solid var(--color-outline-variant);padding-bottom:12px;margin-bottom:24px}.cms-list-title{font-family:var(--font-serif);font-size:20px;font-weight:var(--weight-heading);text-transform:uppercase;letter-spacing:.05em;margin:0}.cms-list-see-more{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-variant);text-decoration:none}.cms-list-see-more:hover{color:var(--color-primary)}.cms-list-cards{display:grid;grid-template-columns:1fr;gap:32px}@media(min-width:768px){.cms-list-cards.cms-list-cols-2{grid-template-columns:repeat(2,1fr)}.cms-list-cards.cms-list-cols-3{grid-template-columns:repeat(3,1fr)}.cms-list-cards.cms-list-cols-4{grid-template-columns:repeat(4,1fr)}}.cms-list-list{display:flex;flex-direction:column;gap:24px}.cms-list-compact{display:flex;flex-direction:column;gap:8px}.cms-list-numbered{display:flex;flex-direction:column;gap:16px}.cms-list-slider{display:flex;gap:16px;overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:8px;-webkit-overflow-scrolling:touch;scrollbar-width:thin}.cms-list-slider>.cms-card{scroll-snap-align:start;flex:0 0 240px}@media(min-width:768px){.cms-list-slider>.cms-card{flex:0 0 280px}}.cms-card-slider{position:relative;display:block;overflow:hidden;aspect-ratio:4/5;background:var(--color-on-surface);color:#fff;text-decoration:none}.cms-card-slider-image-wrap{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1}.cms-card-slider-image{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;display:block;transition:transform .5s ease}.cms-card-slider:hover .cms-card-slider-image{transform:scale(1.05)}.cms-card-slider:after{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:linear-gradient(to top,#000000d9,#0000004d 55%,#0000);z-index:2;pointer-events:none}.cms-card-slider-no-image:after{display:none}.cms-card-slider-overlay{position:absolute;inset:auto 0 0 0;z-index:3;padding:16px;display:flex;flex-direction:column;gap:6px}.cms-card-slider-overlay .cms-card-category{align-self:flex-start;margin:0}.cms-card-slider-overlay .cms-card-title{color:#fff;font-size:16px;line-height:1.25;margin:0}.cms-card-slider-overlay .cms-card-meta{color:#ffffffd9}.cms-card{display:block;text-decoration:none;color:inherit}.cms-card-image-wrap{aspect-ratio:16/9;background:var(--color-surface-mid);overflow:hidden}.cms-card-image{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;display:block;transition:transform .4s ease}.cms-card:hover .cms-card-image{transform:scale(1.03)}.cms-card-category{display:inline-block;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;color:var(--color-on-surface-muted);margin-bottom:6px}.cms-card-title{font-family:var(--font-serif);font-size:20px;font-weight:var(--weight-display);line-height:1.3;margin:0 0 8px;color:var(--color-on-surface);transition:color .2s ease}.cms-card:hover .cms-card-title{color:var(--color-secondary)}.cms-card-excerpt{font-family:var(--font-sans);font-size:15px;line-height:1.6;color:var(--color-on-surface-variant);margin:0 0 8px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.cms-card-meta{display:inline-block;font-family:var(--font-sans);font-size:11px;letter-spacing:.05em;color:var(--color-on-surface-muted)}.cms-card-default{display:flex;flex-direction:column;background:var(--color-surface-low);border:1px solid var(--color-outline-variant);overflow:hidden;height:100%}.cms-card-body{display:flex;flex-direction:column;flex:1;padding:20px}.cms-card-body .cms-card-meta{margin-top:auto;padding-top:8px}.cms-card-compact{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding:8px 0;border-bottom:1px solid var(--color-outline-variant)}.cms-card-compact .cms-card-title{font-size:16px;font-weight:var(--weight-display);margin:0;flex:1;font-family:var(--font-sans)}.cms-card-numbered{display:grid;grid-template-columns:auto 1fr;-moz-column-gap:16px;column-gap:16px;row-gap:2px;align-items:start}.cms-card-number{font-family:var(--font-serif);font-style:italic;font-size:32px;font-weight:700;color:var(--color-outline-variant);line-height:1}.cms-card-numbered .cms-card-title{font-size:16px;font-family:var(--font-sans);font-weight:var(--weight-display);line-height:1.3;margin:0}.cms-card-numbered .cms-card-meta{grid-column:2;display:block}.cms-card-list{display:block;padding-bottom:24px;border-bottom:1px solid var(--color-outline-variant)}.cms-card-list:last-child{border-bottom:none}.cms-card-list-with-image{display:flex;gap:16px;align-items:flex-start}.cms-card-list-with-image .cms-card-list-image-wrap{flex:0 0 120px;aspect-ratio:1;background:var(--color-surface-mid);overflow:hidden}.cms-card-list-with-image .cms-card-list-image{width:100%;height:100%;-o-object-fit:cover;object-fit:cover;display:block;transition:transform .4s ease}.cms-card-list-with-image:hover .cms-card-list-image{transform:scale(1.03)}.cms-card-list-with-image .cms-card-list-body{flex:1;min-width:0;display:flex;flex-direction:column}@media(max-width:480px){.cms-card-list-with-image{gap:12px}.cms-card-list-with-image .cms-card-list-image-wrap{flex:0 0 84px}}.cms-card-list .cms-card-title,.cms-card-list .cms-card-excerpt{margin-bottom:2px}.cms-cta{display:flex;flex-direction:column;gap:16px;padding:32px;margin:32px 0}.cms-cta-light{background:var(--color-surface-mid);color:var(--color-on-surface)}.cms-cta-dark{background:var(--color-primary);color:var(--color-on-primary)}.cms-cta-title{font-family:var(--font-serif);font-size:24px;font-weight:var(--weight-heading);line-height:1.3;margin:0}.cms-cta-description{font-family:var(--font-sans);font-size:15px;line-height:1.6;margin:0;opacity:.85}.cms-cta-button{display:inline-block;align-self:flex-start;font-family:var(--font-sans);font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;border-bottom:2px solid currentColor;padding-bottom:4px;text-decoration:none;color:inherit;margin-top:8px;transition:opacity .2s ease}.cms-cta-button:hover{opacity:.7}@media(min-width:768px){.cms-cta{padding:40px}}.cms-categories{margin:32px 0}.cms-categories-title{font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;border-bottom:1px solid var(--color-outline-variant);padding-bottom:12px;margin:0 0 16px}.cms-categories-items{display:flex;flex-wrap:wrap;gap:8px}.cms-categories-pill{display:inline-block;font-family:var(--font-sans);font-size:11px;font-weight:var(--weight-meta);letter-spacing:.1em;text-transform:uppercase;padding:8px 16px;border:1px solid var(--color-outline-variant);border-radius:9999px;text-decoration:none;color:var(--color-on-surface);transition:background .2s ease,color .2s ease}.cms-categories-pill:hover{background:var(--color-primary);color:var(--color-on-primary)}.cms-categories-list .cms-categories-items{flex-direction:column;gap:4px}.cms-categories-list .cms-categories-pill{border:none;border-radius:0;padding:4px 0;text-transform:none;letter-spacing:0;font-size:14px}.cms-spacer{display:block}.cms-spacer-sm{height:24px}.cms-spacer-md{height:48px}.cms-spacer-lg{height:96px}.cms-spacer-divider{position:relative}.cms-spacer-divider:before{content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:64px;height:1px;background:var(--color-outline-variant)}.archives{max-width:var(--container-max);margin:0 auto;padding:var(--section-gap, 4rem) var(--gutter, 1rem)}.archives__header{margin-bottom:2.5rem}.archives__back{margin:0 0 .75rem;font-size:.875rem}.archives__back a{color:var(--color-on-surface-variant);text-decoration:none}.archives__back a:hover{color:var(--color-on-surface);text-decoration:underline}.archives__title{font-family:var(--font-serif);font-weight:var(--weight-display);font-size:clamp(2rem,4vw,3rem);line-height:1.1;margin:0 0 .5rem;color:var(--color-on-surface)}.archives__subtitle{margin:0;color:var(--color-on-surface-variant);font-size:1rem}.archives__empty{color:var(--color-on-surface-muted);font-style:italic}.archives__years{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2rem}.archives__year{border-top:1px solid var(--color-outline-variant);padding-top:1.5rem}.archives__year:first-child{border-top:0;padding-top:0}.archives__year-heading{font-family:var(--font-serif);font-weight:var(--weight-heading);font-size:1.75rem;margin:0 0 .75rem;display:flex;align-items:baseline;gap:.5rem}.archives__year-link,.archives__group-link,.archives__drilldown-link,.archives__item-link{color:var(--color-on-surface);text-decoration:none;border-bottom:1px solid transparent;transition:border-color .15s}.archives__year-link:hover,.archives__group-link:hover,.archives__drilldown-link:hover,.archives__item-link:hover{border-bottom-color:currentColor}.archives__count{color:var(--color-on-surface-muted);font-size:.875rem;font-weight:400}.archives__drilldown{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:.5rem 1rem}.archives__drilldown-item{display:inline-flex;align-items:baseline;gap:.35rem;font-size:.95rem}.archives__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}.archives__item{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;padding:.5rem 0;border-bottom:1px solid var(--color-outline-variant)}.archives__item:last-child{border-bottom:0}.archives__item-link{flex:1;font-size:1rem}.archives__item-date{color:var(--color-on-surface-muted);font-size:.85rem;white-space:nowrap}.archives__groups{display:flex;flex-direction:column;gap:2.5rem}.archives__group-heading{font-family:var(--font-serif);font-weight:var(--weight-heading);font-size:1.25rem;margin:0 0 .75rem;display:flex;align-items:baseline;gap:.5rem}.archives-link{margin:3rem 0 0;text-align:right;font-size:.95rem}.archives-link a{color:var(--color-secondary);text-decoration:none;border-bottom:1px solid currentColor;padding-bottom:.1rem}.archives-link a:hover{color:var(--color-on-surface)}',yle=`/**
|
|
3892
3892
|
* Default theme — runtime menu loader.
|
|
3893
3893
|
*
|
|
3894
3894
|
* Contract:
|
|
@@ -4657,7 +4657,7 @@ img.ProseMirror-separator {
|
|
|
4657
4657
|
*
|
|
4658
4658
|
* This source code is licensed under the MIT license found in the
|
|
4659
4659
|
* LICENSE file in the root directory of this source tree.
|
|
4660
|
-
*/var sL;function $ge(){if(sL)return I2;sL=1;var t=Ar,e=gI;function n(c,h){return c===h&&(c!==0||1/c===1/h)||c!==c&&h!==h}var r=typeof Object.is=="function"?Object.is:n,s=e.useSyncExternalStore,i=t.useRef,a=t.useEffect,o=t.useMemo,l=t.useDebugValue;return I2.useSyncExternalStoreWithSelector=function(c,h,p,m,g){var y=i(null);if(y.current===null){var x={hasValue:!1,value:null};y.current=x}else x=y.current;y=o(function(){function k(D){if(!C){if(C=!0,N=D,D=m(D),g!==void 0&&x.hasValue){var I=x.value;if(g(I,D))return _=I}return _=D}if(I=_,r(N,D))return I;var L=m(D);return g!==void 0&&g(I,L)?I:(N=D,_=L)}var C=!1,N,_,P=p===void 0?null:p;return[function(){return k(h())},P===null?void 0:function(){return k(P())}]},[h,p,m,g]);var v=s(c,y[0],y[1]);return a(function(){x.hasValue=!0,x.value=v},[v]),l(v),v},I2}EU.exports=$ge();var Hge=EU.exports;const Vge=typeof window<"u"?U.useLayoutEffect:U.useEffect;class qge{constructor(e){this.transactionNumber=0,this.lastTransactionNumber=0,this.subscribers=new Set,this.editor=e,this.lastSnapshot={editor:e,transactionNumber:0},this.getSnapshot=this.getSnapshot.bind(this),this.getServerSnapshot=this.getServerSnapshot.bind(this),this.watch=this.watch.bind(this),this.subscribe=this.subscribe.bind(this)}getSnapshot(){return this.transactionNumber===this.lastTransactionNumber?this.lastSnapshot:(this.lastTransactionNumber=this.transactionNumber,this.lastSnapshot={editor:this.editor,transactionNumber:this.transactionNumber},this.lastSnapshot)}getServerSnapshot(){return{editor:null,transactionNumber:0}}subscribe(e){return this.subscribers.add(e),()=>{this.subscribers.delete(e)}}watch(e){if(this.editor=e,this.editor){const n=()=>{this.transactionNumber+=1,this.subscribers.forEach(s=>s())},r=this.editor;return r.on("transaction",n),()=>{r.off("transaction",n)}}}}function Wge(t){var e;const[n]=U.useState(()=>new qge(t.editor)),r=Hge.useSyncExternalStoreWithSelector(n.subscribe,n.getSnapshot,n.getServerSnapshot,t.selector,(e=t.equalityFn)!==null&&e!==void 0?e:Bge);return Vge(()=>n.watch(t.editor),[t.editor,n]),U.useDebugValue(r),r}const Gge=!1,q_=typeof window>"u",Kge=q_||!!(typeof window<"u"&&window.next);class bI{constructor(e){this.editor=null,this.subscriptions=new Set,this.isComponentMounted=!1,this.previousDeps=null,this.instanceId="",this.options=e,this.subscriptions=new Set,this.setEditor(this.getInitialEditor()),this.scheduleDestroy(),this.getEditor=this.getEditor.bind(this),this.getServerSnapshot=this.getServerSnapshot.bind(this),this.subscribe=this.subscribe.bind(this),this.refreshEditorInstance=this.refreshEditorInstance.bind(this),this.scheduleDestroy=this.scheduleDestroy.bind(this),this.onRender=this.onRender.bind(this),this.createEditor=this.createEditor.bind(this)}setEditor(e){this.editor=e,this.instanceId=Math.random().toString(36).slice(2,9),this.subscriptions.forEach(n=>n())}getInitialEditor(){return this.options.current.immediatelyRender===void 0?q_||Kge?null:this.createEditor():(this.options.current.immediatelyRender,this.options.current.immediatelyRender?this.createEditor():null)}createEditor(){const e={...this.options.current,onBeforeCreate:(...r)=>{var s,i;return(i=(s=this.options.current).onBeforeCreate)===null||i===void 0?void 0:i.call(s,...r)},onBlur:(...r)=>{var s,i;return(i=(s=this.options.current).onBlur)===null||i===void 0?void 0:i.call(s,...r)},onCreate:(...r)=>{var s,i;return(i=(s=this.options.current).onCreate)===null||i===void 0?void 0:i.call(s,...r)},onDestroy:(...r)=>{var s,i;return(i=(s=this.options.current).onDestroy)===null||i===void 0?void 0:i.call(s,...r)},onFocus:(...r)=>{var s,i;return(i=(s=this.options.current).onFocus)===null||i===void 0?void 0:i.call(s,...r)},onSelectionUpdate:(...r)=>{var s,i;return(i=(s=this.options.current).onSelectionUpdate)===null||i===void 0?void 0:i.call(s,...r)},onTransaction:(...r)=>{var s,i;return(i=(s=this.options.current).onTransaction)===null||i===void 0?void 0:i.call(s,...r)},onUpdate:(...r)=>{var s,i;return(i=(s=this.options.current).onUpdate)===null||i===void 0?void 0:i.call(s,...r)},onContentError:(...r)=>{var s,i;return(i=(s=this.options.current).onContentError)===null||i===void 0?void 0:i.call(s,...r)},onDrop:(...r)=>{var s,i;return(i=(s=this.options.current).onDrop)===null||i===void 0?void 0:i.call(s,...r)},onPaste:(...r)=>{var s,i;return(i=(s=this.options.current).onPaste)===null||i===void 0?void 0:i.call(s,...r)}};return new Xpe(e)}getEditor(){return this.editor}getServerSnapshot(){return null}subscribe(e){return this.subscriptions.add(e),()=>{this.subscriptions.delete(e)}}static compareOptions(e,n){return Object.keys(e).every(r=>["onCreate","onBeforeCreate","onDestroy","onUpdate","onTransaction","onFocus","onBlur","onSelectionUpdate","onContentError","onDrop","onPaste"].includes(r)?!0:r==="extensions"&&e.extensions&&n.extensions?e.extensions.length!==n.extensions.length?!1:e.extensions.every((s,i)=>{var a;return s===((a=n.extensions)===null||a===void 0?void 0:a[i])}):e[r]===n[r])}onRender(e){return()=>(this.isComponentMounted=!0,clearTimeout(this.scheduledDestructionTimeout),this.editor&&!this.editor.isDestroyed&&e.length===0?bI.compareOptions(this.options.current,this.editor.options)||this.editor.setOptions({...this.options.current,editable:this.editor.isEditable}):this.refreshEditorInstance(e),()=>{this.isComponentMounted=!1,this.scheduleDestroy()})}refreshEditorInstance(e){if(this.editor&&!this.editor.isDestroyed){if(this.previousDeps===null){this.previousDeps=e;return}if(this.previousDeps.length===e.length&&this.previousDeps.every((r,s)=>r===e[s]))return}this.editor&&!this.editor.isDestroyed&&this.editor.destroy(),this.setEditor(this.createEditor()),this.previousDeps=e}scheduleDestroy(){const e=this.instanceId,n=this.editor;this.scheduledDestructionTimeout=setTimeout(()=>{if(this.isComponentMounted&&this.instanceId===e){n&&n.setOptions(this.options.current);return}n&&!n.isDestroyed&&(n.destroy(),this.instanceId===e&&this.setEditor(null))},1)}}function Jge(t={},e=[]){const n=U.useRef(t);n.current=t;const[r]=U.useState(()=>new bI(n)),s=gI.useSyncExternalStore(r.subscribe,r.getEditor,r.getServerSnapshot);return U.useDebugValue(s),U.useEffect(r.onRender(e)),Wge({editor:s,selector:({transactionNumber:i})=>t.shouldRerenderOnTransaction===!1?null:t.immediatelyRender&&i===0?0:i+1}),s}const _U=U.createContext({editor:null});_U.Consumer;const CU=()=>U.useContext(_U),Qge=t=>{const[e,n]=U.useState(null),{editor:r}=CU();return U.useEffect(()=>{var s;if(!e||!((s=t.editor)===null||s===void 0)&&s.isDestroyed||r!=null&&r.isDestroyed)return;const{pluginKey:i="bubbleMenu",editor:a,tippyOptions:o={},updateDelay:l,shouldShow:c=null}=t,h=a||r;if(!h){console.warn("BubbleMenu component is not rendered inside of an editor component or does not have editor prop.");return}const p=wU({updateDelay:l,editor:h,element:e,pluginKey:i,shouldShow:c,tippyOptions:o});return h.registerPlugin(p),()=>{h.unregisterPlugin(i)}},[t.editor,r,e]),Ar.createElement("div",{ref:n,className:t.className,style:{visibility:"hidden"}},t.children)},Xge=t=>{const[e,n]=U.useState(null),{editor:r}=CU();return U.useEffect(()=>{var s;if(!e||!((s=t.editor)===null||s===void 0)&&s.isDestroyed||r!=null&&r.isDestroyed)return;const{pluginKey:i="floatingMenu",editor:a,tippyOptions:o={},shouldShow:l=null}=t,c=a||r;if(!c){console.warn("FloatingMenu component is not rendered inside of an editor component or does not have editor prop.");return}const h=kU({pluginKey:i,editor:c,element:e,tippyOptions:o,shouldShow:l});return c.registerPlugin(h),()=>{c.unregisterPlugin(i)}},[t.editor,r,e]),Ar.createElement("div",{ref:n,className:t.className,style:{visibility:"hidden"}},t.children)},AU=U.createContext({onDragStart:void 0}),TU=()=>U.useContext(AU),IU=t=>{const e=t.as||"div",{nodeViewContentRef:n}=TU();return Ar.createElement(e,{...t,ref:n,"data-node-view-content":"",style:{whiteSpace:"pre-wrap",...t.style}})},ln=Ar.forwardRef((t,e)=>{const{onDragStart:n}=TU(),r=t.as||"div";return Ar.createElement(r,{...t,ref:e,"data-node-view-wrapper":"",onDragStart:n,style:{whiteSpace:"normal",...t.style}})});function iL(t){return!!(typeof t=="function"&&t.prototype&&t.prototype.isReactComponent)}function aL(t){return!!(typeof t=="object"&&t.$$typeof&&(t.$$typeof.toString()==="Symbol(react.forward_ref)"||t.$$typeof.description==="react.forward_ref"))}function Zge(t){return!!(typeof t=="object"&&t.$$typeof&&(t.$$typeof.toString()==="Symbol(react.memo)"||t.$$typeof.description==="react.memo"))}function Yge(t){if(iL(t)||aL(t))return!0;if(Zge(t)){const e=t.type;if(e)return iL(e)||aL(e)}return!1}function e0e(){try{if(U.version)return parseInt(U.version.split(".")[0],10)>=19}catch{}return!1}class NU{constructor(e,{editor:n,props:r={},as:s="div",className:i=""}){this.ref=null,this.id=Math.floor(Math.random()*4294967295).toString(),this.component=e,this.editor=n,this.props=r,this.element=document.createElement(s),this.element.classList.add("react-renderer"),i&&this.element.classList.add(...i.split(" ")),this.editor.isInitialized?el.flushSync(()=>{this.render()}):queueMicrotask(()=>{this.render()})}render(){var e;const n=this.component,r=this.props,s=this.editor,i=e0e(),a=Yge(n),o={...r};o.ref&&!(i||a)&&delete o.ref,!o.ref&&(i||a)&&(o.ref=l=>{this.ref=l}),this.reactElement=Ar.createElement(n,{...o}),(e=s==null?void 0:s.contentComponent)===null||e===void 0||e.setRenderer(this.id,this)}updateProps(e={}){this.props={...this.props,...e},this.render()}destroy(){var e;const n=this.editor;(e=n==null?void 0:n.contentComponent)===null||e===void 0||e.removeRenderer(this.id)}updateAttributes(e){Object.keys(e).forEach(n=>{this.element.setAttribute(n,e[n])})}}class t0e extends Zpe{constructor(e,n,r){if(super(e,n,r),!this.node.isLeaf){this.options.contentDOMElementTag?this.contentDOMElement=document.createElement(this.options.contentDOMElementTag):this.contentDOMElement=document.createElement(this.node.isInline?"span":"div"),this.contentDOMElement.dataset.nodeViewContentReact="",this.contentDOMElement.dataset.nodeViewWrapper="",this.contentDOMElement.style.whiteSpace="inherit";const s=this.dom.querySelector("[data-node-view-content]");if(!s)return;s.appendChild(this.contentDOMElement)}}mount(){const e={editor:this.editor,node:this.node,decorations:this.decorations,innerDecorations:this.innerDecorations,view:this.view,selected:!1,extension:this.extension,HTMLAttributes:this.HTMLAttributes,getPos:()=>this.getPos(),updateAttributes:(c={})=>this.updateAttributes(c),deleteNode:()=>this.deleteNode(),ref:U.createRef()};if(!this.component.displayName){const c=h=>h.charAt(0).toUpperCase()+h.substring(1);this.component.displayName=c(this.extension.name)}const s={onDragStart:this.onDragStart.bind(this),nodeViewContentRef:c=>{c&&this.contentDOMElement&&c.firstChild!==this.contentDOMElement&&(c.hasAttribute("data-node-view-wrapper")&&c.removeAttribute("data-node-view-wrapper"),c.appendChild(this.contentDOMElement))}},i=this.component,a=U.memo(c=>Ar.createElement(AU.Provider,{value:s},U.createElement(i,c)));a.displayName="ReactNodeView";let o=this.node.isInline?"span":"div";this.options.as&&(o=this.options.as);const{className:l=""}=this.options;this.handleSelectionUpdate=this.handleSelectionUpdate.bind(this),this.renderer=new NU(a,{editor:this.editor,props:e,as:o,className:`node-${this.node.type.name} ${l}`.trim()}),this.editor.on("selectionUpdate",this.handleSelectionUpdate),this.updateElementAttributes()}get dom(){var e;if(this.renderer.element.firstElementChild&&!(!((e=this.renderer.element.firstElementChild)===null||e===void 0)&&e.hasAttribute("data-node-view-wrapper")))throw Error("Please use the NodeViewWrapper component for your node view.");return this.renderer.element}get contentDOM(){return this.node.isLeaf?null:this.contentDOMElement}handleSelectionUpdate(){const{from:e,to:n}=this.editor.state.selection,r=this.getPos();if(typeof r=="number")if(e<=r&&n>=r+this.node.nodeSize){if(this.renderer.props.selected)return;this.selectNode()}else{if(!this.renderer.props.selected)return;this.deselectNode()}}update(e,n,r){const s=i=>{this.renderer.updateProps(i),typeof this.options.attrs=="function"&&this.updateElementAttributes()};if(e.type!==this.node.type)return!1;if(typeof this.options.update=="function"){const i=this.node,a=this.decorations,o=this.innerDecorations;return this.node=e,this.decorations=n,this.innerDecorations=r,this.options.update({oldNode:i,oldDecorations:a,newNode:e,newDecorations:n,oldInnerDecorations:o,innerDecorations:r,updateProps:()=>s({node:e,decorations:n,innerDecorations:r})})}return e===this.node&&this.decorations===n&&this.innerDecorations===r||(this.node=e,this.decorations=n,this.innerDecorations=r,s({node:e,decorations:n,innerDecorations:r})),!0}selectNode(){this.renderer.updateProps({selected:!0}),this.renderer.element.classList.add("ProseMirror-selectednode")}deselectNode(){this.renderer.updateProps({selected:!1}),this.renderer.element.classList.remove("ProseMirror-selectednode")}destroy(){this.renderer.destroy(),this.editor.off("selectionUpdate",this.handleSelectionUpdate),this.contentDOMElement=null}updateElementAttributes(){if(this.options.attrs){let e={};if(typeof this.options.attrs=="function"){const n=this.editor.extensionManager.attributes,r=mx(this.node,n);e=this.options.attrs({node:this.node,HTMLAttributes:r})}else e=this.options.attrs;this.renderer.updateAttributes(e)}}}function ol(t,e){return n=>n.editor.contentComponent?new t0e(t,n,e):{}}function Bn(t){var e,n,r,s,i,a;return((n=(e=t.createdAt)==null?void 0:e.toMillis)==null?void 0:n.call(e))??((s=(r=t.publishedAt)==null?void 0:r.toMillis)==null?void 0:s.call(r))??((a=(i=t.updatedAt)==null?void 0:i.toMillis)==null?void 0:a.call(i))??0}function Ql(t){const{settings:e,posts:n,pages:r,postsLoaded:s}=En(),i=e.paginationMode??"global",a=n0e(t,i==="paginated");return i==="global"?{posts:t==="post"?n:r,loading:!s}:a}function n0e(t,e){const[n,r]=U.useState([]),[s,i]=U.useState(e);return U.useEffect(()=>{if(!e){r([]),i(!1);return}let a=!1;return i(!0),Br({type:t}).then(o=>{a||(r(o),i(!1))}),()=>{a=!0}},[e,t]),{posts:n,loading:s}}const r0e="default";function s0e(t){if(t==null)return"";try{const e=JSON.stringify(t);return typeof window>"u"?Buffer.from(e,"utf-8").toString("base64"):window.btoa(unescape(encodeURIComponent(e)))}catch{return""}}function Tc(t,e){if(!t||typeof t!="string")return e;try{let n;return typeof window>"u"?n=Buffer.from(t,"base64").toString("utf-8"):n=decodeURIComponent(escape(window.atob(t))),JSON.parse(n)}catch{return e}}function PU(t){return`block${t.charAt(0).toUpperCase()}${t.slice(1)}`}function Dr(t){return typeof t!="string"?"":t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function tr(t){return typeof t!="string"?"":t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function cp({subId:t,defaultAttrs:e,view:n}){const r=`${r0e}/${t}`,s=PU(t.replace(/-([a-z])/g,(i,a)=>a.toUpperCase()));return on.create({name:s,group:"block",atom:!0,selectable:!0,draggable:!0,addAttributes(){return{attrs:{default:e,parseHTML:i=>Tc(i.getAttribute("data-attrs")??"",e),renderHTML:i=>({"data-attrs":s0e(i.attrs??e)})}}},parseHTML(){return[{tag:`div[data-cms-block="${r}"]`}]},renderHTML({HTMLAttributes:i}){return["div",Un(i,{"data-cms-block":r})]},addNodeView(){return ol(i=>{const a=i.node.attrs.attrs??e,o=l=>{i.updateAttributes({attrs:{...a,...l}})};return d.jsx(n,{attrs:a,updateAttrs:o,selected:i.selected})})}})}function up(t){return PU(t.replace(/-([a-z])/g,(e,n)=>n.toUpperCase()))}const yI="hero",Km=up(yI),RU={featuredPostId:"latest",variant:"image-overlay",showCategory:!0};function i0e({attrs:t,selected:e}){var i;const{t:n}=Fe("theme-default"),{posts:r}=Ql("post"),s=t.featuredPostId==="latest"||!t.featuredPostId?n("blocks.hero.latestLabel"):((i=r.find(a=>a.id===t.featuredPostId))==null?void 0:i.title)??n("blocks.hero.unknownPost");return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(UC,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:n("blocks.hero.title")}),d.jsx("p",{className:"mt-1 truncate text-sm text-surface-900 dark:text-surface-50",children:s}),d.jsx("p",{className:"mt-1 text-xs text-surface-500 dark:text-surface-400",children:n(`blocks.hero.variants.${t.variant??"image-overlay"}`)})]})]})})}function a0e({editor:t}){const{t:e}=Fe("theme-default"),{posts:n}=Ql("post"),r=t.getAttributes(Km),s={...RU,...r.attrs??{}};function i(o){t.chain().updateAttributes(Km,{attrs:{...s,...o}}).run()}const a=n.filter(o=>o.status==="online").sort((o,l)=>Bn(l)-Bn(o));return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.hero.featured")}),d.jsxs("select",{className:"input",value:s.featuredPostId??"latest",onChange:o=>i({featuredPostId:o.target.value}),children:[d.jsx("option",{value:"latest",children:e("blocks.hero.latestLabel")}),a.map(o=>d.jsx("option",{value:o.id,children:o.title||"(untitled)"},o.id))]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.hero.variant")}),d.jsxs("select",{className:"input",value:s.variant??"image-overlay",onChange:o=>i({variant:o.target.value}),children:[d.jsx("option",{value:"image-overlay",children:e("blocks.hero.variants.image-overlay")}),d.jsx("option",{value:"split-left",children:e("blocks.hero.variants.split-left")}),d.jsx("option",{value:"split-right",children:e("blocks.hero.variants.split-right")}),d.jsx("option",{value:"minimal",children:e("blocks.hero.variants.minimal")})]})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:s.showCategory??!0,onChange:o=>i({showCategory:o.target.checked})}),d.jsx("span",{children:e("blocks.hero.showCategory")})]})]})}const o0e=cp({subId:yI,defaultAttrs:RU,view:i0e}),l0e={id:`default/${yI}`,nodeName:Km,titleKey:"blocks.hero.title",namespace:"theme-default",icon:UC,category:"layout",extensions:[o0e],insert:t=>{t.focus().insertContent({type:Km}).run()},isActive:t=>t.isActive(Km),inspector:t=>d.jsx(a0e,{editor:t.editor})},vI="posts-list",Jm=up(vI),jU={query:"latest",count:6,variant:"cards",columns:2,excludeUsed:!0};function c0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default"),r=[n(`blocks.postsList.queries.${t.query??"latest"}`),`${t.count??6}`,n(`blocks.postsList.variants.${t.variant??"cards"}`)].join(" · ");return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(xw,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsxs("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:[n("blocks.postsList.title"),t.title?` — ${t.title}`:""]}),d.jsx("p",{className:"mt-1 text-xs text-surface-500 dark:text-surface-400",children:r})]})]})})}function u0e({editor:t}){const{t:e}=Fe("theme-default"),{tags:n,users:r}=En(),s=t.getAttributes(Jm),i={...jU,...s.attrs??{}};function a(o){t.chain().updateAttributes(Jm,{attrs:{...i,...o}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.titleField")}),d.jsx("input",{type:"text",className:"input",value:i.title??"",onChange:o=>a({title:o.target.value}),placeholder:e("blocks.postsList.titlePlaceholder")})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.query")}),d.jsxs("select",{className:"input",value:i.query??"latest",onChange:o=>a({query:o.target.value}),children:[d.jsx("option",{value:"latest",children:e("blocks.postsList.queries.latest")}),d.jsx("option",{value:"by-tag",children:e("blocks.postsList.queries.by-tag")}),d.jsx("option",{value:"by-author",children:e("blocks.postsList.queries.by-author")})]})]}),i.query==="by-tag"&&d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.tag")}),d.jsxs("select",{className:"input",value:i.tagId??"",onChange:o=>a({tagId:o.target.value||void 0}),children:[d.jsx("option",{value:"",children:"—"}),n.map(o=>d.jsx("option",{value:o.id,children:o.name},o.id))]})]}),i.query==="by-author"&&d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.author")}),d.jsxs("select",{className:"input",value:i.authorId??"",onChange:o=>a({authorId:o.target.value||void 0}),children:[d.jsx("option",{value:"",children:"—"}),r.map(o=>d.jsx("option",{value:o.id,children:[o.firstName,o.lastName].filter(Boolean).join(" ")||o.displayName||o.email},o.id))]})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.count")}),d.jsx("input",{type:"number",min:1,max:24,className:"input",value:i.count??6,onChange:o=>a({count:Number.parseInt(o.target.value,10)||1})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.columns")}),d.jsx("input",{type:"number",min:1,max:4,className:"input",value:i.columns??2,onChange:o=>a({columns:Number.parseInt(o.target.value,10)||1})})]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.variant")}),d.jsxs("select",{className:"input",value:i.variant??"cards",onChange:o=>a({variant:o.target.value}),children:[d.jsx("option",{value:"cards",children:e("blocks.postsList.variants.cards")}),d.jsx("option",{value:"list",children:e("blocks.postsList.variants.list")}),d.jsx("option",{value:"compact",children:e("blocks.postsList.variants.compact")}),d.jsx("option",{value:"numbered",children:e("blocks.postsList.variants.numbered")}),d.jsx("option",{value:"slider",children:e("blocks.postsList.variants.slider")})]})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.seeMoreLabel")}),d.jsx("input",{type:"text",className:"input",value:i.seeMoreLabel??"",onChange:o=>a({seeMoreLabel:o.target.value})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.seeMoreUrl")}),d.jsx("input",{type:"text",className:"input",value:i.seeMoreUrl??"",onChange:o=>a({seeMoreUrl:o.target.value})})]})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:i.showExcerpt??!0,onChange:o=>a({showExcerpt:o.target.checked})}),d.jsx("span",{children:e("blocks.postsList.showExcerpt")})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:i.excludeUsed??!0,onChange:o=>a({excludeUsed:o.target.checked})}),d.jsx("span",{children:e("blocks.postsList.excludeUsed")})]})]})}const d0e=cp({subId:vI,defaultAttrs:jU,view:c0e}),h0e={id:`default/${vI}`,nodeName:Jm,titleKey:"blocks.postsList.title",namespace:"theme-default",icon:xw,category:"layout",extensions:[d0e],insert:t=>{t.focus().insertContent({type:Jm}).run()},isActive:t=>t.isActive(Jm),inspector:t=>d.jsx(u0e,{editor:t.editor})},xI="category-posts",Qm=up(xI),MU={count:4,variant:"cards",columns:2,excludeUsed:!0};function f0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default"),{categories:r}=En(),s=r.find(i=>i.id===t.categoryId);return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(Wf,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:n("blocks.categoryPosts.title")}),d.jsx("p",{className:"mt-1 text-sm text-surface-900 dark:text-surface-50",children:(s==null?void 0:s.name)??n("blocks.categoryPosts.pickCategory")}),d.jsxs("p",{className:"mt-1 text-xs text-surface-500 dark:text-surface-400",children:[n(`blocks.postsList.variants.${t.variant??"cards"}`)," · ",t.count??4]})]})]})})}function p0e({editor:t}){const{t:e}=Fe("theme-default"),{categories:n}=En(),r=t.getAttributes(Qm),s={...MU,...r.attrs??{}};function i(a){t.chain().updateAttributes(Qm,{attrs:{...s,...a}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.categoryPosts.category")}),d.jsxs("select",{className:"input",value:s.categoryId??"",onChange:a=>i({categoryId:a.target.value||void 0}),children:[d.jsx("option",{value:"",children:"—"}),n.map(a=>d.jsx("option",{value:a.id,children:a.name},a.id))]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.categoryPosts.titleField")}),d.jsx("input",{type:"text",className:"input",value:s.title??"",onChange:a=>i({title:a.target.value}),placeholder:e("blocks.categoryPosts.titlePlaceholder")})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.count")}),d.jsx("input",{type:"number",min:1,max:24,className:"input",value:s.count??4,onChange:a=>i({count:Number.parseInt(a.target.value,10)||1})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.columns")}),d.jsx("input",{type:"number",min:1,max:4,className:"input",value:s.columns??2,onChange:a=>i({columns:Number.parseInt(a.target.value,10)||1})})]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.variant")}),d.jsxs("select",{className:"input",value:s.variant??"cards",onChange:a=>i({variant:a.target.value}),children:[d.jsx("option",{value:"cards",children:e("blocks.postsList.variants.cards")}),d.jsx("option",{value:"list",children:e("blocks.postsList.variants.list")}),d.jsx("option",{value:"compact",children:e("blocks.postsList.variants.compact")}),d.jsx("option",{value:"numbered",children:e("blocks.postsList.variants.numbered")}),d.jsx("option",{value:"slider",children:e("blocks.postsList.variants.slider")})]})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.seeMoreLabel")}),d.jsx("input",{type:"text",className:"input",value:s.seeMoreLabel??"",onChange:a=>i({seeMoreLabel:a.target.value})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.seeMoreUrl")}),d.jsx("input",{type:"text",className:"input",value:s.seeMoreUrl??"",onChange:a=>i({seeMoreUrl:a.target.value}),placeholder:e("blocks.categoryPosts.seeMoreUrlPlaceholder")})]})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:s.showExcerpt??!0,onChange:a=>i({showExcerpt:a.target.checked})}),d.jsx("span",{children:e("blocks.postsList.showExcerpt")})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:s.excludeUsed??!0,onChange:a=>i({excludeUsed:a.target.checked})}),d.jsx("span",{children:e("blocks.postsList.excludeUsed")})]})]})}const m0e=cp({subId:xI,defaultAttrs:MU,view:f0e}),g0e={id:`default/${xI}`,nodeName:Qm,titleKey:"blocks.categoryPosts.title",namespace:"theme-default",icon:Wf,category:"layout",extensions:[m0e],insert:t=>{t.focus().insertContent({type:Qm}).run()},isActive:t=>t.isActive(Qm),inspector:t=>d.jsx(p0e,{editor:t.editor})},wI="cta",Xm=up(wI),LU={variant:"light"};function b0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default");return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(ww,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:n("blocks.cta.title")}),d.jsx("p",{className:"mt-1 truncate text-sm text-surface-900 dark:text-surface-50",children:t.title||n("blocks.cta.placeholder")})]})]})})}function y0e({editor:t}){const{t:e}=Fe("theme-default"),n=t.getAttributes(Xm),r={...LU,...n.attrs??{}};function s(i){t.chain().updateAttributes(Xm,{attrs:{...r,...i}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.titleField")}),d.jsx("input",{type:"text",className:"input",value:r.title??"",onChange:i=>s({title:i.target.value})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.description")}),d.jsx("textarea",{className:"input min-h-[60px]",value:r.description??"",onChange:i=>s({description:i.target.value})})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.buttonLabel")}),d.jsx("input",{type:"text",className:"input",value:r.buttonLabel??"",onChange:i=>s({buttonLabel:i.target.value})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.buttonUrl")}),d.jsx("input",{type:"text",className:"input",value:r.buttonUrl??"",onChange:i=>s({buttonUrl:i.target.value})})]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.variant")}),d.jsxs("select",{className:"input max-w-xs",value:r.variant??"light",onChange:i=>s({variant:i.target.value}),children:[d.jsx("option",{value:"light",children:e("blocks.cta.variants.light")}),d.jsx("option",{value:"dark",children:e("blocks.cta.variants.dark")})]})]})]})}const v0e=cp({subId:wI,defaultAttrs:LU,view:b0e}),x0e={id:`default/${wI}`,nodeName:Xm,titleKey:"blocks.cta.title",namespace:"theme-default",icon:ww,category:"layout",extensions:[v0e],insert:t=>{t.focus().insertContent({type:Xm}).run()},isActive:t=>t.isActive(Xm),inspector:t=>d.jsx(y0e,{editor:t.editor})},kI="categories-pills",Zm=up(kI),DU={style:"pills"};function w0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default");return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(U6,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:n("blocks.categoriesPills.title")}),d.jsxs("p",{className:"mt-1 text-xs text-surface-500 dark:text-surface-400",children:[t.title||n("blocks.categoriesPills.untitled")," ·"," ",n(`blocks.categoriesPills.styles.${t.style??"pills"}`)]})]})]})})}function k0e({editor:t}){const{t:e}=Fe("theme-default"),n=t.getAttributes(Zm),r={...DU,...n.attrs??{}};function s(i){t.chain().updateAttributes(Zm,{attrs:{...r,...i}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.categoriesPills.titleField")}),d.jsx("input",{type:"text",className:"input",value:r.title??"",onChange:i=>s({title:i.target.value}),placeholder:e("blocks.categoriesPills.titlePlaceholder")})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.categoriesPills.style")}),d.jsxs("select",{className:"input max-w-xs",value:r.style??"pills",onChange:i=>s({style:i.target.value}),children:[d.jsx("option",{value:"pills",children:e("blocks.categoriesPills.styles.pills")}),d.jsx("option",{value:"list",children:e("blocks.categoriesPills.styles.list")})]})]})]})}const S0e=cp({subId:kI,defaultAttrs:DU,view:w0e}),E0e={id:`default/${kI}`,nodeName:Zm,titleKey:"blocks.categoriesPills.title",namespace:"theme-default",icon:U6,category:"layout",extensions:[S0e],insert:t=>{t.focus().insertContent({type:Zm}).run()},isActive:t=>t.isActive(Zm),inspector:t=>d.jsx(k0e,{editor:t.editor})},SI="spacer",Ym=up(SI),FU={size:"md",divider:!1};function _0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default");return d.jsx(ln,{contentEditable:!1,className:"my-2 rounded-md border border-dashed border-surface-300 bg-surface-50 p-2 text-center dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-center justify-center gap-2 text-xs text-surface-500 dark:text-surface-400",children:[d.jsx(DC,{className:"h-3 w-3"}),d.jsxs("span",{children:[n("blocks.spacer.title")," · ",n(`blocks.spacer.sizes.${t.size??"md"}`),t.divider?` · ${n("blocks.spacer.dividerOn")}`:""]})]})})}function C0e({editor:t}){const{t:e}=Fe("theme-default"),n=t.getAttributes(Ym),r={...FU,...n.attrs??{}};function s(i){t.chain().updateAttributes(Ym,{attrs:{...r,...i}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.spacer.size")}),d.jsxs("select",{className:"input max-w-xs",value:r.size??"md",onChange:i=>s({size:i.target.value}),children:[d.jsx("option",{value:"sm",children:e("blocks.spacer.sizes.sm")}),d.jsx("option",{value:"md",children:e("blocks.spacer.sizes.md")}),d.jsx("option",{value:"lg",children:e("blocks.spacer.sizes.lg")})]})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:r.divider??!1,onChange:i=>s({divider:i.target.checked})}),d.jsx("span",{children:e("blocks.spacer.divider")})]})]})}const A0e=cp({subId:SI,defaultAttrs:FU,view:_0e}),T0e={id:`default/${SI}`,nodeName:Ym,titleKey:"blocks.spacer.title",namespace:"theme-default",icon:DC,category:"layout",extensions:[A0e],insert:t=>{t.focus().insertContent({type:Ym}).run()},isActive:t=>t.isActive(Ym),inspector:t=>d.jsx(C0e,{editor:t.editor})};let OU=null;function vx(t){OU=t}function zU(){return OU}function I0e(t,e){if(t.featuredPostId&&t.featuredPostId!=="latest"){const r=e.ctx.posts.find(s=>s.id===t.featuredPostId&&s.status==="online");if(r)return r}return e.ctx.posts.filter(r=>r.status==="online"&&r.id!==e.current.id).sort((r,s)=>Bn(s)-Bn(r))[0]??null}function UU(t,e){const n=I0e(t,e);if(!n)return{html:"",consumedPostId:null};const r=t.variant??"image-overlay",s=t.showCategory??!0,i=n.primaryTermId?e.ctx.terms.find(x=>x.id===n.primaryTermId&&x.type==="category"):void 0,a=`/${Tr({post:n,primaryTerm:i})}`,o=ia(e.ctx.media.get(n.heroMediaId??"")),l=Js(o,"large"),c=s&&i?`<a href="/${Dr(sa(i))}" class="cms-hero-category">${tr(i.name)}</a>`:"",h=`<h2 class="cms-hero-title"><a href="${Dr(a)}">${tr(n.title)}</a></h2>`,p=n.excerpt?`<p class="cms-hero-excerpt">${tr(n.excerpt)}</p>`:"",m=l?`<div class="cms-hero-image-wrap"><a href="${Dr(a)}" tabindex="-1" aria-hidden="true"><img class="cms-hero-image" src="${Dr(l)}" alt="${Dr((o==null?void 0:o.alt)??n.title)}" loading="lazy" /></a></div>`:"",g=`<div class="cms-hero-content">${c}${h}${p}</div>`,y=`cms-hero cms-hero-${r}`;return r==="minimal"?{html:`<section class="${y}">${g}</section>`,consumedPostId:n.id}:{html:`<section class="${y}">${m}${g}</section>`,consumedPostId:n.id}}function N0e(t,e){var r,s,i,a,o,l;const n=((s=(r=t.publishedAt)==null?void 0:r.toMillis)==null?void 0:s.call(r))??((a=(i=t.updatedAt)==null?void 0:i.toMillis)==null?void 0:a.call(i))??((l=(o=t.createdAt)==null?void 0:o.toMillis)==null?void 0:l.call(o));if(!n)return"";try{return new Intl.DateTimeFormat(e.settings.language||"en",{month:"short",day:"numeric",year:"numeric"}).format(new Date(n))}catch{return new Date(n).toDateString()}}function BU({post:t,ctx:e,variant:n,index:r,showExcerpt:s=!0}){const i=t.primaryTermId?e.terms.find(y=>y.id===t.primaryTermId&&y.type==="category"):void 0,a=`/${Tr({post:t,primaryTerm:i})}`,o=ia(e.media.get(t.heroMediaId??"")),l=Js(o,"medium"),c=N0e(t,e),h=i&&n!=="compact"?`<span class="cms-card-category">${tr(i.name)}</span>`:"",p=n==="compact"?c?`<span class="cms-card-meta">${tr(c)}</span>`:"":c?`<span class="cms-card-meta">${tr(c)}</span>`:"";if(n==="numbered"){const y=String(r+1).padStart(2,"0");return`<a href="${Dr(a)}" class="cms-card cms-card-numbered"><span class="cms-card-number">${y}</span><span class="cms-card-title">${tr(t.title)}</span>${p?`<span class="cms-card-meta">${tr(c)}</span>`:""}</a>`}if(n==="compact")return`<a href="${Dr(a)}" class="cms-card cms-card-compact"><span class="cms-card-title">${tr(t.title)}</span>${p}</a>`;if(n==="slider"){const y=l?`<div class="cms-card-slider-image-wrap"><img class="cms-card-slider-image" src="${Dr(l)}" alt="${Dr((o==null?void 0:o.alt)??t.title)}" loading="lazy" /></div>`:"",x=y?"":" cms-card-slider-no-image";return`<a href="${Dr(a)}" class="cms-card cms-card-slider${x}">${y}<div class="cms-card-slider-overlay">${h}<h4 class="cms-card-title">${tr(t.title)}</h4>${p}</div></a>`}if(n==="list"){const y=s&&t.excerpt?`<p class="cms-card-excerpt">${tr(t.excerpt)}</p>`:"",x=Js(o,"small"),v=x?`<div class="cms-card-list-image-wrap"><img class="cms-card-list-image" src="${Dr(x)}" alt="${Dr((o==null?void 0:o.alt)??t.title)}" loading="lazy" /></div>`:"";return`<a href="${Dr(a)}" class="cms-card cms-card-list${v?" cms-card-list-with-image":""}">${v}<div class="cms-card-list-body"><h4 class="cms-card-title">${tr(t.title)}</h4>${y}${p}</div></a>`}const m=l?`<div class="cms-card-image-wrap"><img class="cms-card-image" src="${Dr(l)}" alt="${Dr((o==null?void 0:o.alt)??t.title)}" loading="lazy" /></div>`:"",g=s&&t.excerpt?`<p class="cms-card-excerpt">${tr(t.excerpt)}</p>`:"";return`<a href="${Dr(a)}" class="cms-card cms-card-default">${m}<div class="cms-card-body">${h}<h4 class="cms-card-title">${tr(t.title)}</h4>${g}${p}</div></a>`}function $U(t,e,n){const r=Math.max(1,Math.min(4,Math.floor(n)||1));return e==="slider"?`<div class="cms-list cms-list-slider">${t.join("")}</div>`:e==="list"?`<div class="cms-list cms-list-list">${t.join("")}</div>`:e==="compact"?`<div class="cms-list cms-list-compact">${t.join("")}</div>`:e==="numbered"?`<div class="cms-list cms-list-numbered">${t.join("")}</div>`:`<div class="cms-list cms-list-cards cms-list-cols-${r}">${t.join("")}</div>`}function P0e(t,e){const n=e.ctx.posts.filter(s=>s.status==="online"&&s.id!==e.current.id);let r=n;switch(t.query){case"by-tag":t.tagId&&(r=n.filter(s=>s.termIds.includes(t.tagId)));break;case"by-author":t.authorId&&(r=n.filter(s=>s.authorId===t.authorId));break}return r.sort((s,i)=>Bn(i)-Bn(s))}function HU(t,e){const n=t.variant??"cards",r=Math.max(1,Math.min(24,t.count??6)),s=t.columns??(n==="cards"?2:1),i=t.excludeUsed??!0,a=P0e(t,e),l=(i?a.filter(y=>!e.used.has(y.id)):a).slice(0,r);if(l.length===0)return{html:"",consumedPostIds:[]};const c=t.showExcerpt??!0,h=l.map((y,x)=>BU({post:y,ctx:e.ctx,variant:n,index:x,showExcerpt:c})),p=$U(h,n,s),m=[];return t.title&&m.push(`<h3 class="cms-list-title">${tr(t.title)}</h3>`),t.seeMoreUrl&&t.seeMoreLabel&&m.push(`<a class="cms-list-see-more" href="${Dr(t.seeMoreUrl)}">${tr(t.seeMoreLabel)}</a>`),{html:`<section class="cms-list-block">${m.length?`<div class="cms-list-header">${m.join("")}</div>`:""}${p}</section>`,consumedPostIds:l.map(y=>y.id)}}function R0e(t,e){var C,N,_;if(!t.categoryId)return{html:"",consumedPostIds:[]};const n=e.ctx.terms.find(P=>P.id===t.categoryId&&P.type==="category");if(!n)return{html:"",consumedPostIds:[]};const r=t.variant??"cards",s=Math.max(1,Math.min(24,t.count??4)),i=t.columns??(r==="cards"?2:1),a=t.excludeUsed??!0,o=e.ctx.posts.filter(P=>P.status==="online"&&P.id!==e.current.id&&P.primaryTermId===t.categoryId).sort((P,D)=>Bn(D)-Bn(P)),c=(a?o.filter(P=>!e.used.has(P.id)):o).slice(0,s);if(c.length===0)return{html:"",consumedPostIds:[]};const h=t.showExcerpt??!0,p=c.map((P,D)=>BU({post:P,ctx:e.ctx,variant:r,index:D,showExcerpt:h})),m=$U(p,r,i),g=((C=t.title)==null?void 0:C.trim())||n.name,y=((N=t.seeMoreUrl)==null?void 0:N.trim())||`/${sa(n)}`,x=(_=t.seeMoreLabel)==null?void 0:_.trim(),v=[];return g&&v.push(`<h3 class="cms-list-title">${tr(g)}</h3>`),x&&v.push(`<a class="cms-list-see-more" href="${Dr(y)}">${tr(x)}</a>`),{html:`<section class="cms-list-block cms-list-block-category">${v.length?`<div class="cms-list-header">${v.join("")}</div>`:""}${m}</section>`,consumedPostIds:c.map(P=>P.id)}}function j0e(t){if(!t.title&&!t.description)return"";const e=t.variant??"light",n=t.title?`<h3 class="cms-cta-title">${tr(t.title)}</h3>`:"",r=t.description?`<p class="cms-cta-description">${tr(t.description)}</p>`:"",s=t.buttonLabel&&t.buttonUrl?`<a class="cms-cta-button" href="${Dr(t.buttonUrl)}">${tr(t.buttonLabel)}</a>`:"";return`<section class="cms-cta cms-cta-${e}"><div class="cms-cta-body">${n}${r}</div>${s}</section>`}function M0e(t,e){const n=e.ctx.terms.filter(a=>a.type==="category").sort((a,o)=>a.name.localeCompare(o.name));if(n.length===0)return"";const r=t.style??"pills",s=t.title?`<h3 class="cms-categories-title">${tr(t.title)}</h3>`:"",i=n.map(a=>`<a class="cms-categories-pill" href="/${Dr(sa(a))}">${tr(a.name)}</a>`).join("");return`<section class="cms-categories cms-categories-${r}">${s}<div class="cms-categories-items">${i}</div></section>`}function L0e(t){const e=t.size??"md",n=t.divider===!0;return`<div class="cms-spacer cms-spacer-${e}${n?" cms-spacer-divider":""}" aria-hidden="true"></div>`}const eg=/<div\s+([^>]*data-cms-block="default\/([\w-]+)"[^>]*)>\s*<\/div>/g;function D0e(t,e){const n=t.match(new RegExp(`${e}=(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`));return n?n[1]??n[2]??n[3]??"":""}function F0e(t){const e=[];eg.lastIndex=0;let n;for(;(n=eg.exec(t))!==null;)e.push({match:n[0],blockId:n[2],attrsRaw:D0e(n[1],"data-attrs"),index:n.index});return e}function O0e(t,e){switch(t.blockId){case"hero":{const n=Tc(t.attrsRaw,{}),r=UU(n,e);return r.consumedPostId&&e.used.add(r.consumedPostId),r.html}case"posts-list":{const n=Tc(t.attrsRaw,{}),r=HU(n,e);for(const s of r.consumedPostIds)e.used.add(s);return r.html}case"category-posts":{const n=Tc(t.attrsRaw,{}),r=R0e(n,e);for(const s of r.consumedPostIds)e.used.add(s);return r.html}case"cta":{const n=Tc(t.attrsRaw,{});return j0e(n)}case"categories-pills":{const n=Tc(t.attrsRaw,{});return M0e(n,e)}case"spacer":{const n=Tc(t.attrsRaw,{});return L0e(n)}default:return""}}function z0e(t,e){for(const n of t){if(n.blockId!=="hero")continue;const r=Tc(n.attrsRaw,{}),s=U0e(r,e);s&&e.used.add(s)}}function U0e(t,e){var r;return t.featuredPostId&&t.featuredPostId!=="latest"?t.featuredPostId:((r=e.ctx.posts.filter(s=>s.status==="online"&&s.id!==e.current.id).sort((s,i)=>Bn(i)-Bn(s))[0])==null?void 0:r.id)??null}function B0e(t,e){if(!t.includes('data-cms-block="default/'))return t;const n=zU();if(!n)return t.replace(eg,"");const r=F0e(t);if(r.length===0)return t;const s={ctx:n,current:e,used:new Set};z0e(r,s);const i=new Map;for(const c of r)i.set(c.index,O0e(c,s));let a="",o=0;eg.lastIndex=0;let l;for(;(l=eg.exec(t))!==null;)a+=t.slice(o,l.index),a+=i.get(l.index)??"",o=l.index+l[0].length;return a+=t.slice(o),a}const W_={id:"default",name:"Default",version:"1.0.0",description:"Minimal blog/site theme that ships with Flexweg CMS.",scssEntry:"theme.scss",cssText:xj,jsText:yle,jsTextPosts:vle,i18n:{en:xle,fr:wle,de:kle,es:Sle,nl:Ele,pt:_le,ko:Cle},settings:{navLabelKey:"title",defaultConfig:Rle,component:Xue},compileCss:t=>O8(xj,t.style),imageFormats:{inputFormats:[".jpg",".jpeg",".png",".webp",".gif"],outputFormat:"webp",quality:80,formats:{small:{width:480,height:480,fit:"cover"},medium:{width:800,height:800,fit:"cover"},large:{width:1600,height:900,fit:"cover"}},defaultFormat:"medium"},templates:{base:ole,home:lle,single:dle,category:hle,author:gle,notFound:ble},blocks:[l0e,h0e,g0e,x0e,E0e,T0e],register(t){t.addFilter("post.html.body",(e,...n)=>B0e(e,n[0]))}},lu=[],cu=[],$0e=new Set;function dp(){for(const t of $0e)t()}function VU(t){const e=lu.findIndex(n=>n.id===t.id);e>=0?lu[e]=t:lu.push(t),dp()}function qU(t){const e=cu.findIndex(n=>n.id===t.id);e>=0?cu[e]=t:cu.push(t),dp()}function H0e(t){const e=lu.findIndex(n=>n.id===t);e>=0&&(lu.splice(e,1),dp())}function V0e(t){const e=cu.findIndex(n=>n.id===t);e>=0&&(cu.splice(e,1),dp())}function R1(){return lu}function WU(){return cu}function q0e(){lu.length!==0&&(lu.length=0,dp())}function W0e(){cu.length!==0&&(cu.length=0,dp())}const GU={plugins:[],themes:[]};function ga(t){return t.replace(/[&<>"']/g,e=>{switch(e){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";default:return"'"}})}function G0e(t){return t.replace(/]]>/g,"]]]]><![CDATA[>")}function oL(t){return new Date(t).toUTCString()}function K0e(t){const e=['<?xml version="1.0" encoding="UTF-8"?>'];t.xslHref&&e.push(`<?xml-stylesheet type="text/xsl" href="${ga(t.xslHref)}"?>`),e.push('<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">'),e.push(" <channel>"),e.push(` <title>${ga(t.title)}</title>`),e.push(` <link>${ga(t.link)}</link>`),e.push(` <description>${ga(t.description)}</description>`),e.push(` <language>${ga(t.language||"en")}</language>`),e.push(` <lastBuildDate>${oL(Date.now())}</lastBuildDate>`),e.push(` <atom:link href="${ga(t.feedUrl)}" rel="self" type="application/rss+xml"/>`);for(const n of t.items)e.push(" <item>"),e.push(` <title>${ga(n.title)}</title>`),e.push(` <link>${ga(n.link)}</link>`),e.push(` <guid isPermaLink="true">${ga(n.guid)}</guid>`),n.category&&e.push(` <category>${ga(n.category)}</category>`),e.push(` <description><![CDATA[${G0e(n.description)}]]></description>`),e.push(` <pubDate>${oL(n.pubDateMs)}</pubDate>`),n.enclosure&&e.push(` <enclosure url="${ga(n.enclosure.url)}" length="${n.enclosure.length}" type="${ga(n.enclosure.type)}"/>`),e.push(" </item>");return e.push(" </channel>"),e.push("</rss>"),e.join(`
|
|
4660
|
+
*/var sL;function $ge(){if(sL)return I2;sL=1;var t=Ar,e=gI;function n(c,h){return c===h&&(c!==0||1/c===1/h)||c!==c&&h!==h}var r=typeof Object.is=="function"?Object.is:n,s=e.useSyncExternalStore,i=t.useRef,a=t.useEffect,o=t.useMemo,l=t.useDebugValue;return I2.useSyncExternalStoreWithSelector=function(c,h,p,m,g){var y=i(null);if(y.current===null){var x={hasValue:!1,value:null};y.current=x}else x=y.current;y=o(function(){function k(D){if(!C){if(C=!0,N=D,D=m(D),g!==void 0&&x.hasValue){var I=x.value;if(g(I,D))return _=I}return _=D}if(I=_,r(N,D))return I;var L=m(D);return g!==void 0&&g(I,L)?I:(N=D,_=L)}var C=!1,N,_,P=p===void 0?null:p;return[function(){return k(h())},P===null?void 0:function(){return k(P())}]},[h,p,m,g]);var v=s(c,y[0],y[1]);return a(function(){x.hasValue=!0,x.value=v},[v]),l(v),v},I2}EU.exports=$ge();var Hge=EU.exports;const Vge=typeof window<"u"?U.useLayoutEffect:U.useEffect;class qge{constructor(e){this.transactionNumber=0,this.lastTransactionNumber=0,this.subscribers=new Set,this.editor=e,this.lastSnapshot={editor:e,transactionNumber:0},this.getSnapshot=this.getSnapshot.bind(this),this.getServerSnapshot=this.getServerSnapshot.bind(this),this.watch=this.watch.bind(this),this.subscribe=this.subscribe.bind(this)}getSnapshot(){return this.transactionNumber===this.lastTransactionNumber?this.lastSnapshot:(this.lastTransactionNumber=this.transactionNumber,this.lastSnapshot={editor:this.editor,transactionNumber:this.transactionNumber},this.lastSnapshot)}getServerSnapshot(){return{editor:null,transactionNumber:0}}subscribe(e){return this.subscribers.add(e),()=>{this.subscribers.delete(e)}}watch(e){if(this.editor=e,this.editor){const n=()=>{this.transactionNumber+=1,this.subscribers.forEach(s=>s())},r=this.editor;return r.on("transaction",n),()=>{r.off("transaction",n)}}}}function Wge(t){var e;const[n]=U.useState(()=>new qge(t.editor)),r=Hge.useSyncExternalStoreWithSelector(n.subscribe,n.getSnapshot,n.getServerSnapshot,t.selector,(e=t.equalityFn)!==null&&e!==void 0?e:Bge);return Vge(()=>n.watch(t.editor),[t.editor,n]),U.useDebugValue(r),r}const Gge=!1,q_=typeof window>"u",Kge=q_||!!(typeof window<"u"&&window.next);class bI{constructor(e){this.editor=null,this.subscriptions=new Set,this.isComponentMounted=!1,this.previousDeps=null,this.instanceId="",this.options=e,this.subscriptions=new Set,this.setEditor(this.getInitialEditor()),this.scheduleDestroy(),this.getEditor=this.getEditor.bind(this),this.getServerSnapshot=this.getServerSnapshot.bind(this),this.subscribe=this.subscribe.bind(this),this.refreshEditorInstance=this.refreshEditorInstance.bind(this),this.scheduleDestroy=this.scheduleDestroy.bind(this),this.onRender=this.onRender.bind(this),this.createEditor=this.createEditor.bind(this)}setEditor(e){this.editor=e,this.instanceId=Math.random().toString(36).slice(2,9),this.subscriptions.forEach(n=>n())}getInitialEditor(){return this.options.current.immediatelyRender===void 0?q_||Kge?null:this.createEditor():(this.options.current.immediatelyRender,this.options.current.immediatelyRender?this.createEditor():null)}createEditor(){const e={...this.options.current,onBeforeCreate:(...r)=>{var s,i;return(i=(s=this.options.current).onBeforeCreate)===null||i===void 0?void 0:i.call(s,...r)},onBlur:(...r)=>{var s,i;return(i=(s=this.options.current).onBlur)===null||i===void 0?void 0:i.call(s,...r)},onCreate:(...r)=>{var s,i;return(i=(s=this.options.current).onCreate)===null||i===void 0?void 0:i.call(s,...r)},onDestroy:(...r)=>{var s,i;return(i=(s=this.options.current).onDestroy)===null||i===void 0?void 0:i.call(s,...r)},onFocus:(...r)=>{var s,i;return(i=(s=this.options.current).onFocus)===null||i===void 0?void 0:i.call(s,...r)},onSelectionUpdate:(...r)=>{var s,i;return(i=(s=this.options.current).onSelectionUpdate)===null||i===void 0?void 0:i.call(s,...r)},onTransaction:(...r)=>{var s,i;return(i=(s=this.options.current).onTransaction)===null||i===void 0?void 0:i.call(s,...r)},onUpdate:(...r)=>{var s,i;return(i=(s=this.options.current).onUpdate)===null||i===void 0?void 0:i.call(s,...r)},onContentError:(...r)=>{var s,i;return(i=(s=this.options.current).onContentError)===null||i===void 0?void 0:i.call(s,...r)},onDrop:(...r)=>{var s,i;return(i=(s=this.options.current).onDrop)===null||i===void 0?void 0:i.call(s,...r)},onPaste:(...r)=>{var s,i;return(i=(s=this.options.current).onPaste)===null||i===void 0?void 0:i.call(s,...r)}};return new Xpe(e)}getEditor(){return this.editor}getServerSnapshot(){return null}subscribe(e){return this.subscriptions.add(e),()=>{this.subscriptions.delete(e)}}static compareOptions(e,n){return Object.keys(e).every(r=>["onCreate","onBeforeCreate","onDestroy","onUpdate","onTransaction","onFocus","onBlur","onSelectionUpdate","onContentError","onDrop","onPaste"].includes(r)?!0:r==="extensions"&&e.extensions&&n.extensions?e.extensions.length!==n.extensions.length?!1:e.extensions.every((s,i)=>{var a;return s===((a=n.extensions)===null||a===void 0?void 0:a[i])}):e[r]===n[r])}onRender(e){return()=>(this.isComponentMounted=!0,clearTimeout(this.scheduledDestructionTimeout),this.editor&&!this.editor.isDestroyed&&e.length===0?bI.compareOptions(this.options.current,this.editor.options)||this.editor.setOptions({...this.options.current,editable:this.editor.isEditable}):this.refreshEditorInstance(e),()=>{this.isComponentMounted=!1,this.scheduleDestroy()})}refreshEditorInstance(e){if(this.editor&&!this.editor.isDestroyed){if(this.previousDeps===null){this.previousDeps=e;return}if(this.previousDeps.length===e.length&&this.previousDeps.every((r,s)=>r===e[s]))return}this.editor&&!this.editor.isDestroyed&&this.editor.destroy(),this.setEditor(this.createEditor()),this.previousDeps=e}scheduleDestroy(){const e=this.instanceId,n=this.editor;this.scheduledDestructionTimeout=setTimeout(()=>{if(this.isComponentMounted&&this.instanceId===e){n&&n.setOptions(this.options.current);return}n&&!n.isDestroyed&&(n.destroy(),this.instanceId===e&&this.setEditor(null))},1)}}function Jge(t={},e=[]){const n=U.useRef(t);n.current=t;const[r]=U.useState(()=>new bI(n)),s=gI.useSyncExternalStore(r.subscribe,r.getEditor,r.getServerSnapshot);return U.useDebugValue(s),U.useEffect(r.onRender(e)),Wge({editor:s,selector:({transactionNumber:i})=>t.shouldRerenderOnTransaction===!1?null:t.immediatelyRender&&i===0?0:i+1}),s}const _U=U.createContext({editor:null});_U.Consumer;const CU=()=>U.useContext(_U),Qge=t=>{const[e,n]=U.useState(null),{editor:r}=CU();return U.useEffect(()=>{var s;if(!e||!((s=t.editor)===null||s===void 0)&&s.isDestroyed||r!=null&&r.isDestroyed)return;const{pluginKey:i="bubbleMenu",editor:a,tippyOptions:o={},updateDelay:l,shouldShow:c=null}=t,h=a||r;if(!h){console.warn("BubbleMenu component is not rendered inside of an editor component or does not have editor prop.");return}const p=wU({updateDelay:l,editor:h,element:e,pluginKey:i,shouldShow:c,tippyOptions:o});return h.registerPlugin(p),()=>{h.unregisterPlugin(i)}},[t.editor,r,e]),Ar.createElement("div",{ref:n,className:t.className,style:{visibility:"hidden"}},t.children)},Xge=t=>{const[e,n]=U.useState(null),{editor:r}=CU();return U.useEffect(()=>{var s;if(!e||!((s=t.editor)===null||s===void 0)&&s.isDestroyed||r!=null&&r.isDestroyed)return;const{pluginKey:i="floatingMenu",editor:a,tippyOptions:o={},shouldShow:l=null}=t,c=a||r;if(!c){console.warn("FloatingMenu component is not rendered inside of an editor component or does not have editor prop.");return}const h=kU({pluginKey:i,editor:c,element:e,tippyOptions:o,shouldShow:l});return c.registerPlugin(h),()=>{c.unregisterPlugin(i)}},[t.editor,r,e]),Ar.createElement("div",{ref:n,className:t.className,style:{visibility:"hidden"}},t.children)},AU=U.createContext({onDragStart:void 0}),TU=()=>U.useContext(AU),IU=t=>{const e=t.as||"div",{nodeViewContentRef:n}=TU();return Ar.createElement(e,{...t,ref:n,"data-node-view-content":"",style:{whiteSpace:"pre-wrap",...t.style}})},ln=Ar.forwardRef((t,e)=>{const{onDragStart:n}=TU(),r=t.as||"div";return Ar.createElement(r,{...t,ref:e,"data-node-view-wrapper":"",onDragStart:n,style:{whiteSpace:"normal",...t.style}})});function iL(t){return!!(typeof t=="function"&&t.prototype&&t.prototype.isReactComponent)}function aL(t){return!!(typeof t=="object"&&t.$$typeof&&(t.$$typeof.toString()==="Symbol(react.forward_ref)"||t.$$typeof.description==="react.forward_ref"))}function Zge(t){return!!(typeof t=="object"&&t.$$typeof&&(t.$$typeof.toString()==="Symbol(react.memo)"||t.$$typeof.description==="react.memo"))}function Yge(t){if(iL(t)||aL(t))return!0;if(Zge(t)){const e=t.type;if(e)return iL(e)||aL(e)}return!1}function e0e(){try{if(U.version)return parseInt(U.version.split(".")[0],10)>=19}catch{}return!1}class NU{constructor(e,{editor:n,props:r={},as:s="div",className:i=""}){this.ref=null,this.id=Math.floor(Math.random()*4294967295).toString(),this.component=e,this.editor=n,this.props=r,this.element=document.createElement(s),this.element.classList.add("react-renderer"),i&&this.element.classList.add(...i.split(" ")),this.editor.isInitialized?el.flushSync(()=>{this.render()}):queueMicrotask(()=>{this.render()})}render(){var e;const n=this.component,r=this.props,s=this.editor,i=e0e(),a=Yge(n),o={...r};o.ref&&!(i||a)&&delete o.ref,!o.ref&&(i||a)&&(o.ref=l=>{this.ref=l}),this.reactElement=Ar.createElement(n,{...o}),(e=s==null?void 0:s.contentComponent)===null||e===void 0||e.setRenderer(this.id,this)}updateProps(e={}){this.props={...this.props,...e},this.render()}destroy(){var e;const n=this.editor;(e=n==null?void 0:n.contentComponent)===null||e===void 0||e.removeRenderer(this.id)}updateAttributes(e){Object.keys(e).forEach(n=>{this.element.setAttribute(n,e[n])})}}class t0e extends Zpe{constructor(e,n,r){if(super(e,n,r),!this.node.isLeaf){this.options.contentDOMElementTag?this.contentDOMElement=document.createElement(this.options.contentDOMElementTag):this.contentDOMElement=document.createElement(this.node.isInline?"span":"div"),this.contentDOMElement.dataset.nodeViewContentReact="",this.contentDOMElement.dataset.nodeViewWrapper="",this.contentDOMElement.style.whiteSpace="inherit";const s=this.dom.querySelector("[data-node-view-content]");if(!s)return;s.appendChild(this.contentDOMElement)}}mount(){const e={editor:this.editor,node:this.node,decorations:this.decorations,innerDecorations:this.innerDecorations,view:this.view,selected:!1,extension:this.extension,HTMLAttributes:this.HTMLAttributes,getPos:()=>this.getPos(),updateAttributes:(c={})=>this.updateAttributes(c),deleteNode:()=>this.deleteNode(),ref:U.createRef()};if(!this.component.displayName){const c=h=>h.charAt(0).toUpperCase()+h.substring(1);this.component.displayName=c(this.extension.name)}const s={onDragStart:this.onDragStart.bind(this),nodeViewContentRef:c=>{c&&this.contentDOMElement&&c.firstChild!==this.contentDOMElement&&(c.hasAttribute("data-node-view-wrapper")&&c.removeAttribute("data-node-view-wrapper"),c.appendChild(this.contentDOMElement))}},i=this.component,a=U.memo(c=>Ar.createElement(AU.Provider,{value:s},U.createElement(i,c)));a.displayName="ReactNodeView";let o=this.node.isInline?"span":"div";this.options.as&&(o=this.options.as);const{className:l=""}=this.options;this.handleSelectionUpdate=this.handleSelectionUpdate.bind(this),this.renderer=new NU(a,{editor:this.editor,props:e,as:o,className:`node-${this.node.type.name} ${l}`.trim()}),this.editor.on("selectionUpdate",this.handleSelectionUpdate),this.updateElementAttributes()}get dom(){var e;if(this.renderer.element.firstElementChild&&!(!((e=this.renderer.element.firstElementChild)===null||e===void 0)&&e.hasAttribute("data-node-view-wrapper")))throw Error("Please use the NodeViewWrapper component for your node view.");return this.renderer.element}get contentDOM(){return this.node.isLeaf?null:this.contentDOMElement}handleSelectionUpdate(){const{from:e,to:n}=this.editor.state.selection,r=this.getPos();if(typeof r=="number")if(e<=r&&n>=r+this.node.nodeSize){if(this.renderer.props.selected)return;this.selectNode()}else{if(!this.renderer.props.selected)return;this.deselectNode()}}update(e,n,r){const s=i=>{this.renderer.updateProps(i),typeof this.options.attrs=="function"&&this.updateElementAttributes()};if(e.type!==this.node.type)return!1;if(typeof this.options.update=="function"){const i=this.node,a=this.decorations,o=this.innerDecorations;return this.node=e,this.decorations=n,this.innerDecorations=r,this.options.update({oldNode:i,oldDecorations:a,newNode:e,newDecorations:n,oldInnerDecorations:o,innerDecorations:r,updateProps:()=>s({node:e,decorations:n,innerDecorations:r})})}return e===this.node&&this.decorations===n&&this.innerDecorations===r||(this.node=e,this.decorations=n,this.innerDecorations=r,s({node:e,decorations:n,innerDecorations:r})),!0}selectNode(){this.renderer.updateProps({selected:!0}),this.renderer.element.classList.add("ProseMirror-selectednode")}deselectNode(){this.renderer.updateProps({selected:!1}),this.renderer.element.classList.remove("ProseMirror-selectednode")}destroy(){this.renderer.destroy(),this.editor.off("selectionUpdate",this.handleSelectionUpdate),this.contentDOMElement=null}updateElementAttributes(){if(this.options.attrs){let e={};if(typeof this.options.attrs=="function"){const n=this.editor.extensionManager.attributes,r=mx(this.node,n);e=this.options.attrs({node:this.node,HTMLAttributes:r})}else e=this.options.attrs;this.renderer.updateAttributes(e)}}}function ol(t,e){return n=>n.editor.contentComponent?new t0e(t,n,e):{}}function Bn(t){var e,n,r,s,i,a;return((n=(e=t.createdAt)==null?void 0:e.toMillis)==null?void 0:n.call(e))??((s=(r=t.publishedAt)==null?void 0:r.toMillis)==null?void 0:s.call(r))??((a=(i=t.updatedAt)==null?void 0:i.toMillis)==null?void 0:a.call(i))??0}function Ql(t){const{settings:e,posts:n,pages:r,postsLoaded:s}=En(),i=e.paginationMode??"global",a=n0e(t,i==="paginated");return i==="global"?{posts:t==="post"?n:r,loading:!s}:a}function n0e(t,e){const[n,r]=U.useState([]),[s,i]=U.useState(e);return U.useEffect(()=>{if(!e){r([]),i(!1);return}let a=!1;return i(!0),Br({type:t}).then(o=>{a||(r(o),i(!1))}),()=>{a=!0}},[e,t]),{posts:n,loading:s}}const r0e="default";function s0e(t){if(t==null)return"";try{const e=JSON.stringify(t);return typeof window>"u"?Buffer.from(e,"utf-8").toString("base64"):window.btoa(unescape(encodeURIComponent(e)))}catch{return""}}function Tc(t,e){if(!t||typeof t!="string")return e;try{let n;return typeof window>"u"?n=Buffer.from(t,"base64").toString("utf-8"):n=decodeURIComponent(escape(window.atob(t))),JSON.parse(n)}catch{return e}}function PU(t){return`block${t.charAt(0).toUpperCase()}${t.slice(1)}`}function Dr(t){return typeof t!="string"?"":t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function tr(t){return typeof t!="string"?"":t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function cp({subId:t,defaultAttrs:e,view:n}){const r=`${r0e}/${t}`,s=PU(t.replace(/-([a-z])/g,(i,a)=>a.toUpperCase()));return on.create({name:s,group:"block",atom:!0,selectable:!0,draggable:!0,addAttributes(){return{attrs:{default:e,parseHTML:i=>Tc(i.getAttribute("data-attrs")??"",e),renderHTML:i=>({"data-attrs":s0e(i.attrs??e)})}}},parseHTML(){return[{tag:`div[data-cms-block="${r}"]`}]},renderHTML({HTMLAttributes:i}){return["div",Un(i,{"data-cms-block":r})]},addNodeView(){return ol(i=>{const a=i.node.attrs.attrs??e,o=l=>{i.updateAttributes({attrs:{...a,...l}})};return d.jsx(n,{attrs:a,updateAttrs:o,selected:i.selected})})}})}function up(t){return PU(t.replace(/-([a-z])/g,(e,n)=>n.toUpperCase()))}const yI="hero",Km=up(yI),RU={featuredPostId:"latest",variant:"image-overlay",showCategory:!0};function i0e({attrs:t,selected:e}){var i;const{t:n}=Fe("theme-default"),{posts:r}=Ql("post"),s=t.featuredPostId==="latest"||!t.featuredPostId?n("blocks.hero.latestLabel"):((i=r.find(a=>a.id===t.featuredPostId))==null?void 0:i.title)??n("blocks.hero.unknownPost");return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(UC,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:n("blocks.hero.title")}),d.jsx("p",{className:"mt-1 truncate text-sm text-surface-900 dark:text-surface-50",children:s}),d.jsx("p",{className:"mt-1 text-xs text-surface-500 dark:text-surface-400",children:n(`blocks.hero.variants.${t.variant??"image-overlay"}`)})]})]})})}function a0e({editor:t}){const{t:e}=Fe("theme-default"),{posts:n}=Ql("post"),r=t.getAttributes(Km),s={...RU,...r.attrs??{}};function i(o){t.chain().updateAttributes(Km,{attrs:{...s,...o}}).run()}const a=n.filter(o=>o.status==="online").sort((o,l)=>Bn(l)-Bn(o));return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.hero.featured")}),d.jsxs("select",{className:"input",value:s.featuredPostId??"latest",onChange:o=>i({featuredPostId:o.target.value}),children:[d.jsx("option",{value:"latest",children:e("blocks.hero.latestLabel")}),a.map(o=>d.jsx("option",{value:o.id,children:o.title||"(untitled)"},o.id))]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.hero.variant")}),d.jsxs("select",{className:"input",value:s.variant??"image-overlay",onChange:o=>i({variant:o.target.value}),children:[d.jsx("option",{value:"image-overlay",children:e("blocks.hero.variants.image-overlay")}),d.jsx("option",{value:"split-left",children:e("blocks.hero.variants.split-left")}),d.jsx("option",{value:"split-right",children:e("blocks.hero.variants.split-right")}),d.jsx("option",{value:"minimal",children:e("blocks.hero.variants.minimal")})]})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:s.showCategory??!0,onChange:o=>i({showCategory:o.target.checked})}),d.jsx("span",{children:e("blocks.hero.showCategory")})]})]})}const o0e=cp({subId:yI,defaultAttrs:RU,view:i0e}),l0e={id:`default/${yI}`,nodeName:Km,titleKey:"blocks.hero.title",namespace:"theme-default",icon:UC,category:"layout",extensions:[o0e],insert:t=>{t.focus().insertContent({type:Km}).run()},isActive:t=>t.isActive(Km),inspector:t=>d.jsx(a0e,{editor:t.editor})},vI="posts-list",Jm=up(vI),jU={query:"latest",count:6,variant:"cards",columns:2,excludeUsed:!0};function c0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default"),r=[n(`blocks.postsList.queries.${t.query??"latest"}`),`${t.count??6}`,n(`blocks.postsList.variants.${t.variant??"cards"}`)].join(" · ");return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(xw,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsxs("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:[n("blocks.postsList.title"),t.title?` — ${t.title}`:""]}),d.jsx("p",{className:"mt-1 text-xs text-surface-500 dark:text-surface-400",children:r})]})]})})}function u0e({editor:t}){const{t:e}=Fe("theme-default"),{tags:n,users:r}=En(),s=t.getAttributes(Jm),i={...jU,...s.attrs??{}};function a(o){t.chain().updateAttributes(Jm,{attrs:{...i,...o}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.titleField")}),d.jsx("input",{type:"text",className:"input",value:i.title??"",onChange:o=>a({title:o.target.value}),placeholder:e("blocks.postsList.titlePlaceholder")})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.query")}),d.jsxs("select",{className:"input",value:i.query??"latest",onChange:o=>a({query:o.target.value}),children:[d.jsx("option",{value:"latest",children:e("blocks.postsList.queries.latest")}),d.jsx("option",{value:"by-tag",children:e("blocks.postsList.queries.by-tag")}),d.jsx("option",{value:"by-author",children:e("blocks.postsList.queries.by-author")})]})]}),i.query==="by-tag"&&d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.tag")}),d.jsxs("select",{className:"input",value:i.tagId??"",onChange:o=>a({tagId:o.target.value||void 0}),children:[d.jsx("option",{value:"",children:"—"}),n.map(o=>d.jsx("option",{value:o.id,children:o.name},o.id))]})]}),i.query==="by-author"&&d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.author")}),d.jsxs("select",{className:"input",value:i.authorId??"",onChange:o=>a({authorId:o.target.value||void 0}),children:[d.jsx("option",{value:"",children:"—"}),r.map(o=>d.jsx("option",{value:o.id,children:[o.firstName,o.lastName].filter(Boolean).join(" ")||o.displayName||o.email},o.id))]})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.count")}),d.jsx("input",{type:"number",min:1,max:24,className:"input",value:i.count??6,onChange:o=>a({count:Number.parseInt(o.target.value,10)||1})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.columns")}),d.jsx("input",{type:"number",min:1,max:4,className:"input",value:i.columns??2,onChange:o=>a({columns:Number.parseInt(o.target.value,10)||1})})]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.variant")}),d.jsxs("select",{className:"input",value:i.variant??"cards",onChange:o=>a({variant:o.target.value}),children:[d.jsx("option",{value:"cards",children:e("blocks.postsList.variants.cards")}),d.jsx("option",{value:"list",children:e("blocks.postsList.variants.list")}),d.jsx("option",{value:"compact",children:e("blocks.postsList.variants.compact")}),d.jsx("option",{value:"numbered",children:e("blocks.postsList.variants.numbered")}),d.jsx("option",{value:"slider",children:e("blocks.postsList.variants.slider")})]})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.seeMoreLabel")}),d.jsx("input",{type:"text",className:"input",value:i.seeMoreLabel??"",onChange:o=>a({seeMoreLabel:o.target.value})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.seeMoreUrl")}),d.jsx("input",{type:"text",className:"input",value:i.seeMoreUrl??"",onChange:o=>a({seeMoreUrl:o.target.value})})]})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:i.showExcerpt??!0,onChange:o=>a({showExcerpt:o.target.checked})}),d.jsx("span",{children:e("blocks.postsList.showExcerpt")})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:i.excludeUsed??!0,onChange:o=>a({excludeUsed:o.target.checked})}),d.jsx("span",{children:e("blocks.postsList.excludeUsed")})]})]})}const d0e=cp({subId:vI,defaultAttrs:jU,view:c0e}),h0e={id:`default/${vI}`,nodeName:Jm,titleKey:"blocks.postsList.title",namespace:"theme-default",icon:xw,category:"layout",extensions:[d0e],insert:t=>{t.focus().insertContent({type:Jm}).run()},isActive:t=>t.isActive(Jm),inspector:t=>d.jsx(u0e,{editor:t.editor})},xI="category-posts",Qm=up(xI),MU={count:4,variant:"cards",columns:2,excludeUsed:!0};function f0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default"),{categories:r}=En(),s=r.find(i=>i.id===t.categoryId);return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(Wf,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:n("blocks.categoryPosts.title")}),d.jsx("p",{className:"mt-1 text-sm text-surface-900 dark:text-surface-50",children:(s==null?void 0:s.name)??n("blocks.categoryPosts.pickCategory")}),d.jsxs("p",{className:"mt-1 text-xs text-surface-500 dark:text-surface-400",children:[n(`blocks.postsList.variants.${t.variant??"cards"}`)," · ",t.count??4]})]})]})})}function p0e({editor:t}){const{t:e}=Fe("theme-default"),{categories:n}=En(),r=t.getAttributes(Qm),s={...MU,...r.attrs??{}};function i(a){t.chain().updateAttributes(Qm,{attrs:{...s,...a}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.categoryPosts.category")}),d.jsxs("select",{className:"input",value:s.categoryId??"",onChange:a=>i({categoryId:a.target.value||void 0}),children:[d.jsx("option",{value:"",children:"—"}),n.map(a=>d.jsx("option",{value:a.id,children:a.name},a.id))]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.categoryPosts.titleField")}),d.jsx("input",{type:"text",className:"input",value:s.title??"",onChange:a=>i({title:a.target.value}),placeholder:e("blocks.categoryPosts.titlePlaceholder")})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.count")}),d.jsx("input",{type:"number",min:1,max:24,className:"input",value:s.count??4,onChange:a=>i({count:Number.parseInt(a.target.value,10)||1})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.columns")}),d.jsx("input",{type:"number",min:1,max:4,className:"input",value:s.columns??2,onChange:a=>i({columns:Number.parseInt(a.target.value,10)||1})})]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.variant")}),d.jsxs("select",{className:"input",value:s.variant??"cards",onChange:a=>i({variant:a.target.value}),children:[d.jsx("option",{value:"cards",children:e("blocks.postsList.variants.cards")}),d.jsx("option",{value:"list",children:e("blocks.postsList.variants.list")}),d.jsx("option",{value:"compact",children:e("blocks.postsList.variants.compact")}),d.jsx("option",{value:"numbered",children:e("blocks.postsList.variants.numbered")}),d.jsx("option",{value:"slider",children:e("blocks.postsList.variants.slider")})]})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.seeMoreLabel")}),d.jsx("input",{type:"text",className:"input",value:s.seeMoreLabel??"",onChange:a=>i({seeMoreLabel:a.target.value})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.postsList.seeMoreUrl")}),d.jsx("input",{type:"text",className:"input",value:s.seeMoreUrl??"",onChange:a=>i({seeMoreUrl:a.target.value}),placeholder:e("blocks.categoryPosts.seeMoreUrlPlaceholder")})]})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:s.showExcerpt??!0,onChange:a=>i({showExcerpt:a.target.checked})}),d.jsx("span",{children:e("blocks.postsList.showExcerpt")})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:s.excludeUsed??!0,onChange:a=>i({excludeUsed:a.target.checked})}),d.jsx("span",{children:e("blocks.postsList.excludeUsed")})]})]})}const m0e=cp({subId:xI,defaultAttrs:MU,view:f0e}),g0e={id:`default/${xI}`,nodeName:Qm,titleKey:"blocks.categoryPosts.title",namespace:"theme-default",icon:Wf,category:"layout",extensions:[m0e],insert:t=>{t.focus().insertContent({type:Qm}).run()},isActive:t=>t.isActive(Qm),inspector:t=>d.jsx(p0e,{editor:t.editor})},wI="cta",Xm=up(wI),LU={variant:"light"};function b0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default");return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(ww,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:n("blocks.cta.title")}),d.jsx("p",{className:"mt-1 truncate text-sm text-surface-900 dark:text-surface-50",children:t.title||n("blocks.cta.placeholder")})]})]})})}function y0e({editor:t}){const{t:e}=Fe("theme-default"),n=t.getAttributes(Xm),r={...LU,...n.attrs??{}};function s(i){t.chain().updateAttributes(Xm,{attrs:{...r,...i}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.titleField")}),d.jsx("input",{type:"text",className:"input",value:r.title??"",onChange:i=>s({title:i.target.value})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.description")}),d.jsx("textarea",{className:"input min-h-[60px]",value:r.description??"",onChange:i=>s({description:i.target.value})})]}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.buttonLabel")}),d.jsx("input",{type:"text",className:"input",value:r.buttonLabel??"",onChange:i=>s({buttonLabel:i.target.value})})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.buttonUrl")}),d.jsx("input",{type:"text",className:"input",value:r.buttonUrl??"",onChange:i=>s({buttonUrl:i.target.value})})]})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.cta.variant")}),d.jsxs("select",{className:"input max-w-xs",value:r.variant??"light",onChange:i=>s({variant:i.target.value}),children:[d.jsx("option",{value:"light",children:e("blocks.cta.variants.light")}),d.jsx("option",{value:"dark",children:e("blocks.cta.variants.dark")})]})]})]})}const v0e=cp({subId:wI,defaultAttrs:LU,view:b0e}),x0e={id:`default/${wI}`,nodeName:Xm,titleKey:"blocks.cta.title",namespace:"theme-default",icon:ww,category:"layout",extensions:[v0e],insert:t=>{t.focus().insertContent({type:Xm}).run()},isActive:t=>t.isActive(Xm),inspector:t=>d.jsx(y0e,{editor:t.editor})},kI="categories-pills",Zm=up(kI),DU={style:"pills"};function w0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default");return d.jsx(ln,{contentEditable:!1,className:"my-4 rounded-lg border border-dashed border-surface-300 bg-surface-50 p-4 dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx(U6,{className:"h-5 w-5 shrink-0 text-blue-500"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-xs font-semibold uppercase tracking-wide text-surface-500 dark:text-surface-400",children:n("blocks.categoriesPills.title")}),d.jsxs("p",{className:"mt-1 text-xs text-surface-500 dark:text-surface-400",children:[t.title||n("blocks.categoriesPills.untitled")," ·"," ",n(`blocks.categoriesPills.styles.${t.style??"pills"}`)]})]})]})})}function k0e({editor:t}){const{t:e}=Fe("theme-default"),n=t.getAttributes(Zm),r={...DU,...n.attrs??{}};function s(i){t.chain().updateAttributes(Zm,{attrs:{...r,...i}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.categoriesPills.titleField")}),d.jsx("input",{type:"text",className:"input",value:r.title??"",onChange:i=>s({title:i.target.value}),placeholder:e("blocks.categoriesPills.titlePlaceholder")})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.categoriesPills.style")}),d.jsxs("select",{className:"input max-w-xs",value:r.style??"pills",onChange:i=>s({style:i.target.value}),children:[d.jsx("option",{value:"pills",children:e("blocks.categoriesPills.styles.pills")}),d.jsx("option",{value:"list",children:e("blocks.categoriesPills.styles.list")})]})]})]})}const S0e=cp({subId:kI,defaultAttrs:DU,view:w0e}),E0e={id:`default/${kI}`,nodeName:Zm,titleKey:"blocks.categoriesPills.title",namespace:"theme-default",icon:U6,category:"layout",extensions:[S0e],insert:t=>{t.focus().insertContent({type:Zm}).run()},isActive:t=>t.isActive(Zm),inspector:t=>d.jsx(k0e,{editor:t.editor})},SI="spacer",Ym=up(SI),FU={size:"md",divider:!1};function _0e({attrs:t,selected:e}){const{t:n}=Fe("theme-default");return d.jsx(ln,{contentEditable:!1,className:"my-2 rounded-md border border-dashed border-surface-300 bg-surface-50 p-2 text-center dark:border-surface-600 dark:bg-surface-900 "+(e?"ring-2 ring-blue-500/60":""),children:d.jsxs("div",{className:"flex items-center justify-center gap-2 text-xs text-surface-500 dark:text-surface-400",children:[d.jsx(DC,{className:"h-3 w-3"}),d.jsxs("span",{children:[n("blocks.spacer.title")," · ",n(`blocks.spacer.sizes.${t.size??"md"}`),t.divider?` · ${n("blocks.spacer.dividerOn")}`:""]})]})})}function C0e({editor:t}){const{t:e}=Fe("theme-default"),n=t.getAttributes(Ym),r={...FU,...n.attrs??{}};function s(i){t.chain().updateAttributes(Ym,{attrs:{...r,...i}}).run()}return d.jsxs("div",{className:"space-y-3",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",children:e("blocks.spacer.size")}),d.jsxs("select",{className:"input max-w-xs",value:r.size??"md",onChange:i=>s({size:i.target.value}),children:[d.jsx("option",{value:"sm",children:e("blocks.spacer.sizes.sm")}),d.jsx("option",{value:"md",children:e("blocks.spacer.sizes.md")}),d.jsx("option",{value:"lg",children:e("blocks.spacer.sizes.lg")})]})]}),d.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:r.divider??!1,onChange:i=>s({divider:i.target.checked})}),d.jsx("span",{children:e("blocks.spacer.divider")})]})]})}const A0e=cp({subId:SI,defaultAttrs:FU,view:_0e}),T0e={id:`default/${SI}`,nodeName:Ym,titleKey:"blocks.spacer.title",namespace:"theme-default",icon:DC,category:"layout",extensions:[A0e],insert:t=>{t.focus().insertContent({type:Ym}).run()},isActive:t=>t.isActive(Ym),inspector:t=>d.jsx(C0e,{editor:t.editor})};let OU=null;function vx(t){OU=t}function zU(){return OU}function I0e(t,e){if(t.featuredPostId&&t.featuredPostId!=="latest"){const r=e.ctx.posts.find(s=>s.id===t.featuredPostId&&s.status==="online");if(r)return r}return e.ctx.posts.filter(r=>r.status==="online"&&r.id!==e.current.id).sort((r,s)=>Bn(s)-Bn(r))[0]??null}function UU(t,e){const n=I0e(t,e);if(!n)return{html:"",consumedPostId:null};const r=t.variant??"image-overlay",s=t.showCategory??!0,i=n.primaryTermId?e.ctx.terms.find(x=>x.id===n.primaryTermId&&x.type==="category"):void 0,a=`/${Tr({post:n,primaryTerm:i})}`,o=ia(e.ctx.media.get(n.heroMediaId??"")),l=Js(o,"large"),c=s&&i?`<a href="/${Dr(sa(i))}" class="cms-hero-category">${tr(i.name)}</a>`:"",h=`<h2 class="cms-hero-title"><a href="${Dr(a)}">${tr(n.title)}</a></h2>`,p=n.excerpt?`<p class="cms-hero-excerpt">${tr(n.excerpt)}</p>`:"",m=l?`<div class="cms-hero-image-wrap"><a href="${Dr(a)}" tabindex="-1" aria-hidden="true"><img class="cms-hero-image" src="${Dr(l)}" alt="${Dr((o==null?void 0:o.alt)??n.title)}" loading="lazy" /></a></div>`:"",g=`<div class="cms-hero-content">${c}${h}${p}</div>`,y=`cms-hero cms-hero-${r}`;return r==="minimal"?{html:`<section class="${y}">${g}</section>`,consumedPostId:n.id}:{html:`<section class="${y}">${m}${g}</section>`,consumedPostId:n.id}}function N0e(t,e){var r,s,i,a,o,l;const n=((s=(r=t.publishedAt)==null?void 0:r.toMillis)==null?void 0:s.call(r))??((a=(i=t.updatedAt)==null?void 0:i.toMillis)==null?void 0:a.call(i))??((l=(o=t.createdAt)==null?void 0:o.toMillis)==null?void 0:l.call(o));if(!n)return"";try{return new Intl.DateTimeFormat(e.settings.language||"en",{month:"short",day:"numeric",year:"numeric"}).format(new Date(n))}catch{return new Date(n).toDateString()}}function BU({post:t,ctx:e,variant:n,index:r,showExcerpt:s=!0}){const i=t.primaryTermId?e.terms.find(y=>y.id===t.primaryTermId&&y.type==="category"):void 0,a=`/${Tr({post:t,primaryTerm:i})}`,o=ia(e.media.get(t.heroMediaId??"")),l=Js(o,"medium"),c=N0e(t,e),h=i&&n!=="compact"?`<span class="cms-card-category">${tr(i.name)}</span>`:"",p=n==="compact"?c?`<span class="cms-card-meta">${tr(c)}</span>`:"":c?`<span class="cms-card-meta">${tr(c)}</span>`:"";if(n==="numbered"){const y=String(r+1).padStart(2,"0");return`<a href="${Dr(a)}" class="cms-card cms-card-numbered"><span class="cms-card-number">${y}</span><span class="cms-card-title">${tr(t.title)}</span>${p?`<span class="cms-card-meta">${tr(c)}</span>`:""}</a>`}if(n==="compact")return`<a href="${Dr(a)}" class="cms-card cms-card-compact"><span class="cms-card-title">${tr(t.title)}</span>${p}</a>`;if(n==="slider"){const y=l?`<div class="cms-card-slider-image-wrap"><img class="cms-card-slider-image" src="${Dr(l)}" alt="${Dr((o==null?void 0:o.alt)??t.title)}" loading="lazy" /></div>`:"",x=y?"":" cms-card-slider-no-image";return`<a href="${Dr(a)}" class="cms-card cms-card-slider${x}">${y}<div class="cms-card-slider-overlay">${h}<h4 class="cms-card-title">${tr(t.title)}</h4>${p}</div></a>`}if(n==="list"){const y=s&&t.excerpt?`<p class="cms-card-excerpt">${tr(t.excerpt)}</p>`:"",x=Js(o,"small"),v=x?`<div class="cms-card-list-image-wrap"><img class="cms-card-list-image" src="${Dr(x)}" alt="${Dr((o==null?void 0:o.alt)??t.title)}" loading="lazy" /></div>`:"";return`<a href="${Dr(a)}" class="cms-card cms-card-list${v?" cms-card-list-with-image":""}">${v}<div class="cms-card-list-body"><h4 class="cms-card-title">${tr(t.title)}</h4>${y}${p}</div></a>`}const m=l?`<div class="cms-card-image-wrap"><img class="cms-card-image" src="${Dr(l)}" alt="${Dr((o==null?void 0:o.alt)??t.title)}" loading="lazy" /></div>`:"",g=s&&t.excerpt?`<p class="cms-card-excerpt">${tr(t.excerpt)}</p>`:"";return`<a href="${Dr(a)}" class="cms-card cms-card-default">${m}<div class="cms-card-body">${h}<h4 class="cms-card-title">${tr(t.title)}</h4>${g}${p}</div></a>`}function $U(t,e,n){const r=Math.max(1,Math.min(4,Math.floor(n)||1));return e==="slider"?`<div class="cms-list cms-list-slider">${t.join("")}</div>`:e==="list"?`<div class="cms-list cms-list-list">${t.join("")}</div>`:e==="compact"?`<div class="cms-list cms-list-compact">${t.join("")}</div>`:e==="numbered"?`<div class="cms-list cms-list-numbered">${t.join("")}</div>`:`<div class="cms-list cms-list-cards cms-list-cols-${r}">${t.join("")}</div>`}function P0e(t,e){const n=e.ctx.posts.filter(s=>s.status==="online"&&s.id!==e.current.id);let r=n;switch(t.query){case"by-tag":t.tagId&&(r=n.filter(s=>s.termIds.includes(t.tagId)));break;case"by-author":t.authorId&&(r=n.filter(s=>s.authorId===t.authorId));break}return r.sort((s,i)=>Bn(i)-Bn(s))}function HU(t,e){const n=t.variant??"cards",r=Math.max(1,Math.min(24,t.count??6)),s=t.columns??(n==="cards"?2:1),i=t.excludeUsed??!0,a=P0e(t,e),l=(i?a.filter(y=>!e.used.has(y.id)):a).slice(0,r);if(l.length===0)return{html:"",consumedPostIds:[]};const c=t.showExcerpt??!0,h=l.map((y,x)=>BU({post:y,ctx:e.ctx,variant:n,index:x,showExcerpt:c})),p=$U(h,n,s),m=[];return t.title&&m.push(`<h3 class="cms-list-title">${tr(t.title)}</h3>`),t.seeMoreUrl&&t.seeMoreLabel&&m.push(`<a class="cms-list-see-more" href="${Dr(t.seeMoreUrl)}">${tr(t.seeMoreLabel)}</a>`),{html:`<section class="cms-list-block">${m.length?`<div class="cms-list-header">${m.join("")}</div>`:""}${p}</section>`,consumedPostIds:l.map(y=>y.id)}}function R0e(t,e){var C,N,_;if(!t.categoryId)return{html:"",consumedPostIds:[]};const n=e.ctx.terms.find(P=>P.id===t.categoryId&&P.type==="category");if(!n)return{html:"",consumedPostIds:[]};const r=t.variant??"cards",s=Math.max(1,Math.min(24,t.count??4)),i=t.columns??(r==="cards"?2:1),a=t.excludeUsed??!0,o=e.ctx.posts.filter(P=>P.status==="online"&&P.id!==e.current.id&&P.primaryTermId===t.categoryId).sort((P,D)=>Bn(D)-Bn(P)),c=(a?o.filter(P=>!e.used.has(P.id)):o).slice(0,s);if(c.length===0)return{html:"",consumedPostIds:[]};const h=t.showExcerpt??!0,p=c.map((P,D)=>BU({post:P,ctx:e.ctx,variant:r,index:D,showExcerpt:h})),m=$U(p,r,i),g=((C=t.title)==null?void 0:C.trim())||n.name,y=((N=t.seeMoreUrl)==null?void 0:N.trim())||`/${sa(n)}`,x=(_=t.seeMoreLabel)==null?void 0:_.trim(),v=[];return g&&v.push(`<h3 class="cms-list-title">${tr(g)}</h3>`),x&&v.push(`<a class="cms-list-see-more" href="${Dr(y)}">${tr(x)}</a>`),{html:`<section class="cms-list-block cms-list-block-category">${v.length?`<div class="cms-list-header">${v.join("")}</div>`:""}${m}</section>`,consumedPostIds:c.map(P=>P.id)}}function j0e(t){if(!t.title&&!t.description)return"";const e=t.variant??"light",n=t.title?`<h3 class="cms-cta-title">${tr(t.title)}</h3>`:"",r=t.description?`<p class="cms-cta-description">${tr(t.description)}</p>`:"",s=t.buttonLabel&&t.buttonUrl?`<a class="cms-cta-button" href="${Dr(t.buttonUrl)}">${tr(t.buttonLabel)}</a>`:"";return`<section class="cms-cta cms-cta-${e}"><div class="cms-cta-body">${n}${r}</div>${s}</section>`}function M0e(t,e){const n=e.ctx.terms.filter(a=>a.type==="category").sort((a,o)=>a.name.localeCompare(o.name));if(n.length===0)return"";const r=t.style??"pills",s=t.title?`<h3 class="cms-categories-title">${tr(t.title)}</h3>`:"",i=n.map(a=>`<a class="cms-categories-pill" href="/${Dr(sa(a))}">${tr(a.name)}</a>`).join("");return`<section class="cms-categories cms-categories-${r}">${s}<div class="cms-categories-items">${i}</div></section>`}function L0e(t){const e=t.size??"md",n=t.divider===!0;return`<div class="cms-spacer cms-spacer-${e}${n?" cms-spacer-divider":""}" aria-hidden="true"></div>`}const eg=/<div\s+([^>]*data-cms-block="default\/([\w-]+)"[^>]*)>\s*<\/div>/g;function D0e(t,e){const n=t.match(new RegExp(`${e}=(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`));return n?n[1]??n[2]??n[3]??"":""}function F0e(t){const e=[];eg.lastIndex=0;let n;for(;(n=eg.exec(t))!==null;)e.push({match:n[0],blockId:n[2],attrsRaw:D0e(n[1],"data-attrs"),index:n.index});return e}function O0e(t,e){switch(t.blockId){case"hero":{const n=Tc(t.attrsRaw,{}),r=UU(n,e);return r.consumedPostId&&e.used.add(r.consumedPostId),r.html}case"posts-list":{const n=Tc(t.attrsRaw,{}),r=HU(n,e);for(const s of r.consumedPostIds)e.used.add(s);return r.html}case"category-posts":{const n=Tc(t.attrsRaw,{}),r=R0e(n,e);for(const s of r.consumedPostIds)e.used.add(s);return r.html}case"cta":{const n=Tc(t.attrsRaw,{});return j0e(n)}case"categories-pills":{const n=Tc(t.attrsRaw,{});return M0e(n,e)}case"spacer":{const n=Tc(t.attrsRaw,{});return L0e(n)}default:return""}}function z0e(t,e){for(const n of t){if(n.blockId!=="hero")continue;const r=Tc(n.attrsRaw,{}),s=U0e(r,e);s&&e.used.add(s)}}function U0e(t,e){var r;return t.featuredPostId&&t.featuredPostId!=="latest"?t.featuredPostId:((r=e.ctx.posts.filter(s=>s.status==="online"&&s.id!==e.current.id).sort((s,i)=>Bn(i)-Bn(s))[0])==null?void 0:r.id)??null}function B0e(t,e){if(!t.includes('data-cms-block="default/'))return t;const n=zU();if(!n)return t.replace(eg,"");const r=F0e(t);if(r.length===0)return t;const s={ctx:n,current:e,used:new Set};z0e(r,s);const i=new Map;for(const c of r)i.set(c.index,O0e(c,s));let a="",o=0;eg.lastIndex=0;let l;for(;(l=eg.exec(t))!==null;)a+=t.slice(o,l.index),a+=i.get(l.index)??"",o=l.index+l[0].length;return a+=t.slice(o),a}const W_={id:"default",name:"Default",version:"1.0.0",description:"Minimal blog/site theme that ships with AgentCMS.",scssEntry:"theme.scss",cssText:xj,jsText:yle,jsTextPosts:vle,i18n:{en:xle,fr:wle,de:kle,es:Sle,nl:Ele,pt:_le,ko:Cle},settings:{navLabelKey:"title",defaultConfig:Rle,component:Xue},compileCss:t=>O8(xj,t.style),imageFormats:{inputFormats:[".jpg",".jpeg",".png",".webp",".gif"],outputFormat:"webp",quality:80,formats:{small:{width:480,height:480,fit:"cover"},medium:{width:800,height:800,fit:"cover"},large:{width:1600,height:900,fit:"cover"}},defaultFormat:"medium"},templates:{base:ole,home:lle,single:dle,category:hle,author:gle,notFound:ble},blocks:[l0e,h0e,g0e,x0e,E0e,T0e],register(t){t.addFilter("post.html.body",(e,...n)=>B0e(e,n[0]))}},lu=[],cu=[],$0e=new Set;function dp(){for(const t of $0e)t()}function VU(t){const e=lu.findIndex(n=>n.id===t.id);e>=0?lu[e]=t:lu.push(t),dp()}function qU(t){const e=cu.findIndex(n=>n.id===t.id);e>=0?cu[e]=t:cu.push(t),dp()}function H0e(t){const e=lu.findIndex(n=>n.id===t);e>=0&&(lu.splice(e,1),dp())}function V0e(t){const e=cu.findIndex(n=>n.id===t);e>=0&&(cu.splice(e,1),dp())}function R1(){return lu}function WU(){return cu}function q0e(){lu.length!==0&&(lu.length=0,dp())}function W0e(){cu.length!==0&&(cu.length=0,dp())}const GU={plugins:[],themes:[]};function ga(t){return t.replace(/[&<>"']/g,e=>{switch(e){case"&":return"&";case"<":return"<";case">":return">";case'"':return""";default:return"'"}})}function G0e(t){return t.replace(/]]>/g,"]]]]><![CDATA[>")}function oL(t){return new Date(t).toUTCString()}function K0e(t){const e=['<?xml version="1.0" encoding="UTF-8"?>'];t.xslHref&&e.push(`<?xml-stylesheet type="text/xsl" href="${ga(t.xslHref)}"?>`),e.push('<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">'),e.push(" <channel>"),e.push(` <title>${ga(t.title)}</title>`),e.push(` <link>${ga(t.link)}</link>`),e.push(` <description>${ga(t.description)}</description>`),e.push(` <language>${ga(t.language||"en")}</language>`),e.push(` <lastBuildDate>${oL(Date.now())}</lastBuildDate>`),e.push(` <atom:link href="${ga(t.feedUrl)}" rel="self" type="application/rss+xml"/>`);for(const n of t.items)e.push(" <item>"),e.push(` <title>${ga(n.title)}</title>`),e.push(` <link>${ga(n.link)}</link>`),e.push(` <guid isPermaLink="true">${ga(n.guid)}</guid>`),n.category&&e.push(` <category>${ga(n.category)}</category>`),e.push(` <description><![CDATA[${G0e(n.description)}]]></description>`),e.push(` <pubDate>${oL(n.pubDateMs)}</pubDate>`),n.enclosure&&e.push(` <enclosure url="${ga(n.enclosure.url)}" length="${n.enclosure.length}" type="${ga(n.enclosure.type)}"/>`),e.push(" </item>");return e.push(" </channel>"),e.push("</rss>"),e.join(`
|
|
4661
4661
|
`)}const J0e="x-cms-base";function KU(t){if(!t)return"";let e;try{e=new URL(t).pathname}catch{return""}const n=e.replace(/\/+$/,"");return n===""?"":n.startsWith("/")?n:`/${n}`}function EI(t,e){return!e||!t.startsWith("/")||t.startsWith("//")||t===e||t.startsWith(e+"/")?t:e+t}const Q0e=/(\s(?:href|src|action|poster|data-src|data-href)=)(["'])(\/[^"']*)\2/gi,X0e=/(\s(?:srcset|imagesrcset)=)(["'])([^"']*)\2/gi;function Z0e(t,e){return t.split(",").map(n=>{const r=n.match(/^(\s*)(\S+)(.*)$/);return r?r[1]+EI(r[2],e)+r[3]:n}).join(",")}function Y0e(t,e){if(!e)return t;let n=t.replace(Q0e,(s,i,a,o)=>`${i}${a}${EI(o,e)}${a}`);n=n.replace(X0e,(s,i,a,o)=>`${i}${a}${Z0e(o,e)}${a}`);const r=`<meta name="${J0e}" content="${e}/"/>`;return n=n.replace(/<head(\s[^>]*)?>/i,s=>s+r),n}function _I(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var ih=_I();function JU(t){ih=t}var tg={exec:()=>null};function Tn(t,e=""){let n=typeof t=="string"?t:t.source;const r={replace:(s,i)=>{let a=typeof i=="string"?i:i.source;return a=a.replace(li.caret,"$1"),n=n.replace(s,a),r},getRegex:()=>new RegExp(n,e)};return r}var li={codeRemoveIndent:/^(?: {1,4}| {0,3}\t)/gm,outputLinkReplace:/\\([\[\]])/g,indentCodeCompensation:/^(\s+)(?:```)/,beginningSpace:/^\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\n/g,tabCharGlobal:/\t/g,multipleSpaceGlobal:/\s+/g,blankLine:/^[ \t]*$/,doubleBlankLine:/\n[ \t]*\n[ \t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] /,listReplaceTask:/^\[[ xX]\] +/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:t=>new RegExp(`^( {0,3}${t})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}#`),htmlBeginRegex:t=>new RegExp(`^ {0,${Math.min(3,t-1)}}<(?:[a-z].*>|!--)`,"i")},ebe=/^(?:[ \t]*(?:\n|$))+/,tbe=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,nbe=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,O0=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,rbe=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,CI=/(?:[*+-]|\d{1,9}[.)])/,QU=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,XU=Tn(QU).replace(/bull/g,CI).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),sbe=Tn(QU).replace(/bull/g,CI).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),AI=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,ibe=/^[^\n]+/,TI=/(?!\s*\])(?:\\.|[^\[\]\\])+/,abe=Tn(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",TI).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),obe=Tn(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,CI).getRegex(),j1="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",II=/<!--(?:-?>|[\s\S]*?(?:-->|$))/,lbe=Tn("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",II).replace("tag",j1).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),ZU=Tn(AI).replace("hr",O0).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",j1).getRegex(),cbe=Tn(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",ZU).getRegex(),NI={blockquote:cbe,code:tbe,def:abe,fences:nbe,heading:rbe,hr:O0,html:lbe,lheading:XU,list:obe,newline:ebe,paragraph:ZU,table:tg,text:ibe},lL=Tn("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",O0).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",j1).getRegex(),ube={...NI,lheading:sbe,table:lL,paragraph:Tn(AI).replace("hr",O0).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",lL).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html","</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag",j1).getRegex()},dbe={...NI,html:Tn(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",II).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:tg,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:Tn(AI).replace("hr",O0).replace("heading",` *#{1,6} *[^
|
|
4662
4662
|
]`).replace("lheading",XU).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},hbe=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,fbe=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,YU=/^( {2,}|\\)\n(?!\s*$)/,pbe=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,M1=/[\p{P}\p{S}]/u,PI=/[\s\p{P}\p{S}]/u,eB=/[^\s\p{P}\p{S}]/u,mbe=Tn(/^((?![*_])punctSpace)/,"u").replace(/punctSpace/g,PI).getRegex(),tB=/(?!~)[\p{P}\p{S}]/u,gbe=/(?!~)[\s\p{P}\p{S}]/u,bbe=/(?:[^\s\p{P}\p{S}]|~)/u,ybe=/\[[^[\]]*?\]\((?:\\.|[^\\\(\)]|\((?:\\.|[^\\\(\)])*\))*\)|`[^`]*?`|<[^<>]*?>/g,nB=/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,vbe=Tn(nB,"u").replace(/punct/g,M1).getRegex(),xbe=Tn(nB,"u").replace(/punct/g,tB).getRegex(),rB="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",wbe=Tn(rB,"gu").replace(/notPunctSpace/g,eB).replace(/punctSpace/g,PI).replace(/punct/g,M1).getRegex(),kbe=Tn(rB,"gu").replace(/notPunctSpace/g,bbe).replace(/punctSpace/g,gbe).replace(/punct/g,tB).getRegex(),Sbe=Tn("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,eB).replace(/punctSpace/g,PI).replace(/punct/g,M1).getRegex(),Ebe=Tn(/\\(punct)/,"gu").replace(/punct/g,M1).getRegex(),_be=Tn(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Cbe=Tn(II).replace("(?:-->|$)","-->").getRegex(),Abe=Tn("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment",Cbe).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),xx=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,Tbe=Tn(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label",xx).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),sB=Tn(/^!?\[(label)\]\[(ref)\]/).replace("label",xx).replace("ref",TI).getRegex(),iB=Tn(/^!?\[(ref)\](?:\[\])?/).replace("ref",TI).getRegex(),Ibe=Tn("reflink|nolink(?!\\()","g").replace("reflink",sB).replace("nolink",iB).getRegex(),RI={_backpedal:tg,anyPunctuation:Ebe,autolink:_be,blockSkip:ybe,br:YU,code:fbe,del:tg,emStrongLDelim:vbe,emStrongRDelimAst:wbe,emStrongRDelimUnd:Sbe,escape:hbe,link:Tbe,nolink:iB,punctuation:mbe,reflink:sB,reflinkSearch:Ibe,tag:Abe,text:pbe,url:tg},Nbe={...RI,link:Tn(/^!?\[(label)\]\((.*?)\)/).replace("label",xx).getRegex(),reflink:Tn(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",xx).getRegex()},G_={...RI,emStrongRDelimAst:kbe,emStrongLDelim:xbe,url:Tn(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,"i").replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\.|[^\\])*?(?:\\.|[^\s~\\]))\1(?=[^~]|$)/,text:/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/},Pbe={...G_,br:Tn(YU).replace("{2,}","*").getRegex(),text:Tn(G_.text).replace("\\b_","\\b_| {2,}\\n").replace(/\{2,\}/g,"*").getRegex()},by={normal:NI,gfm:ube,pedantic:dbe},nm={normal:RI,gfm:G_,breaks:Pbe,pedantic:Nbe},Rbe={"&":"&","<":"<",">":">",'"':""","'":"'"},cL=t=>Rbe[t];function So(t,e){if(e){if(li.escapeTest.test(t))return t.replace(li.escapeReplace,cL)}else if(li.escapeTestNoEncode.test(t))return t.replace(li.escapeReplaceNoEncode,cL);return t}function uL(t){try{t=encodeURI(t).replace(li.percentDecode,"%")}catch{return null}return t}function dL(t,e){var i;const n=t.replace(li.findPipe,(a,o,l)=>{let c=!1,h=o;for(;--h>=0&&l[h]==="\\";)c=!c;return c?"|":" |"}),r=n.split(li.splitPipe);let s=0;if(r[0].trim()||r.shift(),r.length>0&&!((i=r.at(-1))!=null&&i.trim())&&r.pop(),e)if(r.length>e)r.splice(e);else for(;r.length<e;)r.push("");for(;s<r.length;s++)r[s]=r[s].trim().replace(li.slashPipe,"|");return r}function rm(t,e,n){const r=t.length;if(r===0)return"";let s=0;for(;s<r&&t.charAt(r-s-1)===e;)s++;return t.slice(0,r-s)}function jbe(t,e){if(t.indexOf(e[1])===-1)return-1;let n=0;for(let r=0;r<t.length;r++)if(t[r]==="\\")r++;else if(t[r]===e[0])n++;else if(t[r]===e[1]&&(n--,n<0))return r;return n>0?-2:-1}function hL(t,e,n,r,s){const i=e.href,a=e.title||null,o=t[1].replace(s.other.outputLinkReplace,"$1");r.state.inLink=!0;const l={type:t[0].charAt(0)==="!"?"image":"link",raw:n,href:i,title:a,text:o,tokens:r.inlineTokens(o)};return r.state.inLink=!1,l}function Mbe(t,e,n){const r=t.match(n.other.indentCodeCompensation);if(r===null)return e;const s=r[1];return e.split(`
|
|
4663
4663
|
`).map(i=>{const a=i.match(n.other.beginningSpace);if(a===null)return i;const[o]=a;return o.length>=s.length?i.slice(s.length):i}).join(`
|
|
@@ -4886,7 +4886,7 @@ Disable if you maintain favicons by hand (e.g. you have a legacy \`/favicon.ico\
|
|
|
4886
4886
|
.dark .prose-editor .cms-html-block-preview-wrap,.dark .prose-editor .cms-html-block-preview{background:#0d0d0d;}
|
|
4887
4887
|
.dark .cms-html-block-warning{color:rgba(255,200,100,0.95);background:rgba(255,180,40,0.08);border-color:rgba(255,180,40,0.25);}
|
|
4888
4888
|
`;function mke(){if(typeof document>"u"||document.querySelector("style[data-cms-columns-styles-admin]"))return;const t=document.createElement("style");t.setAttribute("data-cms-columns-styles-admin","true"),t.textContent=L$+pke,document.head.appendChild(t)}let lC=!1;function gke(t){if(lC=!1,!t.includes('data-cms-block="flexweg-blocks/columns"')||typeof DOMParser>"u")return t;const e=new DOMParser().parseFromString(t,"text/html");return e.querySelectorAll('div[data-cms-block="flexweg-blocks/columns"]').forEach(r=>{lC=!0;const s=r.getAttribute("data-cols")??"2",i=yke(s);r.removeAttribute("data-cms-block"),r.removeAttribute("data-cols"),r.classList.add("cms-columns",`cms-columns-cols-${i}`),Array.from(r.children).forEach(a=>{a instanceof HTMLElement&&a.hasAttribute("data-cms-column")&&(a.removeAttribute("data-cms-column"),a.classList.add("cms-column"))})}),e.body.innerHTML}function bke(){return lC?fke:""}function yke(t){const e=Number.parseInt(t,10);return Number.isFinite(e)?Math.max(1,Math.min(4,e)):2}const ff="flexwegHtmlBlock",Xg="flexweg-blocks/html";function vke(t){const e=JSON.stringify({code:t});return typeof window>"u"?Buffer.from(e,"utf-8").toString("base64"):window.btoa(unescape(encodeURIComponent(e)))}function xke(t){if(!t)return"";try{let e;typeof window>"u"?e=Buffer.from(t,"base64").toString("utf-8"):e=decodeURIComponent(escape(window.atob(t)));const n=JSON.parse(e);return typeof n.code=="string"?n.code:""}catch{return""}}const wke=on.create({name:ff,group:"block",atom:!0,selectable:!0,draggable:!0,addAttributes(){return{code:{default:"",parseHTML:t=>xke(t.getAttribute("data-attrs")),renderHTML:t=>({"data-attrs":vke(typeof t.code=="string"?t.code:"")})}}},parseHTML(){return[{tag:`div[data-cms-block="${Xg}"]`}]},renderHTML({HTMLAttributes:t}){return["div",Un(t,{"data-cms-block":Xg})]},addNodeView(){return ol(kke)}});function kke({node:t,selected:e}){const{t:n}=Fe("flexweg-blocks"),r=t.attrs.code||"",s=r.trim()!=="";return d.jsxs(ln,{className:qn("cms-html-block",e&&"is-selected"),"data-cms-html-editor":"true",contentEditable:!1,children:[d.jsxs("div",{className:"cms-html-block-header",children:[d.jsx(I6,{className:"cms-html-block-header-icon"}),d.jsx("span",{className:"cms-html-block-header-label",children:n("blocks.html.title")}),s&&d.jsx("span",{className:"cms-html-block-header-meta",children:n("blocks.html.lines",{n:r.split(`
|
|
4889
|
-
`).length})})]}),s?d.jsx("div",{className:"cms-html-block-preview-wrap",children:d.jsx("iframe",{className:"cms-html-block-preview",sandbox:"allow-scripts",srcDoc:r,title:n("blocks.html.title")})}):d.jsx("div",{className:"cms-html-block-empty",children:n("blocks.html.editInSidebar")})]})}const D$=U.lazy(()=>zv(()=>import("./CodeEditor-
|
|
4889
|
+
`).length})})]}),s?d.jsx("div",{className:"cms-html-block-preview-wrap",children:d.jsx("iframe",{className:"cms-html-block-preview",sandbox:"allow-scripts",srcDoc:r,title:n("blocks.html.title")})}):d.jsx("div",{className:"cms-html-block-empty",children:n("blocks.html.editInSidebar")})]})}const D$=U.lazy(()=>zv(()=>import("./CodeEditor-Wx1WlF3h.js"),[],import.meta.url).then(t=>({default:t.CodeEditor})));function Ske({editor:t}){const{t:e}=Fe("flexweg-blocks"),n=t.getAttributes(ff),r=typeof n.code=="string"?n.code:"",[s,i]=U.useState(r),[a,o]=U.useState(!1);U.useEffect(()=>{i(c=>c===r?c:r)},[r]);function l(){s!==r&&t.chain().updateAttributes(ff,{code:s}).run()}return d.jsxs("div",{className:"space-y-2",children:[d.jsxs("div",{children:[d.jsxs("div",{className:"flex items-center justify-between gap-2",children:[d.jsx("label",{className:"label mb-0",children:e("blocks.html.codeLabel")}),d.jsxs("button",{type:"button",className:"btn-ghost text-xs gap-1.5 px-2 py-1",onClick:()=>o(!0),title:e("blocks.html.expand"),children:[d.jsx(M6,{className:"h-3.5 w-3.5"}),d.jsx("span",{children:e("blocks.html.expand")})]})]}),d.jsx("div",{className:"mt-1.5",children:d.jsx(U.Suspense,{fallback:d.jsxs("div",{className:"cms-html-block-codeeditor-fallback",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),d.jsx("span",{children:e("blocks.html.loadingEditor")})]}),children:d.jsx(D$,{value:s,onChange:i,onBlur:l,placeholder:e("blocks.html.placeholder")})})})]}),d.jsxs("div",{className:"cms-html-block-warning",children:[d.jsx(Zl,{className:"h-3.5 w-3.5 shrink-0 mt-0.5"}),d.jsx("span",{children:e("blocks.html.warning")})]}),a&&d.jsx(Eke,{draft:s,onDraftChange:i,onCommit:l,onClose:()=>{l(),o(!1)},placeholder:e("blocks.html.placeholder")})]})}function Eke({draft:t,onDraftChange:e,onCommit:n,onClose:r,placeholder:s}){const{t:i}=Fe("flexweg-blocks");return U.useEffect(()=>{function a(o){o.key==="Escape"&&r()}return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[r]),el.createPortal(d.jsxs("div",{className:"fixed inset-0 z-[100] flex flex-col bg-white dark:bg-surface-950",children:[d.jsxs("div",{className:"flex items-center justify-between gap-3 border-b border-surface-200 px-4 py-2.5 dark:border-surface-700",children:[d.jsx("span",{className:"text-sm font-medium text-surface-700 dark:text-surface-200",children:i("blocks.html.modalTitle")}),d.jsxs("button",{type:"button",className:"btn-ghost",onClick:r,"aria-label":i("blocks.html.modalClose"),children:[d.jsx(fi,{className:"h-4 w-4"}),d.jsx("span",{className:"hidden sm:inline",children:i("blocks.html.modalClose")})]})]}),d.jsx("div",{className:"cms-html-block-modal-body",children:d.jsx(U.Suspense,{fallback:d.jsxs("div",{className:"cms-html-block-codeeditor-fallback",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),d.jsx("span",{children:i("blocks.html.loadingEditor")})]}),children:d.jsx(D$,{value:t,onChange:e,onBlur:n,placeholder:s,height:"100%",autoFocus:!0})})})]}),document.body)}const _ke={id:Xg,nodeName:ff,titleKey:"blocks.html.title",namespace:"flexweg-blocks",icon:I6,category:"layout",extensions:[wke],insert:t=>{t.focus().insertContent({type:ff,attrs:{code:""}}).run()},isActive:t=>t.isActive(ff),inspector:t=>d.jsx(Ske,{editor:t.editor})};function Cke(t){if(!t)return"";try{let e;typeof window>"u"?e=Buffer.from(t,"base64").toString("utf-8"):e=decodeURIComponent(escape(window.atob(t)));const n=JSON.parse(e);return typeof n.code=="string"?n.code:""}catch{return""}}function Ake(t){if(!t.includes(`data-cms-block="${Xg}"`)||typeof DOMParser>"u")return t;const e=new DOMParser().parseFromString(t,"text/html");return e.querySelectorAll(`div[data-cms-block="${Xg}"]`).forEach(r=>{const s=Cke(r.getAttribute("data-attrs"));if(!s){r.remove();return}r.outerHTML=s}),e.body.innerHTML}const Tke=`# Flexweg Blocks
|
|
4890
4890
|
|
|
4891
4891
|
A pack of layout primitives for the post / page editor. Theme-agnostic — every block here works with any active theme because it ships its own minimal CSS.
|
|
4892
4892
|
|
|
@@ -4945,7 +4945,7 @@ Anything in this block is **not sanitised**. \`<script>\` tags execute on every
|
|
|
4945
4945
|
|
|
4946
4946
|
Disable if your editorial workflow only needs single-column posts with no custom code, and you want a tighter inserter UI. The plugin is purely additive — disabling stops the blocks from appearing in the inserter, existing content using them keeps rendering on the public site (the publish-time transforms still process the markup).
|
|
4947
4947
|
`,Ike="flexweg-blocks";mke();const Nke={id:Ike,name:"Flexweg Blocks",version:"1.0.0",author:"Flexweg",description:"Layout and code primitives for the post editor. Ships a Columns block (2-4 columns, mobile-stacking) and a Custom HTML block for raw HTML/JS / CSS.",readme:Tke,i18n:{en:Y1e,fr:eke,de:tke,es:nke,nl:rke,pt:ske,ko:ike},register(t){t.registerBlock(hke),t.registerBlock(_ke),t.addFilter("post.html.body",e=>gke(e),5),t.addFilter("post.html.body",e=>Ake(e),5),t.addFilter("page.head.extra",(e,...n)=>{n[0];const r=bke();return r?[e,r].filter(Boolean).join(`
|
|
4948
|
-
`):e})}},Pke={title:"Custom code",description:"Inject site-wide HTML / CSS / JS into the <head> or before the </body> of every published page.",warning:"Code is injected as-is on every page. No sanitisation — a broken <script> can take down the whole site until you fix it.",loadingEditor:"Loading code editor…",expand:"Expand",modalClose:"Close",head:{title:"Head",help:"Appended at the bottom of every page's <head>. Best for analytics, fonts, custom <style> overrides.",placeholder:"<!-- e.g. <script>...<\/script> for Google Analytics, <style>body{...}</style> for overrides -->"},body:{title:"Body end",help:"Appended just before </body>. Best for deferred scripts (chat widgets, late analytics) that need the DOM parsed.",placeholder:"<!-- e.g. <script>...<\/script> for a chat widget that needs the DOM ready -->"},save:"Save",saving:"Saving…",saved:"Custom code saved.",saveFailed:"Save failed.",republishHint:"Republish your posts and pages (Themes → Regenerate site) to push the new code to all already-online files."},Rke={title:"Code personnalisé",description:"Injectez du HTML / CSS / JS site-wide dans le <head> ou avant la fin du <body> de chaque page publiée.",warning:"Le code est injecté tel quel sur toutes les pages. Aucune sanitisation — un <script> cassé peut faire tomber tout le site jusqu'à correction.",loadingEditor:"Chargement de l'éditeur…",expand:"Agrandir",modalClose:"Fermer",head:{title:"Head",help:"Ajouté en bas du <head> de chaque page. Idéal pour les analytics, les fonts, les surcharges <style>.",placeholder:"<!-- ex. <script>...<\/script> pour Google Analytics, <style>body{...}</style> pour des surcharges -->"},body:{title:"Fin du body",help:"Ajouté juste avant </body>. Idéal pour les scripts différés (widgets chat, analytics tardifs) qui ont besoin du DOM parsé.",placeholder:"<!-- ex. <script>...<\/script> pour un widget chat qui a besoin du DOM prêt -->"},save:"Enregistrer",saving:"Enregistrement…",saved:"Code personnalisé enregistré.",saveFailed:"Échec de l'enregistrement.",republishHint:"Republiez vos articles et pages (Thèmes → Régénérer le site) pour pousser le nouveau code dans tous les fichiers déjà en ligne."},jke={title:"Eigener Code",description:"Fügen Sie site-weites HTML / CSS / JS in den <head> oder vor das </body> jeder veröffentlichten Seite ein.",warning:"Code wird unverändert auf jeder Seite eingefügt. Keine Bereinigung — ein fehlerhaftes <script> kann die gesamte Website bis zur Korrektur lahmlegen.",loadingEditor:"Code-Editor wird geladen…",expand:"Vergrößern",modalClose:"Schließen",head:{title:"Head",help:"Wird unten im <head> jeder Seite eingefügt. Ideal für Analytics, Fonts, eigene <style>-Überschreibungen.",placeholder:"<!-- z. B. <script>...<\/script> für Google Analytics, <style>body{...}</style> für Überschreibungen -->"},body:{title:"Body-Ende",help:"Wird direkt vor </body> eingefügt. Ideal für verzögerte Skripte (Chat-Widgets, späte Analytics), die ein geparstes DOM benötigen.",placeholder:"<!-- z. B. <script>...<\/script> für ein Chat-Widget, das ein bereites DOM benötigt -->"},save:"Speichern",saving:"Speichert…",saved:"Eigener Code gespeichert.",saveFailed:"Speichern fehlgeschlagen.",republishHint:"Veröffentlichen Sie Ihre Artikel und Seiten erneut (Themes → Website neu generieren), um den neuen Code in alle bereits online stehenden Dateien zu übertragen."},Mke={title:"Código personalizado",description:"Inyecta HTML / CSS / JS para todo el sitio en el <head> o antes de </body> de cada página publicada.",warning:"El código se inyecta tal cual en cada página. Sin sanitización — un <script> roto puede tirar todo el sitio hasta que lo corrijas.",loadingEditor:"Cargando editor de código…",expand:"Ampliar",modalClose:"Cerrar",head:{title:"Head",help:"Añadido al final del <head> de cada página. Ideal para analítica, fuentes, anulaciones <style>.",placeholder:"<!-- p. ej. <script>...<\/script> para Google Analytics, <style>body{...}</style> para anulaciones -->"},body:{title:"Fin del body",help:"Añadido justo antes de </body>. Ideal para scripts diferidos (widgets de chat, analítica tardía) que necesitan el DOM parseado.",placeholder:"<!-- p. ej. <script>...<\/script> para un widget de chat que necesita el DOM listo -->"},save:"Guardar",saving:"Guardando…",saved:"Código personalizado guardado.",saveFailed:"Error al guardar.",republishHint:"Republica tus entradas y páginas (Temas → Regenerar el sitio) para empujar el nuevo código a todos los archivos ya en línea."},Lke={title:"Eigen code",description:"Plaats site-brede HTML / CSS / JS in de <head> of vóór de </body> van elke gepubliceerde pagina.",warning:"Code wordt ongewijzigd op elke pagina ingevoegd. Geen sanering — een kapot <script> kan de hele site neerhalen tot je het herstelt.",loadingEditor:"Code-editor laden…",expand:"Vergroten",modalClose:"Sluiten",head:{title:"Head",help:"Toegevoegd aan het einde van de <head> van elke pagina. Ideaal voor analytics, lettertypen, aangepaste <style>-overrides.",placeholder:"<!-- bv. <script>...<\/script> voor Google Analytics, <style>body{...}</style> voor overrides -->"},body:{title:"Einde body",help:"Toegevoegd vlak vóór </body>. Ideaal voor uitgestelde scripts (chat-widgets, late analytics) die een geparste DOM nodig hebben.",placeholder:"<!-- bv. <script>...<\/script> voor een chat-widget dat een gereed DOM nodig heeft -->"},save:"Opslaan",saving:"Opslaan…",saved:"Eigen code opgeslagen.",saveFailed:"Opslaan mislukt.",republishHint:"Publiceer je berichten en pagina's opnieuw (Thema's → Site opnieuw genereren) om de nieuwe code naar alle reeds online bestanden te pushen."},Dke={title:"Código personalizado",description:"Injeta HTML / CSS / JS para todo o site no <head> ou antes de </body> de cada página publicada.",warning:"O código é injetado tal qual em cada página. Sem sanitização — um <script> avariado pode deitar abaixo o site inteiro até o corrigires.",loadingEditor:"A carregar editor de código…",expand:"Ampliar",modalClose:"Fechar",head:{title:"Head",help:"Adicionado no fim do <head> de cada página. Ideal para analítica, tipos de letra, sobreposições <style>.",placeholder:"<!-- p. ex. <script>...<\/script> para Google Analytics, <style>body{...}</style> para sobreposições -->"},body:{title:"Fim do body",help:"Adicionado mesmo antes de </body>. Ideal para scripts diferidos (widgets de chat, analítica tardia) que precisam do DOM analisado.",placeholder:"<!-- p. ex. <script>...<\/script> para um widget de chat que precisa do DOM pronto -->"},save:"Guardar",saving:"A guardar…",saved:"Código personalizado guardado.",saveFailed:"Falha ao guardar.",republishHint:"Republica os teus artigos e páginas (Temas → Regenerar o site) para empurrar o novo código para todos os ficheiros já online."},Fke={title:"사용자 정의 코드",description:"게시되는 모든 페이지의 <head> 또는 </body> 직전에 사이트 전체 HTML / CSS / JS를 삽입합니다.",warning:"코드는 모든 페이지에 그대로 삽입됩니다. 정제 처리는 없습니다 — 잘못된 <script>는 수정 전까지 사이트 전체를 다운시킬 수 있습니다.",loadingEditor:"코드 편집기 로딩 중…",expand:"확장",modalClose:"닫기",head:{title:"Head",help:"각 페이지의 <head> 하단에 추가됩니다. 분석 도구, 글꼴, 사용자 정의 <style> 재정의에 적합합니다.",placeholder:"<!-- 예: <script>...<\/script> Google Analytics, <style>body{...}</style> 재정의 -->"},body:{title:"Body 끝",help:"</body> 직전에 추가됩니다. DOM 파싱이 필요한 지연 스크립트(채팅 위젯, 후속 분석)에 적합합니다.",placeholder:"<!-- 예: <script>...<\/script> DOM이 준비된 후 실행되는 채팅 위젯 -->"},save:"저장",saving:"저장 중…",saved:"사용자 정의 코드가 저장되었습니다.",saveFailed:"저장에 실패했습니다.",republishHint:"이미 게시된 모든 파일에 새 코드를 적용하려면 게시물과 페이지를 재게시하세요 (테마 → 사이트 재생성)."},F$={head:"",bodyEnd:""},O$=U.lazy(()=>zv(()=>import("./CodeEditor-DcFzGUt8.js"),[],import.meta.url).then(t=>({default:t.CodeEditor})));function Oke({config:t,save:e}){const{t:n}=Fe("flexweg-custom-code"),[r,s]=U.useState(t),[i,a]=U.useState(!1),[o,l]=U.useState(null);U.useEffect(()=>{s(t)},[t]);async function c(){a(!0);try{await e(r),at.success(n("saved"))}catch(h){at.error(h.message||n("saveFailed"))}finally{a(!1)}}return d.jsxs("div",{className:"space-y-6",children:[d.jsxs("section",{className:"card p-4 space-y-3",children:[d.jsxs("div",{children:[d.jsx("h2",{className:"font-semibold",children:n("title")}),d.jsx("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:n("description")})]}),d.jsxs("div",{className:"cms-html-block-warning",children:[d.jsx(Zl,{className:"h-3.5 w-3.5 shrink-0 mt-0.5"}),d.jsx("span",{children:n("warning")})]})]}),d.jsx(zL,{title:n("head.title"),help:n("head.help"),placeholder:n("head.placeholder"),value:r.head,onChange:h=>s(p=>({...p,head:h})),onExpand:()=>l("head"),loadingLabel:n("loadingEditor"),expandLabel:n("expand")}),d.jsx(zL,{title:n("body.title"),help:n("body.help"),placeholder:n("body.placeholder"),value:r.bodyEnd,onChange:h=>s(p=>({...p,bodyEnd:h})),onExpand:()=>l("bodyEnd"),loadingLabel:n("loadingEditor"),expandLabel:n("expand")}),d.jsxs("section",{className:"card p-4 space-y-3",children:[d.jsx("button",{type:"button",className:"btn-primary",onClick:c,disabled:i,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx("span",{children:n(i?"saving":"save")})]})}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:n("republishHint")})]}),o&&d.jsx(zke,{value:o==="head"?r.head:r.bodyEnd,onChange:h=>s(p=>o==="head"?{...p,head:h}:{...p,bodyEnd:h}),onClose:()=>l(null),title:n(o==="head"?"head.title":"body.title"),closeLabel:n("modalClose"),loadingLabel:n("loadingEditor")})]})}function zL({title:t,help:e,placeholder:n,value:r,onChange:s,onExpand:i,loadingLabel:a,expandLabel:o}){return d.jsxs("section",{className:"card p-4 space-y-3",children:[d.jsxs("div",{className:"flex items-start justify-between gap-3",children:[d.jsxs("div",{children:[d.jsx("h3",{className:"font-semibold",children:t}),d.jsx("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:e})]}),d.jsxs("button",{type:"button",className:"btn-ghost text-xs gap-1.5 px-2 py-1 shrink-0",onClick:i,children:[d.jsx(M6,{className:"h-3.5 w-3.5"}),d.jsx("span",{children:o})]})]}),d.jsx(U.Suspense,{fallback:d.jsxs("div",{className:"cms-html-block-codeeditor-fallback",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),d.jsx("span",{children:a})]}),children:d.jsx(O$,{value:r,onChange:s,placeholder:n,minHeight:"200px",maxHeight:"500px"})})]})}function zke({value:t,onChange:e,onClose:n,title:r,closeLabel:s,loadingLabel:i}){return U.useEffect(()=>{function a(o){o.key==="Escape"&&n()}return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[n]),el.createPortal(d.jsxs("div",{className:"fixed inset-0 z-[100] flex flex-col bg-white dark:bg-surface-950",children:[d.jsxs("div",{className:"flex items-center justify-between gap-3 border-b border-surface-200 px-4 py-2.5 dark:border-surface-700",children:[d.jsx("span",{className:"text-sm font-medium text-surface-700 dark:text-surface-200",children:r}),d.jsxs("button",{type:"button",className:"btn-ghost",onClick:n,"aria-label":s,children:[d.jsx(fi,{className:"h-4 w-4"}),d.jsx("span",{className:"hidden sm:inline",children:s})]})]}),d.jsx("div",{className:"cms-html-block-modal-body",children:d.jsx(U.Suspense,{fallback:d.jsxs("div",{className:"cms-html-block-codeeditor-fallback",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),d.jsx("span",{children:i})]}),children:d.jsx(O$,{value:t,onChange:e,height:"100%",autoFocus:!0})})})]}),document.body)}const Uke=`# Flexweg Custom Code
|
|
4948
|
+
`):e})}},Pke={title:"Custom code",description:"Inject site-wide HTML / CSS / JS into the <head> or before the </body> of every published page.",warning:"Code is injected as-is on every page. No sanitisation — a broken <script> can take down the whole site until you fix it.",loadingEditor:"Loading code editor…",expand:"Expand",modalClose:"Close",head:{title:"Head",help:"Appended at the bottom of every page's <head>. Best for analytics, fonts, custom <style> overrides.",placeholder:"<!-- e.g. <script>...<\/script> for Google Analytics, <style>body{...}</style> for overrides -->"},body:{title:"Body end",help:"Appended just before </body>. Best for deferred scripts (chat widgets, late analytics) that need the DOM parsed.",placeholder:"<!-- e.g. <script>...<\/script> for a chat widget that needs the DOM ready -->"},save:"Save",saving:"Saving…",saved:"Custom code saved.",saveFailed:"Save failed.",republishHint:"Republish your posts and pages (Themes → Regenerate site) to push the new code to all already-online files."},Rke={title:"Code personnalisé",description:"Injectez du HTML / CSS / JS site-wide dans le <head> ou avant la fin du <body> de chaque page publiée.",warning:"Le code est injecté tel quel sur toutes les pages. Aucune sanitisation — un <script> cassé peut faire tomber tout le site jusqu'à correction.",loadingEditor:"Chargement de l'éditeur…",expand:"Agrandir",modalClose:"Fermer",head:{title:"Head",help:"Ajouté en bas du <head> de chaque page. Idéal pour les analytics, les fonts, les surcharges <style>.",placeholder:"<!-- ex. <script>...<\/script> pour Google Analytics, <style>body{...}</style> pour des surcharges -->"},body:{title:"Fin du body",help:"Ajouté juste avant </body>. Idéal pour les scripts différés (widgets chat, analytics tardifs) qui ont besoin du DOM parsé.",placeholder:"<!-- ex. <script>...<\/script> pour un widget chat qui a besoin du DOM prêt -->"},save:"Enregistrer",saving:"Enregistrement…",saved:"Code personnalisé enregistré.",saveFailed:"Échec de l'enregistrement.",republishHint:"Republiez vos articles et pages (Thèmes → Régénérer le site) pour pousser le nouveau code dans tous les fichiers déjà en ligne."},jke={title:"Eigener Code",description:"Fügen Sie site-weites HTML / CSS / JS in den <head> oder vor das </body> jeder veröffentlichten Seite ein.",warning:"Code wird unverändert auf jeder Seite eingefügt. Keine Bereinigung — ein fehlerhaftes <script> kann die gesamte Website bis zur Korrektur lahmlegen.",loadingEditor:"Code-Editor wird geladen…",expand:"Vergrößern",modalClose:"Schließen",head:{title:"Head",help:"Wird unten im <head> jeder Seite eingefügt. Ideal für Analytics, Fonts, eigene <style>-Überschreibungen.",placeholder:"<!-- z. B. <script>...<\/script> für Google Analytics, <style>body{...}</style> für Überschreibungen -->"},body:{title:"Body-Ende",help:"Wird direkt vor </body> eingefügt. Ideal für verzögerte Skripte (Chat-Widgets, späte Analytics), die ein geparstes DOM benötigen.",placeholder:"<!-- z. B. <script>...<\/script> für ein Chat-Widget, das ein bereites DOM benötigt -->"},save:"Speichern",saving:"Speichert…",saved:"Eigener Code gespeichert.",saveFailed:"Speichern fehlgeschlagen.",republishHint:"Veröffentlichen Sie Ihre Artikel und Seiten erneut (Themes → Website neu generieren), um den neuen Code in alle bereits online stehenden Dateien zu übertragen."},Mke={title:"Código personalizado",description:"Inyecta HTML / CSS / JS para todo el sitio en el <head> o antes de </body> de cada página publicada.",warning:"El código se inyecta tal cual en cada página. Sin sanitización — un <script> roto puede tirar todo el sitio hasta que lo corrijas.",loadingEditor:"Cargando editor de código…",expand:"Ampliar",modalClose:"Cerrar",head:{title:"Head",help:"Añadido al final del <head> de cada página. Ideal para analítica, fuentes, anulaciones <style>.",placeholder:"<!-- p. ej. <script>...<\/script> para Google Analytics, <style>body{...}</style> para anulaciones -->"},body:{title:"Fin del body",help:"Añadido justo antes de </body>. Ideal para scripts diferidos (widgets de chat, analítica tardía) que necesitan el DOM parseado.",placeholder:"<!-- p. ej. <script>...<\/script> para un widget de chat que necesita el DOM listo -->"},save:"Guardar",saving:"Guardando…",saved:"Código personalizado guardado.",saveFailed:"Error al guardar.",republishHint:"Republica tus entradas y páginas (Temas → Regenerar el sitio) para empujar el nuevo código a todos los archivos ya en línea."},Lke={title:"Eigen code",description:"Plaats site-brede HTML / CSS / JS in de <head> of vóór de </body> van elke gepubliceerde pagina.",warning:"Code wordt ongewijzigd op elke pagina ingevoegd. Geen sanering — een kapot <script> kan de hele site neerhalen tot je het herstelt.",loadingEditor:"Code-editor laden…",expand:"Vergroten",modalClose:"Sluiten",head:{title:"Head",help:"Toegevoegd aan het einde van de <head> van elke pagina. Ideaal voor analytics, lettertypen, aangepaste <style>-overrides.",placeholder:"<!-- bv. <script>...<\/script> voor Google Analytics, <style>body{...}</style> voor overrides -->"},body:{title:"Einde body",help:"Toegevoegd vlak vóór </body>. Ideaal voor uitgestelde scripts (chat-widgets, late analytics) die een geparste DOM nodig hebben.",placeholder:"<!-- bv. <script>...<\/script> voor een chat-widget dat een gereed DOM nodig heeft -->"},save:"Opslaan",saving:"Opslaan…",saved:"Eigen code opgeslagen.",saveFailed:"Opslaan mislukt.",republishHint:"Publiceer je berichten en pagina's opnieuw (Thema's → Site opnieuw genereren) om de nieuwe code naar alle reeds online bestanden te pushen."},Dke={title:"Código personalizado",description:"Injeta HTML / CSS / JS para todo o site no <head> ou antes de </body> de cada página publicada.",warning:"O código é injetado tal qual em cada página. Sem sanitização — um <script> avariado pode deitar abaixo o site inteiro até o corrigires.",loadingEditor:"A carregar editor de código…",expand:"Ampliar",modalClose:"Fechar",head:{title:"Head",help:"Adicionado no fim do <head> de cada página. Ideal para analítica, tipos de letra, sobreposições <style>.",placeholder:"<!-- p. ex. <script>...<\/script> para Google Analytics, <style>body{...}</style> para sobreposições -->"},body:{title:"Fim do body",help:"Adicionado mesmo antes de </body>. Ideal para scripts diferidos (widgets de chat, analítica tardia) que precisam do DOM analisado.",placeholder:"<!-- p. ex. <script>...<\/script> para um widget de chat que precisa do DOM pronto -->"},save:"Guardar",saving:"A guardar…",saved:"Código personalizado guardado.",saveFailed:"Falha ao guardar.",republishHint:"Republica os teus artigos e páginas (Temas → Regenerar o site) para empurrar o novo código para todos os ficheiros já online."},Fke={title:"사용자 정의 코드",description:"게시되는 모든 페이지의 <head> 또는 </body> 직전에 사이트 전체 HTML / CSS / JS를 삽입합니다.",warning:"코드는 모든 페이지에 그대로 삽입됩니다. 정제 처리는 없습니다 — 잘못된 <script>는 수정 전까지 사이트 전체를 다운시킬 수 있습니다.",loadingEditor:"코드 편집기 로딩 중…",expand:"확장",modalClose:"닫기",head:{title:"Head",help:"각 페이지의 <head> 하단에 추가됩니다. 분석 도구, 글꼴, 사용자 정의 <style> 재정의에 적합합니다.",placeholder:"<!-- 예: <script>...<\/script> Google Analytics, <style>body{...}</style> 재정의 -->"},body:{title:"Body 끝",help:"</body> 직전에 추가됩니다. DOM 파싱이 필요한 지연 스크립트(채팅 위젯, 후속 분석)에 적합합니다.",placeholder:"<!-- 예: <script>...<\/script> DOM이 준비된 후 실행되는 채팅 위젯 -->"},save:"저장",saving:"저장 중…",saved:"사용자 정의 코드가 저장되었습니다.",saveFailed:"저장에 실패했습니다.",republishHint:"이미 게시된 모든 파일에 새 코드를 적용하려면 게시물과 페이지를 재게시하세요 (테마 → 사이트 재생성)."},F$={head:"",bodyEnd:""},O$=U.lazy(()=>zv(()=>import("./CodeEditor-Wx1WlF3h.js"),[],import.meta.url).then(t=>({default:t.CodeEditor})));function Oke({config:t,save:e}){const{t:n}=Fe("flexweg-custom-code"),[r,s]=U.useState(t),[i,a]=U.useState(!1),[o,l]=U.useState(null);U.useEffect(()=>{s(t)},[t]);async function c(){a(!0);try{await e(r),at.success(n("saved"))}catch(h){at.error(h.message||n("saveFailed"))}finally{a(!1)}}return d.jsxs("div",{className:"space-y-6",children:[d.jsxs("section",{className:"card p-4 space-y-3",children:[d.jsxs("div",{children:[d.jsx("h2",{className:"font-semibold",children:n("title")}),d.jsx("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:n("description")})]}),d.jsxs("div",{className:"cms-html-block-warning",children:[d.jsx(Zl,{className:"h-3.5 w-3.5 shrink-0 mt-0.5"}),d.jsx("span",{children:n("warning")})]})]}),d.jsx(zL,{title:n("head.title"),help:n("head.help"),placeholder:n("head.placeholder"),value:r.head,onChange:h=>s(p=>({...p,head:h})),onExpand:()=>l("head"),loadingLabel:n("loadingEditor"),expandLabel:n("expand")}),d.jsx(zL,{title:n("body.title"),help:n("body.help"),placeholder:n("body.placeholder"),value:r.bodyEnd,onChange:h=>s(p=>({...p,bodyEnd:h})),onExpand:()=>l("bodyEnd"),loadingLabel:n("loadingEditor"),expandLabel:n("expand")}),d.jsxs("section",{className:"card p-4 space-y-3",children:[d.jsx("button",{type:"button",className:"btn-primary",onClick:c,disabled:i,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx("span",{children:n(i?"saving":"save")})]})}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:n("republishHint")})]}),o&&d.jsx(zke,{value:o==="head"?r.head:r.bodyEnd,onChange:h=>s(p=>o==="head"?{...p,head:h}:{...p,bodyEnd:h}),onClose:()=>l(null),title:n(o==="head"?"head.title":"body.title"),closeLabel:n("modalClose"),loadingLabel:n("loadingEditor")})]})}function zL({title:t,help:e,placeholder:n,value:r,onChange:s,onExpand:i,loadingLabel:a,expandLabel:o}){return d.jsxs("section",{className:"card p-4 space-y-3",children:[d.jsxs("div",{className:"flex items-start justify-between gap-3",children:[d.jsxs("div",{children:[d.jsx("h3",{className:"font-semibold",children:t}),d.jsx("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:e})]}),d.jsxs("button",{type:"button",className:"btn-ghost text-xs gap-1.5 px-2 py-1 shrink-0",onClick:i,children:[d.jsx(M6,{className:"h-3.5 w-3.5"}),d.jsx("span",{children:o})]})]}),d.jsx(U.Suspense,{fallback:d.jsxs("div",{className:"cms-html-block-codeeditor-fallback",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),d.jsx("span",{children:a})]}),children:d.jsx(O$,{value:r,onChange:s,placeholder:n,minHeight:"200px",maxHeight:"500px"})})]})}function zke({value:t,onChange:e,onClose:n,title:r,closeLabel:s,loadingLabel:i}){return U.useEffect(()=>{function a(o){o.key==="Escape"&&n()}return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[n]),el.createPortal(d.jsxs("div",{className:"fixed inset-0 z-[100] flex flex-col bg-white dark:bg-surface-950",children:[d.jsxs("div",{className:"flex items-center justify-between gap-3 border-b border-surface-200 px-4 py-2.5 dark:border-surface-700",children:[d.jsx("span",{className:"text-sm font-medium text-surface-700 dark:text-surface-200",children:r}),d.jsxs("button",{type:"button",className:"btn-ghost",onClick:n,"aria-label":s,children:[d.jsx(fi,{className:"h-4 w-4"}),d.jsx("span",{className:"hidden sm:inline",children:s})]})]}),d.jsx("div",{className:"cms-html-block-modal-body",children:d.jsx(U.Suspense,{fallback:d.jsxs("div",{className:"cms-html-block-codeeditor-fallback",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),d.jsx("span",{children:i})]}),children:d.jsx(O$,{value:t,onChange:e,height:"100%",autoFocus:!0})})})]}),document.body)}const Uke=`# Flexweg Custom Code
|
|
4949
4949
|
|
|
4950
4950
|
Inject site-wide HTML / CSS / JS into the \`<head>\` or just before \`</body>\` of every published page. Useful for analytics tags, fonts, third-party widgets and inline overrides without having to rebuild the theme.
|
|
4951
4951
|
|
|
@@ -5159,7 +5159,7 @@ WordPress import behaviour.
|
|
|
5159
5159
|
`)),at.success(n("log.copied"))},children:[d.jsx(aW,{className:"h-3.5 w-3.5"}),n("log.copy")]})]}),d.jsx("pre",{className:"text-xs leading-relaxed whitespace-pre-wrap break-all rounded bg-surface-50 dark:bg-surface-900 p-3 max-h-[280px] overflow-auto font-mono",children:B.join(`
|
|
5160
5160
|
`)})]}),d.jsxs("section",{className:"card p-4 space-y-4",children:[d.jsx("h3",{className:"font-medium",children:n("defaults.title")}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:n("defaults.statusMode")}),d.jsx("div",{className:"flex flex-col gap-2 text-sm",children:["draft","from-source","online"].map(Se=>d.jsxs("label",{className:"inline-flex items-start gap-2",children:[d.jsx("input",{type:"radio",checked:a.statusMode===Se,onChange:()=>o(we=>({...we,statusMode:Se})),className:"mt-1"}),d.jsxs("span",{children:[d.jsx("span",{className:"font-medium",children:n(Se==="draft"?"defaults.statusDraft":Se==="from-source"?"defaults.statusFromSource":"defaults.statusOnline")}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400",children:n(Se==="draft"?"defaults.statusDraftHelp":Se==="from-source"?"defaults.statusFromSourceHelp":"defaults.statusOnlineHelp")})]})]},Se))})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"import-default-category",children:n("defaults.defaultCategory")}),d.jsxs("select",{id:"import-default-category",className:"input max-w-xs",value:a.defaultCategory,onChange:Se=>o(we=>({...we,defaultCategory:Se.target.value})),children:[d.jsx("option",{value:"",children:n("defaults.defaultCategoryNone")}),s.categories.map(Se=>d.jsx("option",{value:Se.name,children:Se.name},Se.id))]}),d.jsx("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:n("defaults.defaultCategoryHelp")})]}),d.jsx("div",{children:d.jsxs("label",{className:"inline-flex items-center gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",checked:a.moveProcessedFiles,onChange:Se=>o(we=>({...we,moveProcessedFiles:Se.target.checked}))}),d.jsx("span",{children:n("defaults.moveProcessed")})]})}),d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"import-concurrency",children:n("defaults.imageConcurrency")}),d.jsx("input",{id:"import-concurrency",type:"number",min:1,max:16,className:"input max-w-[100px]",value:a.imageFetchConcurrency,onChange:Se=>o(we=>({...we,imageFetchConcurrency:Math.max(1,Math.min(16,Number(Se.target.value)||4))}))}),d.jsx("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:n("defaults.imageConcurrencyHelp")})]}),d.jsx("div",{children:d.jsx("button",{type:"button",className:"btn-secondary",onClick:xe,disabled:l,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(l?"":"hidden")}),d.jsx(Gs,{className:"h-4 w-4 "+(l?"hidden":"")}),d.jsx("span",{children:n("defaults.save")})]})})})]})]})}function I2e({summary:t,warningCount:e,errorCount:n,showDetails:r,onToggleDetails:s}){const{t:i}=Fe("flexweg-import"),a=t.entries.filter(c=>c.source.type==="post").length,o=t.entries.filter(c=>c.source.type==="page").length,l=t.categoriesToCreate.filter(c=>c.parentSlug).length;return t.entries.length===0&&n===0?d.jsx("p",{className:"text-sm text-surface-500 italic",children:i("summary.noEntries")}):d.jsxs("div",{className:"rounded-md border border-surface-200 dark:border-surface-700 p-3 text-sm space-y-2",children:[d.jsx("h4",{className:"font-medium",children:i("summary.title")}),d.jsxs("ul",{className:"space-y-1",children:[a>0&&d.jsxs("li",{className:"flex items-center gap-2",children:[d.jsx(Gs,{className:"h-4 w-4 text-emerald-500 shrink-0"}),i("summary.posts",{count:a})]}),o>0&&d.jsxs("li",{className:"flex items-center gap-2",children:[d.jsx(Gs,{className:"h-4 w-4 text-emerald-500 shrink-0"}),i("summary.pages",{count:o})]}),t.categoriesToCreate.length>0&&d.jsxs("li",{className:"flex items-center gap-2",children:[d.jsx(Gs,{className:"h-4 w-4 text-emerald-500 shrink-0"}),i("summary.categoriesNew",{count:t.categoriesToCreate.length}),l>0&&d.jsxs("span",{className:"text-surface-500",children:[" ",i("summary.categoriesHierarchy",{count:l})]})]}),t.tagsToCreate.length>0&&d.jsxs("li",{className:"flex items-center gap-2",children:[d.jsx(Gs,{className:"h-4 w-4 text-emerald-500 shrink-0"}),i("summary.tagsNew",{count:t.tagsToCreate.length})]}),t.imagesToUpload.length>0&&d.jsxs("li",{className:"flex items-center gap-2",children:[d.jsx(Gs,{className:"h-4 w-4 text-emerald-500 shrink-0"}),i("summary.imagesLocal",{count:t.imagesToUpload.length})]}),t.wpAttachmentsToFetch.length>0&&d.jsxs("li",{className:"flex items-center gap-2",children:[d.jsx(Gf,{className:"h-4 w-4 text-blue-500 shrink-0"}),i("summary.imagesRemote",{count:t.wpAttachmentsToFetch.length})]}),e>0&&d.jsxs("li",{className:"flex items-center gap-2 text-amber-600 dark:text-amber-400",children:[d.jsx(Zl,{className:"h-4 w-4 shrink-0"}),i("summary.warnings",{count:e})]}),n>0&&d.jsxs("li",{className:"flex items-center gap-2 text-red-600 dark:text-red-400",children:[d.jsx(bw,{className:"h-4 w-4 shrink-0"}),i("summary.errors",{count:n})]})]}),d.jsxs("button",{type:"button",className:"btn-ghost text-xs",onClick:s,children:[d.jsx(qf,{className:r?"h-3.5 w-3.5":"hidden"}),d.jsx(gw,{className:r?"hidden":"h-3.5 w-3.5"}),d.jsx("span",{children:i(r?"summary.hideDetails":"summary.showDetails")})]}),r&&d.jsx("div",{className:"mt-2 space-y-2 text-xs",children:d.jsx(N2e,{summary:t})})]})}function N2e({summary:t}){return d.jsxs(d.Fragment,{children:[t.entries.length>0&&d.jsxs("ul",{className:"space-y-0.5 max-h-[180px] overflow-auto rounded bg-surface-50 dark:bg-surface-900 p-2",children:[t.entries.slice(0,200).map(e=>d.jsxs("li",{children:[d.jsxs("span",{className:"font-mono text-surface-500",children:["[",e.source.type,"]"]})," ",e.source.title," →"," ",d.jsxs("span",{className:"font-mono",children:["/",e.finalSlug]}),e.slugWasModified&&d.jsx("span",{className:"text-amber-600 dark:text-amber-400",children:" (renamed)"})]},`${e.source.sourceName}-${e.finalSlug}`)),t.entries.length>200&&d.jsxs("li",{className:"text-surface-500 italic",children:["… and ",t.entries.length-200," more"]})]}),t.warnings.length>0&&d.jsx("ul",{className:"space-y-0.5 max-h-[180px] overflow-auto rounded bg-surface-50 dark:bg-surface-900 p-2",children:t.warnings.map((e,n)=>d.jsxs("li",{className:e.level==="error"?"text-red-600 dark:text-red-400":"text-amber-700 dark:text-amber-400",children:[d.jsxs("span",{className:"font-mono text-surface-500",children:["[",e.source,"]"]})," ",e.message]},n))})]})}const P2e=`# Flexweg Import
|
|
5161
5161
|
|
|
5162
|
-
Bulk-imports posts and pages into
|
|
5162
|
+
Bulk-imports posts and pages into AgentCMS from two source formats:
|
|
5163
5163
|
|
|
5164
5164
|
- **Markdown** files with YAML frontmatter (Hugo, Eleventy, Astro, Jekyll, custom scripts)
|
|
5165
5165
|
- **WordPress** XML exports (Tools → Export → All content)
|
|
@@ -5242,7 +5242,7 @@ The plugin parses the export's XML directly via the browser's native \`DOMParser
|
|
|
5242
5242
|
|
|
5243
5243
|
### Mapping rules
|
|
5244
5244
|
|
|
5245
|
-
| WordPress |
|
|
5245
|
+
| WordPress | AgentCMS | Notes |
|
|
5246
5246
|
|---|---|---|
|
|
5247
5247
|
| \`<wp:post_type>post</wp:post_type>\` | \`Post.type = "post"\` | |
|
|
5248
5248
|
| \`<wp:post_type>page</wp:post_type>\` | \`Post.type = "page"\` | |
|
|
@@ -5261,7 +5261,7 @@ The plugin parses the export's XML directly via the browser's native \`DOMParser
|
|
|
5261
5261
|
|
|
5262
5262
|
- **Gutenberg blocks**: complex blocks (group, columns, navigation, query loops, …) become HTML in the markdown body. They render correctly when published — DOMPurify keeps the HTML intact at publish time — but the editor sees them as opaque blocks.
|
|
5263
5263
|
- **Shortcodes**: \`[caption]\`, \`[gallery]\`, \`[embed]\`, custom plugin shortcodes are preserved verbatim. They render as plain text on the public site unless you handle them post-import.
|
|
5264
|
-
- **Comments**: ignored —
|
|
5264
|
+
- **Comments**: ignored — AgentCMS has no comments.
|
|
5265
5265
|
- **Custom post types** (\`wp_block\`, \`wp_template\`, \`nav_menu_item\`, \`oembed_cache\`): ignored.
|
|
5266
5266
|
- **Custom fields** (postmeta beyond \`_thumbnail_id\`): ignored.
|
|
5267
5267
|
|
|
@@ -5324,7 +5324,7 @@ When disabled, the settings page is unreachable but \`_cms-import/\` and any imp
|
|
|
5324
5324
|
- **No multi-language content**: each entry is one language. Multi-locale content remains the next-major-version conversation.
|
|
5325
5325
|
- **WordPress.com sites**: exports work, but media URLs may need OAuth depending on the privacy setting. Make the source site public before importing.
|
|
5326
5326
|
`,R2e={id:"flexweg-import",name:"Flexweg Import",version:"1.0.0",author:"Flexweg",description:"Bulk-imports posts and pages from markdown (with YAML frontmatter) or WordPress XML exports. Auto-creates categories / tags (with hierarchy), uploads referenced images, rewrites image URLs in the body, and matches authors to existing CMS users.",readme:P2e,i18n:{en:ESe,fr:_Se,de:CSe,es:ASe,nl:TSe,pt:ISe,ko:NSe},settings:{navLabelKey:"title",defaultConfig:A2e,component:T2e},register(){}},K0=[Z1e,Nke,Bke,oSe,SSe,R2e];function o7(){return K0}function j2e(t){return K0.some(e=>e.id===t)}const Zg=[];function l7(){const t=R1();return t.length===0?Zg:[...Zg,...t]}function M2e(t){return Zg.find(e=>e.id===t)??K0.find(e=>e.id===t)??R1().find(e=>e.id===t)}function L2e(){for(const t of[...K0,...Zg])if(t.i18n)for(const[e,n]of Object.entries(t.i18n))n&&jt.addResourceBundle(e,t.id,n,!0,!0)}L2e();function D2e(t){if(t.i18n)for(const[e,n]of Object.entries(t.i18n))n&&jt.addResourceBundle(e,t.id,n,!0,!0)}function F2e(t){Vce(),Tce(),Pce(),Bce(),Mce(),Fce(),zce();for(const e of K0)try{e.register(df)}catch(n){console.error(`MU plugin "${e.id}" failed to register:`,n)}for(const e of Zg)if(t[e.id]!==!1)try{e.register(df)}catch(n){console.error(`Plugin "${e.id}" failed to register:`,n)}for(const e of R1())if(t[e.id]!==!1)try{e.register(df)}catch(n){console.error(`External plugin "${e.id}" failed to register:`,n)}}const c7="externalRegistry";function u7(){return rl(Xs(),ls.settings,c7)}function O2e(t){if(!t||typeof t!="object")return null;const e=t;return!Array.isArray(e.plugins)&&!Array.isArray(e.themes)?null:{plugins:Array.isArray(e.plugins)?e.plugins:[],themes:Array.isArray(e.themes)?e.themes:[]}}async function z2e(){const t=await Cu(u7());return t.exists()?O2e(t.data()):null}async function U2e(t){await ro(u7(),{plugins:t.plugins,themes:t.themes})}const B2e=Object.freeze(Object.defineProperty({__proto__:null,EXTERNAL_REGISTRY_DOC_ID:c7,readBackendRegistry:z2e,writeBackendRegistry:U2e},Symbol.toStringTag,{value:"Module"})),d7="externalRegistry";function $2e(t){if(!t||typeof t!="object")return null;const e=t;return!Array.isArray(e.plugins)&&!Array.isArray(e.themes)?null:{plugins:Array.isArray(e.plugins)?e.plugins:[],themes:Array.isArray(e.themes)?e.themes:[]}}async function H2e(){const{rows:t}=await hs("SELECT value FROM config WHERE key = ?",[d7]);if(t.length===0)return null;let e;try{e=JSON.parse(t[0].value)}catch(n){return console.warn("[external-registry] SQLite row had invalid JSON — treating as empty:",n),null}return $2e(e)}async function V2e(t){const e=JSON.stringify({plugins:t.plugins,themes:t.themes});await Kn(`INSERT INTO config (key, value) VALUES (?, ?)
|
|
5327
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value`,[d7,e])}const q2e=Object.freeze(Object.defineProperty({__proto__:null,readBackendRegistry:H2e,writeBackendRegistry:V2e},Symbol.toStringTag,{value:"Module"})),rN="externalRegistry";function W2e(t){if(!t||typeof t!="object")return null;const e=t;return!Array.isArray(e.plugins)&&!Array.isArray(e.themes)?null:{plugins:Array.isArray(e.plugins)?[...e.plugins]:[],themes:Array.isArray(e.themes)?[...e.themes]:[]}}async function G2e(){const t=Ct();return await t.ready(),W2e(t.get("config",rN))}async function K2e(t){await Ct().write([{op:"set",collection:"config",doc:{id:rN,plugins:t.plugins,themes:t.themes}}],{message:"Update installed plugins and themes"})}const J2e=Object.freeze(Object.defineProperty({__proto__:null,EXTERNAL_REGISTRY_DOC_ID:rN,readBackendRegistry:G2e,writeBackendRegistry:K2e},Symbol.toStringTag,{value:"Module"})),h7="external.default.json",Q2e="external.json";let J2=null;function f7(){if(!J2){const t=$r();J2=t==="flexweg-sqlite"?q2e:ao(t)?J2e:B2e}return J2}function X2e(){return f7().readBackendRegistry()}function dC(t){return f7().writeBackendRegistry(t)}function Z2e(t){if(!t||typeof t!="object")return null;const e=t;return!Array.isArray(e.plugins)&&!Array.isArray(e.themes)?null:{plugins:Array.isArray(e.plugins)?e.plugins:[],themes:Array.isArray(e.themes)?e.themes:[]}}async function hC(t){try{const e=await fetch(`./${t}?_t=${Date.now()}`,{cache:"no-store"});if(e.status===404||!e.ok)return null;const n=await e.json();return Z2e(n)}catch{return null}}async function sN(){let t=null;try{t=await X2e()}catch(r){console.warn("[external-registry] backend read failed:",r)}if(t)return t;const e=await hC(Q2e);if(e)return await dC(e).catch(r=>{console.warn("[external-registry] could not migrate legacy file to backend:",r)}),e;const n=await hC(h7);return n?(await dC(n).catch(r=>{console.warn("[external-registry] could not seed backend from defaults:",r)}),n):{...GU}}async function p7(t){await dC(t)}async function Y2e(){return await hC(h7)??{...GU}}function YL(t,e){const n=i=>i.split(".").slice(0,3).map(a=>Number.parseInt(a,10)||0),r=n(t),s=n(e);for(let i=0;i<3;i++){const a=r[i]??0,o=s[i]??0;if(a!==o)return a<o?-1:1}return 0}function eEe(t){return t?YL(t,W0)>=0&&YL(t,q0)<=0:!1}function tEe(t,e){return`${t}/${e}/bundle.js`}function nEe(t,e){const r=(e.entryPath??tEe(t,e.id)).replace(/^\/+/,""),s=new URL(r,document.baseURI);return e.version&&s.searchParams.set("v",e.version),s.href}async function rEe(t){try{const e=await fetch(t,{method:"GET",cache:"no-store"});if(e.status===404)return!0;if(!e.ok)return!1;const n=e.headers.get("content-type")??"";return!/javascript|ecmascript|module/i.test(n)}catch{return!1}}async function eD(t,e){if(!eEe(e.apiVersion))return console.warn(`[external] skipping ${t}/${e.id}: apiVersion ${e.apiVersion} outside [${W0}, ${q0}]`),{ok:!1,missing:!1};const n=nEe(t,e);let r;try{r=await import(n)}catch(i){return console.error(`[external] failed to import ${n}:`,i),{ok:!1,missing:await rEe(n)}}const s=r.default??r.manifest;if(!s||typeof s!="object"||!("id"in s))return console.error(`[external] ${t}/${e.id} bundle did not export a valid manifest (default or named "manifest")`),{ok:!1,missing:!1};if(s.id!==e.id)return console.error(`[external] ${t}/${e.id} manifest.id mismatch: got "${s.id}"`),{ok:!1,missing:!1};try{if(t==="plugins"){const i=s;D2e(i),VU(i)}else{const i=s;e1e(i),qU(i)}}catch(i){return console.error(`[external] register failed for ${t}/${e.id}:`,i),{ok:!1,missing:!1}}return{ok:!0}}async function sEe(){const t=await sN();q0e(),W0e();let e=0,n=0;const r=new Set,s=new Set;for(const a of t.plugins){const o=await eD("plugins",a);o.ok?e++:(n++,o.missing&&r.add(a.id))}for(const a of t.themes){const o=await eD("themes",a);o.ok?e++:(n++,o.missing&&s.add(a.id))}let i=0;if(r.size>0||s.size>0){const a={plugins:t.plugins.filter(o=>!r.has(o.id)),themes:t.themes.filter(o=>!s.has(o.id))};i=r.size+s.size;try{await p7(a);const o=[...r,...s].join(", ");console.warn(`[external] auto-pruned ${i} stale registry entr${i===1?"y":"ies"}: ${o}`),at.info(jt.t("externalLoader.autoPruned",{count:i,ids:o,defaultValue:`${i} stale external entr${i===1?"y":"ies"} removed from registry: ${o}`})),n-=i}catch(o){console.warn("[external] auto-prune failed to write registry:",o)}}return n>0&&at.warn(jt.t("externalLoader.someFailed",{count:n,defaultValue:`${n} external bundle(s) failed to load. Check the browser console.`})),{loaded:e,failed:n,pruned:i}}function Q2(t){const[e,n]=U.useState(()=>new Map);U.useEffect(()=>{if(e.size===0)return;const a=new Set(t.map(c=>c.id));let o=!1;const l=new Map(e);for(const c of e.keys())a.has(c)&&(l.delete(c),o=!0);o&&n(l)},[t,e]);const r=U.useCallback(a=>{n(o=>{const l=new Map(o);return l.set(a.id,a),l})},[]),s=U.useCallback(a=>{n(o=>{if(!o.has(a))return o;const l=new Map(o);return l.delete(a),l})},[]);return{resolved:U.useMemo(()=>{if(e.size===0)return t;const a=new Set(t.map(l=>l.id)),o=[];for(const l of e.values())a.has(l.id)||o.push(l);return o.length===0?t:[...t,...o]},[t,e]),addOptimistic:r,removeOptimistic:s}}const m7=U.createContext(null);function iEe({children:t}){const[e,n]=U.useState([]),[r,s]=U.useState([]),[i,a]=U.useState([]),[o,l]=U.useState(ll),[c,h]=U.useState([]),[p,m]=U.useState(!1),[g,y]=U.useState({terms:!0,media:!0,users:!0,settings:!0}),[x,v]=U.useState(null);function k(B){console.error("[CmsData] Firestore listener error:",B),v(B)}const[C,N]=U.useState(!1);U.useEffect(()=>{let B=!1;return sEe().catch(X=>{console.error("[CmsData] external bundles loader threw:",X)}).finally(()=>{B||N(!0)}),()=>{B=!0}},[]),U.useEffect(()=>{if(!C)return;const B=[Doe(X=>{n(X),y(fe=>({...fe,terms:!1}))},k),N1e(X=>{s(X),y(fe=>({...fe,media:!1}))},k),OI(X=>{a(X),y(fe=>({...fe,users:!1}))},k),yxe(X=>{l(X),y(fe=>({...fe,settings:!1})),F2e(X.enabledPlugins??{}),t1e(X.activeThemeId,X)},k)];return()=>B.forEach(X=>X())},[C]);const _=o.paginationMode??"global";U.useEffect(()=>{if(_!=="global"){h([]),m(!1);return}const B=Uue(X=>{h(X),m(!0)},k);return()=>B()},[_]);const{resolved:P,addOptimistic:D}=Q2(c),{resolved:I,addOptimistic:L}=Q2(e),{resolved:j,addOptimistic:q}=Q2(r),V=U.useMemo(()=>P.filter(B=>B.type==="post"),[P]),O=U.useMemo(()=>P.filter(B=>B.type==="page"),[P]),$=U.useMemo(()=>({terms:I,categories:I.filter(B=>B.type==="category"),tags:I.filter(B=>B.type==="tag"),media:j,posts:V,pages:O,postsLoaded:p,users:i,settings:o,loading:Object.values(g).some(Boolean),error:x,addOptimisticPost:D,addOptimisticTerm:L,addOptimisticMedia:q}),[I,j,V,O,p,i,o,g,x,D,L,q]);return d.jsx(m7.Provider,{value:$,children:t})}function En(){const t=U.useContext(m7);if(!t)throw new Error("useCmsData must be used inside <CmsDataProvider>");return t}const g7=U.createContext(null),aEe="theme";function oEe(){return typeof document>"u"?"light":document.documentElement.classList.contains("dark")?"dark":"light"}function lEe(t){const e=document.documentElement;t==="dark"?e.classList.add("dark"):e.classList.remove("dark");try{localStorage.setItem(aEe,t)}catch{}}function tD({children:t}){const[e,n]=U.useState(oEe);U.useLayoutEffect(()=>{lEe(e)},[e]);const r=U.useCallback(a=>{(a==="dark"||a==="light")&&n(a)},[]),s=U.useCallback(()=>{n(a=>a==="dark"?"light":"dark")},[]),i=U.useMemo(()=>({theme:e,setTheme:r,toggleTheme:s}),[e,r,s]);return d.jsx(g7.Provider,{value:i,children:t})}function cEe(){const t=U.useContext(g7);if(!t)throw new Error("useTheme must be used inside <ThemeProvider>");return t}const ah=""+new URL("flexweg-logo-CdtuqAFA.png",import.meta.url).href;function uEe({mobileOpen:t,onMobileClose:e}){const{t:n}=Fe(),{user:r,isAdmin:s}=co(),{settings:i}=En(),{theme:a,toggleTheme:o}=cEe(),l=a==="dark",h=!!pi(i.activeThemeId).settings,m=[{to:"/dashboard",labelKey:"nav.dashboard",icon:xW},{to:"/posts",labelKey:"nav.posts",icon:uW},{to:"/pages",labelKey:"nav.pages",icon:SW},{to:"/taxonomies",labelKey:"nav.taxonomies",icon:hW},{to:"/media",labelKey:"nav.media",icon:Go},{to:"/menus",labelKey:"nav.menus",icon:L6},{to:"/themes",labelKey:"nav.themes",icon:kw},{to:"/theme-settings",labelKey:"nav.themeSettings",icon:RW,hidden:!h},{to:"/plugins",labelKey:"nav.plugins",icon:DW},{to:"/settings",labelKey:"nav.settings",icon:zC},{to:"/users",labelKey:"nav.users",icon:GW,adminOnly:!0}].filter(g=>!g.hidden&&(!g.adminOnly||s));return d.jsxs(d.Fragment,{children:[d.jsx("div",{className:qn("fixed inset-0 z-40 bg-black/40 transition-opacity md:hidden",t?"opacity-100":"pointer-events-none opacity-0"),"aria-hidden":"true",onClick:e}),d.jsxs("aside",{className:qn("fixed inset-y-0 left-0 z-50 flex w-72 max-w-[85vw] flex-col border-r border-surface-200 bg-white transition-transform dark:border-surface-800 dark:bg-surface-900","md:static md:z-auto md:w-60 md:max-w-none md:translate-x-0 md:transition-none",t?"translate-x-0":"-translate-x-full"),"aria-hidden":!t,children:[d.jsxs("div",{className:"px-5 h-16 flex items-center gap-2.5 border-b border-surface-200 dark:border-surface-800",children:[d.jsx("img",{src:ah,alt:"Flexweg",className:"h-8 w-8 rounded-lg shadow-card object-cover shrink-0"}),d.jsxs("div",{className:"flex-1 min-w-0",children:[d.jsx("p",{className:"text-sm font-semibold leading-none",children:n("common.appName")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:"Static publisher"})]}),d.jsx("button",{type:"button",onClick:e,"aria-label":n("nav.closeMenu"),className:"md:hidden rounded-md p-1.5 text-surface-500 hover:bg-surface-100 hover:text-surface-900 dark:text-surface-400 dark:hover:bg-surface-800 dark:hover:text-surface-50",children:d.jsx(fi,{className:"h-4 w-4"})})]}),d.jsx("nav",{className:"flex-1 px-3 py-4 space-y-0.5 overflow-y-auto",children:m.map(({to:g,labelKey:y,icon:x})=>d.jsxs(E6,{to:g,className:({isActive:v})=>qn("flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors",v?"bg-surface-900 text-white shadow-card dark:bg-surface-100 dark:text-surface-900":"text-surface-600 hover:bg-surface-100 hover:text-surface-900 dark:text-surface-300 dark:hover:bg-surface-800 dark:hover:text-surface-50"),children:[d.jsx(x,{className:"h-4 w-4"}),n(y)]},g))}),d.jsxs("div",{className:"px-3 py-3 border-t border-surface-200 dark:border-surface-800",children:[r&&d.jsxs("div",{className:"px-2 pb-2",children:[d.jsx("p",{className:"text-xs font-medium text-surface-700 truncate dark:text-surface-200",children:r.email}),d.jsx("p",{className:"text-[11px] text-surface-400 dark:text-surface-500",children:n(s?"common.administrator":"common.editor")})]}),d.jsxs("button",{type:"button",onClick:o,className:"w-full flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-surface-600 hover:bg-surface-100 hover:text-surface-900 transition-colors dark:text-surface-300 dark:hover:bg-surface-800 dark:hover:text-surface-50",children:[d.jsx(BW,{className:qn("h-4 w-4",!l&&"hidden")}),d.jsx(IW,{className:qn("h-4 w-4",l&&"hidden")}),d.jsx("span",{children:n(l?"common.lightMode":"common.darkMode")})]}),d.jsxs("button",{type:"button",onClick:()=>qB(),className:"w-full flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-surface-600 hover:bg-surface-100 hover:text-surface-900 transition-colors dark:text-surface-300 dark:hover:bg-surface-800 dark:hover:text-surface-50",children:[d.jsx(CW,{className:"h-4 w-4"}),n("common.signOut")]})]})]})]})}function xp(){const{t,i18n:e}=Fe(),n=qxe(),r=e.resolvedLanguage??e.language;async function s(i){await s1(i),n!=null&&n.user&&n.record&&await SB(n.user.uid,{adminLocale:i}).catch(()=>{})}return d.jsxs("div",{className:"relative inline-flex items-center gap-1 px-1.5 py-1 rounded-md hover:bg-surface-100 dark:hover:bg-surface-800 transition-colors",children:[d.jsx("span",{className:"text-base leading-none select-none","aria-hidden":!0,children:Rie[r]}),d.jsx(qf,{className:"h-3.5 w-3.5 text-surface-500 dark:text-surface-400","aria-hidden":!0}),d.jsx("select",{className:"absolute inset-0 cursor-pointer opacity-0","aria-label":t("common.language"),value:r,onChange:i=>s(i.target.value),children:r1.map(i=>d.jsx("option",{value:i,children:r_[i]},i))})]})}function dEe({triggerLabel:t,triggerClassName:e="btn-primary",disabled:n,alignEnd:r=!0,sections:s}){const[i,a]=U.useState(!1),o=U.useRef(null);U.useEffect(()=>{if(!i)return;const c=p=>{o.current&&!o.current.contains(p.target)&&a(!1)},h=p=>{p.key==="Escape"&&a(!1)};return document.addEventListener("pointerdown",c),document.addEventListener("keydown",h),()=>{document.removeEventListener("pointerdown",c),document.removeEventListener("keydown",h)}},[i]),U.useEffect(()=>{n&&i&&a(!1)},[n,i]);function l(c){if(c.disabled||(a(!1),!c.onSelect))return;const h=c.onSelect;setTimeout(()=>{h()},0)}return d.jsxs("div",{ref:o,className:"relative inline-block",children:[d.jsxs("button",{type:"button",className:e,onClick:()=>a(c=>!c),disabled:n,"aria-haspopup":"menu","aria-expanded":i,children:[d.jsx("span",{className:"contents",children:t}),d.jsx(qf,{className:"h-4 w-4 transition-transform "+(i?"rotate-180":"")})]}),i&&d.jsx("div",{role:"menu",className:"absolute z-50 mt-1 min-w-[260px] max-w-[360px] max-h-[calc(100vh-4.5rem)] overflow-y-auto overscroll-contain rounded-md border border-surface-200 bg-white shadow-pop dark:border-surface-700 dark:bg-surface-900 animate-scale-in origin-top-right "+(r?"right-0":"left-0"),children:s.map((c,h)=>d.jsxs("div",{className:h>0?"border-t border-surface-100 dark:border-surface-800":"",children:[c.label&&d.jsx("div",{className:"px-3 pt-2 pb-1 text-[10px] font-semibold uppercase tracking-wider text-surface-500 dark:text-surface-400",children:c.label}),c.items.map(p=>d.jsxs("button",{type:"button",role:"menuitem",onClick:()=>l(p),disabled:p.disabled,className:"block w-full text-left px-3 py-2 text-sm transition-colors "+(p.disabled?"cursor-not-allowed text-surface-400 dark:text-surface-500":"hover:bg-surface-100 dark:hover:bg-surface-800 text-surface-900 dark:text-surface-50"),children:[d.jsx("div",{className:"font-medium",children:p.label}),p.description&&d.jsx("div",{className:"text-xs text-surface-500 dark:text-surface-400 mt-0.5",children:p.description})]},p.id))]},c.id))})]})}function hEe({entries:t}){if(t.length===0)return null;const e=[];for(let n=t.length-1;n>=0;n--)e.push(n);return d.jsx("ul",{className:"card divide-y divide-surface-200 dark:divide-surface-800 max-h-64 overflow-y-auto",children:e.map(n=>{const r=t[n];return d.jsxs("li",{className:"flex items-start gap-2 px-3 py-2 text-sm",children:[d.jsx(fEe,{level:r.level}),d.jsx("span",{className:qn(r.level==="error"&&"text-red-700 dark:text-red-300",r.level==="warn"&&"text-amber-700 dark:text-amber-300",r.level==="success"&&"text-emerald-700 dark:text-emerald-300",r.level==="info"&&"text-surface-600 dark:text-surface-300"),children:r.message})]},n)})})}function fEe({level:t}){return t==="success"?d.jsx(Gs,{className:"h-4 w-4 mt-0.5 text-emerald-500 shrink-0"}):t==="warn"?d.jsx(Zl,{className:"h-4 w-4 mt-0.5 text-amber-500 shrink-0"}):t==="error"?d.jsx(bw,{className:"h-4 w-4 mt-0.5 text-red-500 shrink-0"}):d.jsx(Gf,{className:"h-4 w-4 mt-0.5 text-surface-400 shrink-0"})}function iN({entries:t,busy:e,onClear:n,title:r,runningTitle:s}){const{t:i}=Fe(),a=e||t.length>0;if(U.useEffect(()=>{if(!a||e)return;const l=c=>{c.key==="Escape"&&n()};return document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l)},[a,e,n]),!a)return null;const o=e?s??i("themes.regenerate.running"):r??i("themes.regenerate.button");return el.createPortal(d.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4 animate-fade-in",role:"dialog","aria-modal":"true","aria-labelledby":"publish-log-modal-title",onClick:l=>{e||l.target===l.currentTarget&&n()},children:d.jsxs("div",{className:"card w-full max-w-lg max-h-[80vh] flex flex-col animate-scale-in",children:[d.jsxs("div",{className:"flex items-center justify-between border-b border-surface-200 px-4 py-3 dark:border-surface-700",children:[d.jsxs("h2",{id:"publish-log-modal-title",className:"text-sm font-semibold flex items-center gap-2",children:[e?d.jsx(ct,{className:"h-4 w-4 animate-spin text-blue-500"}):d.jsx(Su,{className:"h-4 w-4 text-surface-500"}),o]}),!e&&d.jsx("button",{type:"button",className:"p-1 rounded hover:bg-surface-100 dark:hover:bg-surface-800",onClick:n,"aria-label":i("common.close"),children:d.jsx(fi,{className:"h-4 w-4"})})]}),d.jsx("div",{className:"overflow-y-auto p-3",children:d.jsx(hEe,{entries:t})})]})}),document.body)}async function Yg(t=H1(),e,n=()=>{}){for(const r of t){if(!r.cssText)n({level:"warn",message:`Theme "${r.id}" has no embedded CSS, skipping.`});else{const a=`theme-assets/${r.id}.css`;let o=r.cssText;if(r.compileCss&&r.settings){const l=e==null?void 0:e[r.id],c={...r.settings.defaultConfig,...l??{}};try{o=r.compileCss(c)}catch(h){console.error(`[themes] compileCss for "${r.id}" failed:`,h)}}n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:o})}if(r.jsText){const a=`theme-assets/${r.id}-menu.js`;n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:r.jsText})}if(r.jsTextPosts){const a=`theme-assets/${r.id}-posts.js`;n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:r.jsTextPosts})}const s=r.jsTextCatalog;if(s){const a=`theme-assets/${r.id}-catalog.js`;n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:s})}const i=r.jsTextFilters;if(i){const a=`theme-assets/${r.id}-filters.js`;n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:i})}}n({level:"success",message:"Theme assets synced."})}function pEe(){const{t}=Fe(),{settings:e,terms:n,users:r,media:s}=En(),i=H1(),[a,o]=U.useState(!1),[l,c]=U.useState([]),[h,p]=U.useState(()=>xu());U.useEffect(()=>Tz(()=>{p(xu())}),[]);async function m(v){o(!0),c([]);const k=C=>c(N=>[...N,C]);try{await v(k)}catch(C){k({level:"error",message:C.message})}finally{o(!1)}}function g(v,k){if(!k)return"";const C=v.i18nNamespace??v.id,N=jt.t(k,{ns:C});return N===k?"":N}async function y(v){return eo({terms:n,settings:e,users:r,authorLookup:Ea(r,s),refreshTerms:v==null?void 0:v.refreshTerms})}const x=U.useMemo(()=>{const v=[{id:"home",label:t("themes.regenerate.home"),description:t("themes.regenerate.homeHelp"),onSelect:()=>m(async _=>{const P=await y();await qve(P,_)})},{id:"allHtml",label:t("themes.regenerate.allHtml"),description:t("themes.regenerate.allHtmlHelp"),onSelect:()=>m(async _=>{const P=await y({refreshTerms:!0});await Y_(P,_)})},{id:"repair",label:t("themes.regenerate.repair"),description:t("themes.regenerate.repairHelp"),onSelect:()=>m(async _=>{const P=await y({refreshTerms:!0});await Wve(P,_)})},{id:"assets",label:t("themes.regenerate.assets"),description:t("themes.regenerate.assetsHelp"),onSelect:()=>m(async _=>{await Yg(i,e.themeConfigs,_)})}],k=h.map(_=>({id:_.id,label:g(_,_.labelKey)||_.id,description:g(_,_.descriptionKey)||void 0,onSelect:()=>m(async P=>{const D=await y();await _.run(D,P)})})),C={id:"everything",label:t("themes.regenerate.everything"),description:t("themes.regenerate.everythingHelp"),onSelect:()=>m(async _=>{await Yg(i,e.themeConfigs,_);const P=await y({refreshTerms:!0});await Y_(P,_);for(const D of h)try{await D.run(P,_)}catch(I){_({level:"error",message:`Plugin "${D.id}" regen failed: ${I.message}`})}_({level:"success",message:"Everything regenerated."})})},N=[{id:"site",label:t("themes.regenerate.groupBuiltins"),items:v}];return k.length>0&&N.push({id:"plugins",label:t("themes.regenerate.groupPlugins"),items:k}),N.push({id:"everything",items:[C]}),N},[h,e.themeConfigs,t]);return d.jsxs(d.Fragment,{children:[d.jsx(dEe,{triggerLabel:d.jsxs(d.Fragment,{children:[d.jsx(ct,{className:a?"h-4 w-4 animate-spin":"hidden"}),d.jsx(Su,{className:a?"hidden":"h-4 w-4"}),d.jsx("span",{children:t(a?"themes.regenerate.running":"themes.regenerate.button")})]}),triggerClassName:"btn-secondary",disabled:a,sections:x}),d.jsx(iN,{entries:l,busy:a,onClear:()=>c([])})]})}function mEe({onOpenMobileNav:t}){const{t:e}=Fe();return d.jsx("header",{className:"sticky top-0 z-30 bg-white/80 backdrop-blur border-b border-surface-200 dark:bg-surface-900/80 dark:border-surface-800",children:d.jsxs("div",{className:"flex items-center justify-between px-4 md:px-6 h-14",children:[d.jsxs("div",{className:"flex items-center gap-3 min-w-0",children:[d.jsx("button",{type:"button",onClick:t,"aria-label":e("nav.openMenu"),className:"md:hidden p-1.5 rounded-md text-surface-500 hover:text-surface-900 hover:bg-surface-100 transition-colors dark:text-surface-400 dark:hover:text-surface-50 dark:hover:bg-surface-800",children:d.jsx(L6,{className:"h-5 w-5"})}),d.jsxs("div",{className:"flex items-center gap-2 min-w-0 md:hidden",children:[d.jsx("img",{src:ah,alt:"Flexweg",className:"h-7 w-7 rounded-md object-cover shrink-0"}),d.jsx("p",{className:"text-sm font-semibold truncate",children:e("common.appName")})]})]}),d.jsxs("div",{className:"flex items-center gap-3 ml-auto",children:[d.jsx(pEe,{}),d.jsx(xp,{})]})]})})}function gEe(){const[t,e]=U.useState(!1),n=Gd();return U.useEffect(()=>{e(!1)},[n.pathname]),d.jsxs("div",{className:"flex min-h-full bg-surface-50 dark:bg-surface-950",children:[d.jsx(uEe,{mobileOpen:t,onMobileClose:()=>e(!1)}),d.jsxs("div",{className:"flex-1 min-w-0 flex flex-col",children:[d.jsx(mEe,{onOpenMobileNav:()=>e(!0)}),d.jsx("main",{className:"flex-1 min-w-0 overflow-x-hidden",children:d.jsx(k6,{})})]})]})}function fC({title:t,message:e}){const{t:n}=Fe();return d.jsx("div",{className:"min-h-full flex items-center justify-center p-6",children:d.jsxs("div",{className:"max-w-md w-full text-center",children:[d.jsx("div",{className:"inline-flex h-12 w-12 items-center justify-center rounded-full bg-red-100 mb-4 dark:bg-red-900/40",children:d.jsx(Zl,{className:"h-5 w-5 text-red-600 dark:text-red-400"})}),d.jsx("h1",{className:"text-lg font-semibold text-surface-900 dark:text-surface-50",children:t??n("errors.appError")}),e&&d.jsx("p",{className:"text-sm text-surface-600 mt-2 whitespace-pre-line dark:text-surface-300",children:e}),d.jsx("p",{className:"text-xs text-surface-500 mt-4 dark:text-surface-400",children:n("errors.consoleHint")})]})})}const bEe={info:"bg-blue-50 text-blue-900 ring-blue-200 dark:bg-blue-900/30 dark:text-blue-100 dark:ring-blue-700/50",success:"bg-emerald-50 text-emerald-900 ring-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-100 dark:ring-emerald-700/50",warn:"bg-amber-50 text-amber-900 ring-amber-200 dark:bg-amber-900/30 dark:text-amber-100 dark:ring-amber-700/50",error:"bg-red-50 text-red-900 ring-red-200 dark:bg-red-900/30 dark:text-red-100 dark:ring-red-700/50"},yEe={info:Gf,success:Gs,warn:Zl,error:Qc};function nD(){const[t,e]=U.useState([]);U.useEffect(()=>zie(r=>{e(i=>[...i,r]);const s=r.durationMs??Uie(r.level);s>0&&window.setTimeout(()=>{e(i=>i.filter(a=>a.id!==r.id))},s)}),[]);function n(r){e(s=>s.filter(i=>i.id!==r))}return t.length===0?null:d.jsx("div",{className:"fixed top-4 right-4 z-[100] flex flex-col gap-2 max-w-sm pointer-events-none",role:"region","aria-live":"polite",children:t.map(r=>d.jsx(vEe,{toast:r,onDismiss:()=>n(r.id)},r.id))})}function vEe({toast:t,onDismiss:e}){const n=yEe[t.level];return d.jsxs("div",{className:qn("rounded-lg shadow-pop ring-1 px-3 py-2.5 flex items-start gap-2.5 animate-scale-in pointer-events-auto",bEe[t.level]),role:t.level==="error"?"alert":"status",children:[d.jsx(n,{className:"h-4 w-4 shrink-0 mt-0.5","aria-hidden":!0}),d.jsx("p",{className:"text-sm leading-snug flex-1 whitespace-pre-line break-words",children:t.message}),d.jsx("button",{type:"button",className:"shrink-0 text-current opacity-60 hover:opacity-100 transition-opacity",onClick:e,"aria-label":"Dismiss",children:d.jsx(fi,{className:"h-4 w-4"})})]})}const aN="flexweg.firestoreIndexesReady",xEe="failed-precondition";function wEe(t){const e=t.match(/https:\/\/console\.firebase\.google\.com\/[^\s)]+/);return e?e[0]:""}function kEe(){const t=tp(Xs(),ls.posts);return[{label:"Posts list — all",fields:"type ASC, createdAt DESC",run:()=>Sg(no(t,pd("type","==","post"),Gl("createdAt","desc"),KE(1)))},{label:"Posts list — by status",fields:"type ASC, status ASC, createdAt DESC",run:()=>Sg(no(t,pd("type","==","post"),pd("status","==","online"),Gl("createdAt","desc"),KE(1)))}]}async function SEe(){const t=[];let e;for(const r of kEe())try{await r.run()}catch(s){const i=s;i.code===xEe?t.push({label:r.label,fields:r.fields,createUrl:wEe(i.message??"")}):e=e??{code:i.code??"unknown",message:i.message??String(s)}}const n=t.length===0&&!e;return n&&_Ee(),{ready:n,missingIndexes:t,unexpectedError:e}}function EEe(){try{return window.localStorage.getItem(aN)==="1"}catch{return!1}}function _Ee(){try{window.localStorage.setItem(aN,"1")}catch{}}function b7(){try{window.localStorage.removeItem(aN)}catch{}}function CEe({children:t}){const{settings:e}=En(),n=e.paginationMode??"global",r=$r()==="firebase"?n:"global",{t:s}=Fe(),[i,a]=U.useState(EEe()?{ready:!0,missingIndexes:[]}:null),[o,l]=U.useState(!1),c=U.useCallback(async()=>{l(!0);try{b7();const h=await SEe();a(h)}finally{l(!1)}},[]);return U.useEffect(()=>{r==="paginated"&&(i||c())},[r,i,c]),r!=="paginated"?d.jsx(d.Fragment,{children:t}):i!=null&&i.ready?d.jsx(d.Fragment,{children:t}):d.jsx("div",{className:"min-h-screen bg-surface-50 dark:bg-surface-950 flex items-center justify-center p-6",children:d.jsxs("div",{className:"card w-full max-w-2xl p-6 space-y-5",children:[d.jsxs("header",{className:"space-y-1",children:[d.jsx("h1",{className:"text-xl font-semibold text-surface-900 dark:text-surface-50",children:s("firestoreSetup.title")}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:s("firestoreSetup.intro")})]}),o&&!i&&d.jsxs("div",{className:"flex items-center gap-2 text-sm text-surface-500 dark:text-surface-400",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),s("firestoreSetup.checking")]}),(i==null?void 0:i.unexpectedError)&&d.jsxs("div",{className:"rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-700 dark:border-red-900 dark:bg-red-950/20 dark:text-red-300",children:[d.jsx("p",{className:"font-medium",children:s("firestoreSetup.unexpectedTitle")}),d.jsxs("p",{className:"mt-1 text-xs font-mono break-all",children:["[",i.unexpectedError.code,"] ",i.unexpectedError.message]}),d.jsx("p",{className:"mt-2 text-xs",children:s("firestoreSetup.unexpectedHint")})]}),(i==null?void 0:i.missingIndexes)&&i.missingIndexes.length>0&&d.jsxs("div",{className:"space-y-3",children:[d.jsx("p",{className:"text-sm text-surface-700 dark:text-surface-200",children:s("firestoreSetup.missingCount",{count:i.missingIndexes.length})}),d.jsx("ol",{className:"space-y-2 text-sm",children:i.missingIndexes.map((h,p)=>d.jsxs("li",{className:"rounded-md border border-surface-200 dark:border-surface-700 p-3 space-y-2",children:[d.jsxs("div",{children:[d.jsxs("span",{className:"font-medium",children:[p+1,"."]})," ",h.label,d.jsx("code",{className:"ml-2 text-xs px-1.5 py-0.5 rounded bg-surface-100 dark:bg-surface-800 font-mono",children:h.fields})]}),h.createUrl?d.jsxs("a",{href:h.createUrl,target:"_blank",rel:"noopener noreferrer",className:"btn-secondary inline-flex",children:[d.jsx(vw,{className:"h-4 w-4"}),s("firestoreSetup.openConsole")]}):d.jsx("p",{className:"text-xs text-surface-500 italic",children:s("firestoreSetup.noUrl")})]},h.label))}),d.jsxs("div",{className:"rounded-md bg-blue-50 dark:bg-blue-950/20 p-3 text-xs text-blue-700 dark:text-blue-300",children:[d.jsx("p",{className:"font-medium",children:s("firestoreSetup.howItWorks")}),d.jsxs("ol",{className:"mt-1 list-decimal list-inside space-y-0.5",children:[d.jsx("li",{children:s("firestoreSetup.step1")}),d.jsx("li",{children:s("firestoreSetup.step2")}),d.jsx("li",{children:s("firestoreSetup.step3")})]})]})]}),i&&!i.ready&&d.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[d.jsxs("button",{type:"button",className:"btn-primary",onClick:c,disabled:o,children:[o?d.jsx(ct,{className:"h-4 w-4 animate-spin"}):d.jsx(Su,{className:"h-4 w-4"}),s(o?"firestoreSetup.retrying":"firestoreSetup.retry")]}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:s("firestoreSetup.buildHint")})]}),(i==null?void 0:i.ready)&&d.jsxs("div",{className:"flex items-center gap-2 text-sm text-emerald-700 dark:text-emerald-400",children:[d.jsx(Gs,{className:"h-4 w-4"}),s("firestoreSetup.allReady")]})]})})}function AEe(){const{t}=Fe(),[e,n]=U.useState(""),[r,s]=U.useState(""),[i,a]=U.useState(!1),[o,l]=U.useState(null),[c,h]=U.useState(null);async function p(g){if(g.preventDefault(),!e.trim()||!r){l("auth.emailPasswordRequired");return}a(!0),l(null),h(null);try{await VB(e,r)}catch(y){l(nC(y))}finally{a(!1)}}async function m(){if(!e.trim()){l("auth.enterEmailFirst");return}l(null),h(null);try{await $xe(e),h(t("auth.resetEmailSent",{email:e.trim()}))}catch(g){l(nC(g))}}return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950",children:[d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),d.jsxs("div",{className:"w-full max-w-sm",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"Flexweg",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("common.appName")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:"Static publisher"})]})]}),d.jsxs("div",{className:"card p-6",children:[d.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-surface-50",children:t("auth.signIn")}),d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("auth.signInSubtitle")}),d.jsxs("form",{onSubmit:p,className:"mt-5 space-y-4","data-form-type":"other",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"login-email",children:t("auth.email")}),d.jsx("input",{id:"login-email",type:"email",autoComplete:"email",className:"input",value:e,onChange:g=>n(g.target.value),placeholder:t("auth.emailPlaceholder"),autoFocus:!0})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"login-password",children:t("auth.password")}),d.jsx("input",{id:"login-password",type:"password",autoComplete:"current-password",className:"input",value:r,onChange:g=>s(g.target.value),placeholder:t("auth.passwordPlaceholder")})]}),o&&d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:t(o)}),c&&d.jsx("div",{className:"rounded-lg bg-emerald-50 text-emerald-700 ring-1 ring-emerald-200 px-3 py-2 text-sm dark:bg-emerald-900/30 dark:text-emerald-300 dark:ring-emerald-700/50",children:c}),d.jsx("button",{type:"submit",className:"btn-primary w-full",disabled:i,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx("span",{children:t(i?"auth.signingIn":"auth.signIn")})]})}),d.jsx("button",{type:"button",className:"btn-ghost w-full text-sm",onClick:m,disabled:i,children:t("auth.forgotPassword")})]})]}),d.jsx("p",{className:"text-[11px] text-surface-400 text-center mt-4 dark:text-surface-500",children:t("auth.footer")})]})]})}function TEe(){const{t}=Fe(),[e,n]=U.useState(""),[r,s]=U.useState(""),[i,a]=U.useState(!1),[o,l]=U.useState(null);async function c(h){if(h.preventDefault(),i)return;const p=e.trim().toLowerCase();if(!p||!/.+@.+\..+/.test(p)){l(t("identity.errors.invalidEmail"));return}if(!r){l(t("identity.errors.missingPassword"));return}a(!0),l(null),typeof window<"u"&&window.location.hash&&window.history.replaceState(null,"",window.location.pathname+window.location.search);try{await UB(p,r)}catch(m){l(t(BB(m))),a(!1)}}return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950 overflow-hidden",children:[d.jsxs("div",{className:"flexweg-blobs","aria-hidden":"true",children:[d.jsx("div",{className:"flexweg-blob flexweg-blob-1"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-2"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-3"})]}),d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),d.jsxs("div",{className:"w-full max-w-sm relative z-10",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"Flexweg",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("identity.brandTitle")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:t("identity.brandSubtitle")})]})]}),d.jsxs("div",{className:"card p-6",children:[d.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-surface-50",children:t("identity.login.heading")}),d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("identity.login.intro")}),d.jsxs("form",{onSubmit:c,className:"mt-5 space-y-4","data-form-type":"other",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"identity-email",children:t("identity.fields.email")}),d.jsx("input",{id:"identity-email",type:"email",className:"input",value:e,onChange:h=>n(h.target.value),placeholder:"you@company.com",required:!0,autoComplete:"email",autoFocus:!0})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"identity-password",children:t("identity.fields.password")}),d.jsx("input",{id:"identity-password",type:"password",className:"input",value:r,onChange:h=>s(h.target.value),placeholder:"••••••••",required:!0,autoComplete:"current-password"})]}),o&&d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:o}),d.jsx("button",{type:"submit",className:"btn-primary w-full",disabled:i,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx("span",{children:t(i?"identity.login.submitting":"identity.login.submit")})]})})]})]}),d.jsx("p",{className:"text-[11px] text-surface-400 text-center mt-4 dark:text-surface-500",children:t("identity.footer")})]})]})}function uo({title:t,description:e,actions:n}){return d.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3 mb-6",children:[d.jsxs("div",{className:"min-w-0",children:[d.jsx("h1",{className:"text-xl font-semibold text-surface-900 dark:text-surface-50",children:t}),e&&d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:e})]}),n&&d.jsx("div",{className:"flex items-center gap-2 shrink-0",children:n})]})}function Mh(t){const{settings:e,posts:n,pages:r,postsLoaded:s}=En(),i=e.paginationMode??"global",a=U.useMemo(()=>{const p=t.type==="post"?n:r;return t.status?p.filter(m=>m.status===t.status).length:p.length},[t.type,t.status,n,r]),[o,l]=U.useState(0),[c,h]=U.useState(i==="paginated");return U.useEffect(()=>{if(i!=="paginated")return;let p=!1;return h(!0),Pf(t).then(m=>{p||(l(m),h(!1))}),()=>{p=!0}},[i,t.type,t.status]),i==="global"?{count:a,loading:!s}:{count:o,loading:c}}function IEe(){const{t}=Fe(),{user:e}=co(),n=Mh({type:"post"}),r=Mh({type:"page"}),s=Mh({type:"post",status:"online"}),i=Mh({type:"page",status:"online"}),a=Mh({type:"post",status:"draft"}),o=Mh({type:"page",status:"draft"}),[l,c]=U.useState(()=>Vj());return U.useEffect(()=>Nce(()=>c(Vj())),[]),d.jsxs("div",{className:"p-4 md:p-6 space-y-6",children:[d.jsx(uo,{title:t("dashboard.title"),description:t("dashboard.welcome",{email:(e==null?void 0:e.email)??""})}),d.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3",children:[d.jsx(Ey,{label:t("dashboard.stats.totalPosts"),value:n.count}),d.jsx(Ey,{label:t("dashboard.stats.totalPages"),value:r.count}),d.jsx(Ey,{label:t("dashboard.stats.online"),value:s.count+i.count}),d.jsx(Ey,{label:t("dashboard.stats.drafts"),value:a.count+o.count})]}),l.length>0&&d.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",children:l.map(({id:h,component:p})=>d.jsx(p,{},h))})]})}function Ey({label:t,value:e}){return d.jsxs("div",{className:"card p-4",children:[d.jsx("p",{className:"text-xs font-medium text-surface-500 dark:text-surface-400",children:t}),d.jsx("p",{className:"text-2xl font-semibold text-surface-900 mt-1 dark:text-surface-50",children:e})]})}function y7(t){const{settings:e}=En(),n=e.paginationMode??"global",r=NEe(t,n==="global"),s=PEe(t,n==="paginated");return n==="global"?r:s}function NEe(t,e){const{posts:n,pages:r,postsLoaded:s}=En(),[i,a]=U.useState(1),o=`${t.type}:${t.status??"all"}:${t.pageSize}`;U.useEffect(()=>{a(1)},[o]);const l=U.useMemo(()=>{if(!e)return[];const g=t.type==="post"?n:r;return t.status?g.filter(y=>y.status===t.status):g},[e,t.type,t.status,n,r]),c=l.length,h=Math.max(1,Math.ceil(c/t.pageSize)),p=Math.min(i,h);return{posts:U.useMemo(()=>l.slice((p-1)*t.pageSize,p*t.pageSize),[l,p,t.pageSize]),loading:e&&!s,page:p,totalCount:c,totalPages:h,hasNext:p<h,hasPrev:p>1,nextPage:()=>a(g=>Math.min(h,g+1)),prevPage:()=>a(g=>Math.max(1,g-1)),resetToFirst:()=>a(1)}}function PEe(t,e){const[n,r]=U.useState(1),[s,i]=U.useState([]),[a,o]=U.useState(!0),[l,c]=U.useState(0),h=U.useRef([void 0]),p=`${t.type}:${t.status??"all"}:${t.pageSize}`;U.useEffect(()=>{h.current=[void 0],r(1)},[p]),U.useEffect(()=>{if(!e)return;let x=!1;return Pf({type:t.type,status:t.status}).then(v=>{x||c(v)}),()=>{x=!0}},[e,t.type,t.status]),U.useEffect(()=>{if(!e)return;o(!0);const x=h.current[n-1];return $ue({type:t.type,status:t.status,pageSize:t.pageSize,cursor:x},k=>{i(k.posts),k.nextCursor?h.current[n]=k.nextCursor:h.current=h.current.slice(0,n),o(!1)},k=>{console.error("[usePostsPage] subscription error:",k),o(!1)})},[e,t.type,t.status,t.pageSize,n]);const m=U.useMemo(()=>Math.max(1,Math.ceil(l/t.pageSize)),[l,t.pageSize]),g=n<m&&!!h.current[n],y=n>1;return{posts:s,loading:a,page:n,totalCount:l,totalPages:m,hasNext:g,hasPrev:y,nextPage:()=>r(x=>Math.min(m,x+1)),prevPage:()=>r(x=>Math.max(1,x-1)),resetToFirst:()=>r(1)}}function oN({status:t}){const{t:e}=Fe();return d.jsx("span",{className:t==="online"?"badge-online":"badge-draft",children:e(`posts.status.${t}`)})}const Lh=100;function REe(t,e){if(e.length===0)return!0;const n=`${t.title} ${t.slug} ${t.excerpt??""}`.toLowerCase();return e.every(r=>n.includes(r))}function jEe(){const{t,i18n:e}=Fe(),{terms:n,settings:r,users:s,media:i}=En(),[a,o]=U.useState("all"),[l,c]=U.useState(""),[h,p]=U.useState(new Set),[m,g]=U.useState(null),y=l.trim().length>0,x=y7({type:"post",status:a==="all"?void 0:a,pageSize:Lh}),[v,k]=U.useState(null),[C,N]=U.useState(!1),[_,P]=U.useState(1);U.useEffect(()=>{if(!y){k(null),P(1);return}let je=!1;return N(!0),Br({type:"post"}).then(z=>{je||(k(z),N(!1))}),()=>{je=!0}},[y]),U.useEffect(()=>{P(1)},[l,a]);const D=U.useMemo(()=>l.toLowerCase().split(/\s+/).filter(Boolean),[l]),I=U.useMemo(()=>!y||!v?[]:(a==="all"?v:v.filter(z=>z.status===a)).filter(z=>REe(z,D)),[y,v,a,D]),L=Math.max(1,Math.ceil(I.length/Lh)),j=Math.min(Math.max(_,1),L),q=U.useMemo(()=>I.slice((j-1)*Lh,j*Lh),[I,j]),V=y?{posts:q,loading:C,page:j,totalCount:I.length,totalPages:L,hasNext:j<L,hasPrev:j>1,nextPage:()=>P(je=>Math.min(L,je+1)),prevPage:()=>P(je=>Math.max(1,je-1))}:x,O=U.useRef(new Map);U.useEffect(()=>{for(const je of x.posts)O.current.set(je.id,je)},[x.posts]),U.useEffect(()=>{if(v)for(const je of v)O.current.set(je.id,je)},[v]);const $=h.size,{draftSelected:B,onlineSelected:X}=U.useMemo(()=>{let je=0,z=0;for(const ce of h){const le=O.current.get(ce);le&&(le.status==="draft"?je++:le.status==="online"&&z++)}return{draftSelected:je,onlineSelected:z}},[h]),fe=V.posts.length>0&&V.posts.every(je=>h.has(je.id)),ie=V.totalCount>V.posts.length,ae=y?I.length>0&&I.every(je=>h.has(je.id)):V.totalCount>0&&$>=V.totalCount,ue=fe&&ie&&!ae;function ve(je,z){p(ce=>{const le=new Set(ce);return z?le.add(je):le.delete(je),le})}function K(){p(je=>{const z=new Set(je);if(V.posts.every(le=>z.has(le.id)))for(const le of V.posts)z.delete(le.id);else for(const le of V.posts)z.add(le.id);return z})}async function ee(){if(y&&I.length>0){p(ce=>{const le=new Set(ce);for(const Y of I)le.add(Y.id);return le});return}const je=await Br({type:"post"}),z=a==="all"?je:je.filter(ce=>ce.status===a);for(const ce of z)O.current.set(ce.id,ce);p(ce=>{const le=new Set(ce);for(const Y of z)le.add(Y.id);return le})}function xe(){p(new Set)}function _e(){c("")}async function ge(){return eo({terms:n,settings:r,users:s,authorLookup:Ea(s,i)})}async function He(){const je=[],z=[];for(const Z of h){const re=O.current.get(Z);re?je.push(re):z.push(Z)}if(z.length===0)return je;const ce=await Br({type:"post"}),le=new Map(ce.map(Z=>[Z.id,Z]));for(const Z of ce)O.current.set(Z.id,Z);const Y=je.slice();for(const Z of z){const re=le.get(Z);re&&Y.push(re)}return Y}async function Ye(je,z){if(z.length===0)return;g(je);let ce=0,le=0;try{const Y=await ge();Y.bulkMode=!0;for(const re of z)try{if(je==="publish")await Hd(re.id,Y,()=>{}),ce++;else if(je==="unpublish")await BI(re.id,Y,()=>{}),ce++;else{try{await HI(re.id,Y,()=>{})}catch(be){console.error(`[bulk-delete] Flexweg cleanup failed for "${re.title}", deleting Firestore doc anyway:`,be)}await BT(re.id),ce++}}catch(be){le++,console.error(`[bulk-${je}] failed on "${re.title}":`,be)}try{await $I(Y,()=>{},xu())}catch(re){console.error("[bulk-flush] partial failure:",re)}const Z=je==="publish"?"posts.bulk.publishedCount":je==="unpublish"?"posts.bulk.unpublishedCount":"posts.bulk.deletedCount";le>0?at.warn(t(Z,{ok:ce,failed:le})):at.success(t(Z,{ok:ce,failed:le})),p(re=>{const be=new Set(re);for(const Te of z)be.delete(Te.id);return be})}finally{g(null)}}async function Se(){const z=(await He()).filter(ce=>ce.status==="draft").map(ce=>({id:ce.id,title:ce.title}));await Ye("publish",z)}async function we(){const z=(await He()).filter(ce=>ce.status==="online").map(ce=>({id:ce.id,title:ce.title}));await Ye("unpublish",z)}async function rt(){if($===0||!window.confirm(t("posts.bulk.confirmDelete",{count:$})))return;const z=(await He()).map(ce=>({id:ce.id,title:ce.title}));await Ye("delete",z)}const lt=V.totalCount===0?0:(V.page-1)*Lh+1,Dt=Math.min(V.page*Lh,V.totalCount);return d.jsxs("div",{className:"p-4 md:p-6",children:[d.jsx(uo,{title:t("posts.title"),actions:d.jsxs(_d,{to:"/posts/new",className:"btn-primary",children:[d.jsx(Kd,{className:"h-4 w-4"}),t("posts.newPost")]})}),d.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-3",children:[d.jsxs("div",{className:"relative flex-1 min-w-[240px] max-w-sm",children:[d.jsx(Ew,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-surface-400"}),d.jsx("input",{type:"search",value:l,onChange:je=>c(je.target.value),placeholder:t("posts.search.placeholder"),className:"input pl-8 pr-8"}),l&&d.jsx("button",{type:"button",onClick:_e,className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-surface-400 hover:text-surface-700 dark:hover:text-surface-200","aria-label":t("posts.search.clear"),children:d.jsx(fi,{className:"h-4 w-4"})})]}),d.jsx("div",{className:"inline-flex rounded-lg bg-surface-100 p-1 dark:bg-surface-800",children:["all","draft","online"].map(je=>d.jsx("button",{type:"button",onClick:()=>o(je),className:a===je?"px-3 py-1 rounded-md text-sm font-medium bg-white text-surface-900 shadow-card dark:bg-surface-900 dark:text-surface-50":"px-3 py-1 rounded-md text-sm font-medium text-surface-600 hover:text-surface-900 dark:text-surface-300",children:t(`posts.filters.${je}`)},je))})]}),$>0&&d.jsxs("div",{className:"mb-3 sticky top-0 z-10 flex flex-wrap items-center gap-2 rounded-md border border-surface-200 bg-white px-3 py-2 shadow-card dark:border-surface-700 dark:bg-surface-900",children:[d.jsx("span",{className:"text-sm font-medium",children:t("posts.bulk.selectedCount",{count:$})}),d.jsxs("div",{className:"flex flex-wrap gap-2 ml-auto",children:[d.jsx("button",{type:"button",className:"btn-ghost",onClick:Se,disabled:m!==null||B===0,title:B===0?t("posts.bulk.noDraftSelected"):void 0,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(m==="publish"?"":"hidden")}),d.jsx(OC,{className:"h-4 w-4 "+(m==="publish"?"hidden":"")}),d.jsx("span",{children:m==="publish"?t("posts.bulk.publishing"):t("posts.bulk.publish",{count:B})})]})}),d.jsx("button",{type:"button",className:"btn-ghost",onClick:we,disabled:m!==null||X===0,title:X===0?t("posts.bulk.noOnlineSelected"):void 0,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(m==="unpublish"?"":"hidden")}),d.jsx(BC,{className:"h-4 w-4 "+(m==="unpublish"?"hidden":"")}),d.jsx("span",{children:m==="unpublish"?t("posts.bulk.unpublishing"):t("posts.bulk.unpublish",{count:X})})]})}),d.jsx("button",{type:"button",className:"btn-ghost text-red-600 hover:text-red-700 dark:text-red-400",onClick:rt,disabled:m!==null,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(m==="delete"?"":"hidden")}),d.jsx(Di,{className:"h-4 w-4 "+(m==="delete"?"hidden":"")}),d.jsx("span",{children:t(m==="delete"?"posts.bulk.deleting":"posts.bulk.delete")})]})}),d.jsx("button",{type:"button",className:"btn-ghost",onClick:xe,disabled:m!==null,children:t("posts.bulk.clear")})]})]}),V.loading&&V.posts.length===0?d.jsxs("div",{className:"card p-8 text-center text-sm text-surface-500 dark:text-surface-400",children:[d.jsx(ct,{className:"inline h-4 w-4 animate-spin mr-2"}),t("scan.scanning",{defaultValue:"Loading…"})]}):V.totalCount===0?d.jsx("div",{className:"card p-8 text-center text-sm text-surface-500 dark:text-surface-400",children:y?d.jsxs(d.Fragment,{children:[t("posts.search.noResults")," ",d.jsx("button",{type:"button",className:"text-blue-600 hover:underline dark:text-blue-400",onClick:_e,children:t("posts.search.clear")})]}):t(a==="all"?"posts.noPosts":"posts.noPostsInFilter")}):d.jsxs("div",{className:"card divide-y divide-surface-200 dark:divide-surface-800",children:[d.jsxs("div",{className:"flex items-center gap-3 px-4 py-2 bg-surface-50 dark:bg-surface-900/40",children:[d.jsxs("button",{type:"button",onClick:K,className:"flex items-center gap-2 text-xs text-surface-600 hover:text-surface-900 dark:text-surface-400 dark:hover:text-surface-50","aria-label":fe?t("posts.bulk.deselectPage"):t("posts.bulk.selectPage",{count:V.posts.length}),children:[fe?d.jsx(O6,{className:"h-4 w-4"}):d.jsx(z6,{className:"h-4 w-4"}),d.jsx("span",{children:fe?t("posts.bulk.deselectPage"):t("posts.bulk.selectPage",{count:V.posts.length})})]}),ue&&d.jsxs("span",{className:"ml-auto text-xs text-surface-600 dark:text-surface-400",children:[t("posts.bulk.allOnPageSelected",{count:V.posts.length})," ",d.jsx("button",{type:"button",onClick:()=>void ee(),className:"text-blue-600 hover:underline dark:text-blue-400 font-medium",children:t("posts.bulk.selectAllMatching",{count:V.totalCount})})]}),ae&&V.totalCount>V.posts.length&&d.jsxs("span",{className:"ml-auto text-xs text-surface-600 dark:text-surface-400",children:[t("posts.bulk.allMatchingSelected",{count:V.totalCount})," ",d.jsx("button",{type:"button",onClick:xe,className:"text-blue-600 hover:underline dark:text-blue-400 font-medium",children:t("posts.bulk.clear")})]})]}),V.posts.map(je=>{const z=h.has(je.id);return d.jsxs("div",{className:"flex items-center gap-3 px-4 py-3 hover:bg-surface-50 dark:hover:bg-surface-800/40 "+(z?"bg-surface-50 dark:bg-surface-800/40":""),children:[d.jsx("label",{className:"flex items-center cursor-pointer p-1 -m-1 shrink-0",children:d.jsx("input",{type:"checkbox",checked:z,onChange:ce=>ve(je.id,ce.target.checked),className:"h-4 w-4 cursor-pointer","aria-label":t("posts.bulk.selectOne",{title:je.title||"(untitled)"})})}),d.jsxs(_d,{to:`/posts/${je.id}`,className:"flex flex-1 items-center justify-between gap-3 min-w-0",children:[d.jsxs("div",{className:"min-w-0",children:[d.jsx("p",{className:"text-sm font-medium text-surface-900 truncate dark:text-surface-50",children:je.title||"(untitled)"}),d.jsxs("p",{className:"text-xs text-surface-500 mt-0.5 dark:text-surface-400",children:[je.slug||"—"," · ",zz(je.updatedAt,e.resolvedLanguage)]})]}),d.jsx(oN,{status:je.status})]})]},je.id)}),V.totalPages>1&&d.jsxs("div",{className:"flex flex-wrap items-center gap-3 px-4 py-3 bg-surface-50 dark:bg-surface-900/40",children:[d.jsx("span",{className:"text-xs text-surface-600 dark:text-surface-400",children:t("posts.pagination.showing",{from:lt,to:Dt,total:V.totalCount})}),d.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[d.jsxs("button",{type:"button",className:"btn-ghost text-xs",onClick:V.prevPage,disabled:!V.hasPrev,children:[d.jsx(C6,{className:"h-4 w-4"}),t("posts.pagination.previous")]}),d.jsx("span",{className:"text-xs text-surface-600 dark:text-surface-400",children:t("posts.pagination.pageOf",{page:V.page,total:V.totalPages})}),d.jsxs("button",{type:"button",className:"btn-ghost text-xs",onClick:V.nextPage,disabled:!V.hasNext,children:[t("posts.pagination.next"),d.jsx(gw,{className:"h-4 w-4"})]})]})]})]})]})}const MEe=/^\s*>\s$/,LEe=on.create({name:"blockquote",addOptions(){return{HTMLAttributes:{}}},content:"block+",group:"block",defining:!0,parseHTML(){return[{tag:"blockquote"}]},renderHTML({HTMLAttributes:t}){return["blockquote",Un(this.options.HTMLAttributes,t),0]},addCommands(){return{setBlockquote:()=>({commands:t})=>t.wrapIn(this.name),toggleBlockquote:()=>({commands:t})=>t.toggleWrap(this.name),unsetBlockquote:()=>({commands:t})=>t.lift(this.name)}},addKeyboardShortcuts(){return{"Mod-Shift-b":()=>this.editor.commands.toggleBlockquote()}},addInputRules(){return[Vg({find:MEe,type:this.type})]}}),DEe=/(?:^|\s)(\*\*(?!\s+\*\*)((?:[^*]+))\*\*(?!\s+\*\*))$/,FEe=/(?:^|\s)(\*\*(?!\s+\*\*)((?:[^*]+))\*\*(?!\s+\*\*))/g,OEe=/(?:^|\s)(__(?!\s+__)((?:[^_]+))__(?!\s+__))$/,zEe=/(?:^|\s)(__(?!\s+__)((?:[^_]+))__(?!\s+__))/g,UEe=di.create({name:"bold",addOptions(){return{HTMLAttributes:{}}},parseHTML(){return[{tag:"strong"},{tag:"b",getAttrs:t=>t.style.fontWeight!=="normal"&&null},{style:"font-weight=400",clearMark:t=>t.type.name===this.name},{style:"font-weight",getAttrs:t=>/^(bold(er)?|[5-9]\d{2,})$/.test(t)&&null}]},renderHTML({HTMLAttributes:t}){return["strong",Un(this.options.HTMLAttributes,t),0]},addCommands(){return{setBold:()=>({commands:t})=>t.setMark(this.name),toggleBold:()=>({commands:t})=>t.toggleMark(this.name),unsetBold:()=>({commands:t})=>t.unsetMark(this.name)}},addKeyboardShortcuts(){return{"Mod-b":()=>this.editor.commands.toggleBold(),"Mod-B":()=>this.editor.commands.toggleBold()}},addInputRules(){return[Lf({find:DEe,type:this.type}),Lf({find:OEe,type:this.type})]},addPasteRules(){return[Ud({find:FEe,type:this.type}),Ud({find:zEe,type:this.type})]}}),BEe="listItem",rD="textStyle",sD=/^\s*([-+*])\s$/,$Ee=on.create({name:"bulletList",addOptions(){return{itemTypeName:"listItem",HTMLAttributes:{},keepMarks:!1,keepAttributes:!1}},group:"block list",content(){return`${this.options.itemTypeName}+`},parseHTML(){return[{tag:"ul"}]},renderHTML({HTMLAttributes:t}){return["ul",Un(this.options.HTMLAttributes,t),0]},addCommands(){return{toggleBulletList:()=>({commands:t,chain:e})=>this.options.keepAttributes?e().toggleList(this.name,this.options.itemTypeName,this.options.keepMarks).updateAttributes(BEe,this.editor.getAttributes(rD)).run():t.toggleList(this.name,this.options.itemTypeName,this.options.keepMarks)}},addKeyboardShortcuts(){return{"Mod-Shift-8":()=>this.editor.commands.toggleBulletList()}},addInputRules(){let t=Vg({find:sD,type:this.type});return(this.options.keepMarks||this.options.keepAttributes)&&(t=Vg({find:sD,type:this.type,keepMarks:this.options.keepMarks,keepAttributes:this.options.keepAttributes,getAttributes:()=>this.editor.getAttributes(rD),editor:this.editor})),[t]}}),HEe=/(^|[^`])`([^`]+)`(?!`)/,VEe=/(^|[^`])`([^`]+)`(?!`)/g,qEe=di.create({name:"code",addOptions(){return{HTMLAttributes:{}}},excludes:"_",code:!0,exitable:!0,parseHTML(){return[{tag:"code"}]},renderHTML({HTMLAttributes:t}){return["code",Un(this.options.HTMLAttributes,t),0]},addCommands(){return{setCode:()=>({commands:t})=>t.setMark(this.name),toggleCode:()=>({commands:t})=>t.toggleMark(this.name),unsetCode:()=>({commands:t})=>t.unsetMark(this.name)}},addKeyboardShortcuts(){return{"Mod-e":()=>this.editor.commands.toggleCode()}},addInputRules(){return[Lf({find:HEe,type:this.type})]},addPasteRules(){return[Ud({find:VEe,type:this.type})]}}),WEe=/^```([a-z]+)?[\s\n]$/,GEe=/^~~~([a-z]+)?[\s\n]$/,KEe=on.create({name:"codeBlock",addOptions(){return{languageClassPrefix:"language-",exitOnTripleEnter:!0,exitOnArrowDown:!0,defaultLanguage:null,HTMLAttributes:{}}},content:"text*",marks:"",group:"block",code:!0,defining:!0,addAttributes(){return{language:{default:this.options.defaultLanguage,parseHTML:t=>{var e;const{languageClassPrefix:n}=this.options,i=[...((e=t.firstElementChild)===null||e===void 0?void 0:e.classList)||[]].filter(a=>a.startsWith(n)).map(a=>a.replace(n,""))[0];return i||null},rendered:!1}}},parseHTML(){return[{tag:"pre",preserveWhitespace:"full"}]},renderHTML({node:t,HTMLAttributes:e}){return["pre",Un(this.options.HTMLAttributes,e),["code",{class:t.attrs.language?this.options.languageClassPrefix+t.attrs.language:null},0]]},addCommands(){return{setCodeBlock:t=>({commands:e})=>e.setNode(this.name,t),toggleCodeBlock:t=>({commands:e})=>e.toggleNode(this.name,"paragraph",t)}},addKeyboardShortcuts(){return{"Mod-Alt-c":()=>this.editor.commands.toggleCodeBlock(),Backspace:()=>{const{empty:t,$anchor:e}=this.editor.state.selection,n=e.pos===1;return!t||e.parent.type.name!==this.name?!1:n||!e.parent.textContent.length?this.editor.commands.clearNodes():!1},Enter:({editor:t})=>{if(!this.options.exitOnTripleEnter)return!1;const{state:e}=t,{selection:n}=e,{$from:r,empty:s}=n;if(!s||r.parent.type!==this.type)return!1;const i=r.parentOffset===r.parent.nodeSize-2,a=r.parent.textContent.endsWith(`
|
|
5327
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`,[d7,e])}const q2e=Object.freeze(Object.defineProperty({__proto__:null,readBackendRegistry:H2e,writeBackendRegistry:V2e},Symbol.toStringTag,{value:"Module"})),rN="externalRegistry";function W2e(t){if(!t||typeof t!="object")return null;const e=t;return!Array.isArray(e.plugins)&&!Array.isArray(e.themes)?null:{plugins:Array.isArray(e.plugins)?[...e.plugins]:[],themes:Array.isArray(e.themes)?[...e.themes]:[]}}async function G2e(){const t=Ct();return await t.ready(),W2e(t.get("config",rN))}async function K2e(t){await Ct().write([{op:"set",collection:"config",doc:{id:rN,plugins:t.plugins,themes:t.themes}}],{message:"Update installed plugins and themes"})}const J2e=Object.freeze(Object.defineProperty({__proto__:null,EXTERNAL_REGISTRY_DOC_ID:rN,readBackendRegistry:G2e,writeBackendRegistry:K2e},Symbol.toStringTag,{value:"Module"})),h7="external.default.json",Q2e="external.json";let J2=null;function f7(){if(!J2){const t=$r();J2=t==="flexweg-sqlite"?q2e:ao(t)?J2e:B2e}return J2}function X2e(){return f7().readBackendRegistry()}function dC(t){return f7().writeBackendRegistry(t)}function Z2e(t){if(!t||typeof t!="object")return null;const e=t;return!Array.isArray(e.plugins)&&!Array.isArray(e.themes)?null:{plugins:Array.isArray(e.plugins)?e.plugins:[],themes:Array.isArray(e.themes)?e.themes:[]}}async function hC(t){try{const e=await fetch(`./${t}?_t=${Date.now()}`,{cache:"no-store"});if(e.status===404||!e.ok)return null;const n=await e.json();return Z2e(n)}catch{return null}}async function sN(){let t=null;try{t=await X2e()}catch(r){console.warn("[external-registry] backend read failed:",r)}if(t)return t;const e=await hC(Q2e);if(e)return await dC(e).catch(r=>{console.warn("[external-registry] could not migrate legacy file to backend:",r)}),e;const n=await hC(h7);return n?(await dC(n).catch(r=>{console.warn("[external-registry] could not seed backend from defaults:",r)}),n):{...GU}}async function p7(t){await dC(t)}async function Y2e(){return await hC(h7)??{...GU}}function YL(t,e){const n=i=>i.split(".").slice(0,3).map(a=>Number.parseInt(a,10)||0),r=n(t),s=n(e);for(let i=0;i<3;i++){const a=r[i]??0,o=s[i]??0;if(a!==o)return a<o?-1:1}return 0}function eEe(t){return t?YL(t,W0)>=0&&YL(t,q0)<=0:!1}function tEe(t,e){return`${t}/${e}/bundle.js`}function nEe(t,e){const r=(e.entryPath??tEe(t,e.id)).replace(/^\/+/,""),s=new URL(r,document.baseURI);return e.version&&s.searchParams.set("v",e.version),s.href}async function rEe(t){try{const e=await fetch(t,{method:"GET",cache:"no-store"});if(e.status===404)return!0;if(!e.ok)return!1;const n=e.headers.get("content-type")??"";return!/javascript|ecmascript|module/i.test(n)}catch{return!1}}async function eD(t,e){if(!eEe(e.apiVersion))return console.warn(`[external] skipping ${t}/${e.id}: apiVersion ${e.apiVersion} outside [${W0}, ${q0}]`),{ok:!1,missing:!1};const n=nEe(t,e);let r;try{r=await import(n)}catch(i){return console.error(`[external] failed to import ${n}:`,i),{ok:!1,missing:await rEe(n)}}const s=r.default??r.manifest;if(!s||typeof s!="object"||!("id"in s))return console.error(`[external] ${t}/${e.id} bundle did not export a valid manifest (default or named "manifest")`),{ok:!1,missing:!1};if(s.id!==e.id)return console.error(`[external] ${t}/${e.id} manifest.id mismatch: got "${s.id}"`),{ok:!1,missing:!1};try{if(t==="plugins"){const i=s;D2e(i),VU(i)}else{const i=s;e1e(i),qU(i)}}catch(i){return console.error(`[external] register failed for ${t}/${e.id}:`,i),{ok:!1,missing:!1}}return{ok:!0}}async function sEe(){const t=await sN();q0e(),W0e();let e=0,n=0;const r=new Set,s=new Set;for(const a of t.plugins){const o=await eD("plugins",a);o.ok?e++:(n++,o.missing&&r.add(a.id))}for(const a of t.themes){const o=await eD("themes",a);o.ok?e++:(n++,o.missing&&s.add(a.id))}let i=0;if(r.size>0||s.size>0){const a={plugins:t.plugins.filter(o=>!r.has(o.id)),themes:t.themes.filter(o=>!s.has(o.id))};i=r.size+s.size;try{await p7(a);const o=[...r,...s].join(", ");console.warn(`[external] auto-pruned ${i} stale registry entr${i===1?"y":"ies"}: ${o}`),at.info(jt.t("externalLoader.autoPruned",{count:i,ids:o,defaultValue:`${i} stale external entr${i===1?"y":"ies"} removed from registry: ${o}`})),n-=i}catch(o){console.warn("[external] auto-prune failed to write registry:",o)}}return n>0&&at.warn(jt.t("externalLoader.someFailed",{count:n,defaultValue:`${n} external bundle(s) failed to load. Check the browser console.`})),{loaded:e,failed:n,pruned:i}}function Q2(t){const[e,n]=U.useState(()=>new Map);U.useEffect(()=>{if(e.size===0)return;const a=new Set(t.map(c=>c.id));let o=!1;const l=new Map(e);for(const c of e.keys())a.has(c)&&(l.delete(c),o=!0);o&&n(l)},[t,e]);const r=U.useCallback(a=>{n(o=>{const l=new Map(o);return l.set(a.id,a),l})},[]),s=U.useCallback(a=>{n(o=>{if(!o.has(a))return o;const l=new Map(o);return l.delete(a),l})},[]);return{resolved:U.useMemo(()=>{if(e.size===0)return t;const a=new Set(t.map(l=>l.id)),o=[];for(const l of e.values())a.has(l.id)||o.push(l);return o.length===0?t:[...t,...o]},[t,e]),addOptimistic:r,removeOptimistic:s}}const m7=U.createContext(null);function iEe({children:t}){const[e,n]=U.useState([]),[r,s]=U.useState([]),[i,a]=U.useState([]),[o,l]=U.useState(ll),[c,h]=U.useState([]),[p,m]=U.useState(!1),[g,y]=U.useState({terms:!0,media:!0,users:!0,settings:!0}),[x,v]=U.useState(null);function k(B){console.error("[CmsData] Firestore listener error:",B),v(B)}const[C,N]=U.useState(!1);U.useEffect(()=>{let B=!1;return sEe().catch(X=>{console.error("[CmsData] external bundles loader threw:",X)}).finally(()=>{B||N(!0)}),()=>{B=!0}},[]),U.useEffect(()=>{if(!C)return;const B=[Doe(X=>{n(X),y(fe=>({...fe,terms:!1}))},k),N1e(X=>{s(X),y(fe=>({...fe,media:!1}))},k),OI(X=>{a(X),y(fe=>({...fe,users:!1}))},k),yxe(X=>{l(X),y(fe=>({...fe,settings:!1})),F2e(X.enabledPlugins??{}),t1e(X.activeThemeId,X)},k)];return()=>B.forEach(X=>X())},[C]);const _=o.paginationMode??"global";U.useEffect(()=>{if(_!=="global"){h([]),m(!1);return}const B=Uue(X=>{h(X),m(!0)},k);return()=>B()},[_]);const{resolved:P,addOptimistic:D}=Q2(c),{resolved:I,addOptimistic:L}=Q2(e),{resolved:j,addOptimistic:q}=Q2(r),V=U.useMemo(()=>P.filter(B=>B.type==="post"),[P]),O=U.useMemo(()=>P.filter(B=>B.type==="page"),[P]),$=U.useMemo(()=>({terms:I,categories:I.filter(B=>B.type==="category"),tags:I.filter(B=>B.type==="tag"),media:j,posts:V,pages:O,postsLoaded:p,users:i,settings:o,loading:Object.values(g).some(Boolean),error:x,addOptimisticPost:D,addOptimisticTerm:L,addOptimisticMedia:q}),[I,j,V,O,p,i,o,g,x,D,L,q]);return d.jsx(m7.Provider,{value:$,children:t})}function En(){const t=U.useContext(m7);if(!t)throw new Error("useCmsData must be used inside <CmsDataProvider>");return t}const g7=U.createContext(null),aEe="theme";function oEe(){return typeof document>"u"?"light":document.documentElement.classList.contains("dark")?"dark":"light"}function lEe(t){const e=document.documentElement;t==="dark"?e.classList.add("dark"):e.classList.remove("dark");try{localStorage.setItem(aEe,t)}catch{}}function tD({children:t}){const[e,n]=U.useState(oEe);U.useLayoutEffect(()=>{lEe(e)},[e]);const r=U.useCallback(a=>{(a==="dark"||a==="light")&&n(a)},[]),s=U.useCallback(()=>{n(a=>a==="dark"?"light":"dark")},[]),i=U.useMemo(()=>({theme:e,setTheme:r,toggleTheme:s}),[e,r,s]);return d.jsx(g7.Provider,{value:i,children:t})}function cEe(){const t=U.useContext(g7);if(!t)throw new Error("useTheme must be used inside <ThemeProvider>");return t}const ah=""+new URL("flexweg-logo-CdtuqAFA.png",import.meta.url).href;function uEe({mobileOpen:t,onMobileClose:e}){const{t:n}=Fe(),{user:r,isAdmin:s}=co(),{settings:i}=En(),{theme:a,toggleTheme:o}=cEe(),l=a==="dark",h=!!pi(i.activeThemeId).settings,m=[{to:"/dashboard",labelKey:"nav.dashboard",icon:xW},{to:"/posts",labelKey:"nav.posts",icon:uW},{to:"/pages",labelKey:"nav.pages",icon:SW},{to:"/taxonomies",labelKey:"nav.taxonomies",icon:hW},{to:"/media",labelKey:"nav.media",icon:Go},{to:"/menus",labelKey:"nav.menus",icon:L6},{to:"/themes",labelKey:"nav.themes",icon:kw},{to:"/theme-settings",labelKey:"nav.themeSettings",icon:RW,hidden:!h},{to:"/plugins",labelKey:"nav.plugins",icon:DW},{to:"/settings",labelKey:"nav.settings",icon:zC},{to:"/users",labelKey:"nav.users",icon:GW,adminOnly:!0}].filter(g=>!g.hidden&&(!g.adminOnly||s));return d.jsxs(d.Fragment,{children:[d.jsx("div",{className:qn("fixed inset-0 z-40 bg-black/40 transition-opacity md:hidden",t?"opacity-100":"pointer-events-none opacity-0"),"aria-hidden":"true",onClick:e}),d.jsxs("aside",{className:qn("fixed inset-y-0 left-0 z-50 flex w-72 max-w-[85vw] flex-col border-r border-surface-200 bg-white transition-transform dark:border-surface-800 dark:bg-surface-900","md:static md:z-auto md:w-60 md:max-w-none md:translate-x-0 md:transition-none",t?"translate-x-0":"-translate-x-full"),"aria-hidden":!t,children:[d.jsxs("div",{className:"px-5 h-16 flex items-center gap-2.5 border-b border-surface-200 dark:border-surface-800",children:[d.jsx("img",{src:ah,alt:"AgentCMS",className:"h-8 w-8 rounded-lg shadow-card object-cover shrink-0"}),d.jsxs("div",{className:"flex-1 min-w-0",children:[d.jsx("p",{className:"text-sm font-semibold leading-none",children:n("common.appName")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:"Static publisher"})]}),d.jsx("button",{type:"button",onClick:e,"aria-label":n("nav.closeMenu"),className:"md:hidden rounded-md p-1.5 text-surface-500 hover:bg-surface-100 hover:text-surface-900 dark:text-surface-400 dark:hover:bg-surface-800 dark:hover:text-surface-50",children:d.jsx(fi,{className:"h-4 w-4"})})]}),d.jsx("nav",{className:"flex-1 px-3 py-4 space-y-0.5 overflow-y-auto",children:m.map(({to:g,labelKey:y,icon:x})=>d.jsxs(E6,{to:g,className:({isActive:v})=>qn("flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors",v?"bg-surface-900 text-white shadow-card dark:bg-surface-100 dark:text-surface-900":"text-surface-600 hover:bg-surface-100 hover:text-surface-900 dark:text-surface-300 dark:hover:bg-surface-800 dark:hover:text-surface-50"),children:[d.jsx(x,{className:"h-4 w-4"}),n(y)]},g))}),d.jsxs("div",{className:"px-3 py-3 border-t border-surface-200 dark:border-surface-800",children:[r&&d.jsxs("div",{className:"px-2 pb-2",children:[d.jsx("p",{className:"text-xs font-medium text-surface-700 truncate dark:text-surface-200",children:r.email}),d.jsx("p",{className:"text-[11px] text-surface-400 dark:text-surface-500",children:n(s?"common.administrator":"common.editor")})]}),d.jsxs("button",{type:"button",onClick:o,className:"w-full flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-surface-600 hover:bg-surface-100 hover:text-surface-900 transition-colors dark:text-surface-300 dark:hover:bg-surface-800 dark:hover:text-surface-50",children:[d.jsx(BW,{className:qn("h-4 w-4",!l&&"hidden")}),d.jsx(IW,{className:qn("h-4 w-4",l&&"hidden")}),d.jsx("span",{children:n(l?"common.lightMode":"common.darkMode")})]}),d.jsxs("button",{type:"button",onClick:()=>qB(),className:"w-full flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-surface-600 hover:bg-surface-100 hover:text-surface-900 transition-colors dark:text-surface-300 dark:hover:bg-surface-800 dark:hover:text-surface-50",children:[d.jsx(CW,{className:"h-4 w-4"}),n("common.signOut")]})]})]})]})}function xp(){const{t,i18n:e}=Fe(),n=qxe(),r=e.resolvedLanguage??e.language;async function s(i){await s1(i),n!=null&&n.user&&n.record&&await SB(n.user.uid,{adminLocale:i}).catch(()=>{})}return d.jsxs("div",{className:"relative inline-flex items-center gap-1 px-1.5 py-1 rounded-md hover:bg-surface-100 dark:hover:bg-surface-800 transition-colors",children:[d.jsx("span",{className:"text-base leading-none select-none","aria-hidden":!0,children:Rie[r]}),d.jsx(qf,{className:"h-3.5 w-3.5 text-surface-500 dark:text-surface-400","aria-hidden":!0}),d.jsx("select",{className:"absolute inset-0 cursor-pointer opacity-0","aria-label":t("common.language"),value:r,onChange:i=>s(i.target.value),children:r1.map(i=>d.jsx("option",{value:i,children:r_[i]},i))})]})}function dEe({triggerLabel:t,triggerClassName:e="btn-primary",disabled:n,alignEnd:r=!0,sections:s}){const[i,a]=U.useState(!1),o=U.useRef(null);U.useEffect(()=>{if(!i)return;const c=p=>{o.current&&!o.current.contains(p.target)&&a(!1)},h=p=>{p.key==="Escape"&&a(!1)};return document.addEventListener("pointerdown",c),document.addEventListener("keydown",h),()=>{document.removeEventListener("pointerdown",c),document.removeEventListener("keydown",h)}},[i]),U.useEffect(()=>{n&&i&&a(!1)},[n,i]);function l(c){if(c.disabled||(a(!1),!c.onSelect))return;const h=c.onSelect;setTimeout(()=>{h()},0)}return d.jsxs("div",{ref:o,className:"relative inline-block",children:[d.jsxs("button",{type:"button",className:e,onClick:()=>a(c=>!c),disabled:n,"aria-haspopup":"menu","aria-expanded":i,children:[d.jsx("span",{className:"contents",children:t}),d.jsx(qf,{className:"h-4 w-4 transition-transform "+(i?"rotate-180":"")})]}),i&&d.jsx("div",{role:"menu",className:"absolute z-50 mt-1 min-w-[260px] max-w-[360px] max-h-[calc(100vh-4.5rem)] overflow-y-auto overscroll-contain rounded-md border border-surface-200 bg-white shadow-pop dark:border-surface-700 dark:bg-surface-900 animate-scale-in origin-top-right "+(r?"right-0":"left-0"),children:s.map((c,h)=>d.jsxs("div",{className:h>0?"border-t border-surface-100 dark:border-surface-800":"",children:[c.label&&d.jsx("div",{className:"px-3 pt-2 pb-1 text-[10px] font-semibold uppercase tracking-wider text-surface-500 dark:text-surface-400",children:c.label}),c.items.map(p=>d.jsxs("button",{type:"button",role:"menuitem",onClick:()=>l(p),disabled:p.disabled,className:"block w-full text-left px-3 py-2 text-sm transition-colors "+(p.disabled?"cursor-not-allowed text-surface-400 dark:text-surface-500":"hover:bg-surface-100 dark:hover:bg-surface-800 text-surface-900 dark:text-surface-50"),children:[d.jsx("div",{className:"font-medium",children:p.label}),p.description&&d.jsx("div",{className:"text-xs text-surface-500 dark:text-surface-400 mt-0.5",children:p.description})]},p.id))]},c.id))})]})}function hEe({entries:t}){if(t.length===0)return null;const e=[];for(let n=t.length-1;n>=0;n--)e.push(n);return d.jsx("ul",{className:"card divide-y divide-surface-200 dark:divide-surface-800 max-h-64 overflow-y-auto",children:e.map(n=>{const r=t[n];return d.jsxs("li",{className:"flex items-start gap-2 px-3 py-2 text-sm",children:[d.jsx(fEe,{level:r.level}),d.jsx("span",{className:qn(r.level==="error"&&"text-red-700 dark:text-red-300",r.level==="warn"&&"text-amber-700 dark:text-amber-300",r.level==="success"&&"text-emerald-700 dark:text-emerald-300",r.level==="info"&&"text-surface-600 dark:text-surface-300"),children:r.message})]},n)})})}function fEe({level:t}){return t==="success"?d.jsx(Gs,{className:"h-4 w-4 mt-0.5 text-emerald-500 shrink-0"}):t==="warn"?d.jsx(Zl,{className:"h-4 w-4 mt-0.5 text-amber-500 shrink-0"}):t==="error"?d.jsx(bw,{className:"h-4 w-4 mt-0.5 text-red-500 shrink-0"}):d.jsx(Gf,{className:"h-4 w-4 mt-0.5 text-surface-400 shrink-0"})}function iN({entries:t,busy:e,onClear:n,title:r,runningTitle:s}){const{t:i}=Fe(),a=e||t.length>0;if(U.useEffect(()=>{if(!a||e)return;const l=c=>{c.key==="Escape"&&n()};return document.addEventListener("keydown",l),()=>document.removeEventListener("keydown",l)},[a,e,n]),!a)return null;const o=e?s??i("themes.regenerate.running"):r??i("themes.regenerate.button");return el.createPortal(d.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4 animate-fade-in",role:"dialog","aria-modal":"true","aria-labelledby":"publish-log-modal-title",onClick:l=>{e||l.target===l.currentTarget&&n()},children:d.jsxs("div",{className:"card w-full max-w-lg max-h-[80vh] flex flex-col animate-scale-in",children:[d.jsxs("div",{className:"flex items-center justify-between border-b border-surface-200 px-4 py-3 dark:border-surface-700",children:[d.jsxs("h2",{id:"publish-log-modal-title",className:"text-sm font-semibold flex items-center gap-2",children:[e?d.jsx(ct,{className:"h-4 w-4 animate-spin text-blue-500"}):d.jsx(Su,{className:"h-4 w-4 text-surface-500"}),o]}),!e&&d.jsx("button",{type:"button",className:"p-1 rounded hover:bg-surface-100 dark:hover:bg-surface-800",onClick:n,"aria-label":i("common.close"),children:d.jsx(fi,{className:"h-4 w-4"})})]}),d.jsx("div",{className:"overflow-y-auto p-3",children:d.jsx(hEe,{entries:t})})]})}),document.body)}async function Yg(t=H1(),e,n=()=>{}){for(const r of t){if(!r.cssText)n({level:"warn",message:`Theme "${r.id}" has no embedded CSS, skipping.`});else{const a=`theme-assets/${r.id}.css`;let o=r.cssText;if(r.compileCss&&r.settings){const l=e==null?void 0:e[r.id],c={...r.settings.defaultConfig,...l??{}};try{o=r.compileCss(c)}catch(h){console.error(`[themes] compileCss for "${r.id}" failed:`,h)}}n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:o})}if(r.jsText){const a=`theme-assets/${r.id}-menu.js`;n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:r.jsText})}if(r.jsTextPosts){const a=`theme-assets/${r.id}-posts.js`;n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:r.jsTextPosts})}const s=r.jsTextCatalog;if(s){const a=`theme-assets/${r.id}-catalog.js`;n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:s})}const i=r.jsTextFilters;if(i){const a=`theme-assets/${r.id}-filters.js`;n({level:"info",message:`Uploading ${a}…`}),await bn({path:a,content:i})}}n({level:"success",message:"Theme assets synced."})}function pEe(){const{t}=Fe(),{settings:e,terms:n,users:r,media:s}=En(),i=H1(),[a,o]=U.useState(!1),[l,c]=U.useState([]),[h,p]=U.useState(()=>xu());U.useEffect(()=>Tz(()=>{p(xu())}),[]);async function m(v){o(!0),c([]);const k=C=>c(N=>[...N,C]);try{await v(k)}catch(C){k({level:"error",message:C.message})}finally{o(!1)}}function g(v,k){if(!k)return"";const C=v.i18nNamespace??v.id,N=jt.t(k,{ns:C});return N===k?"":N}async function y(v){return eo({terms:n,settings:e,users:r,authorLookup:Ea(r,s),refreshTerms:v==null?void 0:v.refreshTerms})}const x=U.useMemo(()=>{const v=[{id:"home",label:t("themes.regenerate.home"),description:t("themes.regenerate.homeHelp"),onSelect:()=>m(async _=>{const P=await y();await qve(P,_)})},{id:"allHtml",label:t("themes.regenerate.allHtml"),description:t("themes.regenerate.allHtmlHelp"),onSelect:()=>m(async _=>{const P=await y({refreshTerms:!0});await Y_(P,_)})},{id:"repair",label:t("themes.regenerate.repair"),description:t("themes.regenerate.repairHelp"),onSelect:()=>m(async _=>{const P=await y({refreshTerms:!0});await Wve(P,_)})},{id:"assets",label:t("themes.regenerate.assets"),description:t("themes.regenerate.assetsHelp"),onSelect:()=>m(async _=>{await Yg(i,e.themeConfigs,_)})}],k=h.map(_=>({id:_.id,label:g(_,_.labelKey)||_.id,description:g(_,_.descriptionKey)||void 0,onSelect:()=>m(async P=>{const D=await y();await _.run(D,P)})})),C={id:"everything",label:t("themes.regenerate.everything"),description:t("themes.regenerate.everythingHelp"),onSelect:()=>m(async _=>{await Yg(i,e.themeConfigs,_);const P=await y({refreshTerms:!0});await Y_(P,_);for(const D of h)try{await D.run(P,_)}catch(I){_({level:"error",message:`Plugin "${D.id}" regen failed: ${I.message}`})}_({level:"success",message:"Everything regenerated."})})},N=[{id:"site",label:t("themes.regenerate.groupBuiltins"),items:v}];return k.length>0&&N.push({id:"plugins",label:t("themes.regenerate.groupPlugins"),items:k}),N.push({id:"everything",items:[C]}),N},[h,e.themeConfigs,t]);return d.jsxs(d.Fragment,{children:[d.jsx(dEe,{triggerLabel:d.jsxs(d.Fragment,{children:[d.jsx(ct,{className:a?"h-4 w-4 animate-spin":"hidden"}),d.jsx(Su,{className:a?"hidden":"h-4 w-4"}),d.jsx("span",{children:t(a?"themes.regenerate.running":"themes.regenerate.button")})]}),triggerClassName:"btn-secondary",disabled:a,sections:x}),d.jsx(iN,{entries:l,busy:a,onClear:()=>c([])})]})}function mEe({onOpenMobileNav:t}){const{t:e}=Fe();return d.jsx("header",{className:"sticky top-0 z-30 bg-white/80 backdrop-blur border-b border-surface-200 dark:bg-surface-900/80 dark:border-surface-800",children:d.jsxs("div",{className:"flex items-center justify-between px-4 md:px-6 h-14",children:[d.jsxs("div",{className:"flex items-center gap-3 min-w-0",children:[d.jsx("button",{type:"button",onClick:t,"aria-label":e("nav.openMenu"),className:"md:hidden p-1.5 rounded-md text-surface-500 hover:text-surface-900 hover:bg-surface-100 transition-colors dark:text-surface-400 dark:hover:text-surface-50 dark:hover:bg-surface-800",children:d.jsx(L6,{className:"h-5 w-5"})}),d.jsxs("div",{className:"flex items-center gap-2 min-w-0 md:hidden",children:[d.jsx("img",{src:ah,alt:"AgentCMS",className:"h-7 w-7 rounded-md object-cover shrink-0"}),d.jsx("p",{className:"text-sm font-semibold truncate",children:e("common.appName")})]})]}),d.jsxs("div",{className:"flex items-center gap-3 ml-auto",children:[d.jsx(pEe,{}),d.jsx(xp,{})]})]})})}function gEe(){const[t,e]=U.useState(!1),n=Gd();return U.useEffect(()=>{e(!1)},[n.pathname]),d.jsxs("div",{className:"flex min-h-full bg-surface-50 dark:bg-surface-950",children:[d.jsx(uEe,{mobileOpen:t,onMobileClose:()=>e(!1)}),d.jsxs("div",{className:"flex-1 min-w-0 flex flex-col",children:[d.jsx(mEe,{onOpenMobileNav:()=>e(!0)}),d.jsx("main",{className:"flex-1 min-w-0 overflow-x-hidden",children:d.jsx(k6,{})})]})]})}function fC({title:t,message:e}){const{t:n}=Fe();return d.jsx("div",{className:"min-h-full flex items-center justify-center p-6",children:d.jsxs("div",{className:"max-w-md w-full text-center",children:[d.jsx("div",{className:"inline-flex h-12 w-12 items-center justify-center rounded-full bg-red-100 mb-4 dark:bg-red-900/40",children:d.jsx(Zl,{className:"h-5 w-5 text-red-600 dark:text-red-400"})}),d.jsx("h1",{className:"text-lg font-semibold text-surface-900 dark:text-surface-50",children:t??n("errors.appError")}),e&&d.jsx("p",{className:"text-sm text-surface-600 mt-2 whitespace-pre-line dark:text-surface-300",children:e}),d.jsx("p",{className:"text-xs text-surface-500 mt-4 dark:text-surface-400",children:n("errors.consoleHint")})]})})}const bEe={info:"bg-blue-50 text-blue-900 ring-blue-200 dark:bg-blue-900/30 dark:text-blue-100 dark:ring-blue-700/50",success:"bg-emerald-50 text-emerald-900 ring-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-100 dark:ring-emerald-700/50",warn:"bg-amber-50 text-amber-900 ring-amber-200 dark:bg-amber-900/30 dark:text-amber-100 dark:ring-amber-700/50",error:"bg-red-50 text-red-900 ring-red-200 dark:bg-red-900/30 dark:text-red-100 dark:ring-red-700/50"},yEe={info:Gf,success:Gs,warn:Zl,error:Qc};function nD(){const[t,e]=U.useState([]);U.useEffect(()=>zie(r=>{e(i=>[...i,r]);const s=r.durationMs??Uie(r.level);s>0&&window.setTimeout(()=>{e(i=>i.filter(a=>a.id!==r.id))},s)}),[]);function n(r){e(s=>s.filter(i=>i.id!==r))}return t.length===0?null:d.jsx("div",{className:"fixed top-4 right-4 z-[100] flex flex-col gap-2 max-w-sm pointer-events-none",role:"region","aria-live":"polite",children:t.map(r=>d.jsx(vEe,{toast:r,onDismiss:()=>n(r.id)},r.id))})}function vEe({toast:t,onDismiss:e}){const n=yEe[t.level];return d.jsxs("div",{className:qn("rounded-lg shadow-pop ring-1 px-3 py-2.5 flex items-start gap-2.5 animate-scale-in pointer-events-auto",bEe[t.level]),role:t.level==="error"?"alert":"status",children:[d.jsx(n,{className:"h-4 w-4 shrink-0 mt-0.5","aria-hidden":!0}),d.jsx("p",{className:"text-sm leading-snug flex-1 whitespace-pre-line break-words",children:t.message}),d.jsx("button",{type:"button",className:"shrink-0 text-current opacity-60 hover:opacity-100 transition-opacity",onClick:e,"aria-label":"Dismiss",children:d.jsx(fi,{className:"h-4 w-4"})})]})}const aN="flexweg.firestoreIndexesReady",xEe="failed-precondition";function wEe(t){const e=t.match(/https:\/\/console\.firebase\.google\.com\/[^\s)]+/);return e?e[0]:""}function kEe(){const t=tp(Xs(),ls.posts);return[{label:"Posts list — all",fields:"type ASC, createdAt DESC",run:()=>Sg(no(t,pd("type","==","post"),Gl("createdAt","desc"),KE(1)))},{label:"Posts list — by status",fields:"type ASC, status ASC, createdAt DESC",run:()=>Sg(no(t,pd("type","==","post"),pd("status","==","online"),Gl("createdAt","desc"),KE(1)))}]}async function SEe(){const t=[];let e;for(const r of kEe())try{await r.run()}catch(s){const i=s;i.code===xEe?t.push({label:r.label,fields:r.fields,createUrl:wEe(i.message??"")}):e=e??{code:i.code??"unknown",message:i.message??String(s)}}const n=t.length===0&&!e;return n&&_Ee(),{ready:n,missingIndexes:t,unexpectedError:e}}function EEe(){try{return window.localStorage.getItem(aN)==="1"}catch{return!1}}function _Ee(){try{window.localStorage.setItem(aN,"1")}catch{}}function b7(){try{window.localStorage.removeItem(aN)}catch{}}function CEe({children:t}){const{settings:e}=En(),n=e.paginationMode??"global",r=$r()==="firebase"?n:"global",{t:s}=Fe(),[i,a]=U.useState(EEe()?{ready:!0,missingIndexes:[]}:null),[o,l]=U.useState(!1),c=U.useCallback(async()=>{l(!0);try{b7();const h=await SEe();a(h)}finally{l(!1)}},[]);return U.useEffect(()=>{r==="paginated"&&(i||c())},[r,i,c]),r!=="paginated"?d.jsx(d.Fragment,{children:t}):i!=null&&i.ready?d.jsx(d.Fragment,{children:t}):d.jsx("div",{className:"min-h-screen bg-surface-50 dark:bg-surface-950 flex items-center justify-center p-6",children:d.jsxs("div",{className:"card w-full max-w-2xl p-6 space-y-5",children:[d.jsxs("header",{className:"space-y-1",children:[d.jsx("h1",{className:"text-xl font-semibold text-surface-900 dark:text-surface-50",children:s("firestoreSetup.title")}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:s("firestoreSetup.intro")})]}),o&&!i&&d.jsxs("div",{className:"flex items-center gap-2 text-sm text-surface-500 dark:text-surface-400",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),s("firestoreSetup.checking")]}),(i==null?void 0:i.unexpectedError)&&d.jsxs("div",{className:"rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-700 dark:border-red-900 dark:bg-red-950/20 dark:text-red-300",children:[d.jsx("p",{className:"font-medium",children:s("firestoreSetup.unexpectedTitle")}),d.jsxs("p",{className:"mt-1 text-xs font-mono break-all",children:["[",i.unexpectedError.code,"] ",i.unexpectedError.message]}),d.jsx("p",{className:"mt-2 text-xs",children:s("firestoreSetup.unexpectedHint")})]}),(i==null?void 0:i.missingIndexes)&&i.missingIndexes.length>0&&d.jsxs("div",{className:"space-y-3",children:[d.jsx("p",{className:"text-sm text-surface-700 dark:text-surface-200",children:s("firestoreSetup.missingCount",{count:i.missingIndexes.length})}),d.jsx("ol",{className:"space-y-2 text-sm",children:i.missingIndexes.map((h,p)=>d.jsxs("li",{className:"rounded-md border border-surface-200 dark:border-surface-700 p-3 space-y-2",children:[d.jsxs("div",{children:[d.jsxs("span",{className:"font-medium",children:[p+1,"."]})," ",h.label,d.jsx("code",{className:"ml-2 text-xs px-1.5 py-0.5 rounded bg-surface-100 dark:bg-surface-800 font-mono",children:h.fields})]}),h.createUrl?d.jsxs("a",{href:h.createUrl,target:"_blank",rel:"noopener noreferrer",className:"btn-secondary inline-flex",children:[d.jsx(vw,{className:"h-4 w-4"}),s("firestoreSetup.openConsole")]}):d.jsx("p",{className:"text-xs text-surface-500 italic",children:s("firestoreSetup.noUrl")})]},h.label))}),d.jsxs("div",{className:"rounded-md bg-blue-50 dark:bg-blue-950/20 p-3 text-xs text-blue-700 dark:text-blue-300",children:[d.jsx("p",{className:"font-medium",children:s("firestoreSetup.howItWorks")}),d.jsxs("ol",{className:"mt-1 list-decimal list-inside space-y-0.5",children:[d.jsx("li",{children:s("firestoreSetup.step1")}),d.jsx("li",{children:s("firestoreSetup.step2")}),d.jsx("li",{children:s("firestoreSetup.step3")})]})]})]}),i&&!i.ready&&d.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[d.jsxs("button",{type:"button",className:"btn-primary",onClick:c,disabled:o,children:[o?d.jsx(ct,{className:"h-4 w-4 animate-spin"}):d.jsx(Su,{className:"h-4 w-4"}),s(o?"firestoreSetup.retrying":"firestoreSetup.retry")]}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:s("firestoreSetup.buildHint")})]}),(i==null?void 0:i.ready)&&d.jsxs("div",{className:"flex items-center gap-2 text-sm text-emerald-700 dark:text-emerald-400",children:[d.jsx(Gs,{className:"h-4 w-4"}),s("firestoreSetup.allReady")]})]})})}function AEe(){const{t}=Fe(),[e,n]=U.useState(""),[r,s]=U.useState(""),[i,a]=U.useState(!1),[o,l]=U.useState(null),[c,h]=U.useState(null);async function p(g){if(g.preventDefault(),!e.trim()||!r){l("auth.emailPasswordRequired");return}a(!0),l(null),h(null);try{await VB(e,r)}catch(y){l(nC(y))}finally{a(!1)}}async function m(){if(!e.trim()){l("auth.enterEmailFirst");return}l(null),h(null);try{await $xe(e),h(t("auth.resetEmailSent",{email:e.trim()}))}catch(g){l(nC(g))}}return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950",children:[d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),d.jsxs("div",{className:"w-full max-w-sm",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"AgentCMS",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("common.appName")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:"Static publisher"})]})]}),d.jsxs("div",{className:"card p-6",children:[d.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-surface-50",children:t("auth.signIn")}),d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("auth.signInSubtitle")}),d.jsxs("form",{onSubmit:p,className:"mt-5 space-y-4","data-form-type":"other",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"login-email",children:t("auth.email")}),d.jsx("input",{id:"login-email",type:"email",autoComplete:"email",className:"input",value:e,onChange:g=>n(g.target.value),placeholder:t("auth.emailPlaceholder"),autoFocus:!0})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"login-password",children:t("auth.password")}),d.jsx("input",{id:"login-password",type:"password",autoComplete:"current-password",className:"input",value:r,onChange:g=>s(g.target.value),placeholder:t("auth.passwordPlaceholder")})]}),o&&d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:t(o)}),c&&d.jsx("div",{className:"rounded-lg bg-emerald-50 text-emerald-700 ring-1 ring-emerald-200 px-3 py-2 text-sm dark:bg-emerald-900/30 dark:text-emerald-300 dark:ring-emerald-700/50",children:c}),d.jsx("button",{type:"submit",className:"btn-primary w-full",disabled:i,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx("span",{children:t(i?"auth.signingIn":"auth.signIn")})]})}),d.jsx("button",{type:"button",className:"btn-ghost w-full text-sm",onClick:m,disabled:i,children:t("auth.forgotPassword")})]})]}),d.jsx("p",{className:"text-[11px] text-surface-400 text-center mt-4 dark:text-surface-500",children:t("auth.footer")})]})]})}function TEe(){const{t}=Fe(),[e,n]=U.useState(""),[r,s]=U.useState(""),[i,a]=U.useState(!1),[o,l]=U.useState(null);async function c(h){if(h.preventDefault(),i)return;const p=e.trim().toLowerCase();if(!p||!/.+@.+\..+/.test(p)){l(t("identity.errors.invalidEmail"));return}if(!r){l(t("identity.errors.missingPassword"));return}a(!0),l(null),typeof window<"u"&&window.location.hash&&window.history.replaceState(null,"",window.location.pathname+window.location.search);try{await UB(p,r)}catch(m){l(t(BB(m))),a(!1)}}return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950 overflow-hidden",children:[d.jsxs("div",{className:"flexweg-blobs","aria-hidden":"true",children:[d.jsx("div",{className:"flexweg-blob flexweg-blob-1"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-2"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-3"})]}),d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),d.jsxs("div",{className:"w-full max-w-sm relative z-10",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"AgentCMS",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("identity.brandTitle")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:t("identity.brandSubtitle")})]})]}),d.jsxs("div",{className:"card p-6",children:[d.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-surface-50",children:t("identity.login.heading")}),d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("identity.login.intro")}),d.jsxs("form",{onSubmit:c,className:"mt-5 space-y-4","data-form-type":"other",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"identity-email",children:t("identity.fields.email")}),d.jsx("input",{id:"identity-email",type:"email",className:"input",value:e,onChange:h=>n(h.target.value),placeholder:"you@company.com",required:!0,autoComplete:"email",autoFocus:!0})]}),d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"identity-password",children:t("identity.fields.password")}),d.jsx("input",{id:"identity-password",type:"password",className:"input",value:r,onChange:h=>s(h.target.value),placeholder:"••••••••",required:!0,autoComplete:"current-password"})]}),o&&d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:o}),d.jsx("button",{type:"submit",className:"btn-primary w-full",disabled:i,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx("span",{children:t(i?"identity.login.submitting":"identity.login.submit")})]})})]})]}),d.jsx("p",{className:"text-[11px] text-surface-400 text-center mt-4 dark:text-surface-500",children:t("identity.footer")})]})]})}function uo({title:t,description:e,actions:n}){return d.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3 mb-6",children:[d.jsxs("div",{className:"min-w-0",children:[d.jsx("h1",{className:"text-xl font-semibold text-surface-900 dark:text-surface-50",children:t}),e&&d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:e})]}),n&&d.jsx("div",{className:"flex items-center gap-2 shrink-0",children:n})]})}function Mh(t){const{settings:e,posts:n,pages:r,postsLoaded:s}=En(),i=e.paginationMode??"global",a=U.useMemo(()=>{const p=t.type==="post"?n:r;return t.status?p.filter(m=>m.status===t.status).length:p.length},[t.type,t.status,n,r]),[o,l]=U.useState(0),[c,h]=U.useState(i==="paginated");return U.useEffect(()=>{if(i!=="paginated")return;let p=!1;return h(!0),Pf(t).then(m=>{p||(l(m),h(!1))}),()=>{p=!0}},[i,t.type,t.status]),i==="global"?{count:a,loading:!s}:{count:o,loading:c}}function IEe(){const{t}=Fe(),{user:e}=co(),n=Mh({type:"post"}),r=Mh({type:"page"}),s=Mh({type:"post",status:"online"}),i=Mh({type:"page",status:"online"}),a=Mh({type:"post",status:"draft"}),o=Mh({type:"page",status:"draft"}),[l,c]=U.useState(()=>Vj());return U.useEffect(()=>Nce(()=>c(Vj())),[]),d.jsxs("div",{className:"p-4 md:p-6 space-y-6",children:[d.jsx(uo,{title:t("dashboard.title"),description:t("dashboard.welcome",{email:(e==null?void 0:e.email)??""})}),d.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-3",children:[d.jsx(Ey,{label:t("dashboard.stats.totalPosts"),value:n.count}),d.jsx(Ey,{label:t("dashboard.stats.totalPages"),value:r.count}),d.jsx(Ey,{label:t("dashboard.stats.online"),value:s.count+i.count}),d.jsx(Ey,{label:t("dashboard.stats.drafts"),value:a.count+o.count})]}),l.length>0&&d.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",children:l.map(({id:h,component:p})=>d.jsx(p,{},h))})]})}function Ey({label:t,value:e}){return d.jsxs("div",{className:"card p-4",children:[d.jsx("p",{className:"text-xs font-medium text-surface-500 dark:text-surface-400",children:t}),d.jsx("p",{className:"text-2xl font-semibold text-surface-900 mt-1 dark:text-surface-50",children:e})]})}function y7(t){const{settings:e}=En(),n=e.paginationMode??"global",r=NEe(t,n==="global"),s=PEe(t,n==="paginated");return n==="global"?r:s}function NEe(t,e){const{posts:n,pages:r,postsLoaded:s}=En(),[i,a]=U.useState(1),o=`${t.type}:${t.status??"all"}:${t.pageSize}`;U.useEffect(()=>{a(1)},[o]);const l=U.useMemo(()=>{if(!e)return[];const g=t.type==="post"?n:r;return t.status?g.filter(y=>y.status===t.status):g},[e,t.type,t.status,n,r]),c=l.length,h=Math.max(1,Math.ceil(c/t.pageSize)),p=Math.min(i,h);return{posts:U.useMemo(()=>l.slice((p-1)*t.pageSize,p*t.pageSize),[l,p,t.pageSize]),loading:e&&!s,page:p,totalCount:c,totalPages:h,hasNext:p<h,hasPrev:p>1,nextPage:()=>a(g=>Math.min(h,g+1)),prevPage:()=>a(g=>Math.max(1,g-1)),resetToFirst:()=>a(1)}}function PEe(t,e){const[n,r]=U.useState(1),[s,i]=U.useState([]),[a,o]=U.useState(!0),[l,c]=U.useState(0),h=U.useRef([void 0]),p=`${t.type}:${t.status??"all"}:${t.pageSize}`;U.useEffect(()=>{h.current=[void 0],r(1)},[p]),U.useEffect(()=>{if(!e)return;let x=!1;return Pf({type:t.type,status:t.status}).then(v=>{x||c(v)}),()=>{x=!0}},[e,t.type,t.status]),U.useEffect(()=>{if(!e)return;o(!0);const x=h.current[n-1];return $ue({type:t.type,status:t.status,pageSize:t.pageSize,cursor:x},k=>{i(k.posts),k.nextCursor?h.current[n]=k.nextCursor:h.current=h.current.slice(0,n),o(!1)},k=>{console.error("[usePostsPage] subscription error:",k),o(!1)})},[e,t.type,t.status,t.pageSize,n]);const m=U.useMemo(()=>Math.max(1,Math.ceil(l/t.pageSize)),[l,t.pageSize]),g=n<m&&!!h.current[n],y=n>1;return{posts:s,loading:a,page:n,totalCount:l,totalPages:m,hasNext:g,hasPrev:y,nextPage:()=>r(x=>Math.min(m,x+1)),prevPage:()=>r(x=>Math.max(1,x-1)),resetToFirst:()=>r(1)}}function oN({status:t}){const{t:e}=Fe();return d.jsx("span",{className:t==="online"?"badge-online":"badge-draft",children:e(`posts.status.${t}`)})}const Lh=100;function REe(t,e){if(e.length===0)return!0;const n=`${t.title} ${t.slug} ${t.excerpt??""}`.toLowerCase();return e.every(r=>n.includes(r))}function jEe(){const{t,i18n:e}=Fe(),{terms:n,settings:r,users:s,media:i}=En(),[a,o]=U.useState("all"),[l,c]=U.useState(""),[h,p]=U.useState(new Set),[m,g]=U.useState(null),y=l.trim().length>0,x=y7({type:"post",status:a==="all"?void 0:a,pageSize:Lh}),[v,k]=U.useState(null),[C,N]=U.useState(!1),[_,P]=U.useState(1);U.useEffect(()=>{if(!y){k(null),P(1);return}let je=!1;return N(!0),Br({type:"post"}).then(z=>{je||(k(z),N(!1))}),()=>{je=!0}},[y]),U.useEffect(()=>{P(1)},[l,a]);const D=U.useMemo(()=>l.toLowerCase().split(/\s+/).filter(Boolean),[l]),I=U.useMemo(()=>!y||!v?[]:(a==="all"?v:v.filter(z=>z.status===a)).filter(z=>REe(z,D)),[y,v,a,D]),L=Math.max(1,Math.ceil(I.length/Lh)),j=Math.min(Math.max(_,1),L),q=U.useMemo(()=>I.slice((j-1)*Lh,j*Lh),[I,j]),V=y?{posts:q,loading:C,page:j,totalCount:I.length,totalPages:L,hasNext:j<L,hasPrev:j>1,nextPage:()=>P(je=>Math.min(L,je+1)),prevPage:()=>P(je=>Math.max(1,je-1))}:x,O=U.useRef(new Map);U.useEffect(()=>{for(const je of x.posts)O.current.set(je.id,je)},[x.posts]),U.useEffect(()=>{if(v)for(const je of v)O.current.set(je.id,je)},[v]);const $=h.size,{draftSelected:B,onlineSelected:X}=U.useMemo(()=>{let je=0,z=0;for(const ce of h){const le=O.current.get(ce);le&&(le.status==="draft"?je++:le.status==="online"&&z++)}return{draftSelected:je,onlineSelected:z}},[h]),fe=V.posts.length>0&&V.posts.every(je=>h.has(je.id)),ie=V.totalCount>V.posts.length,ae=y?I.length>0&&I.every(je=>h.has(je.id)):V.totalCount>0&&$>=V.totalCount,ue=fe&&ie&&!ae;function ve(je,z){p(ce=>{const le=new Set(ce);return z?le.add(je):le.delete(je),le})}function K(){p(je=>{const z=new Set(je);if(V.posts.every(le=>z.has(le.id)))for(const le of V.posts)z.delete(le.id);else for(const le of V.posts)z.add(le.id);return z})}async function ee(){if(y&&I.length>0){p(ce=>{const le=new Set(ce);for(const Y of I)le.add(Y.id);return le});return}const je=await Br({type:"post"}),z=a==="all"?je:je.filter(ce=>ce.status===a);for(const ce of z)O.current.set(ce.id,ce);p(ce=>{const le=new Set(ce);for(const Y of z)le.add(Y.id);return le})}function xe(){p(new Set)}function _e(){c("")}async function ge(){return eo({terms:n,settings:r,users:s,authorLookup:Ea(s,i)})}async function He(){const je=[],z=[];for(const Z of h){const re=O.current.get(Z);re?je.push(re):z.push(Z)}if(z.length===0)return je;const ce=await Br({type:"post"}),le=new Map(ce.map(Z=>[Z.id,Z]));for(const Z of ce)O.current.set(Z.id,Z);const Y=je.slice();for(const Z of z){const re=le.get(Z);re&&Y.push(re)}return Y}async function Ye(je,z){if(z.length===0)return;g(je);let ce=0,le=0;try{const Y=await ge();Y.bulkMode=!0;for(const re of z)try{if(je==="publish")await Hd(re.id,Y,()=>{}),ce++;else if(je==="unpublish")await BI(re.id,Y,()=>{}),ce++;else{try{await HI(re.id,Y,()=>{})}catch(be){console.error(`[bulk-delete] Flexweg cleanup failed for "${re.title}", deleting Firestore doc anyway:`,be)}await BT(re.id),ce++}}catch(be){le++,console.error(`[bulk-${je}] failed on "${re.title}":`,be)}try{await $I(Y,()=>{},xu())}catch(re){console.error("[bulk-flush] partial failure:",re)}const Z=je==="publish"?"posts.bulk.publishedCount":je==="unpublish"?"posts.bulk.unpublishedCount":"posts.bulk.deletedCount";le>0?at.warn(t(Z,{ok:ce,failed:le})):at.success(t(Z,{ok:ce,failed:le})),p(re=>{const be=new Set(re);for(const Te of z)be.delete(Te.id);return be})}finally{g(null)}}async function Se(){const z=(await He()).filter(ce=>ce.status==="draft").map(ce=>({id:ce.id,title:ce.title}));await Ye("publish",z)}async function we(){const z=(await He()).filter(ce=>ce.status==="online").map(ce=>({id:ce.id,title:ce.title}));await Ye("unpublish",z)}async function rt(){if($===0||!window.confirm(t("posts.bulk.confirmDelete",{count:$})))return;const z=(await He()).map(ce=>({id:ce.id,title:ce.title}));await Ye("delete",z)}const lt=V.totalCount===0?0:(V.page-1)*Lh+1,Dt=Math.min(V.page*Lh,V.totalCount);return d.jsxs("div",{className:"p-4 md:p-6",children:[d.jsx(uo,{title:t("posts.title"),actions:d.jsxs(_d,{to:"/posts/new",className:"btn-primary",children:[d.jsx(Kd,{className:"h-4 w-4"}),t("posts.newPost")]})}),d.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-3",children:[d.jsxs("div",{className:"relative flex-1 min-w-[240px] max-w-sm",children:[d.jsx(Ew,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-surface-400"}),d.jsx("input",{type:"search",value:l,onChange:je=>c(je.target.value),placeholder:t("posts.search.placeholder"),className:"input pl-8 pr-8"}),l&&d.jsx("button",{type:"button",onClick:_e,className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-surface-400 hover:text-surface-700 dark:hover:text-surface-200","aria-label":t("posts.search.clear"),children:d.jsx(fi,{className:"h-4 w-4"})})]}),d.jsx("div",{className:"inline-flex rounded-lg bg-surface-100 p-1 dark:bg-surface-800",children:["all","draft","online"].map(je=>d.jsx("button",{type:"button",onClick:()=>o(je),className:a===je?"px-3 py-1 rounded-md text-sm font-medium bg-white text-surface-900 shadow-card dark:bg-surface-900 dark:text-surface-50":"px-3 py-1 rounded-md text-sm font-medium text-surface-600 hover:text-surface-900 dark:text-surface-300",children:t(`posts.filters.${je}`)},je))})]}),$>0&&d.jsxs("div",{className:"mb-3 sticky top-0 z-10 flex flex-wrap items-center gap-2 rounded-md border border-surface-200 bg-white px-3 py-2 shadow-card dark:border-surface-700 dark:bg-surface-900",children:[d.jsx("span",{className:"text-sm font-medium",children:t("posts.bulk.selectedCount",{count:$})}),d.jsxs("div",{className:"flex flex-wrap gap-2 ml-auto",children:[d.jsx("button",{type:"button",className:"btn-ghost",onClick:Se,disabled:m!==null||B===0,title:B===0?t("posts.bulk.noDraftSelected"):void 0,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(m==="publish"?"":"hidden")}),d.jsx(OC,{className:"h-4 w-4 "+(m==="publish"?"hidden":"")}),d.jsx("span",{children:m==="publish"?t("posts.bulk.publishing"):t("posts.bulk.publish",{count:B})})]})}),d.jsx("button",{type:"button",className:"btn-ghost",onClick:we,disabled:m!==null||X===0,title:X===0?t("posts.bulk.noOnlineSelected"):void 0,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(m==="unpublish"?"":"hidden")}),d.jsx(BC,{className:"h-4 w-4 "+(m==="unpublish"?"hidden":"")}),d.jsx("span",{children:m==="unpublish"?t("posts.bulk.unpublishing"):t("posts.bulk.unpublish",{count:X})})]})}),d.jsx("button",{type:"button",className:"btn-ghost text-red-600 hover:text-red-700 dark:text-red-400",onClick:rt,disabled:m!==null,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(m==="delete"?"":"hidden")}),d.jsx(Di,{className:"h-4 w-4 "+(m==="delete"?"hidden":"")}),d.jsx("span",{children:t(m==="delete"?"posts.bulk.deleting":"posts.bulk.delete")})]})}),d.jsx("button",{type:"button",className:"btn-ghost",onClick:xe,disabled:m!==null,children:t("posts.bulk.clear")})]})]}),V.loading&&V.posts.length===0?d.jsxs("div",{className:"card p-8 text-center text-sm text-surface-500 dark:text-surface-400",children:[d.jsx(ct,{className:"inline h-4 w-4 animate-spin mr-2"}),t("scan.scanning",{defaultValue:"Loading…"})]}):V.totalCount===0?d.jsx("div",{className:"card p-8 text-center text-sm text-surface-500 dark:text-surface-400",children:y?d.jsxs(d.Fragment,{children:[t("posts.search.noResults")," ",d.jsx("button",{type:"button",className:"text-blue-600 hover:underline dark:text-blue-400",onClick:_e,children:t("posts.search.clear")})]}):t(a==="all"?"posts.noPosts":"posts.noPostsInFilter")}):d.jsxs("div",{className:"card divide-y divide-surface-200 dark:divide-surface-800",children:[d.jsxs("div",{className:"flex items-center gap-3 px-4 py-2 bg-surface-50 dark:bg-surface-900/40",children:[d.jsxs("button",{type:"button",onClick:K,className:"flex items-center gap-2 text-xs text-surface-600 hover:text-surface-900 dark:text-surface-400 dark:hover:text-surface-50","aria-label":fe?t("posts.bulk.deselectPage"):t("posts.bulk.selectPage",{count:V.posts.length}),children:[fe?d.jsx(O6,{className:"h-4 w-4"}):d.jsx(z6,{className:"h-4 w-4"}),d.jsx("span",{children:fe?t("posts.bulk.deselectPage"):t("posts.bulk.selectPage",{count:V.posts.length})})]}),ue&&d.jsxs("span",{className:"ml-auto text-xs text-surface-600 dark:text-surface-400",children:[t("posts.bulk.allOnPageSelected",{count:V.posts.length})," ",d.jsx("button",{type:"button",onClick:()=>void ee(),className:"text-blue-600 hover:underline dark:text-blue-400 font-medium",children:t("posts.bulk.selectAllMatching",{count:V.totalCount})})]}),ae&&V.totalCount>V.posts.length&&d.jsxs("span",{className:"ml-auto text-xs text-surface-600 dark:text-surface-400",children:[t("posts.bulk.allMatchingSelected",{count:V.totalCount})," ",d.jsx("button",{type:"button",onClick:xe,className:"text-blue-600 hover:underline dark:text-blue-400 font-medium",children:t("posts.bulk.clear")})]})]}),V.posts.map(je=>{const z=h.has(je.id);return d.jsxs("div",{className:"flex items-center gap-3 px-4 py-3 hover:bg-surface-50 dark:hover:bg-surface-800/40 "+(z?"bg-surface-50 dark:bg-surface-800/40":""),children:[d.jsx("label",{className:"flex items-center cursor-pointer p-1 -m-1 shrink-0",children:d.jsx("input",{type:"checkbox",checked:z,onChange:ce=>ve(je.id,ce.target.checked),className:"h-4 w-4 cursor-pointer","aria-label":t("posts.bulk.selectOne",{title:je.title||"(untitled)"})})}),d.jsxs(_d,{to:`/posts/${je.id}`,className:"flex flex-1 items-center justify-between gap-3 min-w-0",children:[d.jsxs("div",{className:"min-w-0",children:[d.jsx("p",{className:"text-sm font-medium text-surface-900 truncate dark:text-surface-50",children:je.title||"(untitled)"}),d.jsxs("p",{className:"text-xs text-surface-500 mt-0.5 dark:text-surface-400",children:[je.slug||"—"," · ",zz(je.updatedAt,e.resolvedLanguage)]})]}),d.jsx(oN,{status:je.status})]})]},je.id)}),V.totalPages>1&&d.jsxs("div",{className:"flex flex-wrap items-center gap-3 px-4 py-3 bg-surface-50 dark:bg-surface-900/40",children:[d.jsx("span",{className:"text-xs text-surface-600 dark:text-surface-400",children:t("posts.pagination.showing",{from:lt,to:Dt,total:V.totalCount})}),d.jsxs("div",{className:"ml-auto flex items-center gap-2",children:[d.jsxs("button",{type:"button",className:"btn-ghost text-xs",onClick:V.prevPage,disabled:!V.hasPrev,children:[d.jsx(C6,{className:"h-4 w-4"}),t("posts.pagination.previous")]}),d.jsx("span",{className:"text-xs text-surface-600 dark:text-surface-400",children:t("posts.pagination.pageOf",{page:V.page,total:V.totalPages})}),d.jsxs("button",{type:"button",className:"btn-ghost text-xs",onClick:V.nextPage,disabled:!V.hasNext,children:[t("posts.pagination.next"),d.jsx(gw,{className:"h-4 w-4"})]})]})]})]})]})}const MEe=/^\s*>\s$/,LEe=on.create({name:"blockquote",addOptions(){return{HTMLAttributes:{}}},content:"block+",group:"block",defining:!0,parseHTML(){return[{tag:"blockquote"}]},renderHTML({HTMLAttributes:t}){return["blockquote",Un(this.options.HTMLAttributes,t),0]},addCommands(){return{setBlockquote:()=>({commands:t})=>t.wrapIn(this.name),toggleBlockquote:()=>({commands:t})=>t.toggleWrap(this.name),unsetBlockquote:()=>({commands:t})=>t.lift(this.name)}},addKeyboardShortcuts(){return{"Mod-Shift-b":()=>this.editor.commands.toggleBlockquote()}},addInputRules(){return[Vg({find:MEe,type:this.type})]}}),DEe=/(?:^|\s)(\*\*(?!\s+\*\*)((?:[^*]+))\*\*(?!\s+\*\*))$/,FEe=/(?:^|\s)(\*\*(?!\s+\*\*)((?:[^*]+))\*\*(?!\s+\*\*))/g,OEe=/(?:^|\s)(__(?!\s+__)((?:[^_]+))__(?!\s+__))$/,zEe=/(?:^|\s)(__(?!\s+__)((?:[^_]+))__(?!\s+__))/g,UEe=di.create({name:"bold",addOptions(){return{HTMLAttributes:{}}},parseHTML(){return[{tag:"strong"},{tag:"b",getAttrs:t=>t.style.fontWeight!=="normal"&&null},{style:"font-weight=400",clearMark:t=>t.type.name===this.name},{style:"font-weight",getAttrs:t=>/^(bold(er)?|[5-9]\d{2,})$/.test(t)&&null}]},renderHTML({HTMLAttributes:t}){return["strong",Un(this.options.HTMLAttributes,t),0]},addCommands(){return{setBold:()=>({commands:t})=>t.setMark(this.name),toggleBold:()=>({commands:t})=>t.toggleMark(this.name),unsetBold:()=>({commands:t})=>t.unsetMark(this.name)}},addKeyboardShortcuts(){return{"Mod-b":()=>this.editor.commands.toggleBold(),"Mod-B":()=>this.editor.commands.toggleBold()}},addInputRules(){return[Lf({find:DEe,type:this.type}),Lf({find:OEe,type:this.type})]},addPasteRules(){return[Ud({find:FEe,type:this.type}),Ud({find:zEe,type:this.type})]}}),BEe="listItem",rD="textStyle",sD=/^\s*([-+*])\s$/,$Ee=on.create({name:"bulletList",addOptions(){return{itemTypeName:"listItem",HTMLAttributes:{},keepMarks:!1,keepAttributes:!1}},group:"block list",content(){return`${this.options.itemTypeName}+`},parseHTML(){return[{tag:"ul"}]},renderHTML({HTMLAttributes:t}){return["ul",Un(this.options.HTMLAttributes,t),0]},addCommands(){return{toggleBulletList:()=>({commands:t,chain:e})=>this.options.keepAttributes?e().toggleList(this.name,this.options.itemTypeName,this.options.keepMarks).updateAttributes(BEe,this.editor.getAttributes(rD)).run():t.toggleList(this.name,this.options.itemTypeName,this.options.keepMarks)}},addKeyboardShortcuts(){return{"Mod-Shift-8":()=>this.editor.commands.toggleBulletList()}},addInputRules(){let t=Vg({find:sD,type:this.type});return(this.options.keepMarks||this.options.keepAttributes)&&(t=Vg({find:sD,type:this.type,keepMarks:this.options.keepMarks,keepAttributes:this.options.keepAttributes,getAttributes:()=>this.editor.getAttributes(rD),editor:this.editor})),[t]}}),HEe=/(^|[^`])`([^`]+)`(?!`)/,VEe=/(^|[^`])`([^`]+)`(?!`)/g,qEe=di.create({name:"code",addOptions(){return{HTMLAttributes:{}}},excludes:"_",code:!0,exitable:!0,parseHTML(){return[{tag:"code"}]},renderHTML({HTMLAttributes:t}){return["code",Un(this.options.HTMLAttributes,t),0]},addCommands(){return{setCode:()=>({commands:t})=>t.setMark(this.name),toggleCode:()=>({commands:t})=>t.toggleMark(this.name),unsetCode:()=>({commands:t})=>t.unsetMark(this.name)}},addKeyboardShortcuts(){return{"Mod-e":()=>this.editor.commands.toggleCode()}},addInputRules(){return[Lf({find:HEe,type:this.type})]},addPasteRules(){return[Ud({find:VEe,type:this.type})]}}),WEe=/^```([a-z]+)?[\s\n]$/,GEe=/^~~~([a-z]+)?[\s\n]$/,KEe=on.create({name:"codeBlock",addOptions(){return{languageClassPrefix:"language-",exitOnTripleEnter:!0,exitOnArrowDown:!0,defaultLanguage:null,HTMLAttributes:{}}},content:"text*",marks:"",group:"block",code:!0,defining:!0,addAttributes(){return{language:{default:this.options.defaultLanguage,parseHTML:t=>{var e;const{languageClassPrefix:n}=this.options,i=[...((e=t.firstElementChild)===null||e===void 0?void 0:e.classList)||[]].filter(a=>a.startsWith(n)).map(a=>a.replace(n,""))[0];return i||null},rendered:!1}}},parseHTML(){return[{tag:"pre",preserveWhitespace:"full"}]},renderHTML({node:t,HTMLAttributes:e}){return["pre",Un(this.options.HTMLAttributes,e),["code",{class:t.attrs.language?this.options.languageClassPrefix+t.attrs.language:null},0]]},addCommands(){return{setCodeBlock:t=>({commands:e})=>e.setNode(this.name,t),toggleCodeBlock:t=>({commands:e})=>e.toggleNode(this.name,"paragraph",t)}},addKeyboardShortcuts(){return{"Mod-Alt-c":()=>this.editor.commands.toggleCodeBlock(),Backspace:()=>{const{empty:t,$anchor:e}=this.editor.state.selection,n=e.pos===1;return!t||e.parent.type.name!==this.name?!1:n||!e.parent.textContent.length?this.editor.commands.clearNodes():!1},Enter:({editor:t})=>{if(!this.options.exitOnTripleEnter)return!1;const{state:e}=t,{selection:n}=e,{$from:r,empty:s}=n;if(!s||r.parent.type!==this.type)return!1;const i=r.parentOffset===r.parent.nodeSize-2,a=r.parent.textContent.endsWith(`
|
|
5328
5328
|
|
|
5329
5329
|
`);return!i||!a?!1:t.chain().command(({tr:o})=>(o.delete(r.pos-2,r.pos),!0)).exitCode().run()},ArrowDown:({editor:t})=>{if(!this.options.exitOnArrowDown)return!1;const{state:e}=t,{selection:n,doc:r}=e,{$from:s,empty:i}=n;if(!i||s.parent.type!==this.type||!(s.parentOffset===s.parent.nodeSize-2))return!1;const o=s.after();return o===void 0?!1:r.nodeAt(o)?t.commands.command(({tr:c})=>(c.setSelection(Qt.near(r.resolve(o))),!0)):t.commands.exitCode()}}},addInputRules(){return[z_({find:WEe,type:this.type,getAttributes:t=>({language:t[1]})}),z_({find:GEe,type:this.type,getAttributes:t=>({language:t[1]})})]},addProseMirrorPlugins(){return[new ir({key:new Jr("codeBlockVSCodeHandler"),props:{handlePaste:(t,e)=>{if(!e.clipboardData||this.editor.isActive(this.type.name))return!1;const n=e.clipboardData.getData("text/plain"),r=e.clipboardData.getData("vscode-editor-data"),s=r?JSON.parse(r):void 0,i=s==null?void 0:s.mode;if(!n||!i)return!1;const{tr:a,schema:o}=t.state,l=o.text(n.replace(/\r\n?/g,`
|
|
5330
5330
|
`));return a.replaceSelectionWith(this.type.create({language:i},l)),a.selection.$from.parent.type!==this.type&&a.setSelection(Wt.near(a.doc.resolve(Math.max(0,a.selection.from-2)))),a.setMeta("paste",!0),t.dispatch(a),!0}}})]}}),JEe=on.create({name:"doc",topNode:!0,content:"block+"});function QEe(t={}){return new ir({view(e){return new XEe(e,t)}})}class XEe{constructor(e,n){var r;this.editorView=e,this.cursorPos=null,this.element=null,this.timeout=-1,this.width=(r=n.width)!==null&&r!==void 0?r:1,this.color=n.color===!1?void 0:n.color||"black",this.class=n.class,this.handlers=["dragover","dragend","drop","dragleave"].map(s=>{let i=a=>{this[s](a)};return e.dom.addEventListener(s,i),{name:s,handler:i}})}destroy(){this.handlers.forEach(({name:e,handler:n})=>this.editorView.dom.removeEventListener(e,n))}update(e,n){this.cursorPos!=null&&n.doc!=e.state.doc&&(this.cursorPos>e.state.doc.content.size?this.setCursor(null):this.updateOverlay())}setCursor(e){e!=this.cursorPos&&(this.cursorPos=e,e==null?(this.element.parentNode.removeChild(this.element),this.element=null):this.updateOverlay())}updateOverlay(){let e=this.editorView.state.doc.resolve(this.cursorPos),n=!e.parent.inlineContent,r,s=this.editorView.dom,i=s.getBoundingClientRect(),a=i.width/s.offsetWidth,o=i.height/s.offsetHeight;if(n){let p=e.nodeBefore,m=e.nodeAfter;if(p||m){let g=this.editorView.nodeDOM(this.cursorPos-(p?p.nodeSize:0));if(g){let y=g.getBoundingClientRect(),x=p?y.bottom:y.top;p&&m&&(x=(x+this.editorView.nodeDOM(this.cursorPos).getBoundingClientRect().top)/2);let v=this.width/2*o;r={left:y.left,right:y.right,top:x-v,bottom:x+v}}}}if(!r){let p=this.editorView.coordsAtPos(this.cursorPos),m=this.width/2*a;r={left:p.left-m,right:p.left+m,top:p.top,bottom:p.bottom}}let l=this.editorView.dom.offsetParent;this.element||(this.element=l.appendChild(document.createElement("div")),this.class&&(this.element.className=this.class),this.element.style.cssText="position: absolute; z-index: 50; pointer-events: none;",this.color&&(this.element.style.backgroundColor=this.color)),this.element.classList.toggle("prosemirror-dropcursor-block",n),this.element.classList.toggle("prosemirror-dropcursor-inline",!n);let c,h;if(!l||l==document.body&&getComputedStyle(l).position=="static")c=-pageXOffset,h=-pageYOffset;else{let p=l.getBoundingClientRect(),m=p.width/l.offsetWidth,g=p.height/l.offsetHeight;c=p.left-l.scrollLeft*m,h=p.top-l.scrollTop*g}this.element.style.left=(r.left-c)/a+"px",this.element.style.top=(r.top-h)/o+"px",this.element.style.width=(r.right-r.left)/a+"px",this.element.style.height=(r.bottom-r.top)/o+"px"}scheduleRemoval(e){clearTimeout(this.timeout),this.timeout=setTimeout(()=>this.setCursor(null),e)}dragover(e){if(!this.editorView.editable)return;let n=this.editorView.posAtCoords({left:e.clientX,top:e.clientY}),r=n&&n.inside>=0&&this.editorView.state.doc.nodeAt(n.inside),s=r&&r.type.spec.disableDropCursor,i=typeof s=="function"?s(this.editorView,n,e):s;if(n&&!i){let a=n.pos;if(this.editorView.dragging&&this.editorView.dragging.slice){let o=dz(this.editorView.state.doc,a,this.editorView.dragging.slice);o!=null&&(a=o)}this.setCursor(a),this.scheduleRemoval(5e3)}}dragend(){this.scheduleRemoval(20)}drop(){this.scheduleRemoval(20)}dragleave(e){this.editorView.dom.contains(e.relatedTarget)||this.setCursor(null)}}const ZEe=sr.create({name:"dropCursor",addOptions(){return{color:"currentColor",width:1,class:void 0}},addProseMirrorPlugins(){return[QEe(this.options)]}});class fr extends Qt{constructor(e){super(e,e)}map(e,n){let r=e.resolve(n.map(this.head));return fr.valid(r)?new fr(r):Qt.near(r)}content(){return ht.empty}eq(e){return e instanceof fr&&e.head==this.head}toJSON(){return{type:"gapcursor",pos:this.head}}static fromJSON(e,n){if(typeof n.pos!="number")throw new RangeError("Invalid input for GapCursor.fromJSON");return new fr(e.resolve(n.pos))}getBookmark(){return new lN(this.anchor)}static valid(e){let n=e.parent;if(n.inlineContent||!YEe(e)||!e_e(e))return!1;let r=n.type.spec.allowGapCursor;if(r!=null)return r;let s=n.contentMatchAt(e.index()).defaultType;return s&&s.isTextblock}static findGapCursorFrom(e,n,r=!1){e:for(;;){if(!r&&fr.valid(e))return e;let s=e.pos,i=null;for(let a=e.depth;;a--){let o=e.node(a);if(n>0?e.indexAfter(a)<o.childCount:e.index(a)>0){i=o.child(n>0?e.indexAfter(a):e.index(a)-1);break}else if(a==0)return null;s+=n;let l=e.doc.resolve(s);if(fr.valid(l))return l}for(;;){let a=n>0?i.firstChild:i.lastChild;if(!a){if(i.isAtom&&!i.isText&&!kt.isSelectable(i)){e=e.doc.resolve(s+i.nodeSize*n),r=!1;continue e}break}i=a,s+=n;let o=e.doc.resolve(s);if(fr.valid(o))return o}return null}}}fr.prototype.visible=!1;fr.findFrom=fr.findGapCursorFrom;Qt.jsonID("gapcursor",fr);class lN{constructor(e){this.pos=e}map(e){return new lN(e.map(this.pos))}resolve(e){let n=e.resolve(this.pos);return fr.valid(n)?new fr(n):Qt.near(n)}}function v7(t){return t.isAtom||t.spec.isolating||t.spec.createGapCursor}function YEe(t){for(let e=t.depth;e>=0;e--){let n=t.index(e),r=t.node(e);if(n==0){if(r.type.spec.isolating)return!0;continue}for(let s=r.child(n-1);;s=s.lastChild){if(s.childCount==0&&!s.inlineContent||v7(s.type))return!0;if(s.inlineContent)return!1}}return!0}function e_e(t){for(let e=t.depth;e>=0;e--){let n=t.indexAfter(e),r=t.node(e);if(n==r.childCount){if(r.type.spec.isolating)return!0;continue}for(let s=r.child(n);;s=s.firstChild){if(s.childCount==0&&!s.inlineContent||v7(s.type))return!0;if(s.inlineContent)return!1}}return!0}function t_e(){return new ir({props:{decorations:i_e,createSelectionBetween(t,e,n){return e.pos==n.pos&&fr.valid(n)?new fr(n):null},handleClick:r_e,handleKeyDown:n_e,handleDOMEvents:{beforeinput:s_e}}})}const n_e=k9({ArrowLeft:_y("horiz",-1),ArrowRight:_y("horiz",1),ArrowUp:_y("vert",-1),ArrowDown:_y("vert",1)});function _y(t,e){const n=t=="vert"?e>0?"down":"up":e>0?"right":"left";return function(r,s,i){let a=r.selection,o=e>0?a.$to:a.$from,l=a.empty;if(a instanceof Wt){if(!i.endOfTextblock(n)||o.depth==0)return!1;l=!1,o=r.doc.resolve(e>0?o.after():o.before())}let c=fr.findGapCursorFrom(o,e,l);return c?(s&&s(r.tr.setSelection(new fr(c))),!0):!1}}function r_e(t,e,n){if(!t||!t.editable)return!1;let r=t.state.doc.resolve(e);if(!fr.valid(r))return!1;let s=t.posAtCoords({left:n.clientX,top:n.clientY});return s&&s.inside>-1&&kt.isSelectable(t.state.doc.nodeAt(s.inside))?!1:(t.dispatch(t.state.tr.setSelection(new fr(r))),!0)}function s_e(t,e){if(e.inputType!="insertCompositionText"||!(t.state.selection instanceof fr))return!1;let{$from:n}=t.state.selection,r=n.parent.contentMatchAt(n.index()).findWrapping(t.state.schema.nodes.text);if(!r)return!1;let s=qe.empty;for(let a=r.length-1;a>=0;a--)s=qe.from(r[a].createAndFill(null,s));let i=t.state.tr.replace(n.pos,n.pos,new ht(s,0,0));return i.setSelection(Wt.near(i.doc.resolve(n.pos+1))),t.dispatch(i),!1}function i_e(t){if(!(t.selection instanceof fr))return null;let e=document.createElement("div");return e.className="ProseMirror-gapcursor",_r.create(t.doc,[Ii.widget(t.selection.head,e,{key:"gapcursor"})])}const a_e=sr.create({name:"gapCursor",addProseMirrorPlugins(){return[t_e()]},extendNodeSchema(t){var e;const n={name:t.name,options:t.options,storage:t.storage};return{allowGapCursor:(e=Zt(yt(t,"allowGapCursor",n)))!==null&&e!==void 0?e:null}}}),o_e=on.create({name:"hardBreak",addOptions(){return{keepMarks:!0,HTMLAttributes:{}}},inline:!0,group:"inline",selectable:!1,linebreakReplacement:!0,parseHTML(){return[{tag:"br"}]},renderHTML({HTMLAttributes:t}){return["br",Un(this.options.HTMLAttributes,t)]},renderText(){return`
|
|
@@ -5455,6 +5455,6 @@ window.fetch=function(input,init){
|
|
|
5455
5455
|
)`},{sql:`CREATE TABLE IF NOT EXISTS config (
|
|
5456
5456
|
key TEXT PRIMARY KEY,
|
|
5457
5457
|
value TEXT NOT NULL
|
|
5458
|
-
)`}];async function vH(){await wte(BPe),await $Pe(),await HPe()}async function $Pe(){await s6("posts",[{name:"translations",ddl:"TEXT"},{name:"last_published_paths_by_locale",ddl:"TEXT"}]),await s6("terms",[{name:"translations",ddl:"TEXT"},{name:"seo",ddl:"TEXT"}])}async function s6(t,e){const{rows:n}=await hs(`PRAGMA table_info(${t})`,[]),r=new Set(n.map(s=>s.name));for(const s of e)r.has(s.name)||await Kn(`ALTER TABLE ${t} ADD COLUMN ${s.name} ${s.ddl}`,[])}async function HPe(){(await hs("SELECT value FROM settings WHERE key = ?",["site"])).rows.length>0||await Kn("INSERT INTO settings (key, value) VALUES (?, ?)",["site",JSON.stringify(ll)])}class Wn extends Error{constructor(e,n){super(n??e),this.kind=e,this.detail=n,this.name="SetupError"}}async function DN(t,e,n,r,s){if(!e)return{configUploaded:!1};if(n.hostAdminFolder){const a=s("setup.adminHosting.deploying");return r.step(a),await yH(n.hostAdminFolder,t,(o,l)=>r.step(`${a} ${o}/${l}`)),r.done(a),{configUploaded:!0,adminUrl:RN(e,n.hostAdminFolder)??void 0}}const i=tk(e);return i?(r.step(s("setup.steps.uploadConfig")),await MN(i,t),r.done(s("setup.steps.uploadConfig")),{configUploaded:!0}):{configUploaded:!1}}const xH=/.+@.+\..+/;function VPe(t){return[t.apiKey,t.authDomain,t.projectId,t.storageBucket,t.messagingSenderId,t.appId,t.adminEmail,t.adminPassword].every(Boolean)&&xH.test(t.adminEmail)}function qPe(t){return[t.flexwegApiKey,t.flexwegSiteUrl,t.flexwegApiBaseUrl,t.sqlitePath,t.adminEmail].every(Boolean)&&xH.test(t.adminEmail)&&t.adminPassword.length>=8&&/^[\w./-]+\.(sqlite|db)$/i.test(t.sqlitePath)}function wH(t){return{backend:"firebase",firebase:{apiKey:t.apiKey,authDomain:t.authDomain,projectId:t.projectId,storageBucket:t.storageBucket,messagingSenderId:t.messagingSenderId,appId:t.appId}}}function WPe(t){switch((t==null?void 0:t.code)??""){case"auth/invalid-credential":case"auth/wrong-password":return"setup.errors.firebaseAuthInvalidCredential";case"auth/user-not-found":return"setup.errors.firebaseAuthUserNotFound";case"auth/invalid-email":return"setup.errors.firebaseAuthInvalidEmail";case"auth/api-key-not-valid":case"auth/invalid-api-key":return"setup.errors.firebaseInvalidApiKey";case"auth/network-request-failed":return"setup.errors.firebaseNetwork";case"auth/too-many-requests":return"setup.errors.firebaseTooManyRequests";case"auth/operation-not-allowed":return"setup.errors.firebaseOperationNotAllowed";case"auth/user-disabled":return"setup.errors.firebaseUserDisabled";default:return"setup.errors.firebaseAuthGeneric"}}function kH(t,e){const n=t instanceof uT||t instanceof t1?t.status:0;return n===401||n===403?new Wn("flexwegAuth"):n?new Wn("generic",e("setup.errors.flexwegHttp",{status:n,detail:t.message})):new Wn("flexwegNetwork")}async function GPe(t,e){var n;if(!VPe(t))throw new Wn("missingFields");cte(wH(t));try{await hO(_f(),t.adminEmail,t.adminPassword)}catch(r){const s=WPe(r);if(s==="setup.errors.firebaseAuthInvalidCredential")throw new Wn("firebaseAuthInvalidCredential");const i=r;let a=e(s);throw s==="setup.errors.firebaseAuthGeneric"&&(i.code&&(a+=` [${i.code}]`),i.message&&(a+=`: ${i.message}`)),new Wn("firebaseAuth",a)}if((((n=_f().currentUser)==null?void 0:n.email)??"").toLowerCase()!==t.adminEmail)throw new Wn("wrongAdminEmail");try{await Cu(rl(Xs(),ls.config,e1.admin))}catch(r){throw(r==null?void 0:r.code)==="permission-denied"?new Wn("rulesNotPinned",t.adminEmail):r}}async function KPe(t,e){if(!qPe(t))throw new Wn("missingFields");try{await d8({apiKey:t.flexwegApiKey,siteUrl:t.flexwegSiteUrl,apiBaseUrl:t.flexwegApiBaseUrl})}catch(n){throw kH(n,e)}}async function JPe(t,e,n){if(t.provider==="local"){if(!await Cf(Ig))throw new Wn("generic",n("setup.docstore.folderRequired"));return null}if(!e.trim()||(t.provider==="github"?!t.owner||!t.repo:!t.project))throw new Wn("missingFields");const r=Af(t.provider==="github"?{provider:"github",owner:t.owner??"",repo:t.repo??"",branch:t.branch,token:e,apiBaseUrl:t.apiBaseUrl}:{provider:"gitlab",project:t.project??"",branch:t.branch,token:e,apiBaseUrl:t.apiBaseUrl});let s;try{s=await r.permissions()}catch{throw new Wn("generic",n("gitAccess.failed"))}if(!s.canWrite)throw new Wn("generic",n("gitAccess.failed"));const i=await r.listTree(),a=Ov(t.contentDir,".cms/config/storage.json"),o=i.entries.find(h=>h.path===a);if(!o)return null;const l=(await r.readTexts([o])).get(o.path),c=l?JSON.parse(l):null;return c!=null&&c.connectorId?{connectorId:c.connectorId,settings:c.settings??{}}:null}async function QPe(t,e,n,r){if(!/^[\w./-]+\.(sqlite|db)$/i.test(e.trim()))throw new Wn("missingFields");const s=await l1(t.connectorId,t.settings,{ignore:["siteUrl"]});if(!s.ok)throw new Wn("generic",`${n("connectors.testFailed")} — ${s.detail}`);const i=o1(t.connectorId,t.settings);if(!i.getBytes)throw new Wn("generic",n("docstore.errors.sqliteUnsupported",{connector:t.connectorId}));const a=await i.getBytes(e.trim().replace(/^\/+/,""));if(a&&WO(a))try{await b8(a,r??null)}catch(o){throw o instanceof Pg?new Wn("generic",n(o.reason==="wrong"?"sqliteAccess.passphraseWrong":"setup.sqliteFile.existingEncrypted")):o}return a!==null}function FN(t){window.__FLEXWEG_CONFIG__=t,u0()}async function ON(t,e,n,r){if(_w(t),!e||voe())return!1;n.step(r("setup.steps.uploadConfig"));try{await xoe(e,HC(t))}catch(s){throw new Wn("uploadFailed",s instanceof Error?s.message:String(s))}return n.done(r("setup.steps.uploadConfig")),!0}async function zN(t,e,n,r){if(t){e.step(n("setup.install.saveTarget"));try{await mH(t,{siteUrl:"always"})}catch(s){throw(s==null?void 0:s.code)==="permission-denied"&&r?r():new Wn("firestoreOther",s.message)}e.done(n("setup.install.saveTarget"))}}async function UN(t,e){t.step(e("setup.steps.syncThemes"));try{await ja(()=>Yg(void 0,void 0))}catch(n){console.error("[setup] theme assets sync failed:",n)}t.done(e("setup.steps.syncThemes"))}const SH=t=>(t==null?void 0:t.connectorId)==="flexweg"?{apiKey:String(t.settings.apiKey??""),siteUrl:String(t.settings.siteUrl??""),apiBaseUrl:String(t.settings.apiBaseUrl??"")}:null;async function XPe(t,e,n,r,s={}){const i=wH(t);FN(i),await zN(e,n,r,()=>new Wn("firestoreRules",t.adminEmail));const a=await ON(i,SH(e),n,r);await UN(n,r);const o=await DN(i,e,s,n,r);return{runtime:i,configUploaded:a||o.configUploaded,adminUrl:o.adminUrl}}async function ZPe(t,e,n,r,s={}){n.step(r("setup.steps.sqliteInstall"));let i;try{i=(await Ste({masterApiKey:t.flexwegApiKey,apiBaseUrl:t.flexwegApiBaseUrl,path:t.sqlitePath,name:"Flexweg CMS",requireUserAuth:!0,allowedOrigins:[window.location.origin]})).token}catch(c){throw kH(c,r)}n.done(r("setup.stepsDone.sqliteInstall"));const a={backend:"flexweg-sqlite",flexweg:{siteUrl:t.flexwegSiteUrl,apiBaseUrl:t.flexwegApiBaseUrl,sqliteToken:i,sqlitePath:t.sqlitePath}};FN(a),n.step(r("setup.steps.sqliteRegisterAdmin"));try{await hB({email:t.adminEmail,password:t.adminPassword,displayName:t.adminEmail.split("@")[0],masterApiKey:t.flexwegApiKey}),await fB({email:t.adminEmail,password:t.adminPassword})}catch(c){throw new Wn("generic",c instanceof Error?c.message:String(c))}n.done(r("setup.stepsDone.sqliteRegisterAdmin")),n.step(r("setup.steps.sqliteSchema"));try{await vH()}catch(c){throw new Wn("generic",c.message)}n.done(r("setup.stepsDone.sqliteSchema")),await zN(e,n,r);const o=await ON(a,{apiKey:t.flexwegApiKey,siteUrl:t.flexwegSiteUrl,apiBaseUrl:t.flexwegApiBaseUrl},n,r);await UN(n,r);const l=await DN(a,e,s,n,r);return{runtime:a,configUploaded:o||l.configUploaded,adminUrl:l.adminUrl}}async function YPe(t,e,n,r,s={}){var a,o,l,c,h;let i;if(t.backend==="local")i={backend:"local"};else if(t.backend==="sqlite-file"){const{publicSettings:p,secrets:m}=g8(t.location.settings);dT(m);const g=((a=t.passphrase)==null?void 0:a.trim())||null;qv(g),i={backend:"sqlite-file",sqlite:{connectorId:t.location.connectorId,settings:p,path:t.path.trim().replace(/^\/+/,""),...g?{encrypted:!0}:{}}}}else{const p=t.git;i={backend:"markdown-git",git:{...p,owner:p.provider==="github"?(o=p.owner)==null?void 0:o.trim():void 0,repo:p.provider==="github"?(l=p.repo)==null?void 0:l.trim():void 0,project:p.provider==="gitlab"?(c=p.project)==null?void 0:c.trim():void 0,branch:p.branch.trim()||"main",contentDir:p.contentDir.trim().replace(/^\/+|\/+$/g,""),apiBaseUrl:((h=p.apiBaseUrl)==null?void 0:h.trim())||void 0}},i.git.provider!=="local"&&rT(i.git,t.token)}FN(i);try{t.backend==="sqlite-file"&&e&&await UPe(e),n.step(r("setup.docstore.steps.content")),await Ct().ready(),n.done(r("setup.docstore.steps.content")),await zN(e,n,r);const p=await ON(i,SH(e),n,r);await UN(n,r);const m=await DN(i,e??s.reusedTarget??null,s,n,r);return{runtime:i,configUploaded:p||m.configUploaded,adminUrl:m.adminUrl}}catch(p){throw _w(null),window.__FLEXWEG_CONFIG__=null,u0(),p}}function e3e(t){const e=new Blob([HC(t)],{type:"text/javascript"}),n=URL.createObjectURL(e),r=document.createElement("a");r.href=n,r.download="config.js",r.click(),setTimeout(()=>URL.revokeObjectURL(n),1e4)}function t3e(){if(typeof window>"u")return"";const t=window.location.hostname;if(t==="localhost"||t==="127.0.0.1"||t==="[::1]"||t==="::1"||t==="0.0.0.0"||t.endsWith(".localhost"))return"";const e=A0();return e?`${window.location.origin}/${e}`:window.location.origin}function n3e(){if(typeof window>"u")return"admin/cms.sqlite";const t=A0();return t?`${t}/cms.sqlite`:"admin/cms.sqlite"}function r3e(){if(typeof window>"u")return"";try{const t=new URL(window.location.href).searchParams.get("apikey");return(t==null?void 0:t.trim())??""}catch{return""}}function TC(){if(typeof window>"u")return;const t=new URL(window.location.href);t.search="",window.location.replace(t.toString())}const s3e={apiKey:"",authDomain:"",projectId:"",storageBucket:"",messagingSenderId:"",appId:"",adminEmail:"",adminPassword:"",flexwegApiKey:r3e(),flexwegSiteUrl:t3e(),flexwegApiBaseUrl:io,sqlitePath:n3e()},i3e={provider:"github",owner:"",repo:"",project:"",branch:"main",contentDir:"content"},i6=t=>t==="sqlite-file"||t==="markdown-git"||t==="local";function a3e(){return`${A0()||"admin"}/data/cms.sqlite`}function o3e(t){return t instanceof Wn?{kind:t.kind,detail:t.detail}:{kind:"generic",detail:t instanceof Error?t.message:String(t)}}function l3e(t,e,n){const r=(s,i={})=>{const a=IN(s);return{connectorId:a.connectorId,settings:{...a.preset,...i}}};return t==="sqlite-file"||t==="firebase"?r("flexweg",{apiKey:e.flexwegApiKey,siteUrl:e.flexwegSiteUrl,apiBaseUrl:e.flexwegApiBaseUrl||io}):t==="markdown-git"&&n.provider==="github"?r("github-pages",{owner:n.owner}):t==="markdown-git"&&n.provider==="gitlab"?r("gitlab-pages"):r("zip")}function c3e(){const{t}=Fe(),[e,n]=U.useState("terms"),[r,s]=U.useState("sqlite-file"),[i,a]=U.useState(a3e),[o,l]=U.useState(!1),[c,h]=U.useState(!0),[p,m]=U.useState(Uv),[g,y]=U.useState(!1),[x,v]=U.useState(()=>{const Re=IN("s3");return{connectorId:Re.connectorId,settings:{...Re.preset}}}),[k,C]=U.useState(!0),[N,_]=U.useState(NN),[P,D]=U.useState(!1);U.useEffect(()=>{jN().then(Re=>D(!!Re))},[]);const[I,L]=U.useState(!1),[j,q]=U.useState(s3e),[V,O]=U.useState(i3e),[$,B]=U.useState(""),[X,fe]=U.useState(null),[ie,ae]=U.useState(null),[ue,ve]=U.useState(null),[K,ee]=U.useState(!1),[xe,_e]=U.useState(null),[ge,He]=U.useState([]),[Ye,Se]=U.useState(null),[we,rt]=U.useState(null);function lt(Re,Be){q(st=>({...st,[Re]:Be}))}function Dt(){return{...j,apiKey:j.apiKey.trim(),authDomain:j.authDomain.trim(),projectId:j.projectId.trim(),storageBucket:j.storageBucket.trim(),messagingSenderId:j.messagingSenderId.trim(),appId:j.appId.trim(),adminEmail:j.adminEmail.trim().toLowerCase(),flexwegApiKey:j.flexwegApiKey.trim(),flexwegSiteUrl:j.flexwegSiteUrl.trim().replace(/\/+$/,""),flexwegApiBaseUrl:j.flexwegApiBaseUrl.trim().replace(/\/+$/,"")||io,sqlitePath:j.sqlitePath.trim().replace(/^\/+|\/+$/g,"")}}const je={step:Re=>_e(Re),done:Re=>He(Be=>[...Be,Re])};async function z(Re){ee(!0),Se(null);try{await Re()}catch(Be){Se(o3e(Be))}finally{ee(!1),_e(null)}}function ce(){z(async()=>{const Re=Dt();let Be=null;r==="firebase"?(_e(t("setup.steps.signInFirebase")),await GPe(Re,t)):r==="markdown-git"&&(_e(t("setup.docstore.checking")),Be=await JPe(V,$,t)),ve(Be),Be?(fe(Be),ae(r)):(!X||ie!==r)&&(fe(l3e(r,Re,V)),ae(r)),n("hosting")})}function le(){X&&z(async()=>{if(X.connectorId!=="browser-mirror"){_e(t("setup.docstore.steps.testTarget"));const Be=r==="markdown-git"&&X.connectorId==="git-pages"&&X.settings.provider===V.provider&&!X.settings.token?{...X.settings,token:$}:X.settings,st=await l1(X.connectorId,Be);if(!st.ok)throw new Wn("generic",`${t("connectors.testFailed")} — ${st.detail}`)}if(Z)await KPe(be(),t);else if(r==="sqlite-file"){if(c&&p.trim().length<12)throw new Wn("generic",t("setup.sqliteFile.passphraseTooShort"));L(await QPe(re(X),i,t,c?p:null))}n("install")})}function Y(){X&&(He([]),z(async()=>{const Re=Dt(),Be=ue&&X===ue?null:X,st={hostAdminFolder:he&&k?N:null},ot=r==="firebase"?await XPe(Re,X,je,t,st):Z?await ZPe(be(),X,je,t,st):await YPe(r==="sqlite-file"?{backend:r,location:re(X),path:i,passphrase:c?p:null}:r==="markdown-git"?{backend:r,git:V,token:$}:{backend:"local"},Be,je,t,{...st,reusedTarget:X});rt(ot),ot.configUploaded&&!ot.adminUrl&&window.setTimeout(TC,2e3)}))}const Z=r==="sqlite-file"&&o&&(X==null?void 0:X.connectorId)==="flexweg";function re(Re){return g?x:zPe(Re)}function be(){const Re=(X==null?void 0:X.settings)??{};return{...Dt(),flexwegApiKey:String(Re.apiKey??"").trim(),flexwegSiteUrl:String(Re.siteUrl??"").trim().replace(/\/+$/,""),flexwegApiBaseUrl:String(Re.apiBaseUrl??"").trim().replace(/\/+$/,"")||io}}const Te=X?tk(X):null,he=P&&!!X&&X.connectorId!=="flexweg"&&X.connectorId!=="browser-mirror"&&!Te,Me=K&&e==="install",$e=!!we;return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950 overflow-hidden",children:[d.jsxs("div",{className:"flexweg-blobs","aria-hidden":"true",children:[d.jsx("div",{className:"flexweg-blob flexweg-blob-1"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-2"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-3"})]}),d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),(Me||(we==null?void 0:we.configUploaded)&&!we.adminUrl)&&el.createPortal(d.jsx(x3e,{step:xe,progressLog:ge,done:!!(we!=null&&we.configUploaded)}),document.body),d.jsxs("div",{className:"w-full max-w-2xl relative z-10",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"Flexweg",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{className:"text-center",children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("setup.title")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:t("setup.subtitle")})]})]}),d.jsx(u3e,{currentStep:e}),e==="terms"?d.jsx(y3e,{onAccept:()=>n("data")}):e==="data"?d.jsxs(yE,{title:t("setup.data.title"),intro:t("setup.data.intro"),error:Ye,busy:K,busyLabel:xe,onBack:()=>{Se(null),n("terms")},onContinue:ce,children:[d.jsx(h3e,{value:r,onChange:Re=>{Se(null),s(Re)}}),d.jsx("div",{className:"border-t border-surface-200 pt-5 dark:border-surface-700",children:r==="firebase"?d.jsx(f3e,{form:j,patch:lt}):r==="sqlite-file"?d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:t("setup.sqliteFile.dataNote")}):r==="markdown-git"?d.jsx(m3e,{git:V,setGit:O,token:$,setToken:B}):d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:t("setup.data.localNote")})})]}):e==="hosting"?d.jsxs(yE,{title:t("setup.hosting.title"),intro:t("setup.hosting.intro"),error:Ye,busy:K,busyLabel:xe,onBack:()=>{Se(null),n("data")},onContinue:le,children:[ue&&X===ue&&d.jsx("p",{className:"rounded-lg bg-emerald-50 ring-1 ring-emerald-200 px-3 py-2 text-sm text-emerald-800 dark:bg-emerald-900/20 dark:ring-emerald-700/40 dark:text-emerald-200",children:t("setup.hosting.existing")}),X&&d.jsx(Y1,{value:X,onChange:fe,picker:"cards",exclude:r==="sqlite-file"?["zip"]:[]}),r==="sqlite-file"&&X&&d.jsx(p3e,{onFlexweg:X.connectorId==="flexweg",onGit:X.connectorId==="git-pages",useService:Z,setUseService:l,path:i,setPath:a,form:j,patch:lt,encrypt:c,setEncrypt:h,passphrase:p,setPassphrase:m,separate:g,setSeparate:y,location:x,setLocation:v})]}):we?d.jsx(g3e,{result:we}):d.jsxs(yE,{title:t("setup.install.title"),intro:t("setup.install.intro"),error:Ye,busy:K,busyLabel:null,onBack:()=>{Se(null),n("hosting")},onContinue:Y,continueLabel:t("setup.docstore.install"),children:[d.jsxs("dl",{className:"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-sm",children:[d.jsx("dt",{className:"text-surface-500",children:t("setup.install.data")}),d.jsxs("dd",{className:"font-medium",children:[t(`setup.data.options.${r}.title`),r==="sqlite-file"&&d.jsx("span",{className:"block text-xs font-normal text-surface-500 break-all",children:Z?t("setup.sqliteFile.summaryService",{path:j.sqlitePath}):[t("setup.sqliteFile.summaryFile",{path:i}),t(I?"setup.sqliteFile.existing":"setup.sqliteFile.new"),c?t("setup.sqliteFile.summaryEncrypted"):null,g?t("setup.sqliteFile.summaryLocation",{location:t(`hosting.${uw(x.connectorId,x.settings).id}.title`)}):(X==null?void 0:X.connectorId)==="git-pages"?t("setup.sqliteFile.summaryBranch",{branch:LN}):null].filter(Boolean).join(" · ")})]}),d.jsx("dt",{className:"text-surface-500",children:t("setup.install.hosting")}),d.jsxs("dd",{className:"font-medium",children:[X?t(`hosting.${uw(X.connectorId,X.settings).id}.title`):"—",typeof(X==null?void 0:X.settings.siteUrl)=="string"&&X.settings.siteUrl&&d.jsx("span",{className:"block text-xs font-normal text-surface-500 break-all",children:X.settings.siteUrl})]})]}),he&&X&&d.jsxs("fieldset",{className:"space-y-2 border-t border-surface-200 pt-4 dark:border-surface-700",children:[d.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",className:"mt-1",checked:k,onChange:Re=>C(Re.target.checked)}),d.jsxs("span",{children:[d.jsx("span",{className:"font-medium",children:t("setup.adminHosting.label")}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400",children:t("setup.adminHosting.hint",{url:RN(X,N)??`…/${N}/`})})]})]}),k&&d.jsx(Er,{label:t("setup.adminHosting.folder"),value:N,onChange:_,required:!0})]}),Te?d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:t("setup.adminHosting.alreadyHere")}):!(he&&k)&&d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:t(i6(r)?"setup.install.noteLocalConfig":"setup.install.noteConfigJs")})]}),!$e&&d.jsx("p",{className:"text-[11px] text-surface-400 text-center mt-4 dark:text-surface-500",children:t(i6(r)?"setup.docstore.footer":"setup.footer")})]})]})}function u3e({currentStep:t}){const{t:e}=Fe(),n=[{id:"terms",label:e("setup.stepper.terms")},{id:"data",label:e("setup.stepper.data")},{id:"hosting",label:e("setup.stepper.hosting")},{id:"install",label:e("setup.stepper.install")}],r=n.findIndex(s=>s.id===t);return d.jsx("div",{className:"flex items-center justify-center gap-3 mb-6 flex-wrap",children:n.map((s,i)=>{const a=i===r,o=i<r;return d.jsxs("div",{className:"flex items-center gap-3",children:[d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsx("div",{className:"h-6 w-6 rounded-full flex items-center justify-center text-[11px] font-semibold transition-colors "+(o?"bg-emerald-500 text-white":a?"bg-blue-600 text-white":"bg-surface-200 text-surface-500 dark:bg-surface-800 dark:text-surface-400"),children:o?d.jsx(Gs,{className:"h-3.5 w-3.5"}):i+1}),d.jsx("span",{className:"text-xs font-medium "+(a?"text-surface-900 dark:text-surface-50":"text-surface-500 dark:text-surface-400"),children:s.label})]}),i<n.length-1&&d.jsx("div",{className:"h-px w-8 transition-colors "+(o?"bg-emerald-500":"bg-surface-300 dark:bg-surface-700")})]},s.id)})})}function yE({title:t,intro:e,error:n,busy:r,busyLabel:s,onBack:i,onContinue:a,continueLabel:o,children:l}){const{t:c}=Fe();return d.jsxs("div",{className:"card p-6",children:[d.jsx("h2",{className:"text-lg font-semibold text-surface-900 dark:text-surface-50",children:t}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300 mt-2",children:e}),d.jsxs("form",{className:"mt-5 space-y-5","data-form-type":"other",onSubmit:h=>{h.preventDefault(),r||a()},children:[l,d.jsx("div",{"aria-live":"polite","aria-atomic":"true",children:n?d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm break-words dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:d.jsx(v3e,{error:n})}):r&&s?d.jsxs("p",{className:"flex items-center gap-2 text-sm text-surface-600 dark:text-surface-300",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),s]}):null}),d.jsxs("div",{className:"flex flex-col sm:flex-row gap-3",children:[d.jsx("button",{type:"button",onClick:i,className:"btn-secondary flex-1 justify-center",disabled:r,children:c("common.back")}),d.jsx("button",{type:"submit",className:"btn-primary flex-1 justify-center",disabled:r,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(r?"":"hidden")}),d.jsx("span",{children:o??c("setup.backend.continue")}),d.jsx(jC,{className:"h-4 w-4 "+(r||o?"hidden":"")})]})})]})]})]})}const d3e=[{id:"sqlite-file",icon:dg},{id:"markdown-git",icon:Nm},{id:"firebase",icon:N6},{id:"local",icon:LC}];function h3e({value:t,onChange:e}){const{t:n}=Fe();return d.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:d3e.map(({id:r,icon:s})=>d.jsxs("label",{className:"flex items-start gap-3 p-3 rounded-lg ring-1 ring-inset cursor-pointer transition-colors "+(t===r?"ring-blue-500 bg-blue-50/60 dark:ring-blue-400 dark:bg-blue-900/20":"ring-surface-200 hover:bg-surface-50 dark:ring-surface-700 dark:hover:bg-surface-800/60"),children:[d.jsx("input",{type:"radio",name:"backend",checked:t===r,onChange:()=>e(r),className:"mt-1"}),d.jsxs("span",{className:"flex-1 min-w-0",children:[d.jsxs("span",{className:"text-sm font-semibold flex items-center gap-1.5",children:[d.jsx(s,{className:"h-4 w-4 text-surface-500"}),n(`setup.data.options.${r}.title`)]}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400 mt-1 leading-relaxed",children:n(`setup.data.options.${r}.hint`)})]})]},r))})}function f3e({form:t,patch:e}){const{t:n}=Fe();return d.jsxs("div",{className:"space-y-6",children:[d.jsxs("fieldset",{className:"space-y-4",children:[d.jsx("legend",{className:"text-sm font-semibold text-surface-900 dark:text-surface-50",children:n("setup.sections.firebase")}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:n("setup.help.firebase")}),d.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[d.jsx(Er,{label:n("setup.fields.apiKey"),value:t.apiKey,onChange:r=>e("apiKey",r),required:!0}),d.jsx(Er,{label:n("setup.fields.authDomain"),placeholder:"your-project.firebaseapp.com",value:t.authDomain,onChange:r=>e("authDomain",r),required:!0}),d.jsx(Er,{label:n("setup.fields.projectId"),placeholder:"your-project",value:t.projectId,onChange:r=>e("projectId",r),required:!0}),d.jsx(Er,{label:n("setup.fields.storageBucket"),placeholder:"your-project.appspot.com",value:t.storageBucket,onChange:r=>e("storageBucket",r),required:!0}),d.jsx(Er,{label:n("setup.fields.messagingSenderId"),value:t.messagingSenderId,onChange:r=>e("messagingSenderId",r),required:!0}),d.jsx(Er,{label:n("setup.fields.appId"),value:t.appId,onChange:r=>e("appId",r),required:!0})]})]}),d.jsxs("fieldset",{className:"space-y-4",children:[d.jsx("legend",{className:"text-sm font-semibold text-surface-900 dark:text-surface-50",children:n("setup.sections.admin")}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:n("setup.help.admin")}),d.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[d.jsx(Er,{type:"email",label:n("setup.fields.adminEmail"),placeholder:"you@company.com",value:t.adminEmail,onChange:r=>e("adminEmail",r),required:!0,autoComplete:"email"}),d.jsx(Er,{type:"password",label:n("setup.fields.adminPassword"),placeholder:"••••••••",value:t.adminPassword,onChange:r=>e("adminPassword",r),required:!0,autoComplete:"current-password"})]})]})]})}function p3e({onFlexweg:t,onGit:e,useService:n,setUseService:r,path:s,setPath:i,form:a,patch:o,encrypt:l,setEncrypt:c,passphrase:h,setPassphrase:p,separate:m,setSeparate:g,location:y,setLocation:x}){const{t:v}=Fe(),[k,C]=U.useState(!1);return d.jsxs("fieldset",{className:"space-y-3 border-t border-surface-200 pt-5 dark:border-surface-700",children:[d.jsx("legend",{className:"text-sm font-semibold text-surface-900 dark:text-surface-50",children:v("setup.sqliteFile.heading")}),t&&d.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",className:"mt-1",checked:n,onChange:N=>r(N.target.checked)}),d.jsxs("span",{children:[d.jsx("span",{className:"font-medium",children:v("setup.sqliteFile.flexwegService")}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400",children:v("setup.sqliteFile.flexwegServiceHint")})]})]}),n?d.jsxs(d.Fragment,{children:[d.jsxs("div",{children:[d.jsx(Er,{label:v("setup.fields.sqlitePath"),placeholder:"admin/cms.sqlite",value:a.sqlitePath,onChange:N=>o("sqlitePath",N),required:!0}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400 mt-1",children:v("setup.sqlite.pathHint")})]}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:v("setup.sqlite.adminIntro")}),d.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[d.jsx(Er,{type:"email",label:v("setup.fields.adminEmail"),placeholder:"you@company.com",value:a.adminEmail,onChange:N=>o("adminEmail",N),required:!0,autoComplete:"email"}),d.jsx(Er,{type:"password",label:v("setup.fields.adminPassword"),placeholder:"••••••••",value:a.adminPassword,onChange:N=>o("adminPassword",N),required:!0,autoComplete:"new-password"})]}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400",children:v("setup.sqlite.passwordHint")})]}):d.jsxs(d.Fragment,{children:[d.jsx("div",{className:"rounded-lg bg-amber-50 text-amber-800 ring-1 ring-amber-200 px-3 py-2 text-xs leading-relaxed dark:bg-amber-900/30 dark:text-amber-200 dark:ring-amber-700/50",children:v("setup.sqliteFile.security")}),d.jsxs("div",{children:[d.jsx(Er,{label:v("setup.sqliteFile.path"),value:s,onChange:i,required:!0,placeholder:"admin/data/cms.sqlite"}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400 mt-1",children:e&&!m?v("setup.sqliteFile.gitBranchNote",{branch:LN}):v("setup.sqliteFile.pathHint")})]}),d.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",className:"mt-1",checked:l,onChange:N=>c(N.target.checked)}),d.jsxs("span",{children:[d.jsx("span",{className:"font-medium",children:v("setup.sqliteFile.encrypt")}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400",children:v("setup.sqliteFile.encryptHint")})]})]}),l&&d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"sqlite-passphrase",children:v("setup.sqliteFile.passphrase")}),d.jsxs("div",{className:"flex gap-2",children:[d.jsx("input",{id:"sqlite-passphrase",className:"input font-mono text-xs",autoComplete:"off",spellCheck:!1,value:h,onChange:N=>{p(N.target.value),C(!1)},required:!0}),d.jsx("button",{type:"button",className:"btn-secondary shrink-0",onClick:()=>{var N;(N=navigator.clipboard)==null||N.writeText(h).then(()=>C(!0))},children:d.jsx("span",{children:v(k?"setup.sqliteFile.copied":"setup.sqliteFile.copy")})}),d.jsx("button",{type:"button",className:"btn-secondary shrink-0",onClick:()=>{p(Uv()),C(!1)},children:d.jsx("span",{children:v("setup.sqliteFile.generate")})})]}),d.jsx("p",{className:"text-[11px] text-amber-700 dark:text-amber-300 mt-1",children:v("setup.sqliteFile.passphraseHint")})]}),d.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",className:"mt-1",checked:m,onChange:N=>g(N.target.checked)}),d.jsxs("span",{children:[d.jsx("span",{className:"font-medium",children:v("setup.sqliteFile.separate")}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400",children:v("setup.sqliteFile.separateHint")})]})]}),m&&d.jsx(Y1,{value:y,onChange:x,exclude:["zip","flexweg"],pickerLabel:v("setup.sqliteFile.locationLabel"),hideFields:["siteUrl","publicRead"],testIgnore:["siteUrl"]})]})]})}function m3e({git:t,setGit:e,token:n,setToken:r}){const{t:s}=Fe(),[i,a]=U.useState(null),o=c=>e({...t,...c});async function l(){const c=await ZA();await YA(Ig,c),a(c.name)}return d.jsxs("div",{className:"space-y-3",children:[d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:s("setup.docstore.contentIntro")}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:s("connectors.fields.git-pages.provider")}),d.jsxs("select",{className:"input",value:t.provider,onChange:c=>o({provider:c.target.value}),children:[d.jsx("option",{value:"github",children:"GitHub"}),d.jsx("option",{value:"gitlab",children:"GitLab"}),d.jsx("option",{value:"local",disabled:!Fv(),children:s("setup.docstore.localClone")})]})]}),t.provider==="github"&&d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsx(Er,{label:s("connectors.fields.git-pages.owner"),value:t.owner??"",onChange:c=>o({owner:c}),required:!0}),d.jsx(Er,{label:s("connectors.fields.git-pages.repo"),value:t.repo??"",onChange:c=>o({repo:c}),required:!0})]}),t.provider==="gitlab"&&d.jsx(Er,{label:s("connectors.fields.git-pages.project"),placeholder:"group/my-content",value:t.project??"",onChange:c=>o({project:c}),required:!0}),t.provider!=="local"?d.jsxs(d.Fragment,{children:[d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsx(Er,{label:s("connectors.fields.git-pages.branch"),value:t.branch,onChange:c=>o({branch:c}),required:!0}),d.jsx(Er,{label:s("setup.docstore.contentDir"),value:t.contentDir,onChange:c=>o({contentDir:c})})]}),d.jsxs("div",{children:[d.jsx(Er,{label:s("gitAccess.token"),type:"password",value:n,onChange:r,required:!0,autoComplete:"off"}),d.jsxs("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:[s(t.provider==="github"?"gitAccess.tokenHelpGithub":"gitAccess.tokenHelpGitlab")," ",s("setup.docstore.privateRepo")]})]}),d.jsx(Er,{label:s("connectors.fields.git-pages.apiBaseUrl"),value:t.apiBaseUrl??"",onChange:c=>o({apiBaseUrl:c})})]}):d.jsxs("div",{className:"space-y-2",children:[d.jsx(Er,{label:s("setup.docstore.contentDir"),value:t.contentDir,onChange:c=>o({contentDir:c})}),d.jsx("button",{type:"button",className:"btn-secondary",onClick:l,children:d.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[d.jsx(Wf,{className:"h-4 w-4"}),d.jsx("span",{children:i??s("connectors.folder.choose")})]})}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:s("setup.docstore.localCloneHint")})]})]})}function g3e({result:t}){const{t:e}=Fe();return t.adminUrl?d.jsxs("div",{className:"card p-6 space-y-4",children:[d.jsxs("p",{className:"flex items-center gap-2 text-base font-semibold text-emerald-700 dark:text-emerald-400",children:[d.jsx(Gs,{className:"h-5 w-5"}),e("setup.docstore.doneTitle")]}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:e("setup.adminHosting.doneBody")}),d.jsx("a",{className:"btn-primary w-full justify-center",href:t.adminUrl,target:"_blank",rel:"noopener noreferrer",children:e("setup.adminHosting.open",{url:t.adminUrl})}),d.jsx("button",{type:"button",className:"btn-secondary w-full justify-center",onClick:TC,children:e("setup.adminHosting.continueHere")})]}):t.configUploaded?null:d.jsxs("div",{className:"card p-6 space-y-4",children:[d.jsxs("p",{className:"flex items-center gap-2 text-base font-semibold text-emerald-700 dark:text-emerald-400",children:[d.jsx(Gs,{className:"h-5 w-5"}),e("setup.docstore.doneTitle")]}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:e("setup.docstore.doneBody")}),d.jsx("button",{type:"button",className:"btn-secondary w-full justify-center",onClick:()=>e3e(t.runtime),children:d.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[d.jsx(yw,{className:"h-4 w-4"}),d.jsx("span",{children:e("setup.docstore.downloadConfig")})]})}),d.jsx("button",{type:"button",className:"btn-primary w-full justify-center",onClick:TC,children:e("setup.docstore.open")})]})}const b3e=7;function y3e({onAccept:t}){const{t:e}=Fe(),[n,r]=U.useState(!1);return d.jsxs("div",{className:"card p-6",children:[d.jsx("h2",{className:"text-lg font-semibold text-surface-900 dark:text-surface-50",children:e("setup.terms.title")}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300 mt-3",children:e("setup.terms.intro")}),d.jsx("div",{className:"mt-5 max-h-80 overflow-y-auto pr-2 space-y-4 rounded-lg border border-surface-200 bg-surface-50 p-4 dark:border-surface-700 dark:bg-surface-900/40",children:Array.from({length:b3e},(s,i)=>i+1).map(s=>d.jsxs("section",{children:[d.jsx("h3",{className:"text-sm font-semibold text-surface-900 dark:text-surface-50",children:e(`setup.terms.section${s}.title`)}),d.jsx("p",{className:"text-xs text-surface-600 dark:text-surface-300 mt-1.5 leading-relaxed",children:e(`setup.terms.section${s}.body`)})]},s))}),d.jsxs("label",{className:"mt-5 flex items-start gap-2.5 cursor-pointer",children:[d.jsx("input",{type:"checkbox",className:"mt-0.5 h-4 w-4 rounded border-surface-300 text-blue-600 focus:ring-blue-500 dark:border-surface-600 dark:bg-surface-800",checked:n,onChange:s=>r(s.target.checked)}),d.jsx("span",{className:"text-sm text-surface-700 dark:text-surface-200",children:e("setup.terms.accept")})]}),d.jsx("div",{className:"mt-6 flex justify-end",children:d.jsx("button",{type:"button",onClick:t,disabled:!n,className:"btn-primary justify-center",children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx("span",{children:e("setup.terms.continue")}),d.jsx(jC,{className:"h-4 w-4"})]})})})]})}function Er({label:t,value:e,onChange:n,placeholder:r,required:s,type:i="text",autoComplete:a,autoFocus:o}){return d.jsxs("div",{children:[d.jsx("label",{className:"label",children:t}),d.jsx("input",{type:i,className:"input",value:e,onChange:l=>n(l.target.value),placeholder:r,required:s,autoComplete:a,autoFocus:o})]})}function v3e({error:t}){const{t:e}=Fe();switch(t.kind){case"missingFields":return d.jsx("span",{children:e("setup.errors.missingFields")});case"rootDeployment":return d.jsxs("div",{className:"space-y-1.5",children:[d.jsx("p",{children:e("setup.errors.rootDeploymentTitle")}),d.jsx("p",{className:"text-xs",children:e("setup.errors.rootDeploymentHint")})]});case"firebaseAuth":return d.jsx("span",{children:t.detail??e("setup.errors.firebaseAuthGeneric")});case"firebaseAuthInvalidCredential":return d.jsxs("div",{className:"space-y-1.5",children:[d.jsx("p",{children:e("setup.errors.firebaseAuthInvalidCredential")}),d.jsx("p",{className:"text-xs whitespace-pre-line leading-relaxed",children:e("setup.errors.firebaseAuthInvalidCredentialHint")})]});case"wrongAdminEmail":return d.jsx("span",{children:e("setup.errors.wrongAdminEmail")});case"rulesNotPinned":return d.jsxs("div",{className:"space-y-1.5",children:[d.jsx("p",{children:e("setup.errors.rulesNotPinnedTitle")}),d.jsx("p",{className:"text-xs leading-relaxed",children:e("setup.errors.rulesNotPinnedHint",{email:t.detail??""})})]});case"flexwegAuth":return d.jsx("span",{children:e("setup.errors.flexwegAuth")});case"flexwegNetwork":return d.jsx("span",{children:e("setup.errors.flexwegNetwork")});case"firestoreRules":return d.jsxs("div",{className:"space-y-1.5",children:[d.jsx("p",{children:e("setup.errors.firestoreRulesTitle")}),d.jsx("p",{className:"text-xs",children:e("setup.errors.firestoreRulesHint",{email:t.detail})})]});case"firestoreOther":return d.jsxs("span",{children:[e("setup.errors.firestoreOther"),": ",t.detail]});case"uploadFailed":return d.jsxs("span",{children:[e("setup.errors.uploadFailed"),t.detail?`: ${t.detail}`:""]});case"generic":default:return d.jsx("span",{children:t.detail??e("setup.errors.generic")})}}function x3e({step:t,progressLog:e,done:n}){const{t:r}=Fe();return d.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-surface-950/80 backdrop-blur-sm p-6",children:d.jsxs("div",{className:"card w-full max-w-md p-6 text-center",children:[n?d.jsx(Gs,{className:"h-10 w-10 text-emerald-500 mx-auto mb-4"}):d.jsx(ct,{className:"h-10 w-10 text-blue-500 mx-auto mb-4 animate-spin"}),d.jsx("h2",{className:"text-lg font-semibold text-surface-900 dark:text-surface-50",children:r(n?"setup.success":"setup.submitting")}),!n&&t&&d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300 mt-2",children:t}),e.length>0&&d.jsx("ul",{className:"mt-5 space-y-1.5 text-left",children:e.map((s,i)=>d.jsxs("li",{className:"flex items-start gap-2 text-xs text-surface-500 dark:text-surface-400",children:[d.jsx(Gs,{className:"h-3.5 w-3.5 text-emerald-500 shrink-0 mt-0.5"}),d.jsx("span",{children:s})]},i))}),n&&d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400 mt-4",children:r("setup.reloadingHint")})]})})}const w3e={github:"https://github.com/settings/personal-access-tokens/new",gitlab:"https://gitlab.com/-/user_settings/personal_access_tokens?scopes=api&name=Flexweg%20CMS"};function EH(){const t=Ct();bae(t)&&t.resetSession()}function k3e(){const t=ra();if((t==null?void 0:t.backend)==="sqlite-file"){tC(()=>{dT({}),Ct().resetSession()});return}(t==null?void 0:t.backend)==="markdown-git"&&tC(()=>{t.git.provider!=="local"&&rT(t.git,null),EH()})}function S3e(){const{t}=Fe(),e=ra(),n=(e==null?void 0:e.backend)==="markdown-git"?e.git:null,[r,s]=U.useState(()=>n?nT(n)??"":""),[i,a]=U.useState(!1),[o,l]=U.useState(null);if(!n)return null;const c=n.provider==="github"?`${n.owner}/${n.repo}`:n.provider==="gitlab"?n.project:"";async function h(){EH(),await WI(),await Ct().identity()||l(t("gitAccess.failed"))}async function p(g){if(g.preventDefault(),!(!n||!r.trim())){a(!0),l(null);try{rT(n,r),await h()}finally{a(!1)}}}async function m(){a(!0),l(null);try{let g=await Cf(Ig);(!g||!await _0(g,!0))&&(g=await ZA(),await YA(Ig,g)),await h()}catch(g){g.name!=="AbortError"&&l(g.message)}finally{a(!1)}}return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950 overflow-hidden",children:[d.jsxs("div",{className:"flexweg-blobs","aria-hidden":"true",children:[d.jsx("div",{className:"flexweg-blob flexweg-blob-1"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-2"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-3"})]}),d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),d.jsxs("div",{className:"w-full max-w-sm relative z-10",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"Flexweg",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("identity.brandTitle")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:t("identity.brandSubtitle")})]})]}),d.jsxs("div",{className:"card p-6",children:[d.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-surface-50",children:t("gitAccess.heading")}),n.provider==="local"?d.jsxs(d.Fragment,{children:[d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("gitAccess.folderIntro")}),!Fv()&&d.jsx("p",{className:"text-xs text-amber-600 mt-3",children:t("connectors.folder.unsupported")}),o&&d.jsx("div",{className:"mt-4 rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:o}),d.jsx("button",{type:"button",className:"btn-primary w-full justify-center mt-5",onClick:m,disabled:i||!Fv(),children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx(Wf,{className:"h-4 w-4 "+(i?"hidden":"")}),d.jsx("span",{children:t("gitAccess.openFolder")})]})})]}):d.jsxs(d.Fragment,{children:[d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("gitAccess.tokenIntro",{repo:c,provider:n.provider==="github"?"GitHub":"GitLab"})}),d.jsxs("form",{onSubmit:p,className:"mt-5 space-y-4","data-form-type":"other",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"git-token",children:t("gitAccess.token")}),d.jsx("input",{id:"git-token",type:"password",className:"input font-mono",value:r,onChange:g=>s(g.target.value),autoComplete:"off",autoFocus:!0,required:!0}),d.jsxs("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:[t(n.provider==="github"?"gitAccess.tokenHelpGithub":"gitAccess.tokenHelpGitlab")," ",d.jsxs("a",{href:w3e[n.provider],target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-0.5 text-blue-600 hover:underline dark:text-blue-400",children:[t("gitAccess.createToken"),d.jsx(vw,{className:"h-3 w-3"})]})]})]}),o&&d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:o}),d.jsx("button",{type:"submit",className:"btn-primary w-full justify-center",disabled:i||!r.trim(),children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx("span",{children:t("gitAccess.connect")})]})}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400",children:t("gitAccess.tokenStorage")})]})]})]})]})]})}function E3e(){var y;const{t}=Fe(),e=ra(),n=(e==null?void 0:e.backend)==="sqlite-file"?e.sqlite:null,[r,s]=U.useState(()=>n?{connectorId:n.connectorId,settings:o_(n)}:{connectorId:"",settings:{}}),i=Ct(),[a,o]=U.useState(()=>wm()??""),[l,c]=U.useState(!1),[h,p]=U.useState(()=>{var x;return((x=i.passphraseProblem)==null?void 0:x.call(i))==="wrong"?t("sqliteAccess.passphraseWrong"):null});if(!n)return null;const m=!!n.encrypted||((y=i.passphraseProblem)==null?void 0:y.call(i))!=null;async function g(){c(!0),p(null);try{const x=await l1(r.connectorId,r.settings,{ignore:["siteUrl"]});if(!x.ok){p(`${t("connectors.testFailed")} — ${x.detail}`);return}dT(g8(r.settings).secrets),m&&qv(a.trim()||null),i.resetSession(),await WI();const v=i.passphraseProblem();v&&p(t(v==="wrong"?"sqliteAccess.passphraseWrong":"sqliteAccess.passphraseMissing"))}finally{c(!1)}}return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950 overflow-hidden",children:[d.jsxs("div",{className:"flexweg-blobs","aria-hidden":"true",children:[d.jsx("div",{className:"flexweg-blob flexweg-blob-1"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-2"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-3"})]}),d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),d.jsxs("div",{className:"w-full max-w-md relative z-10",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"Flexweg",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("identity.brandTitle")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:t("identity.brandSubtitle")})]})]}),d.jsxs("div",{className:"card p-6",children:[d.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-surface-50",children:t("sqliteAccess.heading")}),d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("sqliteAccess.intro",{path:n.path})}),d.jsxs("form",{className:"mt-5 space-y-4","data-form-type":"other",onSubmit:x=>{x.preventDefault(),l||g()},children:[d.jsx(Y1,{value:r,onChange:s,lockHosting:!0,hideFields:["siteUrl"],testIgnore:["siteUrl"]}),m&&d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"sqlite-passphrase",children:t("sqliteAccess.passphrase")}),d.jsx("input",{id:"sqlite-passphrase",type:"password",className:"input",autoComplete:"current-password",value:a,onChange:x=>o(x.target.value),required:!0}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400 mt-1",children:t("sqliteAccess.passphraseHint")})]}),h&&d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm break-words dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:h}),d.jsx("button",{type:"submit",className:"btn-primary w-full justify-center",disabled:l,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(l?"":"hidden")}),d.jsx("span",{children:t("gitAccess.connect")})]})}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400",children:t("sqliteAccess.storage")})]})]})]})]})}const _3e=[/Node\.insertBefore/i,/Node\.removeChild/i,/Node\.appendChild/i,/failed to execute 'insertBefore'/i,/failed to execute 'removeChild'/i],a6=3,C3e=5e3,A3e=80;function T3e(t){return t!=null&&t.message?_3e.some(e=>e.test(t.message)):!1}class o6 extends U.Component{constructor(n){super(n);Pn(this,"resetTimer",null);this.state={error:null,recovering:!1,resetCount:0,lastErrorAt:0}}static getDerivedStateFromError(n){return{error:n,lastErrorAt:Date.now()}}componentDidCatch(n,r){if(console.error("App error:",n,r),!T3e(n))return;const a=Date.now()-this.state.lastErrorAt<C3e?this.state.resetCount+1:1;if(a>a6){console.warn(`[AppErrorBoundary] giving up after ${a6} retries`);return}this.setState({resetCount:a,recovering:!0}),this.resetTimer=setTimeout(()=>{this.setState({error:null,recovering:!1})},A3e)}componentWillUnmount(){this.resetTimer&&clearTimeout(this.resetTimer)}render(){return this.state.error?this.state.recovering?d.jsx("div",{className:"min-h-full bg-surface-50 dark:bg-surface-950","aria-hidden":!0}):d.jsx(fC,{message:this.state.error.message}):this.props.children}}function _H(){return d.jsx("div",{className:"min-h-full flex items-center justify-center",children:d.jsx(ct,{className:"h-5 w-5 animate-spin text-surface-400"})})}function I3e({children:t}){const{isAdmin:e}=co();return d.jsx(d.Fragment,{children:e?t:d.jsx(fd,{to:"/dashboard",replace:!0})})}function N3e(){const{t}=Fe(),{user:e,loading:n,disabled:r,error:s}=co();if(n)return d.jsx(_H,{});if(!e){const i=$r();return i==="flexweg-sqlite"?d.jsx(TEe,{}):i==="markdown-git"?d.jsx(S3e,{}):i==="sqlite-file"?d.jsx(E3e,{}):d.jsx(AEe,{})}return s?d.jsx(fC,{title:t("errors.loadAccountFailed"),message:`${s.message}
|
|
5458
|
+
)`}];async function vH(){await wte(BPe),await $Pe(),await HPe()}async function $Pe(){await s6("posts",[{name:"translations",ddl:"TEXT"},{name:"last_published_paths_by_locale",ddl:"TEXT"}]),await s6("terms",[{name:"translations",ddl:"TEXT"},{name:"seo",ddl:"TEXT"}])}async function s6(t,e){const{rows:n}=await hs(`PRAGMA table_info(${t})`,[]),r=new Set(n.map(s=>s.name));for(const s of e)r.has(s.name)||await Kn(`ALTER TABLE ${t} ADD COLUMN ${s.name} ${s.ddl}`,[])}async function HPe(){(await hs("SELECT value FROM settings WHERE key = ?",["site"])).rows.length>0||await Kn("INSERT INTO settings (key, value) VALUES (?, ?)",["site",JSON.stringify(ll)])}class Wn extends Error{constructor(e,n){super(n??e),this.kind=e,this.detail=n,this.name="SetupError"}}async function DN(t,e,n,r,s){if(!e)return{configUploaded:!1};if(n.hostAdminFolder){const a=s("setup.adminHosting.deploying");return r.step(a),await yH(n.hostAdminFolder,t,(o,l)=>r.step(`${a} ${o}/${l}`)),r.done(a),{configUploaded:!0,adminUrl:RN(e,n.hostAdminFolder)??void 0}}const i=tk(e);return i?(r.step(s("setup.steps.uploadConfig")),await MN(i,t),r.done(s("setup.steps.uploadConfig")),{configUploaded:!0}):{configUploaded:!1}}const xH=/.+@.+\..+/;function VPe(t){return[t.apiKey,t.authDomain,t.projectId,t.storageBucket,t.messagingSenderId,t.appId,t.adminEmail,t.adminPassword].every(Boolean)&&xH.test(t.adminEmail)}function qPe(t){return[t.flexwegApiKey,t.flexwegSiteUrl,t.flexwegApiBaseUrl,t.sqlitePath,t.adminEmail].every(Boolean)&&xH.test(t.adminEmail)&&t.adminPassword.length>=8&&/^[\w./-]+\.(sqlite|db)$/i.test(t.sqlitePath)}function wH(t){return{backend:"firebase",firebase:{apiKey:t.apiKey,authDomain:t.authDomain,projectId:t.projectId,storageBucket:t.storageBucket,messagingSenderId:t.messagingSenderId,appId:t.appId}}}function WPe(t){switch((t==null?void 0:t.code)??""){case"auth/invalid-credential":case"auth/wrong-password":return"setup.errors.firebaseAuthInvalidCredential";case"auth/user-not-found":return"setup.errors.firebaseAuthUserNotFound";case"auth/invalid-email":return"setup.errors.firebaseAuthInvalidEmail";case"auth/api-key-not-valid":case"auth/invalid-api-key":return"setup.errors.firebaseInvalidApiKey";case"auth/network-request-failed":return"setup.errors.firebaseNetwork";case"auth/too-many-requests":return"setup.errors.firebaseTooManyRequests";case"auth/operation-not-allowed":return"setup.errors.firebaseOperationNotAllowed";case"auth/user-disabled":return"setup.errors.firebaseUserDisabled";default:return"setup.errors.firebaseAuthGeneric"}}function kH(t,e){const n=t instanceof uT||t instanceof t1?t.status:0;return n===401||n===403?new Wn("flexwegAuth"):n?new Wn("generic",e("setup.errors.flexwegHttp",{status:n,detail:t.message})):new Wn("flexwegNetwork")}async function GPe(t,e){var n;if(!VPe(t))throw new Wn("missingFields");cte(wH(t));try{await hO(_f(),t.adminEmail,t.adminPassword)}catch(r){const s=WPe(r);if(s==="setup.errors.firebaseAuthInvalidCredential")throw new Wn("firebaseAuthInvalidCredential");const i=r;let a=e(s);throw s==="setup.errors.firebaseAuthGeneric"&&(i.code&&(a+=` [${i.code}]`),i.message&&(a+=`: ${i.message}`)),new Wn("firebaseAuth",a)}if((((n=_f().currentUser)==null?void 0:n.email)??"").toLowerCase()!==t.adminEmail)throw new Wn("wrongAdminEmail");try{await Cu(rl(Xs(),ls.config,e1.admin))}catch(r){throw(r==null?void 0:r.code)==="permission-denied"?new Wn("rulesNotPinned",t.adminEmail):r}}async function KPe(t,e){if(!qPe(t))throw new Wn("missingFields");try{await d8({apiKey:t.flexwegApiKey,siteUrl:t.flexwegSiteUrl,apiBaseUrl:t.flexwegApiBaseUrl})}catch(n){throw kH(n,e)}}async function JPe(t,e,n){if(t.provider==="local"){if(!await Cf(Ig))throw new Wn("generic",n("setup.docstore.folderRequired"));return null}if(!e.trim()||(t.provider==="github"?!t.owner||!t.repo:!t.project))throw new Wn("missingFields");const r=Af(t.provider==="github"?{provider:"github",owner:t.owner??"",repo:t.repo??"",branch:t.branch,token:e,apiBaseUrl:t.apiBaseUrl}:{provider:"gitlab",project:t.project??"",branch:t.branch,token:e,apiBaseUrl:t.apiBaseUrl});let s;try{s=await r.permissions()}catch{throw new Wn("generic",n("gitAccess.failed"))}if(!s.canWrite)throw new Wn("generic",n("gitAccess.failed"));const i=await r.listTree(),a=Ov(t.contentDir,".cms/config/storage.json"),o=i.entries.find(h=>h.path===a);if(!o)return null;const l=(await r.readTexts([o])).get(o.path),c=l?JSON.parse(l):null;return c!=null&&c.connectorId?{connectorId:c.connectorId,settings:c.settings??{}}:null}async function QPe(t,e,n,r){if(!/^[\w./-]+\.(sqlite|db)$/i.test(e.trim()))throw new Wn("missingFields");const s=await l1(t.connectorId,t.settings,{ignore:["siteUrl"]});if(!s.ok)throw new Wn("generic",`${n("connectors.testFailed")} — ${s.detail}`);const i=o1(t.connectorId,t.settings);if(!i.getBytes)throw new Wn("generic",n("docstore.errors.sqliteUnsupported",{connector:t.connectorId}));const a=await i.getBytes(e.trim().replace(/^\/+/,""));if(a&&WO(a))try{await b8(a,r??null)}catch(o){throw o instanceof Pg?new Wn("generic",n(o.reason==="wrong"?"sqliteAccess.passphraseWrong":"setup.sqliteFile.existingEncrypted")):o}return a!==null}function FN(t){window.__FLEXWEG_CONFIG__=t,u0()}async function ON(t,e,n,r){if(_w(t),!e||voe())return!1;n.step(r("setup.steps.uploadConfig"));try{await xoe(e,HC(t))}catch(s){throw new Wn("uploadFailed",s instanceof Error?s.message:String(s))}return n.done(r("setup.steps.uploadConfig")),!0}async function zN(t,e,n,r){if(t){e.step(n("setup.install.saveTarget"));try{await mH(t,{siteUrl:"always"})}catch(s){throw(s==null?void 0:s.code)==="permission-denied"&&r?r():new Wn("firestoreOther",s.message)}e.done(n("setup.install.saveTarget"))}}async function UN(t,e){t.step(e("setup.steps.syncThemes"));try{await ja(()=>Yg(void 0,void 0))}catch(n){console.error("[setup] theme assets sync failed:",n)}t.done(e("setup.steps.syncThemes"))}const SH=t=>(t==null?void 0:t.connectorId)==="flexweg"?{apiKey:String(t.settings.apiKey??""),siteUrl:String(t.settings.siteUrl??""),apiBaseUrl:String(t.settings.apiBaseUrl??"")}:null;async function XPe(t,e,n,r,s={}){const i=wH(t);FN(i),await zN(e,n,r,()=>new Wn("firestoreRules",t.adminEmail));const a=await ON(i,SH(e),n,r);await UN(n,r);const o=await DN(i,e,s,n,r);return{runtime:i,configUploaded:a||o.configUploaded,adminUrl:o.adminUrl}}async function ZPe(t,e,n,r,s={}){n.step(r("setup.steps.sqliteInstall"));let i;try{i=(await Ste({masterApiKey:t.flexwegApiKey,apiBaseUrl:t.flexwegApiBaseUrl,path:t.sqlitePath,name:"AgentCMS",requireUserAuth:!0,allowedOrigins:[window.location.origin]})).token}catch(c){throw kH(c,r)}n.done(r("setup.stepsDone.sqliteInstall"));const a={backend:"flexweg-sqlite",flexweg:{siteUrl:t.flexwegSiteUrl,apiBaseUrl:t.flexwegApiBaseUrl,sqliteToken:i,sqlitePath:t.sqlitePath}};FN(a),n.step(r("setup.steps.sqliteRegisterAdmin"));try{await hB({email:t.adminEmail,password:t.adminPassword,displayName:t.adminEmail.split("@")[0],masterApiKey:t.flexwegApiKey}),await fB({email:t.adminEmail,password:t.adminPassword})}catch(c){throw new Wn("generic",c instanceof Error?c.message:String(c))}n.done(r("setup.stepsDone.sqliteRegisterAdmin")),n.step(r("setup.steps.sqliteSchema"));try{await vH()}catch(c){throw new Wn("generic",c.message)}n.done(r("setup.stepsDone.sqliteSchema")),await zN(e,n,r);const o=await ON(a,{apiKey:t.flexwegApiKey,siteUrl:t.flexwegSiteUrl,apiBaseUrl:t.flexwegApiBaseUrl},n,r);await UN(n,r);const l=await DN(a,e,s,n,r);return{runtime:a,configUploaded:o||l.configUploaded,adminUrl:l.adminUrl}}async function YPe(t,e,n,r,s={}){var a,o,l,c,h;let i;if(t.backend==="local")i={backend:"local"};else if(t.backend==="sqlite-file"){const{publicSettings:p,secrets:m}=g8(t.location.settings);dT(m);const g=((a=t.passphrase)==null?void 0:a.trim())||null;qv(g),i={backend:"sqlite-file",sqlite:{connectorId:t.location.connectorId,settings:p,path:t.path.trim().replace(/^\/+/,""),...g?{encrypted:!0}:{}}}}else{const p=t.git;i={backend:"markdown-git",git:{...p,owner:p.provider==="github"?(o=p.owner)==null?void 0:o.trim():void 0,repo:p.provider==="github"?(l=p.repo)==null?void 0:l.trim():void 0,project:p.provider==="gitlab"?(c=p.project)==null?void 0:c.trim():void 0,branch:p.branch.trim()||"main",contentDir:p.contentDir.trim().replace(/^\/+|\/+$/g,""),apiBaseUrl:((h=p.apiBaseUrl)==null?void 0:h.trim())||void 0}},i.git.provider!=="local"&&rT(i.git,t.token)}FN(i);try{t.backend==="sqlite-file"&&e&&await UPe(e),n.step(r("setup.docstore.steps.content")),await Ct().ready(),n.done(r("setup.docstore.steps.content")),await zN(e,n,r);const p=await ON(i,SH(e),n,r);await UN(n,r);const m=await DN(i,e??s.reusedTarget??null,s,n,r);return{runtime:i,configUploaded:p||m.configUploaded,adminUrl:m.adminUrl}}catch(p){throw _w(null),window.__FLEXWEG_CONFIG__=null,u0(),p}}function e3e(t){const e=new Blob([HC(t)],{type:"text/javascript"}),n=URL.createObjectURL(e),r=document.createElement("a");r.href=n,r.download="config.js",r.click(),setTimeout(()=>URL.revokeObjectURL(n),1e4)}function t3e(){if(typeof window>"u")return"";const t=window.location.hostname;if(t==="localhost"||t==="127.0.0.1"||t==="[::1]"||t==="::1"||t==="0.0.0.0"||t.endsWith(".localhost"))return"";const e=A0();return e?`${window.location.origin}/${e}`:window.location.origin}function n3e(){if(typeof window>"u")return"admin/cms.sqlite";const t=A0();return t?`${t}/cms.sqlite`:"admin/cms.sqlite"}function r3e(){if(typeof window>"u")return"";try{const t=new URL(window.location.href).searchParams.get("apikey");return(t==null?void 0:t.trim())??""}catch{return""}}function TC(){if(typeof window>"u")return;const t=new URL(window.location.href);t.search="",window.location.replace(t.toString())}const s3e={apiKey:"",authDomain:"",projectId:"",storageBucket:"",messagingSenderId:"",appId:"",adminEmail:"",adminPassword:"",flexwegApiKey:r3e(),flexwegSiteUrl:t3e(),flexwegApiBaseUrl:io,sqlitePath:n3e()},i3e={provider:"github",owner:"",repo:"",project:"",branch:"main",contentDir:"content"},i6=t=>t==="sqlite-file"||t==="markdown-git"||t==="local";function a3e(){return`${A0()||"admin"}/data/cms.sqlite`}function o3e(t){return t instanceof Wn?{kind:t.kind,detail:t.detail}:{kind:"generic",detail:t instanceof Error?t.message:String(t)}}function l3e(t,e,n){const r=(s,i={})=>{const a=IN(s);return{connectorId:a.connectorId,settings:{...a.preset,...i}}};return t==="sqlite-file"||t==="firebase"?r("flexweg",{apiKey:e.flexwegApiKey,siteUrl:e.flexwegSiteUrl,apiBaseUrl:e.flexwegApiBaseUrl||io}):t==="markdown-git"&&n.provider==="github"?r("github-pages",{owner:n.owner}):t==="markdown-git"&&n.provider==="gitlab"?r("gitlab-pages"):r("zip")}function c3e(){const{t}=Fe(),[e,n]=U.useState("terms"),[r,s]=U.useState("sqlite-file"),[i,a]=U.useState(a3e),[o,l]=U.useState(!1),[c,h]=U.useState(!0),[p,m]=U.useState(Uv),[g,y]=U.useState(!1),[x,v]=U.useState(()=>{const Re=IN("s3");return{connectorId:Re.connectorId,settings:{...Re.preset}}}),[k,C]=U.useState(!0),[N,_]=U.useState(NN),[P,D]=U.useState(!1);U.useEffect(()=>{jN().then(Re=>D(!!Re))},[]);const[I,L]=U.useState(!1),[j,q]=U.useState(s3e),[V,O]=U.useState(i3e),[$,B]=U.useState(""),[X,fe]=U.useState(null),[ie,ae]=U.useState(null),[ue,ve]=U.useState(null),[K,ee]=U.useState(!1),[xe,_e]=U.useState(null),[ge,He]=U.useState([]),[Ye,Se]=U.useState(null),[we,rt]=U.useState(null);function lt(Re,Be){q(st=>({...st,[Re]:Be}))}function Dt(){return{...j,apiKey:j.apiKey.trim(),authDomain:j.authDomain.trim(),projectId:j.projectId.trim(),storageBucket:j.storageBucket.trim(),messagingSenderId:j.messagingSenderId.trim(),appId:j.appId.trim(),adminEmail:j.adminEmail.trim().toLowerCase(),flexwegApiKey:j.flexwegApiKey.trim(),flexwegSiteUrl:j.flexwegSiteUrl.trim().replace(/\/+$/,""),flexwegApiBaseUrl:j.flexwegApiBaseUrl.trim().replace(/\/+$/,"")||io,sqlitePath:j.sqlitePath.trim().replace(/^\/+|\/+$/g,"")}}const je={step:Re=>_e(Re),done:Re=>He(Be=>[...Be,Re])};async function z(Re){ee(!0),Se(null);try{await Re()}catch(Be){Se(o3e(Be))}finally{ee(!1),_e(null)}}function ce(){z(async()=>{const Re=Dt();let Be=null;r==="firebase"?(_e(t("setup.steps.signInFirebase")),await GPe(Re,t)):r==="markdown-git"&&(_e(t("setup.docstore.checking")),Be=await JPe(V,$,t)),ve(Be),Be?(fe(Be),ae(r)):(!X||ie!==r)&&(fe(l3e(r,Re,V)),ae(r)),n("hosting")})}function le(){X&&z(async()=>{if(X.connectorId!=="browser-mirror"){_e(t("setup.docstore.steps.testTarget"));const Be=r==="markdown-git"&&X.connectorId==="git-pages"&&X.settings.provider===V.provider&&!X.settings.token?{...X.settings,token:$}:X.settings,st=await l1(X.connectorId,Be);if(!st.ok)throw new Wn("generic",`${t("connectors.testFailed")} — ${st.detail}`)}if(Z)await KPe(be(),t);else if(r==="sqlite-file"){if(c&&p.trim().length<12)throw new Wn("generic",t("setup.sqliteFile.passphraseTooShort"));L(await QPe(re(X),i,t,c?p:null))}n("install")})}function Y(){X&&(He([]),z(async()=>{const Re=Dt(),Be=ue&&X===ue?null:X,st={hostAdminFolder:he&&k?N:null},ot=r==="firebase"?await XPe(Re,X,je,t,st):Z?await ZPe(be(),X,je,t,st):await YPe(r==="sqlite-file"?{backend:r,location:re(X),path:i,passphrase:c?p:null}:r==="markdown-git"?{backend:r,git:V,token:$}:{backend:"local"},Be,je,t,{...st,reusedTarget:X});rt(ot),ot.configUploaded&&!ot.adminUrl&&window.setTimeout(TC,2e3)}))}const Z=r==="sqlite-file"&&o&&(X==null?void 0:X.connectorId)==="flexweg";function re(Re){return g?x:zPe(Re)}function be(){const Re=(X==null?void 0:X.settings)??{};return{...Dt(),flexwegApiKey:String(Re.apiKey??"").trim(),flexwegSiteUrl:String(Re.siteUrl??"").trim().replace(/\/+$/,""),flexwegApiBaseUrl:String(Re.apiBaseUrl??"").trim().replace(/\/+$/,"")||io}}const Te=X?tk(X):null,he=P&&!!X&&X.connectorId!=="flexweg"&&X.connectorId!=="browser-mirror"&&!Te,Me=K&&e==="install",$e=!!we;return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950 overflow-hidden",children:[d.jsxs("div",{className:"flexweg-blobs","aria-hidden":"true",children:[d.jsx("div",{className:"flexweg-blob flexweg-blob-1"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-2"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-3"})]}),d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),(Me||(we==null?void 0:we.configUploaded)&&!we.adminUrl)&&el.createPortal(d.jsx(x3e,{step:xe,progressLog:ge,done:!!(we!=null&&we.configUploaded)}),document.body),d.jsxs("div",{className:"w-full max-w-2xl relative z-10",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"AgentCMS",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{className:"text-center",children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("setup.title")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:t("setup.subtitle")})]})]}),d.jsx(u3e,{currentStep:e}),e==="terms"?d.jsx(y3e,{onAccept:()=>n("data")}):e==="data"?d.jsxs(yE,{title:t("setup.data.title"),intro:t("setup.data.intro"),error:Ye,busy:K,busyLabel:xe,onBack:()=>{Se(null),n("terms")},onContinue:ce,children:[d.jsx(h3e,{value:r,onChange:Re=>{Se(null),s(Re)}}),d.jsx("div",{className:"border-t border-surface-200 pt-5 dark:border-surface-700",children:r==="firebase"?d.jsx(f3e,{form:j,patch:lt}):r==="sqlite-file"?d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:t("setup.sqliteFile.dataNote")}):r==="markdown-git"?d.jsx(m3e,{git:V,setGit:O,token:$,setToken:B}):d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:t("setup.data.localNote")})})]}):e==="hosting"?d.jsxs(yE,{title:t("setup.hosting.title"),intro:t("setup.hosting.intro"),error:Ye,busy:K,busyLabel:xe,onBack:()=>{Se(null),n("data")},onContinue:le,children:[ue&&X===ue&&d.jsx("p",{className:"rounded-lg bg-emerald-50 ring-1 ring-emerald-200 px-3 py-2 text-sm text-emerald-800 dark:bg-emerald-900/20 dark:ring-emerald-700/40 dark:text-emerald-200",children:t("setup.hosting.existing")}),X&&d.jsx(Y1,{value:X,onChange:fe,picker:"cards",exclude:r==="sqlite-file"?["zip"]:[]}),r==="sqlite-file"&&X&&d.jsx(p3e,{onFlexweg:X.connectorId==="flexweg",onGit:X.connectorId==="git-pages",useService:Z,setUseService:l,path:i,setPath:a,form:j,patch:lt,encrypt:c,setEncrypt:h,passphrase:p,setPassphrase:m,separate:g,setSeparate:y,location:x,setLocation:v})]}):we?d.jsx(g3e,{result:we}):d.jsxs(yE,{title:t("setup.install.title"),intro:t("setup.install.intro"),error:Ye,busy:K,busyLabel:null,onBack:()=>{Se(null),n("hosting")},onContinue:Y,continueLabel:t("setup.docstore.install"),children:[d.jsxs("dl",{className:"grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-sm",children:[d.jsx("dt",{className:"text-surface-500",children:t("setup.install.data")}),d.jsxs("dd",{className:"font-medium",children:[t(`setup.data.options.${r}.title`),r==="sqlite-file"&&d.jsx("span",{className:"block text-xs font-normal text-surface-500 break-all",children:Z?t("setup.sqliteFile.summaryService",{path:j.sqlitePath}):[t("setup.sqliteFile.summaryFile",{path:i}),t(I?"setup.sqliteFile.existing":"setup.sqliteFile.new"),c?t("setup.sqliteFile.summaryEncrypted"):null,g?t("setup.sqliteFile.summaryLocation",{location:t(`hosting.${uw(x.connectorId,x.settings).id}.title`)}):(X==null?void 0:X.connectorId)==="git-pages"?t("setup.sqliteFile.summaryBranch",{branch:LN}):null].filter(Boolean).join(" · ")})]}),d.jsx("dt",{className:"text-surface-500",children:t("setup.install.hosting")}),d.jsxs("dd",{className:"font-medium",children:[X?t(`hosting.${uw(X.connectorId,X.settings).id}.title`):"—",typeof(X==null?void 0:X.settings.siteUrl)=="string"&&X.settings.siteUrl&&d.jsx("span",{className:"block text-xs font-normal text-surface-500 break-all",children:X.settings.siteUrl})]})]}),he&&X&&d.jsxs("fieldset",{className:"space-y-2 border-t border-surface-200 pt-4 dark:border-surface-700",children:[d.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",className:"mt-1",checked:k,onChange:Re=>C(Re.target.checked)}),d.jsxs("span",{children:[d.jsx("span",{className:"font-medium",children:t("setup.adminHosting.label")}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400",children:t("setup.adminHosting.hint",{url:RN(X,N)??`…/${N}/`})})]})]}),k&&d.jsx(Er,{label:t("setup.adminHosting.folder"),value:N,onChange:_,required:!0})]}),Te?d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:t("setup.adminHosting.alreadyHere")}):!(he&&k)&&d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:t(i6(r)?"setup.install.noteLocalConfig":"setup.install.noteConfigJs")})]}),!$e&&d.jsx("p",{className:"text-[11px] text-surface-400 text-center mt-4 dark:text-surface-500",children:t(i6(r)?"setup.docstore.footer":"setup.footer")})]})]})}function u3e({currentStep:t}){const{t:e}=Fe(),n=[{id:"terms",label:e("setup.stepper.terms")},{id:"data",label:e("setup.stepper.data")},{id:"hosting",label:e("setup.stepper.hosting")},{id:"install",label:e("setup.stepper.install")}],r=n.findIndex(s=>s.id===t);return d.jsx("div",{className:"flex items-center justify-center gap-3 mb-6 flex-wrap",children:n.map((s,i)=>{const a=i===r,o=i<r;return d.jsxs("div",{className:"flex items-center gap-3",children:[d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsx("div",{className:"h-6 w-6 rounded-full flex items-center justify-center text-[11px] font-semibold transition-colors "+(o?"bg-emerald-500 text-white":a?"bg-blue-600 text-white":"bg-surface-200 text-surface-500 dark:bg-surface-800 dark:text-surface-400"),children:o?d.jsx(Gs,{className:"h-3.5 w-3.5"}):i+1}),d.jsx("span",{className:"text-xs font-medium "+(a?"text-surface-900 dark:text-surface-50":"text-surface-500 dark:text-surface-400"),children:s.label})]}),i<n.length-1&&d.jsx("div",{className:"h-px w-8 transition-colors "+(o?"bg-emerald-500":"bg-surface-300 dark:bg-surface-700")})]},s.id)})})}function yE({title:t,intro:e,error:n,busy:r,busyLabel:s,onBack:i,onContinue:a,continueLabel:o,children:l}){const{t:c}=Fe();return d.jsxs("div",{className:"card p-6",children:[d.jsx("h2",{className:"text-lg font-semibold text-surface-900 dark:text-surface-50",children:t}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300 mt-2",children:e}),d.jsxs("form",{className:"mt-5 space-y-5","data-form-type":"other",onSubmit:h=>{h.preventDefault(),r||a()},children:[l,d.jsx("div",{"aria-live":"polite","aria-atomic":"true",children:n?d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm break-words dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:d.jsx(v3e,{error:n})}):r&&s?d.jsxs("p",{className:"flex items-center gap-2 text-sm text-surface-600 dark:text-surface-300",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin"}),s]}):null}),d.jsxs("div",{className:"flex flex-col sm:flex-row gap-3",children:[d.jsx("button",{type:"button",onClick:i,className:"btn-secondary flex-1 justify-center",disabled:r,children:c("common.back")}),d.jsx("button",{type:"submit",className:"btn-primary flex-1 justify-center",disabled:r,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(r?"":"hidden")}),d.jsx("span",{children:o??c("setup.backend.continue")}),d.jsx(jC,{className:"h-4 w-4 "+(r||o?"hidden":"")})]})})]})]})]})}const d3e=[{id:"sqlite-file",icon:dg},{id:"markdown-git",icon:Nm},{id:"firebase",icon:N6},{id:"local",icon:LC}];function h3e({value:t,onChange:e}){const{t:n}=Fe();return d.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:d3e.map(({id:r,icon:s})=>d.jsxs("label",{className:"flex items-start gap-3 p-3 rounded-lg ring-1 ring-inset cursor-pointer transition-colors "+(t===r?"ring-blue-500 bg-blue-50/60 dark:ring-blue-400 dark:bg-blue-900/20":"ring-surface-200 hover:bg-surface-50 dark:ring-surface-700 dark:hover:bg-surface-800/60"),children:[d.jsx("input",{type:"radio",name:"backend",checked:t===r,onChange:()=>e(r),className:"mt-1"}),d.jsxs("span",{className:"flex-1 min-w-0",children:[d.jsxs("span",{className:"text-sm font-semibold flex items-center gap-1.5",children:[d.jsx(s,{className:"h-4 w-4 text-surface-500"}),n(`setup.data.options.${r}.title`)]}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400 mt-1 leading-relaxed",children:n(`setup.data.options.${r}.hint`)})]})]},r))})}function f3e({form:t,patch:e}){const{t:n}=Fe();return d.jsxs("div",{className:"space-y-6",children:[d.jsxs("fieldset",{className:"space-y-4",children:[d.jsx("legend",{className:"text-sm font-semibold text-surface-900 dark:text-surface-50",children:n("setup.sections.firebase")}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:n("setup.help.firebase")}),d.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[d.jsx(Er,{label:n("setup.fields.apiKey"),value:t.apiKey,onChange:r=>e("apiKey",r),required:!0}),d.jsx(Er,{label:n("setup.fields.authDomain"),placeholder:"your-project.firebaseapp.com",value:t.authDomain,onChange:r=>e("authDomain",r),required:!0}),d.jsx(Er,{label:n("setup.fields.projectId"),placeholder:"your-project",value:t.projectId,onChange:r=>e("projectId",r),required:!0}),d.jsx(Er,{label:n("setup.fields.storageBucket"),placeholder:"your-project.appspot.com",value:t.storageBucket,onChange:r=>e("storageBucket",r),required:!0}),d.jsx(Er,{label:n("setup.fields.messagingSenderId"),value:t.messagingSenderId,onChange:r=>e("messagingSenderId",r),required:!0}),d.jsx(Er,{label:n("setup.fields.appId"),value:t.appId,onChange:r=>e("appId",r),required:!0})]})]}),d.jsxs("fieldset",{className:"space-y-4",children:[d.jsx("legend",{className:"text-sm font-semibold text-surface-900 dark:text-surface-50",children:n("setup.sections.admin")}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:n("setup.help.admin")}),d.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[d.jsx(Er,{type:"email",label:n("setup.fields.adminEmail"),placeholder:"you@company.com",value:t.adminEmail,onChange:r=>e("adminEmail",r),required:!0,autoComplete:"email"}),d.jsx(Er,{type:"password",label:n("setup.fields.adminPassword"),placeholder:"••••••••",value:t.adminPassword,onChange:r=>e("adminPassword",r),required:!0,autoComplete:"current-password"})]})]})]})}function p3e({onFlexweg:t,onGit:e,useService:n,setUseService:r,path:s,setPath:i,form:a,patch:o,encrypt:l,setEncrypt:c,passphrase:h,setPassphrase:p,separate:m,setSeparate:g,location:y,setLocation:x}){const{t:v}=Fe(),[k,C]=U.useState(!1);return d.jsxs("fieldset",{className:"space-y-3 border-t border-surface-200 pt-5 dark:border-surface-700",children:[d.jsx("legend",{className:"text-sm font-semibold text-surface-900 dark:text-surface-50",children:v("setup.sqliteFile.heading")}),t&&d.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",className:"mt-1",checked:n,onChange:N=>r(N.target.checked)}),d.jsxs("span",{children:[d.jsx("span",{className:"font-medium",children:v("setup.sqliteFile.flexwegService")}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400",children:v("setup.sqliteFile.flexwegServiceHint")})]})]}),n?d.jsxs(d.Fragment,{children:[d.jsxs("div",{children:[d.jsx(Er,{label:v("setup.fields.sqlitePath"),placeholder:"admin/cms.sqlite",value:a.sqlitePath,onChange:N=>o("sqlitePath",N),required:!0}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400 mt-1",children:v("setup.sqlite.pathHint")})]}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:v("setup.sqlite.adminIntro")}),d.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[d.jsx(Er,{type:"email",label:v("setup.fields.adminEmail"),placeholder:"you@company.com",value:a.adminEmail,onChange:N=>o("adminEmail",N),required:!0,autoComplete:"email"}),d.jsx(Er,{type:"password",label:v("setup.fields.adminPassword"),placeholder:"••••••••",value:a.adminPassword,onChange:N=>o("adminPassword",N),required:!0,autoComplete:"new-password"})]}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400",children:v("setup.sqlite.passwordHint")})]}):d.jsxs(d.Fragment,{children:[d.jsx("div",{className:"rounded-lg bg-amber-50 text-amber-800 ring-1 ring-amber-200 px-3 py-2 text-xs leading-relaxed dark:bg-amber-900/30 dark:text-amber-200 dark:ring-amber-700/50",children:v("setup.sqliteFile.security")}),d.jsxs("div",{children:[d.jsx(Er,{label:v("setup.sqliteFile.path"),value:s,onChange:i,required:!0,placeholder:"admin/data/cms.sqlite"}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400 mt-1",children:e&&!m?v("setup.sqliteFile.gitBranchNote",{branch:LN}):v("setup.sqliteFile.pathHint")})]}),d.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",className:"mt-1",checked:l,onChange:N=>c(N.target.checked)}),d.jsxs("span",{children:[d.jsx("span",{className:"font-medium",children:v("setup.sqliteFile.encrypt")}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400",children:v("setup.sqliteFile.encryptHint")})]})]}),l&&d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"sqlite-passphrase",children:v("setup.sqliteFile.passphrase")}),d.jsxs("div",{className:"flex gap-2",children:[d.jsx("input",{id:"sqlite-passphrase",className:"input font-mono text-xs",autoComplete:"off",spellCheck:!1,value:h,onChange:N=>{p(N.target.value),C(!1)},required:!0}),d.jsx("button",{type:"button",className:"btn-secondary shrink-0",onClick:()=>{var N;(N=navigator.clipboard)==null||N.writeText(h).then(()=>C(!0))},children:d.jsx("span",{children:v(k?"setup.sqliteFile.copied":"setup.sqliteFile.copy")})}),d.jsx("button",{type:"button",className:"btn-secondary shrink-0",onClick:()=>{p(Uv()),C(!1)},children:d.jsx("span",{children:v("setup.sqliteFile.generate")})})]}),d.jsx("p",{className:"text-[11px] text-amber-700 dark:text-amber-300 mt-1",children:v("setup.sqliteFile.passphraseHint")})]}),d.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[d.jsx("input",{type:"checkbox",className:"mt-1",checked:m,onChange:N=>g(N.target.checked)}),d.jsxs("span",{children:[d.jsx("span",{className:"font-medium",children:v("setup.sqliteFile.separate")}),d.jsx("span",{className:"block text-xs text-surface-500 dark:text-surface-400",children:v("setup.sqliteFile.separateHint")})]})]}),m&&d.jsx(Y1,{value:y,onChange:x,exclude:["zip","flexweg"],pickerLabel:v("setup.sqliteFile.locationLabel"),hideFields:["siteUrl","publicRead"],testIgnore:["siteUrl"]})]})]})}function m3e({git:t,setGit:e,token:n,setToken:r}){const{t:s}=Fe(),[i,a]=U.useState(null),o=c=>e({...t,...c});async function l(){const c=await ZA();await YA(Ig,c),a(c.name)}return d.jsxs("div",{className:"space-y-3",children:[d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:s("setup.docstore.contentIntro")}),d.jsxs("div",{children:[d.jsx("label",{className:"label",children:s("connectors.fields.git-pages.provider")}),d.jsxs("select",{className:"input",value:t.provider,onChange:c=>o({provider:c.target.value}),children:[d.jsx("option",{value:"github",children:"GitHub"}),d.jsx("option",{value:"gitlab",children:"GitLab"}),d.jsx("option",{value:"local",disabled:!Fv(),children:s("setup.docstore.localClone")})]})]}),t.provider==="github"&&d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsx(Er,{label:s("connectors.fields.git-pages.owner"),value:t.owner??"",onChange:c=>o({owner:c}),required:!0}),d.jsx(Er,{label:s("connectors.fields.git-pages.repo"),value:t.repo??"",onChange:c=>o({repo:c}),required:!0})]}),t.provider==="gitlab"&&d.jsx(Er,{label:s("connectors.fields.git-pages.project"),placeholder:"group/my-content",value:t.project??"",onChange:c=>o({project:c}),required:!0}),t.provider!=="local"?d.jsxs(d.Fragment,{children:[d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsx(Er,{label:s("connectors.fields.git-pages.branch"),value:t.branch,onChange:c=>o({branch:c}),required:!0}),d.jsx(Er,{label:s("setup.docstore.contentDir"),value:t.contentDir,onChange:c=>o({contentDir:c})})]}),d.jsxs("div",{children:[d.jsx(Er,{label:s("gitAccess.token"),type:"password",value:n,onChange:r,required:!0,autoComplete:"off"}),d.jsxs("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:[s(t.provider==="github"?"gitAccess.tokenHelpGithub":"gitAccess.tokenHelpGitlab")," ",s("setup.docstore.privateRepo")]})]}),d.jsx(Er,{label:s("connectors.fields.git-pages.apiBaseUrl"),value:t.apiBaseUrl??"",onChange:c=>o({apiBaseUrl:c})})]}):d.jsxs("div",{className:"space-y-2",children:[d.jsx(Er,{label:s("setup.docstore.contentDir"),value:t.contentDir,onChange:c=>o({contentDir:c})}),d.jsx("button",{type:"button",className:"btn-secondary",onClick:l,children:d.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[d.jsx(Wf,{className:"h-4 w-4"}),d.jsx("span",{children:i??s("connectors.folder.choose")})]})}),d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400",children:s("setup.docstore.localCloneHint")})]})]})}function g3e({result:t}){const{t:e}=Fe();return t.adminUrl?d.jsxs("div",{className:"card p-6 space-y-4",children:[d.jsxs("p",{className:"flex items-center gap-2 text-base font-semibold text-emerald-700 dark:text-emerald-400",children:[d.jsx(Gs,{className:"h-5 w-5"}),e("setup.docstore.doneTitle")]}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:e("setup.adminHosting.doneBody")}),d.jsx("a",{className:"btn-primary w-full justify-center",href:t.adminUrl,target:"_blank",rel:"noopener noreferrer",children:e("setup.adminHosting.open",{url:t.adminUrl})}),d.jsx("button",{type:"button",className:"btn-secondary w-full justify-center",onClick:TC,children:e("setup.adminHosting.continueHere")})]}):t.configUploaded?null:d.jsxs("div",{className:"card p-6 space-y-4",children:[d.jsxs("p",{className:"flex items-center gap-2 text-base font-semibold text-emerald-700 dark:text-emerald-400",children:[d.jsx(Gs,{className:"h-5 w-5"}),e("setup.docstore.doneTitle")]}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:e("setup.docstore.doneBody")}),d.jsx("button",{type:"button",className:"btn-secondary w-full justify-center",onClick:()=>e3e(t.runtime),children:d.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[d.jsx(yw,{className:"h-4 w-4"}),d.jsx("span",{children:e("setup.docstore.downloadConfig")})]})}),d.jsx("button",{type:"button",className:"btn-primary w-full justify-center",onClick:TC,children:e("setup.docstore.open")})]})}const b3e=7;function y3e({onAccept:t}){const{t:e}=Fe(),[n,r]=U.useState(!1);return d.jsxs("div",{className:"card p-6",children:[d.jsx("h2",{className:"text-lg font-semibold text-surface-900 dark:text-surface-50",children:e("setup.terms.title")}),d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300 mt-3",children:e("setup.terms.intro")}),d.jsx("div",{className:"mt-5 max-h-80 overflow-y-auto pr-2 space-y-4 rounded-lg border border-surface-200 bg-surface-50 p-4 dark:border-surface-700 dark:bg-surface-900/40",children:Array.from({length:b3e},(s,i)=>i+1).map(s=>d.jsxs("section",{children:[d.jsx("h3",{className:"text-sm font-semibold text-surface-900 dark:text-surface-50",children:e(`setup.terms.section${s}.title`)}),d.jsx("p",{className:"text-xs text-surface-600 dark:text-surface-300 mt-1.5 leading-relaxed",children:e(`setup.terms.section${s}.body`)})]},s))}),d.jsxs("label",{className:"mt-5 flex items-start gap-2.5 cursor-pointer",children:[d.jsx("input",{type:"checkbox",className:"mt-0.5 h-4 w-4 rounded border-surface-300 text-blue-600 focus:ring-blue-500 dark:border-surface-600 dark:bg-surface-800",checked:n,onChange:s=>r(s.target.checked)}),d.jsx("span",{className:"text-sm text-surface-700 dark:text-surface-200",children:e("setup.terms.accept")})]}),d.jsx("div",{className:"mt-6 flex justify-end",children:d.jsx("button",{type:"button",onClick:t,disabled:!n,className:"btn-primary justify-center",children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx("span",{children:e("setup.terms.continue")}),d.jsx(jC,{className:"h-4 w-4"})]})})})]})}function Er({label:t,value:e,onChange:n,placeholder:r,required:s,type:i="text",autoComplete:a,autoFocus:o}){return d.jsxs("div",{children:[d.jsx("label",{className:"label",children:t}),d.jsx("input",{type:i,className:"input",value:e,onChange:l=>n(l.target.value),placeholder:r,required:s,autoComplete:a,autoFocus:o})]})}function v3e({error:t}){const{t:e}=Fe();switch(t.kind){case"missingFields":return d.jsx("span",{children:e("setup.errors.missingFields")});case"rootDeployment":return d.jsxs("div",{className:"space-y-1.5",children:[d.jsx("p",{children:e("setup.errors.rootDeploymentTitle")}),d.jsx("p",{className:"text-xs",children:e("setup.errors.rootDeploymentHint")})]});case"firebaseAuth":return d.jsx("span",{children:t.detail??e("setup.errors.firebaseAuthGeneric")});case"firebaseAuthInvalidCredential":return d.jsxs("div",{className:"space-y-1.5",children:[d.jsx("p",{children:e("setup.errors.firebaseAuthInvalidCredential")}),d.jsx("p",{className:"text-xs whitespace-pre-line leading-relaxed",children:e("setup.errors.firebaseAuthInvalidCredentialHint")})]});case"wrongAdminEmail":return d.jsx("span",{children:e("setup.errors.wrongAdminEmail")});case"rulesNotPinned":return d.jsxs("div",{className:"space-y-1.5",children:[d.jsx("p",{children:e("setup.errors.rulesNotPinnedTitle")}),d.jsx("p",{className:"text-xs leading-relaxed",children:e("setup.errors.rulesNotPinnedHint",{email:t.detail??""})})]});case"flexwegAuth":return d.jsx("span",{children:e("setup.errors.flexwegAuth")});case"flexwegNetwork":return d.jsx("span",{children:e("setup.errors.flexwegNetwork")});case"firestoreRules":return d.jsxs("div",{className:"space-y-1.5",children:[d.jsx("p",{children:e("setup.errors.firestoreRulesTitle")}),d.jsx("p",{className:"text-xs",children:e("setup.errors.firestoreRulesHint",{email:t.detail})})]});case"firestoreOther":return d.jsxs("span",{children:[e("setup.errors.firestoreOther"),": ",t.detail]});case"uploadFailed":return d.jsxs("span",{children:[e("setup.errors.uploadFailed"),t.detail?`: ${t.detail}`:""]});case"generic":default:return d.jsx("span",{children:t.detail??e("setup.errors.generic")})}}function x3e({step:t,progressLog:e,done:n}){const{t:r}=Fe();return d.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-surface-950/80 backdrop-blur-sm p-6",children:d.jsxs("div",{className:"card w-full max-w-md p-6 text-center",children:[n?d.jsx(Gs,{className:"h-10 w-10 text-emerald-500 mx-auto mb-4"}):d.jsx(ct,{className:"h-10 w-10 text-blue-500 mx-auto mb-4 animate-spin"}),d.jsx("h2",{className:"text-lg font-semibold text-surface-900 dark:text-surface-50",children:r(n?"setup.success":"setup.submitting")}),!n&&t&&d.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300 mt-2",children:t}),e.length>0&&d.jsx("ul",{className:"mt-5 space-y-1.5 text-left",children:e.map((s,i)=>d.jsxs("li",{className:"flex items-start gap-2 text-xs text-surface-500 dark:text-surface-400",children:[d.jsx(Gs,{className:"h-3.5 w-3.5 text-emerald-500 shrink-0 mt-0.5"}),d.jsx("span",{children:s})]},i))}),n&&d.jsx("p",{className:"text-xs text-surface-500 dark:text-surface-400 mt-4",children:r("setup.reloadingHint")})]})})}const w3e={github:"https://github.com/settings/personal-access-tokens/new",gitlab:"https://gitlab.com/-/user_settings/personal_access_tokens?scopes=api&name=Flexweg%20CMS"};function EH(){const t=Ct();bae(t)&&t.resetSession()}function k3e(){const t=ra();if((t==null?void 0:t.backend)==="sqlite-file"){tC(()=>{dT({}),Ct().resetSession()});return}(t==null?void 0:t.backend)==="markdown-git"&&tC(()=>{t.git.provider!=="local"&&rT(t.git,null),EH()})}function S3e(){const{t}=Fe(),e=ra(),n=(e==null?void 0:e.backend)==="markdown-git"?e.git:null,[r,s]=U.useState(()=>n?nT(n)??"":""),[i,a]=U.useState(!1),[o,l]=U.useState(null);if(!n)return null;const c=n.provider==="github"?`${n.owner}/${n.repo}`:n.provider==="gitlab"?n.project:"";async function h(){EH(),await WI(),await Ct().identity()||l(t("gitAccess.failed"))}async function p(g){if(g.preventDefault(),!(!n||!r.trim())){a(!0),l(null);try{rT(n,r),await h()}finally{a(!1)}}}async function m(){a(!0),l(null);try{let g=await Cf(Ig);(!g||!await _0(g,!0))&&(g=await ZA(),await YA(Ig,g)),await h()}catch(g){g.name!=="AbortError"&&l(g.message)}finally{a(!1)}}return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950 overflow-hidden",children:[d.jsxs("div",{className:"flexweg-blobs","aria-hidden":"true",children:[d.jsx("div",{className:"flexweg-blob flexweg-blob-1"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-2"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-3"})]}),d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),d.jsxs("div",{className:"w-full max-w-sm relative z-10",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"AgentCMS",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("identity.brandTitle")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:t("identity.brandSubtitle")})]})]}),d.jsxs("div",{className:"card p-6",children:[d.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-surface-50",children:t("gitAccess.heading")}),n.provider==="local"?d.jsxs(d.Fragment,{children:[d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("gitAccess.folderIntro")}),!Fv()&&d.jsx("p",{className:"text-xs text-amber-600 mt-3",children:t("connectors.folder.unsupported")}),o&&d.jsx("div",{className:"mt-4 rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:o}),d.jsx("button",{type:"button",className:"btn-primary w-full justify-center mt-5",onClick:m,disabled:i||!Fv(),children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx(Wf,{className:"h-4 w-4 "+(i?"hidden":"")}),d.jsx("span",{children:t("gitAccess.openFolder")})]})})]}):d.jsxs(d.Fragment,{children:[d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("gitAccess.tokenIntro",{repo:c,provider:n.provider==="github"?"GitHub":"GitLab"})}),d.jsxs("form",{onSubmit:p,className:"mt-5 space-y-4","data-form-type":"other",children:[d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"git-token",children:t("gitAccess.token")}),d.jsx("input",{id:"git-token",type:"password",className:"input font-mono",value:r,onChange:g=>s(g.target.value),autoComplete:"off",autoFocus:!0,required:!0}),d.jsxs("p",{className:"text-xs text-surface-500 mt-1 dark:text-surface-400",children:[t(n.provider==="github"?"gitAccess.tokenHelpGithub":"gitAccess.tokenHelpGitlab")," ",d.jsxs("a",{href:w3e[n.provider],target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-0.5 text-blue-600 hover:underline dark:text-blue-400",children:[t("gitAccess.createToken"),d.jsx(vw,{className:"h-3 w-3"})]})]})]}),o&&d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:o}),d.jsx("button",{type:"submit",className:"btn-primary w-full justify-center",disabled:i||!r.trim(),children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(i?"":"hidden")}),d.jsx("span",{children:t("gitAccess.connect")})]})}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400",children:t("gitAccess.tokenStorage")})]})]})]})]})]})}function E3e(){var y;const{t}=Fe(),e=ra(),n=(e==null?void 0:e.backend)==="sqlite-file"?e.sqlite:null,[r,s]=U.useState(()=>n?{connectorId:n.connectorId,settings:o_(n)}:{connectorId:"",settings:{}}),i=Ct(),[a,o]=U.useState(()=>wm()??""),[l,c]=U.useState(!1),[h,p]=U.useState(()=>{var x;return((x=i.passphraseProblem)==null?void 0:x.call(i))==="wrong"?t("sqliteAccess.passphraseWrong"):null});if(!n)return null;const m=!!n.encrypted||((y=i.passphraseProblem)==null?void 0:y.call(i))!=null;async function g(){c(!0),p(null);try{const x=await l1(r.connectorId,r.settings,{ignore:["siteUrl"]});if(!x.ok){p(`${t("connectors.testFailed")} — ${x.detail}`);return}dT(g8(r.settings).secrets),m&&qv(a.trim()||null),i.resetSession(),await WI();const v=i.passphraseProblem();v&&p(t(v==="wrong"?"sqliteAccess.passphraseWrong":"sqliteAccess.passphraseMissing"))}finally{c(!1)}}return d.jsxs("div",{className:"relative min-h-full flex items-center justify-center p-6 bg-surface-50 dark:bg-surface-950 overflow-hidden",children:[d.jsxs("div",{className:"flexweg-blobs","aria-hidden":"true",children:[d.jsx("div",{className:"flexweg-blob flexweg-blob-1"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-2"}),d.jsx("div",{className:"flexweg-blob flexweg-blob-3"})]}),d.jsx("div",{className:"absolute top-4 right-4 z-10",children:d.jsx(xp,{})}),d.jsxs("div",{className:"w-full max-w-md relative z-10",children:[d.jsxs("div",{className:"flex items-center gap-2.5 justify-center mb-6",children:[d.jsx("img",{src:ah,alt:"AgentCMS",className:"h-10 w-10 rounded-xl shadow-card object-cover"}),d.jsxs("div",{children:[d.jsx("p",{className:"text-base font-semibold leading-none",children:t("identity.brandTitle")}),d.jsx("p",{className:"text-[11px] text-surface-500 mt-0.5 dark:text-surface-400",children:t("identity.brandSubtitle")})]})]}),d.jsxs("div",{className:"card p-6",children:[d.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-surface-50",children:t("sqliteAccess.heading")}),d.jsx("p",{className:"text-sm text-surface-500 mt-1 dark:text-surface-400",children:t("sqliteAccess.intro",{path:n.path})}),d.jsxs("form",{className:"mt-5 space-y-4","data-form-type":"other",onSubmit:x=>{x.preventDefault(),l||g()},children:[d.jsx(Y1,{value:r,onChange:s,lockHosting:!0,hideFields:["siteUrl"],testIgnore:["siteUrl"]}),m&&d.jsxs("div",{children:[d.jsx("label",{className:"label",htmlFor:"sqlite-passphrase",children:t("sqliteAccess.passphrase")}),d.jsx("input",{id:"sqlite-passphrase",type:"password",className:"input",autoComplete:"current-password",value:a,onChange:x=>o(x.target.value),required:!0}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400 mt-1",children:t("sqliteAccess.passphraseHint")})]}),h&&d.jsx("div",{className:"rounded-lg bg-red-50 text-red-700 ring-1 ring-red-200 px-3 py-2 text-sm break-words dark:bg-red-900/30 dark:text-red-300 dark:ring-red-700/50",children:h}),d.jsx("button",{type:"submit",className:"btn-primary w-full justify-center",disabled:l,children:d.jsxs("span",{className:"inline-flex items-center justify-center gap-1.5",children:[d.jsx(ct,{className:"h-4 w-4 animate-spin "+(l?"":"hidden")}),d.jsx("span",{children:t("gitAccess.connect")})]})}),d.jsx("p",{className:"text-[11px] text-surface-500 dark:text-surface-400",children:t("sqliteAccess.storage")})]})]})]})]})}const _3e=[/Node\.insertBefore/i,/Node\.removeChild/i,/Node\.appendChild/i,/failed to execute 'insertBefore'/i,/failed to execute 'removeChild'/i],a6=3,C3e=5e3,A3e=80;function T3e(t){return t!=null&&t.message?_3e.some(e=>e.test(t.message)):!1}class o6 extends U.Component{constructor(n){super(n);Pn(this,"resetTimer",null);this.state={error:null,recovering:!1,resetCount:0,lastErrorAt:0}}static getDerivedStateFromError(n){return{error:n,lastErrorAt:Date.now()}}componentDidCatch(n,r){if(console.error("App error:",n,r),!T3e(n))return;const a=Date.now()-this.state.lastErrorAt<C3e?this.state.resetCount+1:1;if(a>a6){console.warn(`[AppErrorBoundary] giving up after ${a6} retries`);return}this.setState({resetCount:a,recovering:!0}),this.resetTimer=setTimeout(()=>{this.setState({error:null,recovering:!1})},A3e)}componentWillUnmount(){this.resetTimer&&clearTimeout(this.resetTimer)}render(){return this.state.error?this.state.recovering?d.jsx("div",{className:"min-h-full bg-surface-50 dark:bg-surface-950","aria-hidden":!0}):d.jsx(fC,{message:this.state.error.message}):this.props.children}}function _H(){return d.jsx("div",{className:"min-h-full flex items-center justify-center",children:d.jsx(ct,{className:"h-5 w-5 animate-spin text-surface-400"})})}function I3e({children:t}){const{isAdmin:e}=co();return d.jsx(d.Fragment,{children:e?t:d.jsx(fd,{to:"/dashboard",replace:!0})})}function N3e(){const{t}=Fe(),{user:e,loading:n,disabled:r,error:s}=co();if(n)return d.jsx(_H,{});if(!e){const i=$r();return i==="flexweg-sqlite"?d.jsx(TEe,{}):i==="markdown-git"?d.jsx(S3e,{}):i==="sqlite-file"?d.jsx(E3e,{}):d.jsx(AEe,{})}return s?d.jsx(fC,{title:t("errors.loadAccountFailed"),message:`${s.message}
|
|
5459
5459
|
|
|
5460
5460
|
${t("errors.loadAccountHint")}`}):r?d.jsx(fC,{title:t("errors.accountDisabled"),message:t("errors.accountDisabledMessage")}):d.jsx(iEe,{children:d.jsx(CEe,{children:d.jsx(Lq,{children:d.jsxs(dr,{element:d.jsx(gEe,{}),children:[d.jsx(dr,{index:!0,element:d.jsx(fd,{to:"/dashboard",replace:!0})}),d.jsx(dr,{path:"/dashboard",element:d.jsx(IEe,{})}),d.jsx(dr,{path:"/posts",element:d.jsx(jEe,{})}),d.jsx(dr,{path:"/posts/new",element:d.jsx(GD,{})}),d.jsx(dr,{path:"/posts/:id",element:d.jsx(GD,{})}),d.jsx(dr,{path:"/pages",element:d.jsx(HNe,{})}),d.jsx(dr,{path:"/pages/new",element:d.jsx(QD,{})}),d.jsx(dr,{path:"/pages/:id",element:d.jsx(QD,{})}),d.jsx(dr,{path:"/taxonomies",element:d.jsx(VNe,{})}),d.jsx(dr,{path:"/media",element:d.jsx(KNe,{})}),d.jsx(dr,{path:"/themes",element:d.jsx(sPe,{})}),d.jsx(dr,{path:"/plugins",element:d.jsx(aPe,{})}),d.jsx(dr,{path:"/menus",element:d.jsx(dPe,{})}),d.jsx(dr,{path:"/theme-settings",element:d.jsx(RPe,{})}),d.jsxs(dr,{path:"/settings",element:d.jsx(PPe,{}),children:[d.jsx(dr,{index:!0,element:d.jsx(fd,{to:"general",replace:!0})}),d.jsx(dr,{path:"general",element:d.jsx(SPe,{})}),d.jsx(dr,{path:"plugin/:pluginId",element:d.jsx(IPe,{})})]}),d.jsx(dr,{path:"/users",element:d.jsx(I3e,{children:d.jsx(LPe,{})})}),d.jsx(dr,{path:"*",element:d.jsx(fd,{to:"/dashboard",replace:!0})})]})})})})}function P3e(){return ra()?(k3e(),d.jsx(o6,{children:d.jsx(tD,{children:d.jsx(R3e,{children:d.jsxs(Vxe,{children:[d.jsx(N3e,{}),d.jsx(nD,{})]})})})})):d.jsx(o6,{children:d.jsxs(tD,{children:[d.jsx(c3e,{}),d.jsx(nD,{})]})})}function R3e({children:t}){const[e,n]=U.useState(()=>$r()!=="flexweg-sqlite");return U.useEffect(()=>{if(e)return;let r=!1;return vH().catch(s=>{console.error("[sqlite] ensureSchema failed at boot:",s)}).finally(()=>{r||n(!0)}),()=>{r=!0}},[e]),e?d.jsx(d.Fragment,{children:t}):d.jsx(_H,{})}nc({id:"core/paragraph",titleKey:"posts.edit.blocks.paragraph",icon:qW,category:"text",insert:t=>{t.focus().setParagraph().run()},isActive:t=>t.isActive("paragraph")&&!t.isActive("blockquote")&&!t.isActive("listItem")});nc({id:"core/heading-2",titleKey:"posts.edit.blocks.heading2",icon:fW,category:"text",insert:t=>{t.focus().toggleHeading({level:2}).run()},isActive:t=>t.isActive("heading",{level:2})});nc({id:"core/heading-3",titleKey:"posts.edit.blocks.heading3",icon:pW,category:"text",insert:t=>{t.focus().toggleHeading({level:3}).run()},isActive:t=>t.isActive("heading",{level:3})});nc({id:"core/bullet-list",titleKey:"posts.edit.blocks.bulletList",icon:EW,category:"text",insert:t=>{t.focus().toggleBulletList().run()},isActive:t=>t.isActive("bulletList")});nc({id:"core/ordered-list",titleKey:"posts.edit.blocks.orderedList",icon:xw,category:"text",insert:t=>{t.focus().toggleOrderedList().run()},isActive:t=>t.isActive("orderedList")});nc({id:"core/blockquote",titleKey:"posts.edit.blocks.blockquote",icon:FC,category:"text",insert:t=>{t.focus().toggleBlockquote().run()},isActive:t=>t.isActive("blockquote")});nc({id:"core/code-block",titleKey:"posts.edit.blocks.codeBlock",icon:A6,category:"text",insert:t=>{t.focus().toggleCodeBlock().run()},isActive:t=>t.isActive("codeBlock")});nc({id:"core/horizontal-rule",titleKey:"posts.edit.blocks.horizontalRule",icon:DC,category:"layout",insert:t=>{t.focus().setHorizontalRule().run()}});nc({id:"core/image",titleKey:"posts.edit.blocks.image",icon:Go,category:"media",insert:async(t,e)=>{if(!e.pickMedia)return;const n=await e.pickMedia();n&&t.focus().setImage({src:n.url,alt:n.alt??""}).run()},isActive:t=>t.isActive("image")});const CH=document.getElementById("root");if(!CH)throw new Error("Root container #root is missing from index.html");IC.createRoot(CH).render(d.jsx(U.StrictMode,{children:d.jsx(Hq,{children:d.jsx(P3e,{})})}));export{qd as a,wu as b,qn as c,M3e as g,d as j,$he as k,U as r,px as s,cEe as u};
|