const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-DXQKqyV-.js","assets/color-Cj4R7Jwi.js","assets/color-BstlScmF.css","assets/index-CHz0y_OU.css","assets/404-b8XRalOG.js","assets/index-D-kw78Ie.js","assets/provisioning-BdbPCuso.js","assets/audit-xsrj3O9J.js","assets/tone-Dxc177Ck.js","assets/auditLinks-DEHKOTNk.js","assets/useKpiText-IK5KBWi1.js","assets/download-BofR5azV.js","assets/ChevronDownIcon-CMXDUsOq.js","assets/CurrencyDollarIcon-DCiUTKx3.js","assets/ChartBarIcon-C6cpgw8_.js","assets/CheckIcon-De2bFu5C.js","assets/CalendarIcon-CeovsUO0.js","assets/useMoney-p1Rn0vzV.js","assets/dict-DFqpuATH.js","assets/useKpiText-z9-FssR_.css","assets/pageState-D9Ub81HX.js","assets/PageActions-DoApwKzS.js","assets/useTable-DIhfqvuf.js","assets/DataError-B8UvrxO0.js","assets/DataError-DmqhQEqJ.css","assets/KeyIcon-VCqYEdpC.js","assets/BoltIcon-CzyB-zY-.js","assets/NoSymbolIcon-B4inaPF8.js","assets/ArrowPathIcon-lZNoj9KY.js","assets/index-BGC3NX_U.css","assets/index-DDIreSTD.js","assets/TabCount-DzuCbG22.js","assets/TabCount-DYR0mwzS.css","assets/InformationCircleIcon-DaKA94KP.js","assets/useHandoverStepName-CfFHWw8F.js","assets/initials-RUHTlIgV.js","assets/PencilSquareIcon-BMB8huEj.js","assets/ChevronRightIcon-BZ1daNxR.js","assets/index-3NpQqrOe.css","assets/index-C3GCEMRK.js","assets/ListPagination-CslO9ICP.js","assets/ListPagination-BMnhAopI.css","assets/tab-BLoNChAJ.js","assets/ClockIcon-XuH1EnHw.js","assets/ExclamationTriangleIcon-CQ__101-.js","assets/index-DQNZtUPm.css","assets/index-SWfQHGjZ.js","assets/ArrowDownTrayIcon-6lvsuzn6.js","assets/index-DnS28t0P.css","assets/index-BmWqmj3Y.js","assets/useListSnapshot-fdZxI9kE.js","assets/ExportAction-DqY3LUbQ.js","assets/export-BfloZNzB.js","assets/DocumentIcon-DJqeC5E9.js","assets/ExportAction-BbA2Hvxc.css","assets/routeContext-CtKMLSQE.js","assets/useConfirmAction-HLpht086.js","assets/CompanyFormDialog-D0vfniek.js","assets/form-C0srv2Dq.js","assets/UserSelect.vue_vue_type_script_setup_true_lang-Lg_BxBkb.js","assets/useCanSelect-Bp9IX3LW.js","assets/CompanySelect.vue_vue_type_script_setup_true_lang-ifvRZQmc.js","assets/useEditConflict-BLsAEyb7.js","assets/CompanyFormDialog-ChfJL8h8.css","assets/QuotationFormDialog-BSMFIK_i.js","assets/ProjectLinkSelect--ZJ2iYJy.js","assets/ProjectLinkSelect-ymJ6qpeg.css","assets/NumberInput-CleDPCCi.js","assets/NumberInput-DYJoKUcs.css","assets/product-CK-NllcI.js","assets/QuotationFormDialog-CNZ_VVBL.css","assets/RowMenu-9h97HJSf.js","assets/RowMenu-CAwFqxeA.css","assets/rowLink-CSmTE32z.js","assets/PlusIcon-4pNYwA0i.js","assets/EyeIcon-bA6Zy61Y.js","assets/DocumentPlusIcon-ruQAixQk.js","assets/index-kbY_8YC0.css","assets/detail-CJLCvgV6.js","assets/ProjectLink-aU-D_kX0.js","assets/ProjectLink-BHZcM_Lz.css","assets/AuditHistory-yHdH7iaf.js","assets/TraceDialog-DSwEqehV.js","assets/TraceDialog-khxRw7ED.css","assets/AuditHistory-DEEc2G7n.css","assets/TrashIcon-85QzoMLo.js","assets/MapPinIcon-B6SGyz6H.js","assets/grantActions-CYG3MAYg.js","assets/EllipsisHorizontalIcon-BSFGJnSs.js","assets/EnvelopeIcon-Djam0PwR.js","assets/PhoneIcon-D8uR21cs.js","assets/detail-yNmH-CSt.css","assets/index-3SIznyo9.js","assets/QuotationPdfDialog-CV6ZhXsc.js","assets/documents-Cl6TtP_g.js","assets/QuotationPdfDialog-ByCLSQGF.css","assets/DocumentDuplicateIcon-BzAp54rd.js","assets/index-dlrZ7-9d.css","assets/detail-C5tkQz5D.js","assets/usePolling-B8GTV0Kw.js","assets/term-DWSCtfFA.js","assets/usePolling-BEGE1tdH.css","assets/CheckIcon-h3mPD5Gx.js","assets/FilePicker-CMonvon4.js","assets/ArrowUpTrayIcon-DEyvKbhl.js","assets/FilePicker-Bu520GOS.css","assets/FilePreviewDialog-DK-Vd9aq.js","assets/FilePreviewDialog-Ccq_Is_M.css","assets/ClipboardDocumentIcon-DO3U-sG0.js","assets/BuildingOfficeIcon-B5dOO6b8.js","assets/detail-DC5gzyTw.css","assets/index-C9sa7cy7.js","assets/TerminateContractDialog-COt87quT.js","assets/TerminateContractDialog-DCtTG4t_.css","assets/RenewContractDialog-D10qxIre.js","assets/RenewContractDialog-BCKX17pQ.css","assets/DocumentArrowDownIcon-GQN6GDIS.js","assets/XCircleIcon-DZgEH6JL.js","assets/index-uWB7TVFM.css","assets/detail-Ce_wiY24.js","assets/OnboardingRef-C379lPQX.js","assets/OnboardingRef-DS6lFg1r.css","assets/inventory-ABJiW9kd.js","assets/workflow-DahRsv_6.js","assets/detail-PyjTRQxN.css","assets/index-BdXJriId.js","assets/ProductFormDialog-DYDvFitk.js","assets/ProductFormDialog-C5z-UHQt.css","assets/index-JzCIkVsj.css","assets/index-BIonH9wD.js","assets/useDataScope-CSfa3m2U.js","assets/StepBadge-DA0QMCz9.js","assets/StepBadge-Dh2h0mMv.css","assets/XMarkIcon-BSPLN49p.js","assets/index-qo88JrEI.css","assets/index--7TL5ZIF.js","assets/role-ou5det9_.js","assets/index-DMS_YnY4.css","assets/detail-0dV3CsYl.js","assets/ProductStatusDialog-3iX0emGV.js","assets/ProductStatusDialog-1MA6LMgq.css","assets/detail-CgzInBAE.css","assets/hardware-detail-CgazElxP.js","assets/hardware-detail-DzmjVt_y.css","assets/role-template-B8q9WUj5.js","assets/role-template-zXXbVFle.css","assets/index-DMseGPDc.js","assets/termActions-Bq3RO-Q1.js","assets/termActions-CEXRYeaL.css","assets/index-CI2fAwWA.css","assets/detail-Db_z_nzQ.js","assets/detail-BxcUfYW6.css","assets/index-O3g_z3yr.js","assets/useUserActions-CCn9UN-9.js","assets/useUserActions-BxE2aEGx.css","assets/index-CStmdPeF.css","assets/detail-CWhVyn3c.js","assets/detail-CFoBJ0s3.css","assets/index-C6XsvfXj.js","assets/AccessPlanes-BUEQqkOf.js","assets/AccessPlanes-BQDtlgAl.css","assets/index-gw7B_UAy.css","assets/index-DJnY4xgr.js","assets/index-uf-mW0br.css","assets/detail-DbhrQTHW.js","assets/detail-Be7MXXS0.css","assets/org-general-D_IR0U81.js","assets/SettingsSideNav-CQr0Tq2S.js","assets/SettingsSideNav-BSBfHjHv.css","assets/org-general-CybPHsf4.css","assets/auth-policy-Cyygvchr.js","assets/auth-policy-Bq0ndhpA.css","assets/compliance-DH4XosMl.js","assets/compliance-DRaJbFoA.css","assets/events-CC-xH08S.js","assets/ProjectSelect.vue_vue_type_script_setup_true_lang-C6U7b8ab.js","assets/ZoneHint-CG1CsRyd.js","assets/ZoneHint-Dh3uYS6K.css","assets/events-CY0V139a.css","assets/access-logs-cbfhFl4M.js","assets/access-logs-CPtA6xEG.css","assets/index-BzPM8_d-.js","assets/index-BA13KSIM.css","assets/index-BOsSPP6V.js","assets/index-CltG1Px2.css","assets/index-BW6RWg8i.js","assets/ProjectFormDialog-MO4h0JSn.js","assets/ProjectFormDialog-Dh1HoQsG.css","assets/index-Dn8o75rY.css","assets/detail-BLoq3d1u.js","assets/onboarding-DxTngmtc.js","assets/handover-BFrdXfho.js","assets/detail-CN1M3vo7.css","assets/index-DnpIosmR.js","assets/ProjectContextTag-DDtPnD_a.js","assets/ProjectContextTag-HoCIzuPg.css","assets/index-MAoHo_1b.css","assets/detail-CkAN-bfn.js","assets/detail-gRAjYuxS.css","assets/index-BtI9L6Ss.js","assets/ContractSelect.vue_vue_type_script_setup_true_lang-DpcfHILz.js","assets/runRetry-Pn4DnVvC.js","assets/runRetry-NBAeFaJw.css","assets/index-3e0kzVsR.css","assets/detail-D2sjd-u1.js","assets/detail-WYxUa_YN.css","assets/index-DXWJjgUc.js","assets/deliveredProduct-BOiWmy0N.js","assets/index-L-MdSuyO.css","assets/detail-T5D8td-M.js","assets/NotesCard-Dtx7imwW.js","assets/NotesCard-n8-QaUKt.css","assets/ClaimRef-k4O2cxyM.js","assets/ClaimRef-BbjjS1uo.css","assets/ConfirmInstallDialog-BB_n8Uf8.js","assets/ConfirmInstallDialog-DLPy-XX5.css","assets/AmendmentRef-Db84E3bp.js","assets/AmendmentRef-Q_W--X5s.css","assets/detail-Ch53xJu4.css","assets/claims-B4Qeuoln.js","assets/ClaimFormDialog-EJ3bnbpf.js","assets/ClaimFormDialog-BT2LSXb3.css","assets/claims-CmX2Hqvz.css","assets/claim-detail-kS6E_l8L.js","assets/claim-detail-YW0oWdoH.css","assets/invoices-CE0Tsp1Z.js","assets/invoices-C4g76YmI.css","assets/invoice-detail-DIE8SZKx.js","assets/invoice-detail-CeVzPX5R.css","assets/index-BMcK0B3y.js","assets/DeliveryReceiptDialog-BlycZhzN.js","assets/DeliveryReceiptDialog-Mtd4a_jl.css","assets/index-CXaVEafS.css","assets/over-installation-detail-CKtD2-zU.js","assets/over-installation-detail-B8RZxt8X.css","assets/index-B_IUGBfF.js","assets/CancelHandoverDialog-C8lRNa4P.js","assets/CancelHandoverDialog-DeIlB6k6.css","assets/index-CPuIx4Sr.css","assets/detail-B60UVMEg.js","assets/detail-CLvleiRr.css"])))=>i.map(i=>d[i]); var Ir=Object.defineProperty;var Or=(e,t,n)=>t in e?Ir(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Vt=(e,t,n)=>Or(e,typeof t!="symbol"?t+"":t,n);import{e as sa,r as Re,m as Vo,i as Xe,h as Lr,a as Kt,b as jo,t as qr,g as Go,o as Wo,c as ct,n as $o,d as Mr,f as z,w as je,s as la,j as Ue,k as Hr,l as ca,p as Yo,q as Ye,u as Q,T as Ur,F as we,v as Br,x as M,y as I,z as _,A as xr,E as Qo,B as Fr,C as le,D as Y,G as C,H as Ie,I as fe,J as j,K as he,L as Lt,_ as kt,M as Vr,N as kn,O as jr,P as Gr,Q as Ko,R as Wr,S as da,U as it,V as zo,W as Zo,X as Pn,Y as $r,Z as Yr,$ as Qr}from"./color-Cj4R7Jwi.js";/*! * pinia v2.3.1 * (c) 2025 Eduardo San Martin Morote * @license MIT */let Xo;const Sn=e=>Xo=e,Jo=Symbol();function Fn(e){return e&&typeof e=="object"&&Object.prototype.toString.call(e)==="[object Object]"&&typeof e.toJSON!="function"}var $t;(function(e){e.direct="direct",e.patchObject="patch object",e.patchFunction="patch function"})($t||($t={}));function Kr(){const e=sa(!0),t=e.run(()=>Re({}));let n=[],a=[];const o=Vo({install(i){Sn(o),o._a=i,i.provide(Jo,o),i.config.globalProperties.$pinia=o,a.forEach(r=>n.push(r)),a=[]},use(i){return this._a?n.push(i):a.push(i),this},_p:n,_a:null,_e:e,_s:new Map,state:t});return o}const ei=()=>{};function ka(e,t,n,a=ei){e.push(t);const o=()=>{const i=e.indexOf(t);i>-1&&(e.splice(i,1),a())};return!n&&Go()&&Wo(o),o}function Pt(e,...t){e.slice().forEach(n=>{n(...t)})}const zr=e=>e(),Pa=Symbol(),Dn=Symbol();function Vn(e,t){e instanceof Map&&t instanceof Map?t.forEach((n,a)=>e.set(a,n)):e instanceof Set&&t instanceof Set&&t.forEach(e.add,e);for(const n in t){if(!t.hasOwnProperty(n))continue;const a=t[n],o=e[n];Fn(o)&&Fn(a)&&e.hasOwnProperty(n)&&!Kt(a)&&!jo(a)?e[n]=Vn(o,a):e[n]=a}return e}const Zr=Symbol();function Xr(e){return!Fn(e)||!e.hasOwnProperty(Zr)}const{assign:ut}=Object;function Jr(e){return!!(Kt(e)&&e.effect)}function es(e,t,n,a){const{state:o,actions:i,getters:r}=t,l=n.state.value[e];let s;function c(){l||(n.state.value[e]=o?o():{});const m=Mr(n.state.value[e]);return ut(m,i,Object.keys(r||{}).reduce((d,u)=>(d[u]=Vo(z(()=>{Sn(n);const f=n._s.get(e);return r[u].call(f,f)})),d),{}))}return s=ti(e,c,t,n,a,!0),s}function ti(e,t,n={},a,o,i){let r;const l=ut({actions:{}},n),s={deep:!0};let c,m,d=[],u=[],f;const A=a.state.value[e];!i&&!A&&(a.state.value[e]={});let P;function N(W){let U;c=m=!1,typeof W=="function"?(W(a.state.value[e]),U={type:$t.patchFunction,storeId:e,events:f}):(Vn(a.state.value[e],W),U={type:$t.patchObject,payload:W,storeId:e,events:f});const G=P=Symbol();$o().then(()=>{P===G&&(c=!0)}),m=!0,Pt(d,U,a.state.value[e])}const v=i?function(){const{state:U}=n,G=U?U():{};this.$patch(se=>{ut(se,G)})}:ei;function S(){r.stop(),d=[],u=[],a._s.delete(e)}const b=(W,U="")=>{if(Pa in W)return W[Dn]=U,W;const G=function(){Sn(a);const se=Array.from(arguments),te=[],be=[];function Ge(ge){te.push(ge)}function He(ge){be.push(ge)}Pt(u,{args:se,name:G[Dn],store:k,after:Ge,onError:He});let Le;try{Le=W.apply(this&&this.$id===e?this:k,se)}catch(ge){throw Pt(be,ge),ge}return Le instanceof Promise?Le.then(ge=>(Pt(te,ge),ge)).catch(ge=>(Pt(be,ge),Promise.reject(ge))):(Pt(te,Le),Le)};return G[Pa]=!0,G[Dn]=U,G},g={_p:a,$id:e,$onAction:ka.bind(null,u),$patch:N,$reset:v,$subscribe(W,U={}){const G=ka(d,W,U.detached,()=>se()),se=r.run(()=>je(()=>a.state.value[e],te=>{(U.flush==="sync"?m:c)&&W({storeId:e,type:$t.direct,events:f},te)},ut({},s,U)));return G},$dispose:S},k=ct(g);a._s.set(e,k);const w=(a._a&&a._a.runWithContext||zr)(()=>a._e.run(()=>(r=sa()).run(()=>t({action:b}))));for(const W in w){const U=w[W];if(Kt(U)&&!Jr(U)||jo(U))i||(A&&Xr(U)&&(Kt(U)?U.value=A[W]:Vn(U,A[W])),a.state.value[e][W]=U);else if(typeof U=="function"){const G=b(U,W);w[W]=G,l.actions[W]=U}}return ut(k,w),ut(qr(k),w),Object.defineProperty(k,"$state",{get:()=>a.state.value[e],set:W=>{N(U=>{ut(U,W)})}}),a._p.forEach(W=>{ut(k,r.run(()=>W({store:k,app:a._a,pinia:a,options:l})))}),A&&i&&n.hydrate&&n.hydrate(k.$state,A),c=!0,m=!0,k}/*! #__NO_SIDE_EFFECTS__ */function ni(e,t,n){let a,o;const i=typeof t=="function";typeof e=="string"?(a=e,o=i?n:t):(o=e,a=e.id);function r(l,s){const c=Lr();return l=l||(c?Xe(Jo,null):null),l&&Sn(l),l=Xo,l._s.has(a)||(i?ti(a,t,o,l):es(a,o,l)),l._s.get(a)}return r.$id=a,r}/*! * shared v11.4.9 * (c) 2026 kazuya kawaguchi * Released under the MIT License. */const mn=typeof window<"u",St=(e,t=!1)=>t?Symbol.for(e):Symbol(e),ts=(e,t,n)=>ai({l:e,k:t,s:n}),ai=e=>JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),Ce=e=>typeof e=="number"&&isFinite(e),oi=e=>pa(e)==="[object Date]",qt=e=>pa(e)==="[object RegExp]",ua=e=>ce(e)&&Object.keys(e).length===0,Ae=Object.assign,ns=Object.create,ue=(e=null)=>ns(e);let Da;const ft=()=>Da||(Da=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:ue()),as=Object.prototype.hasOwnProperty;function Ve(e,t){return as.call(e,t)}const ve=Array.isArray,Te=e=>typeof e=="function",F=e=>typeof e=="string",ne=e=>typeof e=="boolean",ae=e=>e!==null&&typeof e=="object",os=e=>ae(e)&&Te(e.then)&&Te(e.catch),ii=Object.prototype.toString,pa=e=>ii.call(e),ce=e=>pa(e)==="[object Object]",is=e=>e==null?"":ve(e)||ce(e)&&e.toString===ii?JSON.stringify(e,null,2):String(e);function ma(e,t=""){return e.reduce((n,a,o)=>o===0?n+a:n+t+a,"")}function rs(e,t){typeof console<"u"&&(console.warn("[intlify] "+e),t&&console.warn(t.stack))}function _a(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/").replace(/=/g,"=")}function ss(e){return e.replace(/&(?![a-z0-9#]{2,6};)/gi,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}const ls=/^javascript:/i,cs=/^(?:href|src|action|formaction)$/i,ds=/&#(?:x([0-9a-f]+)|(\d+));?/gi,us=/&(?:Tab|NewLine);/g,ps=/:?/gi,ms=/[\u0000-\u0020\u007f-\u009f]/g,hs=/(?:^|[\s"'<>/])on\w+\s*=\s*["']?[^"'>]+["']?/i,fs=/(^|[\s"'<>/])on(\w+\s*=)/gi,vs=/(^|[\s"'<>/])((?:href|src|action|formaction)\s*=\s*)([^\s"'=<>`]+)/gi;function gs(e,t,n){const a=t||n;if(!a)return e;const o=Number.parseInt(a,t?16:10);return o<=127?String.fromCharCode(o):e}function ha(e){const t=e.replace(ds,gs).replace(us,"").replace(ps,":").replace(ms,"");return ls.test(t)}function ys(e){const t=/url\s*\(/gi;let n="",a=0,o;for(;(o=t.exec(e))!==null;){const i=o.index,r=t.lastIndex-1;let l=r+1,s=1,c=null;for(;l`${n}="${Ia(n,a)}"`),e=e.replace(/([\w:-]+)\s*=\s*'([^']*)'/g,(t,n,a)=>`${n}='${Ia(n,a)}'`),hs.test(e)&&(e=e.replace(fs,"$1on$2")),e=e.replace(vs,(t,n,a,o)=>ha(o)?`${n}${a}about:blank`:t),e}const Oa=e=>!ae(e)||ve(e);function un(e,t){if(Oa(e)||Oa(t))throw new Error("Invalid value");const n=[{src:e,des:t}];for(;n.length;){const{src:a,des:o}=n.pop();Object.keys(a).forEach(i=>{if(i==="__proto__")return;const r=a[i];if(ve(r)){const l=[];l.length=r.length,o[i]=l,n.push({src:r,des:l})}else ae(r)?((!ae(o[i])||ve(o[i]))&&(o[i]=ue()),n.push({src:r,des:o[i]})):o[i]=r})}}/*! * message-compiler v11.4.9 * (c) 2026 kazuya kawaguchi * Released under the MIT License. */function Ts(e,t,n){return{line:e,column:t,offset:n}}function jn(e,t,n){return{start:e,end:t}}const re={EXPECTED_TOKEN:1,INVALID_TOKEN_IN_PLACEHOLDER:2,UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER:3,UNKNOWN_ESCAPE_SEQUENCE:4,INVALID_UNICODE_ESCAPE_SEQUENCE:5,UNBALANCED_CLOSING_BRACE:6,UNTERMINATED_CLOSING_BRACE:7,EMPTY_PLACEHOLDER:8,NOT_ALLOW_NEST_PLACEHOLDER:9,INVALID_LINKED_FORMAT:10,MUST_HAVE_MESSAGES_IN_PLURAL:11,UNEXPECTED_EMPTY_LINKED_MODIFIER:12,UNEXPECTED_EMPTY_LINKED_KEY:13,UNEXPECTED_LEXICAL_ANALYSIS:14},bs=17;function Tn(e,t,n={}){const{domain:a,messages:o,args:i}=n,r=e,l=new SyntaxError(String(r));return l.code=e,t&&(l.location=t),l.domain=a,l}function Es(e){throw e}const Ke=" ",ws="\r",_e=` `,Cs="\u2028",As="\u2029";function Rs(e){const t=e;let n=0,a=1,o=1,i=0;const r=w=>t[w]===ws&&t[w+1]===_e,l=w=>t[w]===_e,s=w=>t[w]===As,c=w=>t[w]===Cs,m=w=>r(w)||l(w)||s(w)||c(w),d=()=>n,u=()=>a,f=()=>o,A=()=>i,P=w=>r(w)||s(w)||c(w)?_e:t[w],N=()=>P(n),v=()=>P(n+i);function S(){return i=0,m(n)&&(a++,o=0),r(n)&&n++,n++,o++,t[n]}function b(){return r(n+i)&&i++,i++,t[n+i]}function g(){n=0,a=1,o=1,i=0}function k(w=0){i=w}function O(){const w=n+i;for(;w!==n;)S();i=0}return{index:d,line:u,column:f,peekOffset:A,charAt:P,currentChar:N,currentPeek:v,next:S,peek:b,reset:g,resetPeek:k,skipToPeek:O}}const nt=void 0,Ns=".",La="'",ks="tokenizer";function Ps(e,t={}){const n=t.location!==!1,a=Rs(e),o=()=>a.index(),i=()=>Ts(a.line(),a.column(),a.index()),r=i(),l=o(),s={currentType:13,offset:l,startLoc:r,endLoc:r,lastType:13,lastOffset:l,lastStartLoc:r,lastEndLoc:r,braceNest:0,inLinked:!1,text:""},c=()=>s,{onError:m}=t;function d(p,h,R,...x){const Se=c();if(h.column+=R,h.offset+=R,m){const ee=n?jn(Se.startLoc,h):null,E=Tn(p,ee,{domain:ks,args:x});m(E)}}function u(p,h,R){p.endLoc=i(),p.currentType=h;const x={type:h};return n&&(x.loc=jn(p.startLoc,p.endLoc)),R!=null&&(x.value=R),x}const f=p=>u(p,13);function A(p,h){return p.currentChar()===h?(p.next(),h):(d(re.EXPECTED_TOKEN,i(),0,h),"")}function P(p){let h="";for(;p.currentPeek()===Ke||p.currentPeek()===_e;)h+=p.currentPeek(),p.peek();return h}function N(p){const h=P(p);return p.skipToPeek(),h}function v(p){if(p===nt)return!1;const h=p.charCodeAt(0);return h>=97&&h<=122||h>=65&&h<=90||h===95}function S(p){if(p===nt)return!1;const h=p.charCodeAt(0);return h>=48&&h<=57}function b(p,h){const{currentType:R}=h;if(R!==2)return!1;P(p);const x=v(p.currentPeek());return p.resetPeek(),x}function g(p,h){const{currentType:R}=h;if(R!==2)return!1;P(p);const x=p.currentPeek()==="-"?p.peek():p.currentPeek(),Se=S(x);return p.resetPeek(),Se}function k(p,h){const{currentType:R}=h;if(R!==2)return!1;P(p);const x=p.currentPeek()===La;return p.resetPeek(),x}function O(p,h){const{currentType:R}=h;if(R!==7)return!1;P(p);const x=p.currentPeek()===".";return p.resetPeek(),x}function w(p,h){const{currentType:R}=h;if(R!==8)return!1;P(p);const x=v(p.currentPeek());return p.resetPeek(),x}function W(p,h){const{currentType:R}=h;if(!(R===7||R===11))return!1;P(p);const x=p.currentPeek()===":";return p.resetPeek(),x}function U(p,h){const{currentType:R}=h;if(R!==9)return!1;const x=()=>{const ee=p.currentPeek();return ee==="{"?v(p.peek()):ee==="@"||ee==="|"||ee===":"||ee==="."||ee===Ke||!ee?!1:ee===_e?(p.peek(),x()):se(p,!1)},Se=x();return p.resetPeek(),Se}function G(p){P(p);const h=p.currentPeek()==="|";return p.resetPeek(),h}function se(p,h=!0){const R=(Se=!1,ee="")=>{const E=p.currentPeek();return E==="{"||E==="@"||!E?Se:E==="|"?!(ee===Ke||ee===_e):E===Ke?(p.peek(),R(!0,Ke)):E===_e?(p.peek(),R(!0,_e)):!0},x=R();return h&&p.resetPeek(),x}function te(p,h){const R=p.currentChar();return R===nt?nt:h(R)?(p.next(),R):null}function be(p){const h=p.charCodeAt(0);return h>=97&&h<=122||h>=65&&h<=90||h>=48&&h<=57||h===95||h===36}function Ge(p){return te(p,be)}function He(p){const h=p.charCodeAt(0);return h>=97&&h<=122||h>=65&&h<=90||h>=48&&h<=57||h===95||h===36||h===45}function Le(p){return te(p,He)}function ge(p){const h=p.charCodeAt(0);return h>=48&&h<=57}function tt(p){return te(p,ge)}function qe(p){const h=p.charCodeAt(0);return h>=48&&h<=57||h>=65&&h<=70||h>=97&&h<=102}function B(p){return te(p,qe)}function V(p){let h="",R="";for(;h=tt(p);)R+=h;return R}function H(p){let h="";for(;;){const R=p.currentChar();if(R==="\\"){const x=p.peek();x==="{"||x==="}"||x==="@"||x==="|"||x==="\\"?(h+=R+x,p.next(),p.next()):(p.resetPeek(),h+=R,p.next())}else{if(R==="{"||R==="}"||R==="@"||R==="|"||!R)break;if(R===Ke||R===_e)if(se(p))h+=R,p.next();else{if(G(p))break;h+=R,p.next()}else h+=R,p.next()}}return h}function ke(p){N(p);let h="",R="";for(;h=Le(p);)R+=h;const x=p.currentChar();if(x&&x!=="}"&&x!==nt&&x!==Ke&&x!==_e&&x!==" "){const Se=$(p);return d(re.INVALID_TOKEN_IN_PLACEHOLDER,i(),0,R+Se),R+Se}return p.currentChar()===nt&&d(re.UNTERMINATED_CLOSING_BRACE,i(),0),R}function Pe(p){N(p);let h="";return p.currentChar()==="-"?(p.next(),h+=`-${V(p)}`):h+=V(p),p.currentChar()===nt&&d(re.UNTERMINATED_CLOSING_BRACE,i(),0),h}function wt(p){return p!==La&&p!==_e}function X(p){N(p),A(p,"'");let h="",R="";for(;h=te(p,wt);)h==="\\"?R+=T(p):R+=h;const x=p.currentChar();return x===_e||x===nt?(d(re.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER,i(),0),x===_e&&(p.next(),A(p,"'")),R):(A(p,"'"),R)}function T(p){const h=p.currentChar();switch(h){case"\\":case"'":return p.next(),`\\${h}`;case"u":return L(p,h,4);case"U":return L(p,h,6);default:return d(re.UNKNOWN_ESCAPE_SEQUENCE,i(),0,h),""}}function L(p,h,R){A(p,h);let x="";for(let Se=0;Se{const x=p.currentChar();return x==="{"||x==="@"||x==="|"||x==="("||x===")"||!x||x===Ke?R:(R+=x,p.next(),h(R))};return h("")}function J(p){N(p);const h=A(p,"|");return N(p),h}function Z(p,h){let R=null;switch(p.currentChar()){case"{":return h.braceNest>=1&&d(re.NOT_ALLOW_NEST_PLACEHOLDER,i(),0),p.next(),R=u(h,2,"{"),N(p),h.braceNest++,R;case"}":return h.braceNest>0&&h.currentType===2&&d(re.EMPTY_PLACEHOLDER,i(),0),p.next(),R=u(h,3,"}"),h.braceNest--,h.braceNest>0&&N(p),h.inLinked&&h.braceNest===0&&(h.inLinked=!1),R;case"@":return h.braceNest>0&&d(re.UNTERMINATED_CLOSING_BRACE,i(),0),R=me(p,h)||f(h),h.braceNest=0,R;default:{let Se=!0,ee=!0,E=!0;if(G(p))return h.braceNest>0&&d(re.UNTERMINATED_CLOSING_BRACE,i(),0),R=u(h,1,J(p)),h.braceNest=0,h.inLinked=!1,R;if(h.braceNest>0&&(h.currentType===4||h.currentType===5||h.currentType===6))return d(re.UNTERMINATED_CLOSING_BRACE,i(),0),h.braceNest=0,We(p,h);if(Se=b(p,h))return R=u(h,4,ke(p)),N(p),R;if(ee=g(p,h))return R=u(h,5,Pe(p)),N(p),R;if(E=k(p,h))return R=u(h,6,X(p)),N(p),R;if(!Se&&!ee&&!E)return R=u(h,12,$(p)),d(re.INVALID_TOKEN_IN_PLACEHOLDER,i(),0,R.value),N(p),R;break}}return R}function me(p,h){const{currentType:R}=h;let x=null;const Se=p.currentChar();switch((R===7||R===8||R===11||R===9)&&(Se===_e||Se===Ke)&&d(re.INVALID_LINKED_FORMAT,i(),0),Se){case"@":return p.next(),x=u(h,7,"@"),h.inLinked=!0,x;case".":return N(p),p.next(),u(h,8,".");case":":return N(p),p.next(),u(h,9,":");default:return G(p)?(x=u(h,1,J(p)),h.braceNest=0,h.inLinked=!1,x):O(p,h)||W(p,h)?(N(p),me(p,h)):w(p,h)?(N(p),u(h,11,oe(p))):U(p,h)?(N(p),Se==="{"?Z(p,h)||x:u(h,10,ye(p))):(R===7&&d(re.INVALID_LINKED_FORMAT,i(),0),h.braceNest=0,h.inLinked=!1,We(p,h))}}function We(p,h){let R={type:13};if(h.braceNest>0)return Z(p,h)||f(h);if(h.inLinked)return me(p,h)||f(h);switch(p.currentChar()){case"{":return Z(p,h)||f(h);case"}":return d(re.UNBALANCED_CLOSING_BRACE,i(),0),p.next(),u(h,3,"}");case"@":return me(p,h)||f(h);default:{if(G(p))return R=u(h,1,J(p)),h.braceNest=0,h.inLinked=!1,R;if(se(p))return u(h,0,H(p));break}}return R}function Ne(){const{currentType:p,offset:h,startLoc:R,endLoc:x}=s;return s.lastType=p,s.lastOffset=h,s.lastStartLoc=R,s.lastEndLoc=x,s.offset=o(),s.startLoc=i(),a.currentChar()===nt?u(s,13):We(a,s)}return{nextToken:Ne,currentOffset:o,currentPosition:i,context:c}}const Ds="parser",_s=/(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g,Is=/\\([\\@{}|])/g;function Os(e,t){return t}function Ls(e,t,n){switch(e){case"\\\\":return"\\";case"\\'":return"'";default:{const a=parseInt(t||n,16);return a<=55295||a>=57344?String.fromCodePoint(a):"�"}}}function qs(e={}){const t=e.location!==!1,{onError:n}=e;function a(v,S,b,g,...k){const O=v.currentPosition();if(O.offset+=g,O.column+=g,n){const w=t?jn(b,O):null,W=Tn(S,w,{domain:Ds,args:k});n(W)}}function o(v,S,b){const g={type:v};return t&&(g.start=S,g.end=S,g.loc={start:b,end:b}),g}function i(v,S,b,g){t&&(v.end=S,v.loc&&(v.loc.end=b))}function r(v,S){const b=v.context(),g=o(3,b.offset,b.startLoc);return g.value=S.replace(Is,Os),i(g,v.currentOffset(),v.currentPosition()),g}function l(v,S){const b=v.context(),{lastOffset:g,lastStartLoc:k}=b,O=o(5,g,k);return O.index=parseInt(S,10),v.nextToken(),i(O,v.currentOffset(),v.currentPosition()),O}function s(v,S){const b=v.context(),{lastOffset:g,lastStartLoc:k}=b,O=o(4,g,k);return O.key=S,v.nextToken(),i(O,v.currentOffset(),v.currentPosition()),O}function c(v,S){const b=v.context(),{lastOffset:g,lastStartLoc:k}=b,O=o(9,g,k);return O.value=S.replace(_s,Ls),v.nextToken(),i(O,v.currentOffset(),v.currentPosition()),O}function m(v){const S=v.nextToken(),b=v.context(),{lastOffset:g,lastStartLoc:k}=b,O=o(8,g,k);return S.type!==11?(a(v,re.UNEXPECTED_EMPTY_LINKED_MODIFIER,b.lastStartLoc,0),O.value="",i(O,g,k),{nextConsumeToken:S,node:O}):(S.value==null&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,b.lastStartLoc,0,ze(S)),O.value=S.value||"",i(O,v.currentOffset(),v.currentPosition()),{node:O})}function d(v,S){const b=v.context(),g=o(7,b.offset,b.startLoc);return g.value=S,i(g,v.currentOffset(),v.currentPosition()),g}function u(v){const S=v.context(),b=o(6,S.offset,S.startLoc);let g=v.nextToken();if(g.type===8){const k=m(v);b.modifier=k.node,g=k.nextConsumeToken||v.nextToken()}switch(g.type!==9&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,S.lastStartLoc,0,ze(g)),g=v.nextToken(),g.type===2&&(g=v.nextToken()),g.type){case 10:g.value==null&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,S.lastStartLoc,0,ze(g)),b.key=d(v,g.value||"");break;case 4:g.value==null&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,S.lastStartLoc,0,ze(g)),b.key=s(v,g.value||"");break;case 5:g.value==null&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,S.lastStartLoc,0,ze(g)),b.key=l(v,g.value||"");break;case 6:g.value==null&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,S.lastStartLoc,0,ze(g)),b.key=c(v,g.value||"");break;default:{a(v,re.UNEXPECTED_EMPTY_LINKED_KEY,S.lastStartLoc,0);const k=v.context(),O=o(7,k.offset,k.startLoc);return O.value="",i(O,k.offset,k.startLoc),b.key=O,i(b,k.offset,k.startLoc),{nextConsumeToken:g,node:b}}}return i(b,v.currentOffset(),v.currentPosition()),{node:b}}function f(v){const S=v.context(),b=S.currentType===1?v.currentOffset():S.offset,g=S.currentType===1?S.endLoc:S.startLoc,k=o(2,b,g);k.items=[];let O=null;do{const U=O||v.nextToken();switch(O=null,U.type){case 0:U.value==null&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,S.lastStartLoc,0,ze(U)),k.items.push(r(v,U.value||""));break;case 5:U.value==null&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,S.lastStartLoc,0,ze(U)),k.items.push(l(v,U.value||""));break;case 4:U.value==null&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,S.lastStartLoc,0,ze(U)),k.items.push(s(v,U.value||""));break;case 6:U.value==null&&a(v,re.UNEXPECTED_LEXICAL_ANALYSIS,S.lastStartLoc,0,ze(U)),k.items.push(c(v,U.value||""));break;case 7:{const G=u(v);k.items.push(G.node),O=G.nextConsumeToken||null;break}}}while(S.currentType!==13&&S.currentType!==1);const w=S.currentType===1?S.lastOffset:v.currentOffset(),W=S.currentType===1?S.lastEndLoc:v.currentPosition();return i(k,w,W),k}function A(v,S,b,g){const k=v.context();let O=g.items.length===0;const w=o(1,S,b);w.cases=[],w.cases.push(g);do{const W=f(v);O||(O=W.items.length===0),w.cases.push(W)}while(k.currentType!==13);return O&&a(v,re.MUST_HAVE_MESSAGES_IN_PLURAL,b,0),i(w,v.currentOffset(),v.currentPosition()),w}function P(v){const S=v.context(),{offset:b,startLoc:g}=S,k=f(v);return S.currentType===13?k:A(v,b,g,k)}function N(v){const S=Ps(v,Ae({},e)),b=S.context(),g=o(0,b.offset,b.startLoc);return t&&g.loc&&(g.loc.source=v),g.body=P(S),e.onCacheKey&&(g.cacheKey=e.onCacheKey(v)),b.currentType!==13&&a(S,re.UNEXPECTED_LEXICAL_ANALYSIS,b.lastStartLoc,0,v[b.offset]||""),i(g,S.currentOffset(),S.currentPosition()),g}return{parse:N}}function ze(e){if(e.type===13)return"EOF";const t=(e.value||"").replace(/\r?\n/gu,"\\n");return t.length>10?t.slice(0,9)+"…":t}function Ms(e,t={}){const n={ast:e,helpers:new Set};return{context:()=>n,helper:i=>(n.helpers.add(i),i)}}function qa(e,t){for(let n=0;nMa(n)),e}function Ma(e){if(e.items.length===1){const t=e.items[0];(t.type===3||t.type===9)&&(e.static=t.value,delete t.value)}else{const t=[];for(let n=0;nr;function s(P,N){r.code+=P}function c(P,N=!0){const v=N?a:"";s(o?v+" ".repeat(P):v)}function m(P=!0){const N=++r.indentLevel;P&&c(N)}function d(P=!0){const N=--r.indentLevel;P&&c(N)}function u(){c(r.indentLevel)}return{context:l,push:s,indent:m,deindent:d,newline:u,helper:P=>`_${P}`,needIndent:()=>r.needIndent}}function xs(e,t){const{helper:n}=e;e.push(`${n("linked")}(`),Mt(e,t.key),t.modifier?(e.push(", "),Mt(e,t.modifier),e.push(", _type")):e.push(", undefined, _type"),e.push(")")}function Fs(e,t){const{helper:n,needIndent:a}=e;e.push(`${n("normalize")}([`),e.indent(a());const o=t.items.length;for(let i=0;i1){e.push(`${n("plural")}([`),e.indent(a());const o=t.cases.length;for(let i=0;i{const n=F(t.mode)?t.mode:"normal",a=F(t.filename)?t.filename:"message.intl";t.sourceMap;const o=t.breakLineCode!=null?t.breakLineCode:n==="arrow"?";":` `,i=t.needIndent?t.needIndent:n!=="arrow",r=e.helpers||[],l=Bs(e,{filename:a,breakLineCode:o,needIndent:i});l.push(n==="normal"?"function __msg__ (ctx) {":"(ctx) => {"),l.indent(i),r.length>0&&(l.push(`const { ${ma(r.map(m=>`${m}: _${m}`),", ")} } = ctx`),l.newline()),l.push("return "),Mt(l,e),l.deindent(i),l.push("}"),delete e.helpers;const{code:s,map:c}=l.context();return{ast:e,code:s,map:c?c.toJSON():void 0}};function Ws(e,t={}){const n=Ae({},t),a=!!n.jit,o=!!n.minify,i=n.optimize==null?!0:n.optimize,l=qs(n).parse(e);return a?(i&&Us(l),o&&Dt(l),{ast:l,code:""}):(Hs(l,n),Gs(l,n))}/*! * core-base v11.4.9 * (c) 2026 kazuya kawaguchi * Released under the MIT License. */function $s(){typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(ft().__INTLIFY_PROD_DEVTOOLS__=!1),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(ft().__INTLIFY_DROP_MESSAGE_COMPILER__=!1)}function Ze(e){return ae(e)&&va(e)===0&&(Ve(e,"b")||Ve(e,"body"))}const ri=["b","body"];function Ys(e){return Tt(e,ri)}const si=["c","cases"];function Qs(e){return Tt(e,si,[])}const li=["s","static"];function Ks(e){return Tt(e,li)}const ci=["i","items"];function zs(e){return Tt(e,ci,[])}const di=["t","type"];function va(e){return Tt(e,di)}const ui=["v","value"];function sn(e,t){const n=Tt(e,ui);if(n!=null)return n;throw zt(t)}const pi=["m","modifier"];function Zs(e){return Tt(e,pi)}const mi=["k","key"];function Xs(e){const t=Tt(e,mi);if(t)return t;throw zt(6)}function Tt(e,t,n){for(let a=0;aJs(n,e)}function Js(e,t){const n=Ys(t);if(n==null)throw zt(0);if(va(n)===1){const i=Qs(n);return e.plural(i.reduce((r,l)=>[...r,Ha(e,l)],[]))}else return Ha(e,n)}function Ha(e,t){const n=Ks(t);if(n!=null)return e.type==="text"?n:e.normalize([n]);{const a=zs(t).reduce((o,i)=>[...o,Gn(e,i)],[]);return e.normalize(a)}}function Gn(e,t){const n=va(t);switch(n){case 3:return sn(t,n);case 9:return sn(t,n);case 4:{const a=t;if(Ve(a,"k")&&a.k)return e.interpolate(e.named(a.k));if(Ve(a,"key")&&a.key)return e.interpolate(e.named(a.key));throw zt(n)}case 5:{const a=t;if(Ve(a,"i")&&Ce(a.i))return e.interpolate(e.list(a.i));if(Ve(a,"index")&&Ce(a.index))return e.interpolate(e.list(a.index));throw zt(n)}case 6:{const a=t,o=Zs(a),i=Xs(a);return e.linked(Gn(e,i),o?Gn(e,o):void 0,e.type)}case 7:return sn(t,n);case 8:return sn(t,n);default:throw new Error(`unhandled node on format message part: ${n}`)}}const el=e=>e;let ln=ue();function tl(e,t={}){let n=!1;const a=t.onError||Es;return t.onError=o=>{n=!0,a(o)},{...Ws(e,t),detectError:n}}function nl(e,t){if(!__INTLIFY_DROP_MESSAGE_COMPILER__&&F(e)){ne(t.warnHtmlMessage)&&t.warnHtmlMessage;const a=(t.onCacheKey||el)(e),o=ln[a];if(o)return o;const{ast:i,detectError:r}=tl(e,{...t,location:!1,jit:!0}),l=_n(i);return r?l:ln[a]=l}else{const n=e.cacheKey;if(n){const a=ln[n];return a||(ln[n]=_n(e))}else return _n(e)}}let Zt=null;function al(e){Zt=e}function ol(e,t,n){Zt&&Zt.emit("i18n:init",{timestamp:Date.now(),i18n:e,version:t,meta:n})}const il=rl("function:translate");function rl(e){return t=>Zt&&Zt.emit(e,t)}const rt={INVALID_ARGUMENT:bs,INVALID_DATE_ARGUMENT:18,INVALID_ISO_DATE_ARGUMENT:19,NOT_SUPPORT_LOCALE_PROMISE_VALUE:21,NOT_SUPPORT_LOCALE_ASYNC_FUNCTION:22,NOT_SUPPORT_LOCALE_TYPE:23},sl=24;function st(e){return Tn(e,null,void 0)}function ga(e,t){return t.locale!=null?Ua(t.locale):Ua(e.locale)}let In;function Ua(e){if(F(e))return e;if(Te(e)){if(e.resolvedOnce&&In!=null)return In;if(e.constructor.name==="Function"){const t=e();if(os(t))throw st(rt.NOT_SUPPORT_LOCALE_PROMISE_VALUE);return In=t}else throw st(rt.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION)}else throw st(rt.NOT_SUPPORT_LOCALE_TYPE)}function ll(e,t,n){return[...new Set([n,...ve(t)?t:ae(t)?Object.keys(t).filter(a=>a!=="default"):F(t)?[t]:[n]])]}function Wn(e,t,n){const a=F(n)?n:Xt,o=e;o.__localeChainCache||(o.__localeChainCache=new Map);const i=ai(t);let r=o.__localeChainCache.get(a);r||(r=new Map,o.__localeChainCache.set(a,r));const l=r.get(i);if(l)return l;const s=[];let c=[n];for(;ve(c);)c=Ba(s,c,t);const m=ve(t)||!ce(t)?t:t.default?t.default:null;return c=F(m)?[m]:m,ve(c)&&Ba(s,c,!1),r.set(i,s),s}function Ba(e,t,n){let a=!0;for(let o=0;o{r===void 0?r=l:r+=l},u[1]=()=>{r!==void 0&&(t.push(r),r=void 0)},u[2]=()=>{u[0](),o++},u[3]=()=>{if(o>0)o--,a=4,u[0]();else{if(o=0,r===void 0||(r=fl(r),r===!1))return!1;u[1]()}};function f(){const A=e[n+1];if(a===5&&A==="'"||a===6&&A==='"')return n++,l="\\"+A,u[0](),!0}for(;a!==null;)if(n++,i=e[n],!(i==="\\"&&f())){if(s=hl(i),d=bt[a],c=d[s]||d.l||8,c===8||(a=c[0],c[1]!==void 0&&(m=u[c[1]],m&&(l=i,m()===!1))))return;if(a===7)return t}}const xa=new Map;function gl(e,t){return ae(e)?e[t]:null}function yl(e,t){if(!ae(e))return null;let n=xa.get(t);if(n||(n=vl(t),n&&xa.set(t,n)),!n)return null;const a=n.length;let o=e,i=0;for(;i`${e.charAt(0).toLocaleUpperCase()}${e.substr(1)}`;function Tl(){return{upper:(e,t)=>t==="text"&&F(e)?e.toUpperCase():t==="vnode"&&ae(e)&&"__v_isVNode"in e?e.children.toUpperCase():e,lower:(e,t)=>t==="text"&&F(e)?e.toLowerCase():t==="vnode"&&ae(e)&&"__v_isVNode"in e?e.children.toLowerCase():e,capitalize:(e,t)=>t==="text"&&F(e)?Fa(e):t==="vnode"&&ae(e)&&"__v_isVNode"in e?Fa(e.children):e}}let fi;function bl(e){fi=e}let vi;function El(e){vi=e}let gi;function wl(e){gi=e}let yi=null;const Cl=e=>{yi=e},Al=()=>yi;let Si=null;const Va=e=>{Si=e},Rl=()=>Si;let ja=0;function Nl(e={}){const t=Te(e.onWarn)?e.onWarn:rs,n=F(e.version)?e.version:Sl,a=F(e.locale)||Te(e.locale)?e.locale:Xt,o=Te(a)?Xt:a,i=ve(e.fallbackLocale)||ce(e.fallbackLocale)||F(e.fallbackLocale)||e.fallbackLocale===!1?e.fallbackLocale:o,r=ce(e.messages)?e.messages:On(o),l=ce(e.datetimeFormats)?e.datetimeFormats:On(o),s=ce(e.numberFormats)?e.numberFormats:On(o),c=Ae(ue(),e.modifiers,Tl()),m=e.pluralRules||ue(),d=Te(e.missing)?e.missing:null,u=ne(e.missingWarn)||qt(e.missingWarn)?e.missingWarn:!0,f=ne(e.fallbackWarn)||qt(e.fallbackWarn)?e.fallbackWarn:!0,A=!!e.fallbackFormat,P=!!e.unresolving,N=Te(e.postTranslation)?e.postTranslation:null,v=ce(e.processor)?e.processor:null,S=ne(e.warnHtmlMessage)?e.warnHtmlMessage:!0,b=!!e.escapeParameter,g=Te(e.messageCompiler)?e.messageCompiler:fi,k=Te(e.messageResolver)?e.messageResolver:vi||gl,O=Te(e.localeFallbacker)?e.localeFallbacker:gi||ll,w=ae(e.fallbackContext)?e.fallbackContext:void 0,W=e,U=ae(W.__datetimeFormatters)?W.__datetimeFormatters:new Map,G=ae(W.__numberFormatters)?W.__numberFormatters:new Map,se=ae(W.__meta)?W.__meta:{};ja++;const te={version:n,cid:ja,locale:a,fallbackLocale:i,messages:r,modifiers:c,pluralRules:m,missing:d,missingWarn:u,fallbackWarn:f,fallbackFormat:A,unresolving:P,postTranslation:N,processor:v,warnHtmlMessage:S,escapeParameter:b,messageCompiler:g,messageResolver:k,localeFallbacker:O,fallbackContext:w,onWarn:t,__meta:se};return te.datetimeFormats=l,te.numberFormats=s,te.__datetimeFormatters=U,te.__numberFormatters=G,__INTLIFY_PROD_DEVTOOLS__&&ol(te,n,se),te}const On=e=>({[e]:ue()});function Ti(e,t,n,a,o){const{missing:i,onWarn:r}=e;if(i!==null){const l=i(e,n,t,o);return F(l)?l:t}else return t}function jt(e,t,n){const a=e;a.__localeChainCache=new Map,e.localeFallbacker(e,n,t)}function kl(e,t){return e===t?!1:e.split("-")[0]===t.split("-")[0]}function Pl(e,t){const n=t.indexOf(e);if(n===-1)return!1;for(let a=n+1;a{a.includes(s)?l[s]=o[s]:t[s]=o[s]}),F(i)?t.locale=i:ce(i)&&(l=i),ce(r)&&(l=r),l}function Ga(e,...t){const{datetimeFormats:n,unresolving:a,onWarn:o}=e,{__datetimeFormatters:i}=e;if(!F(t[0])&&!oi(t[0])&&!Ce(t[0]))return hn;const[r,l,s,c]=$n(...t),m=ne(s.missingWarn)?s.missingWarn:e.missingWarn,d=ne(s.fallbackWarn)?s.fallbackWarn:e.fallbackWarn,u=!!s.part,f=ga(e,s);if(!F(r)||r===""){const S=new Intl.DateTimeFormat(f.replace(/!/g,""),c);return u?S.formatToParts(l):S.format(l)}const A=bi(e,r,f,n,m,d,"datetime format");if(!F(A))return a?bn:r;const P=n[A][r],N=Ei(A,r,c);let v=i.get(N);return v||(v=new Intl.DateTimeFormat(A,Ae({},P,c)),i.set(N,v)),u?v.formatToParts(l):v.format(l)}const Ai=["localeMatcher","weekday","era","year","month","day","hour","minute","second","timeZoneName","formatMatcher","hour12","timeZone","dateStyle","timeStyle","calendar","dayPeriod","numberingSystem","hourCycle","fractionalSecondDigits"];function $n(...e){const[t]=e,n=ue(),a=ue();let o;if(F(t)){const r=t.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);if(!r)throw st(rt.INVALID_ISO_DATE_ARGUMENT);const l=r[3]?r[3].trim().startsWith("T")?`${r[1].trim()}${r[3].trim()}`:`${r[1].trim()}T${r[3].trim()}`:r[1].trim();o=new Date(l);try{o.toISOString()}catch{throw st(rt.INVALID_ISO_DATE_ARGUMENT)}}else if(oi(t)){if(isNaN(t.getTime()))throw st(rt.INVALID_DATE_ARGUMENT);o=t}else if(Ce(t))o=t;else throw st(rt.INVALID_ARGUMENT);const i=Ci(e,n,a,Ai);return[n.key||"",o,n,i]}function Wa(e,t,n){wi(e.__datetimeFormatters,t,n)}function $a(e,...t){const{numberFormats:n,unresolving:a,onWarn:o}=e,{__numberFormatters:i}=e;if(!Ce(t[0]))return hn;const[r,l,s,c]=Yn(...t),m=ne(s.missingWarn)?s.missingWarn:e.missingWarn,d=ne(s.fallbackWarn)?s.fallbackWarn:e.fallbackWarn,u=!!s.part,f=ga(e,s);if(!F(r)||r===""){const S=new Intl.NumberFormat(f.replace(/!/g,""),c);return u?S.formatToParts(l):S.format(l)}const A=bi(e,r,f,n,m,d,"number format");if(!F(A))return a?bn:r;const P=n[A][r],N=Ei(A,r,c);let v=i.get(N);return v||(v=new Intl.NumberFormat(A,Ae({},P,c)),i.set(N,v)),u?v.formatToParts(l):v.format(l)}const Ri=["localeMatcher","style","currency","currencyDisplay","currencySign","useGrouping","minimumIntegerDigits","minimumFractionDigits","maximumFractionDigits","minimumSignificantDigits","maximumSignificantDigits","compactDisplay","notation","signDisplay","unit","unitDisplay","roundingMode","roundingPriority","roundingIncrement","trailingZeroDisplay"];function Yn(...e){const[t]=e,n=ue(),a=ue();if(!Ce(t))throw st(rt.INVALID_ARGUMENT);const o=t,i=Ci(e,n,a,Ri);return[n.key||"",o,n,i]}function Ya(e,t,n){wi(e.__numberFormatters,t,n)}const Dl=e=>e,_l=e=>"",Il="text",Ol=e=>e.length===0?"":ma(e),Ll=is;function Ln(e,t){return e=Math.abs(e),t===2?e===1?0:1:Math.min(e,2)}function ql(e){var n,a;const t=Ce(e.pluralIndex)?e.pluralIndex:-1;return Ce((n=e.named)==null?void 0:n.count)?e.named.count:Ce((a=e.named)==null?void 0:a.n)?e.named.n:t}function Ml(e={}){var v,S,b,g;const t=e.locale,n=ql(e),a=F(t)&&Te((v=e.pluralRules)==null?void 0:v[t])?e.pluralRules[t]:Ln,o=a===Ln?void 0:Ln,i=k=>k[a(n,k.length,o)],r=e.list||[],l=k=>r[k],s=e.named||ue();Ce(e.pluralIndex)&&(s.count||(s.count=e.pluralIndex),s.n||(s.n=e.pluralIndex));const c=k=>s[k];function m(k,O){const w=Te(e.messages)?e.messages(k,!!O):ae(e.messages)?e.messages[k]:!1;return w||(e.parent?e.parent.message(k):_l)}const d=k=>e.modifiers?e.modifiers[k]:Dl,u=Te((S=e.processor)==null?void 0:S.normalize)?e.processor.normalize:Ol,f=Te((b=e.processor)==null?void 0:b.interpolate)?e.processor.interpolate:Ll,A=F((g=e.processor)==null?void 0:g.type)?e.processor.type:Il,N={list:l,named:c,plural:i,linked:(k,...O)=>{const[w,W]=O;let U="text",G="";O.length===1?ae(w)?(G=w.modifier||G,U=w.type||U):F(w)&&(G=w||G):O.length===2&&(F(w)&&(G=w||G),F(W)&&(U=W||U));const se=m(k,!0)(N),te=se===""||se===void 0?k:se,be=U==="vnode"&&ve(te)&&G?te[0]:te;return G?d(G)(be,U):be},message:m,type:A,interpolate:f,normalize:u,values:Ae(ue(),r,s)};return N}const Qa=()=>"",Fe=e=>Te(e);function Ka(e,...t){const{fallbackFormat:n,postTranslation:a,unresolving:o,messageCompiler:i,fallbackLocale:r,messages:l}=e,[s,c]=Qn(...t),m=ne(c.missingWarn)?c.missingWarn:e.missingWarn,d=ne(c.fallbackWarn)?c.fallbackWarn:e.fallbackWarn,u=ne(c.escapeParameter)?c.escapeParameter:e.escapeParameter,f=!!c.resolvedMessage,A=F(c.default)||ne(c.default)?ne(c.default)?i?s:()=>s:c.default:n?i?s:()=>s:null,P=n||A!=null&&(F(A)||Te(A)),N=ga(e,c);u&&Hl(c);let[v,S,b]=f?[s,N,l[N]||ue()]:Ni(e,s,N,r,d,m),g=v,k=s;if(!f&&!(F(g)||Ze(g)||Fe(g))&&P&&(g=A,k=g),!f&&(!(F(g)||Ze(g)||Fe(g))||!F(S)))return o?bn:s;let O=!1;const w=()=>{O=!0},W=Fe(g)?g:ki(e,s,S,g,k,w);if(O)return g;const U=xl(e,S,b,c),G=Ml(U),se=Ul(e,W,G);let te=a?a(se,s):se;if(u&&F(te)&&(te=Ss(te)),__INTLIFY_PROD_DEVTOOLS__){const be={timestamp:Date.now(),key:F(s)?s:Fe(g)?g.key:"",locale:S||(Fe(g)?g.locale:""),format:F(g)?g:Fe(g)?g.source:"",message:te};be.meta=Ae({},e.__meta,Al()||{}),il(be)}return te}function Hl(e){ve(e.list)?e.list=e.list.map(t=>F(t)?_a(t):t):ae(e.named)&&Object.keys(e.named).forEach(t=>{F(e.named[t])&&(e.named[t]=_a(e.named[t]))})}function Ni(e,t,n,a,o,i){const{messages:r,onWarn:l,messageResolver:s,localeFallbacker:c}=e,m=c(e,a,n);let d=ue(),u,f=null;const A="translate";for(let P=0;Pa;return c.locale=n,c.key=t,c}const s=r(a,Bl(e,n,o,a,l,i));return s.locale=n,s.key=t,s.source=a,s}function Ul(e,t,n){return t(n)}function Qn(...e){const[t,n,a]=e,o=ue();if(!F(t)&&!Ce(t)&&!Fe(t)&&!Ze(t))throw st(rt.INVALID_ARGUMENT);const i=Ce(t)?String(t):(Fe(t),t);return Ce(n)?o.plural=n:F(n)?o.default=n:ce(n)&&!ua(n)?o.named=n:ve(n)&&(o.list=n),Ce(a)?o.plural=a:F(a)?o.default=a:ce(a)&&Ae(o,a),[i,o]}function Bl(e,t,n,a,o,i){return{locale:t,key:n,warnHtmlMessage:o,onError:r=>{throw i&&i(r),r},onCacheKey:r=>ts(t,n,r)}}function xl(e,t,n,a){const{modifiers:o,pluralRules:i,messageResolver:r,fallbackLocale:l,fallbackWarn:s,missingWarn:c,fallbackContext:m}=e,u={locale:t,modifiers:o,pluralRules:i,messages:(f,A)=>{let P=r(n,f);if(P==null&&(m||A)){const[N,,v]=Ni(m||e,f,t,l,s,c);P=N??r(v,f)}if(F(P)||Ze(P)){let N=!1;const S=ki(e,f,t,P,f,()=>{N=!0});return N?Qa:S}else return Fe(P)?P:Qa}};return e.processor&&(u.processor=e.processor),a.list&&(u.list=a.list),a.named&&(u.named=a.named),Ce(a.plural)&&(u.pluralIndex=a.plural),u}$s();/*! * vue-i18n v11.4.9 * (c) 2026 kazuya kawaguchi * Released under the MIT License. */const Fl="11.4.9";function Vl(){typeof __VUE_I18N_FULL_INSTALL__!="boolean"&&(ft().__VUE_I18N_FULL_INSTALL__=!0),typeof __VUE_I18N_LEGACY_API__!="boolean"&&(ft().__VUE_I18N_LEGACY_API__=!0),typeof __INTLIFY_DROP_MESSAGE_COMPILER__!="boolean"&&(ft().__INTLIFY_DROP_MESSAGE_COMPILER__=!1),typeof __INTLIFY_PROD_DEVTOOLS__!="boolean"&&(ft().__INTLIFY_PROD_DEVTOOLS__=!1)}const Oe={UNEXPECTED_RETURN_TYPE:sl,INVALID_ARGUMENT:25,MUST_BE_CALL_SETUP_TOP:26,NOT_INSTALLED:27,REQUIRED_VALUE:28,INVALID_VALUE:29,NOT_INSTALLED_WITH_PROVIDE:31,UNEXPECTED_ERROR:32,NOT_AVAILABLE_COMPOSITION_IN_LEGACY:34};function Me(e,...t){return Tn(e,null,void 0)}const Kn=St("__translateVNode"),zn=St("__datetimeParts"),Zn=St("__numberParts"),Pi=St("__setPluralRules"),Di=St("__injectWithOption"),It=St("__dispose");let _i=null;{const e=ft().__VUE_INSTANCE_SETTERS__;ve(e)&&e.push(t=>{_i=t})}function Jt(e){if(!ae(e)||Ze(e))return e;for(const t in e)if(Ve(e,t))if(!t.includes("."))ae(e[t])&&Jt(e[t]);else{const n=t.split("."),a=n.length-1;let o=e,i=!1;for(let r=0;r{if("locale"in l&&"resource"in l){const{locale:s,resource:c}=l;s?(r[s]=r[s]||ue(),un(c,r[s])):un(c,r)}else F(l)&&un(JSON.parse(l),r)}),o==null&&i)for(const l in r)Ve(r,l)&&Jt(r[l]);return r}function Ii(e){return e.type}function Oi(e,t,n){let a=ae(t.messages)?t.messages:ue();"__i18nGlobal"in n&&(a=ya(e.locale.value,{messages:a,__i18n:n.__i18nGlobal}));const o=Object.keys(a);o.length&&o.forEach(i=>{e.mergeLocaleMessage(i,a[i])});{if(ae(t.datetimeFormats)){const i=Object.keys(t.datetimeFormats);i.length&&i.forEach(r=>{e.mergeDateTimeFormat(r,t.datetimeFormats[r])})}if(ae(t.numberFormats)){const i=Object.keys(t.numberFormats);i.length&&i.forEach(r=>{e.mergeNumberFormat(r,t.numberFormats[r])})}}}function za(e){return Q(Ur,null,e,0)}function en(){return _i??Hr()}const Za="__INTLIFY_META__",Xa=()=>[],jl=()=>!1;let Ja=0;function eo(e){return(t,n,a,o)=>e(n,a,en()||void 0,o)}const Gl=()=>{const e=en();let t=null;return e&&(t=Ii(e)[Za])?{[Za]:t}:null};function fn(e={}){const{__root:t,__injectWithOption:n}=e,a=t===void 0,o=e.flatJson,i=mn?Re:la;let r=ne(e.inheritLocale)?e.inheritLocale:!0;const l=i(t&&r?t.locale.value:F(e.locale)?e.locale:Xt),s=i(t&&r?t.fallbackLocale.value:F(e.fallbackLocale)||ve(e.fallbackLocale)||ce(e.fallbackLocale)||e.fallbackLocale===!1?e.fallbackLocale:l.value),c=i(ya(l.value,e)),m=i(ce(e.datetimeFormats)?e.datetimeFormats:{[l.value]:{}}),d=i(ce(e.numberFormats)?e.numberFormats:{[l.value]:{}});let u=t?t.missingWarn:ne(e.missingWarn)||qt(e.missingWarn)?e.missingWarn:!0,f=t?t.fallbackWarn:ne(e.fallbackWarn)||qt(e.fallbackWarn)?e.fallbackWarn:!0,A=t?t.fallbackRoot:ne(e.fallbackRoot)?e.fallbackRoot:!0,P=!!e.fallbackFormat,N=Te(e.missing)?e.missing:null,v=Te(e.missing)?eo(e.missing):null,S=Te(e.postTranslation)?e.postTranslation:null,b=t?t.warnHtmlMessage:ne(e.warnHtmlMessage)?e.warnHtmlMessage:!0,g=!!e.escapeParameter;const k=t?t.modifiers:ce(e.modifiers)?e.modifiers:{};let O=e.pluralRules||t&&t.pluralRules,w;w=(()=>{a&&Va(null);const E={version:Fl,locale:l.value,fallbackLocale:s.value,messages:c.value,modifiers:k,pluralRules:O,missing:v===null?void 0:v,missingWarn:u,fallbackWarn:f,fallbackFormat:P,unresolving:!0,postTranslation:S===null?void 0:S,warnHtmlMessage:b,escapeParameter:g,messageResolver:e.messageResolver,messageCompiler:e.messageCompiler,__meta:{framework:"vue"}};E.datetimeFormats=m.value,E.numberFormats=d.value,E.__datetimeFormatters=ce(w)?w.__datetimeFormatters:void 0,E.__numberFormatters=ce(w)?w.__numberFormatters:void 0;const D=Nl(E);return a&&Va(D),D})(),jt(w,l.value,s.value);function U(){return[l.value,s.value,c.value,m.value,d.value]}const G=z({get:()=>l.value,set:E=>{w.locale=E,l.value=E}}),se=z({get:()=>s.value,set:E=>{w.fallbackLocale=E,s.value=E,jt(w,l.value,E)}}),te=z(()=>c.value),be=z(()=>m.value),Ge=z(()=>d.value);function He(){return Te(S)?S:null}function Le(E){S=E,w.postTranslation=E}function ge(){return N}function tt(E){E!==null&&(v=eo(E)),N=E,w.missing=v}const qe=(E,D,de,Ee,Ct,At)=>{U();let Be;try{__INTLIFY_PROD_DEVTOOLS__,a||(w.fallbackContext=t?Rl():void 0),Be=E(w)}finally{__INTLIFY_PROD_DEVTOOLS__,a||(w.fallbackContext=void 0)}if(de!=="translate exists"&&Ce(Be)&&Be===bn||de==="translate exists"&&!Be){const[_r,Om]=D();return t&&A?Ee(t):Ct(_r)}else{if(At(Be))return Be;throw Me(Oe.UNEXPECTED_RETURN_TYPE)}};function B(...E){return qe(D=>Reflect.apply(Ka,null,[D,...E]),()=>Qn(...E),"translate",D=>Reflect.apply(D.t,D,[...E]),D=>D,D=>F(D))}function V(...E){const[D,de,Ee]=E;if(Ee&&!ae(Ee))throw Me(Oe.INVALID_ARGUMENT);return B(D,de,Ae({resolvedMessage:!0},Ee||{}))}function H(...E){return qe(D=>Reflect.apply(Ga,null,[D,...E]),()=>$n(...E),"datetime format",D=>Reflect.apply(D.d,D,[...E]),()=>hn,D=>F(D)||ve(D))}function ke(...E){return qe(D=>Reflect.apply($a,null,[D,...E]),()=>Yn(...E),"number format",D=>Reflect.apply(D.n,D,[...E]),()=>hn,D=>F(D)||ve(D))}function Pe(E){return E.map(D=>F(D)||Ce(D)||ne(D)?za(String(D)):D)}const X={normalize:Pe,interpolate:E=>E,type:"vnode"};function T(...E){return qe(D=>{let de;const Ee=D;try{Ee.processor=X,de=Reflect.apply(Ka,null,[Ee,...E])}finally{Ee.processor=null}return de},()=>Qn(...E),"translate",D=>D[Kn](...E),D=>[za(D)],D=>ve(D))}function L(...E){return qe(D=>Reflect.apply($a,null,[D,...E]),()=>Yn(...E),"number format",D=>D[Zn](...E),Xa,D=>F(D)||ve(D))}function q(...E){return qe(D=>Reflect.apply(Ga,null,[D,...E]),()=>$n(...E),"datetime format",D=>D[zn](...E),Xa,D=>F(D)||ve(D))}function $(E){O=E,w.pluralRules=O}function oe(E,D){return qe(()=>{if(!E)return!1;const de=F(D)?D:l.value,Ee=F(D)?[de]:Wn(w,s.value,de);for(let Ct=0;Ct[E],"translate exists",de=>Reflect.apply(de.te,de,[E,D]),jl,de=>ne(de))}function ye(E){let D=null;const de=Wn(w,s.value,l.value);for(let Ee=0;Ee{r&&(l.value=E,w.locale=E,jt(w,l.value,s.value))}),je(t.fallbackLocale,E=>{r&&(s.value=E,w.fallbackLocale=E,jt(w,l.value,s.value))}));const ee={id:Ja,locale:G,fallbackLocale:se,get inheritLocale(){return r},set inheritLocale(E){r=E,E&&t&&(l.value=t.locale.value,s.value=t.fallbackLocale.value,jt(w,l.value,s.value))},get availableLocales(){return Object.keys(c.value).sort()},messages:te,get modifiers(){return k},get pluralRules(){return O||{}},get isGlobal(){return a},get missingWarn(){return u},set missingWarn(E){u=E,w.missingWarn=u},get fallbackWarn(){return f},set fallbackWarn(E){f=E,w.fallbackWarn=f},get fallbackRoot(){return A},set fallbackRoot(E){A=E},get fallbackFormat(){return P},set fallbackFormat(E){P=E,w.fallbackFormat=P},get warnHtmlMessage(){return b},set warnHtmlMessage(E){b=E,w.warnHtmlMessage=E},get escapeParameter(){return g},set escapeParameter(E){g=E,w.escapeParameter=E},t:B,getLocaleMessage:Z,setLocaleMessage:me,mergeLocaleMessage:We,getPostTranslationHandler:He,setPostTranslationHandler:Le,getMissingHandler:ge,setMissingHandler:tt,[Pi]:$};return ee.datetimeFormats=be,ee.numberFormats=Ge,ee.rt=V,ee.te=oe,ee.tm=J,ee.d=H,ee.n=ke,ee.getDateTimeFormat=Ne,ee.setDateTimeFormat=p,ee.mergeDateTimeFormat=h,ee.getNumberFormat=R,ee.setNumberFormat=x,ee.mergeNumberFormat=Se,ee[Di]=n,ee[Kn]=T,ee[zn]=q,ee[Zn]=L,ee}function Wl(e){const t=F(e.locale)?e.locale:Xt,n=F(e.fallbackLocale)||ve(e.fallbackLocale)||ce(e.fallbackLocale)||e.fallbackLocale===!1?e.fallbackLocale:t,a=Te(e.missing)?e.missing:void 0,o=ne(e.silentTranslationWarn)||qt(e.silentTranslationWarn)?!e.silentTranslationWarn:!0,i=ne(e.silentFallbackWarn)||qt(e.silentFallbackWarn)?!e.silentFallbackWarn:!0,r=ne(e.fallbackRoot)?e.fallbackRoot:!0,l=!!e.formatFallbackMessages,s=ce(e.modifiers)?e.modifiers:{},c=e.pluralizationRules,m=Te(e.postTranslation)?e.postTranslation:void 0,d=F(e.warnHtmlInMessage)?e.warnHtmlInMessage!=="off":!0,u=!!e.escapeParameterHtml,f=ne(e.sync)?e.sync:!0;let A=e.messages;if(ce(e.sharedMessages)){const k=e.sharedMessages;A=Object.keys(k).reduce((w,W)=>{const U=w[W]||(w[W]={});return Ae(U,k[W]),w},A||{})}const{__i18n:P,__root:N,__injectWithOption:v}=e,S=e.datetimeFormats,b=e.numberFormats,g=e.flatJson;return{locale:t,fallbackLocale:n,messages:A,flatJson:g,datetimeFormats:S,numberFormats:b,missing:a,missingWarn:o,fallbackWarn:i,fallbackRoot:r,fallbackFormat:l,modifiers:s,pluralRules:c,postTranslation:m,warnHtmlMessage:d,escapeParameter:u,messageResolver:e.messageResolver,inheritLocale:f,__i18n:P,__root:N,__injectWithOption:v}}function Xn(e={}){const t=fn(Wl(e)),{__extender:n}=e,a={id:t.id,get locale(){return t.locale.value},set locale(o){t.locale.value=o},get fallbackLocale(){return t.fallbackLocale.value},set fallbackLocale(o){t.fallbackLocale.value=o},get messages(){return t.messages.value},get datetimeFormats(){return t.datetimeFormats.value},get numberFormats(){return t.numberFormats.value},get availableLocales(){return t.availableLocales},get missing(){return t.getMissingHandler()},set missing(o){t.setMissingHandler(o)},get silentTranslationWarn(){return ne(t.missingWarn)?!t.missingWarn:t.missingWarn},set silentTranslationWarn(o){t.missingWarn=ne(o)?!o:o},get silentFallbackWarn(){return ne(t.fallbackWarn)?!t.fallbackWarn:t.fallbackWarn},set silentFallbackWarn(o){t.fallbackWarn=ne(o)?!o:o},get modifiers(){return t.modifiers},get formatFallbackMessages(){return t.fallbackFormat},set formatFallbackMessages(o){t.fallbackFormat=o},get postTranslation(){return t.getPostTranslationHandler()},set postTranslation(o){t.setPostTranslationHandler(o)},get sync(){return t.inheritLocale},set sync(o){t.inheritLocale=o},get warnHtmlInMessage(){return t.warnHtmlMessage?"warn":"off"},set warnHtmlInMessage(o){t.warnHtmlMessage=o!=="off"},get escapeParameterHtml(){return t.escapeParameter},set escapeParameterHtml(o){t.escapeParameter=o},get pluralizationRules(){return t.pluralRules||{}},__composer:t,t(...o){return Reflect.apply(t.t,t,[...o])},rt(...o){return Reflect.apply(t.rt,t,[...o])},te(o,i){return t.te(o,i)},tm(o){return t.tm(o)},getLocaleMessage(o){return t.getLocaleMessage(o)},setLocaleMessage(o,i){t.setLocaleMessage(o,i)},mergeLocaleMessage(o,i){t.mergeLocaleMessage(o,i)},d(...o){return Reflect.apply(t.d,t,[...o])},getDateTimeFormat(o){return t.getDateTimeFormat(o)},setDateTimeFormat(o,i){t.setDateTimeFormat(o,i)},mergeDateTimeFormat(o,i){t.mergeDateTimeFormat(o,i)},n(...o){return Reflect.apply(t.n,t,[...o])},getNumberFormat(o){return t.getNumberFormat(o)},setNumberFormat(o,i){t.setNumberFormat(o,i)},mergeNumberFormat(o,i){t.mergeNumberFormat(o,i)}};return a.__extender=n,a}function $l(e,t,n){return{beforeCreate(){const a=en();if(!a)throw Me(Oe.UNEXPECTED_ERROR);const o=this.$options;if(o.i18n){const i=o.i18n;if(o.__i18n&&(i.__i18n=o.__i18n),i.__root=t,this===this.$root)this.$i18n=to(e,i);else{i.__injectWithOption=!0,i.__extender=n.__vueI18nExtend,this.$i18n=Xn(i);const r=this.$i18n;r.__extender&&(r.__disposer=r.__extender(this.$i18n))}}else if(o.__i18n)if(this===this.$root)this.$i18n=to(e,o);else{this.$i18n=Xn({__i18n:o.__i18n,__injectWithOption:!0,__extender:n.__vueI18nExtend,__root:t});const i=this.$i18n;i.__extender&&(i.__disposer=i.__extender(this.$i18n))}else this.$i18n=e;o.__i18nGlobal&&Oi(t,o,o),this.$t=(...i)=>this.$i18n.t(...i),this.$rt=(...i)=>this.$i18n.rt(...i),this.$te=(i,r)=>this.$i18n.te(i,r),this.$d=(...i)=>this.$i18n.d(...i),this.$n=(...i)=>this.$i18n.n(...i),this.$tm=i=>this.$i18n.tm(i),n.__setInstance(a,this.$i18n)},mounted(){},unmounted(){const a=en();if(!a)throw Me(Oe.UNEXPECTED_ERROR);const o=this.$i18n;o&&(delete this.$t,delete this.$rt,delete this.$te,delete this.$d,delete this.$n,delete this.$tm,o!=null&&o.__disposer&&(o.__disposer(),delete o.__disposer,delete o.__extender),n.__deleteInstance(a),delete this.$i18n)}}}function to(e,t){e.locale=t.locale||e.locale,e.fallbackLocale=t.fallbackLocale||e.fallbackLocale,e.missing=t.missing||e.missing,e.silentTranslationWarn=t.silentTranslationWarn||e.silentFallbackWarn,e.silentFallbackWarn=t.silentFallbackWarn||e.silentFallbackWarn,e.formatFallbackMessages=t.formatFallbackMessages||e.formatFallbackMessages,e.postTranslation=t.postTranslation||e.postTranslation,e.warnHtmlInMessage=t.warnHtmlInMessage||e.warnHtmlInMessage,e.escapeParameterHtml=t.escapeParameterHtml||e.escapeParameterHtml,e.sync=t.sync||e.sync,e.__composer[Pi](t.pluralizationRules||e.pluralizationRules);const n=ya(e.locale,{messages:t.messages,__i18n:t.__i18n});return Object.keys(n).forEach(a=>e.mergeLocaleMessage(a,n[a])),t.datetimeFormats&&Object.keys(t.datetimeFormats).forEach(a=>e.mergeDateTimeFormat(a,t.datetimeFormats[a])),t.numberFormats&&Object.keys(t.numberFormats).forEach(a=>e.mergeNumberFormat(a,t.numberFormats[a])),e}const Sa={tag:{type:[String,Object]},locale:{type:String},scope:{type:String,validator:e=>e==="parent"||e==="global",default:"parent"},i18n:{type:Object}};function Yl({slots:e},t){return t.length===1&&t[0]==="default"?(e.default?e.default():[]).reduce((a,o)=>[...a,...o.type===we?o.children:[o]],[]):t.reduce((n,a)=>{const o=e[a];return o&&(n[a]=o()),n},ue())}function Li(){return we}const Ql=Ue({name:"i18n-t",props:Ae({keypath:{type:String,required:!0},plural:{type:[Number,String],validator:e=>Ce(e)||!isNaN(e)}},Sa),setup(e,t){const{slots:n,attrs:a}=t,o=e.i18n||et({useScope:e.scope,__useComponent:!0});return()=>{const i=()=>{const s=Object.keys(n).filter(d=>d[0]!=="_"),c=ue();e.locale&&(c.locale=e.locale),e.plural!==void 0&&(c.plural=F(e.plural)?+e.plural:e.plural);const m=Yl(t,s);return o[Kn](e.keypath,m,c)},r=Ae(ue(),a),l=F(e.tag)||ae(e.tag)?e.tag:Li();return ae(l)?Ye(l,r,{default:i}):Ye(l,r,i())}}}),no=Ql;function Kl(e){return ve(e)&&!F(e[0])}function qi(e,t,n,a){const{slots:o,attrs:i}=t;return()=>{const r=()=>{const c={part:!0};let m=ue();e.locale&&(c.locale=e.locale),F(e.format)?c.key=e.format:ae(e.format)&&(F(e.format.key)&&(c.key=e.format.key),m=Object.keys(e.format).reduce((f,A)=>n.includes(A)?Ae(ue(),f,{[A]:e.format[A]}):f,ue()));const d=a(e.value,c,m);let u=[c.key];return ve(d)?u=d.map((f,A)=>{const P=o[f.type],N=P?P({[f.type]:f.value,index:A,parts:d}):[f.value];return Kl(N)&&(N[0].key=`${f.type}-${A}`),N}):F(d)&&(u=[d]),u},l=Ae(ue(),i),s=F(e.tag)||ae(e.tag)?e.tag:Li();return ae(s)?Ye(s,l,{default:r}):Ye(s,l,r())}}const zl=Ue({name:"i18n-n",props:Ae({value:{type:Number,required:!0},format:{type:[String,Object]}},Sa),setup(e,t){const n=e.i18n||et({useScope:e.scope,__useComponent:!0});return qi(e,t,Ri,(...a)=>n[Zn](...a))}}),ao=zl;function Zl(e,t){const n=e;if(e.mode==="composition")return n.__getInstance(t)||e.global;{const a=n.__getInstance(t);return a!=null?a.__composer:e.global.__composer}}function Xl(e){const t=r=>{const{instance:l,value:s}=r;if(!l||!l.$)throw Me(Oe.UNEXPECTED_ERROR);const c=Zl(e,l.$),m=oo(s);return[Reflect.apply(c.t,c,[...io(m)]),c]};return{created:(r,l)=>{const[s,c]=t(l);mn&&(r.__i18nWatcher=je(c.locale,()=>{l.instance&&l.instance.$forceUpdate()})),r.__composer=c,r.textContent=s},unmounted:r=>{mn&&r.__i18nWatcher&&(r.__i18nWatcher(),r.__i18nWatcher=void 0,delete r.__i18nWatcher),r.__composer&&(r.__composer=void 0,delete r.__composer)},beforeUpdate:(r,{value:l})=>{if(r.__composer){const s=r.__composer,c=oo(l);r.textContent=Reflect.apply(s.t,s,[...io(c)])}},getSSRProps:r=>{const[l]=t(r);return{textContent:l}}}}function oo(e){if(F(e))return{path:e};if(ce(e)){if(!("path"in e))throw Me(Oe.REQUIRED_VALUE,"path");return e}else throw Me(Oe.INVALID_VALUE)}function io(e){const{path:t,locale:n,args:a,choice:o,plural:i}=e,r={},l=a||{};return F(n)&&(r.locale=n),Ce(o)&&(r.plural=o),Ce(i)&&(r.plural=i),[t,l,r]}function Jl(e,t,...n){const a=ce(n[0])?n[0]:{};(ne(a.globalInstall)?a.globalInstall:!0)&&([no.name,"I18nT"].forEach(i=>e.component(i,no)),[ao.name,"I18nN"].forEach(i=>e.component(i,ao)),[lo.name,"I18nD"].forEach(i=>e.component(i,lo))),e.directive("t",Xl(t))}const ec=St("global-vue-i18n");function tc(e={}){const t=__VUE_I18N_LEGACY_API__&&ne(e.legacy)?e.legacy:__VUE_I18N_LEGACY_API__,n=ne(e.globalInjection)?e.globalInjection:!0,a=new Map,[o,i]=nc(e,t),r=St("");function l(d){return a.get(d)||null}function s(d,u){a.set(d,u)}function c(d){a.delete(d)}const m={get mode(){return __VUE_I18N_LEGACY_API__&&t?"legacy":"composition"},async install(d,...u){if(d.__VUE_I18N_SYMBOL__=r,d.provide(d.__VUE_I18N_SYMBOL__,m),ce(u[0])){const P=u[0];m.__composerExtend=P.__composerExtend,m.__vueI18nExtend=P.__vueI18nExtend}let f=null;!t&&n&&(f=cc(d,m.global)),__VUE_I18N_FULL_INSTALL__&&Jl(d,m,...u),__VUE_I18N_LEGACY_API__&&t&&d.mixin($l(i,i.__composer,m));const A=d.unmount;d.unmount=()=>{f&&f(),m.dispose(),A()}},get global(){return i},dispose(){o.stop()},__instances:a,__getInstance:l,__setInstance:s,__deleteInstance:c};return m}function et(e={}){const t=en();if(t==null)throw Me(Oe.MUST_BE_CALL_SETUP_TOP);if(!t.isCE&&t.appContext.app!=null&&!t.appContext.app.__VUE_I18N_SYMBOL__)throw Me(Oe.NOT_INSTALLED);const n=ac(t),a=ic(n),o=Ii(t),i=oc(e,o);if(i==="global")return Oi(a,e,o),a;if(i==="parent"){let s=ro(n,t,e.__useComponent);return s==null&&(s=a),s}if(i==="isolated"){if(n.mode!=="composition")throw Me(Oe.NOT_AVAILABLE_COMPOSITION_IN_LEGACY);const s=n,c=Ae({},e),m=ro(n,t);c.__root=m||a;const d=fn(c);return s.__composerExtend&&(d[It]=s.__composerExtend(d)),Go()&&Wo(()=>{const f=d[It];f&&(f(),delete d[It])}),d}const r=n;let l=r.__getInstance(t);if(l==null){const s=Ae({},e);"__i18n"in o&&(s.__i18n=o.__i18n),a&&(s.__root=a),l=fn(s),r.__composerExtend&&(l[It]=r.__composerExtend(l)),sc(r,t,l),r.__setInstance(t,l)}return l}function nc(e,t){const n=sa(),a=__VUE_I18N_LEGACY_API__&&t?n.run(()=>Xn(e)):n.run(()=>fn(e));if(a==null)throw Me(Oe.UNEXPECTED_ERROR);return[n,a]}function ac(e){const t=Xe(e.isCE?ec:e.appContext.app.__VUE_I18N_SYMBOL__);if(!t)throw Me(e.isCE?Oe.NOT_INSTALLED_WITH_PROVIDE:Oe.UNEXPECTED_ERROR);return t}function oc(e,t){return ua(e)?"__i18n"in t?"local":"global":e.useScope?e.useScope:"local"}function ic(e){return e.mode==="composition"?e.global:e.global.__composer}function ro(e,t,n=!1){let a=null;const o=t.root;let i=rc(t,n);for(;i!=null;){const r=e;if(e.mode==="composition")a=r.__getInstance(i);else if(__VUE_I18N_LEGACY_API__){const l=r.__getInstance(i);l!=null&&(a=l.__composer,n&&a&&!a[Di]&&(a=null))}if(a!=null||o===i)break;i=i.parent}return a}function rc(e,t=!1){return e==null?null:t&&e.vnode.ctx||e.parent}function sc(e,t,n){ca(()=>{},t),Yo(()=>{const a=n;e.__deleteInstance(t);const o=a[It];o&&(o(),delete a[It])},t)}const lc=["locale","fallbackLocale","availableLocales"],so=["t","rt","d","n","tm","te"];function cc(e,t){const n=Object.create(null);return lc.forEach(o=>{const i=Object.getOwnPropertyDescriptor(t,o);if(!i)throw Me(Oe.UNEXPECTED_ERROR);const r=Kt(i.value)?{get(){return i.value.value},set(l){i.value.value=l}}:{get(){return i.get&&i.get()}};Object.defineProperty(n,o,r)}),e.config.globalProperties.$i18n=n,so.forEach(o=>{const i=Object.getOwnPropertyDescriptor(t,o);if(!i||!i.value)throw Me(Oe.UNEXPECTED_ERROR);Object.defineProperty(e.config.globalProperties,`$${o}`,i)}),()=>{delete e.config.globalProperties.$i18n,so.forEach(o=>{delete e.config.globalProperties[`$${o}`]})}}const dc=Ue({name:"i18n-d",props:Ae({value:{type:[Number,Date],required:!0},format:{type:[String,Object]}},Sa),setup(e,t){const n=e.i18n||et({useScope:e.scope,__useComponent:!0});return qi(e,t,Ai,(...a)=>n[zn](...a))}}),lo=dc;Vl();bl(nl);El(yl);wl(Wn);if(__INTLIFY_PROD_DEVTOOLS__){const e=ft();e.__INTLIFY__=!0,al(e.__INTLIFY_DEVTOOLS_GLOBAL_HOOK__)}var uc={name:"zh-cn",el:{breadcrumb:{label:"面包屑"},colorpicker:{confirm:"确定",clear:"清空",defaultLabel:"颜色选择器",description:"当前颜色 {color},按 Enter 键选择新颜色",alphaLabel:"选择透明度的值",alphaDescription:"透明度 {alpha}, 当前颜色 {color}",hueLabel:"选择色相值",hueDescription:"色相 {hue}, 当前颜色 {color}",svLabel:"选择饱和度与明度的值",svDescription:"饱和度 {saturation}, 明度 {brightness}, 当前颜色 {color}",predefineDescription:"选择 {value} 作为颜色"},datepicker:{now:"此刻",today:"今天",cancel:"取消",clear:"清空",confirm:"确定",dateTablePrompt:"使用方向键与 Enter 键可选择日期",monthTablePrompt:"使用方向键与 Enter 键可选择月份",yearTablePrompt:"使用方向键与 Enter 键可选择年份",selectedDate:"已选日期",selectDate:"选择日期",selectTime:"选择时间",startDate:"开始日期",startTime:"开始时间",endDate:"结束日期",endTime:"结束时间",prevYear:"前一年",nextYear:"后一年",prevMonth:"上个月",nextMonth:"下个月",year:"年",month1:"1 月",month2:"2 月",month3:"3 月",month4:"4 月",month5:"5 月",month6:"6 月",month7:"7 月",month8:"8 月",month9:"9 月",month10:"10 月",month11:"11 月",month12:"12 月",weeks:{sun:"日",mon:"一",tue:"二",wed:"三",thu:"四",fri:"五",sat:"六"},weeksFull:{sun:"星期日",mon:"星期一",tue:"星期二",wed:"星期三",thu:"星期四",fri:"星期五",sat:"星期六"},months:{jan:"一月",feb:"二月",mar:"三月",apr:"四月",may:"五月",jun:"六月",jul:"七月",aug:"八月",sep:"九月",oct:"十月",nov:"十一月",dec:"十二月"}},inputNumber:{decrease:"减少数值",increase:"增加数值"},select:{loading:"加载中",noMatch:"无匹配数据",noData:"无数据",placeholder:"请选择"},mention:{loading:"加载中"},dropdown:{toggleDropdown:"切换下拉选项"},cascader:{noMatch:"无匹配数据",loading:"加载中",placeholder:"请选择",noData:"暂无数据"},pagination:{goto:"前往",pagesize:"条/页",total:"共 {total} 条",pageClassifier:"页",page:"页",prev:"上一页",next:"下一页",currentPage:"第 {pager} 页",prevPages:"向前 {pager} 页",nextPages:"向后 {pager} 页",deprecationWarning:"你使用了一些已被废弃的用法,请参考 el-pagination 的官方文档"},dialog:{close:"关闭此对话框"},drawer:{close:"关闭此对话框"},messagebox:{title:"提示",confirm:"确定",cancel:"取消",error:"输入的数据不合法!",close:"关闭此对话框"},upload:{deleteTip:"按 Delete 键可删除",delete:"删除",preview:"查看图片",continue:"继续上传"},slider:{defaultLabel:"滑块介于 {min} 至 {max}",defaultRangeStartLabel:"选择起始值",defaultRangeEndLabel:"选择结束值"},table:{emptyText:"暂无数据",confirmFilter:"筛选",resetFilter:"重置",clearFilter:"全部",sumText:"合计",selectAllLabel:"选择所有行",selectRowLabel:"选择当前行",expandRowLabel:"展开当前行",collapseRowLabel:"收起当前行",sortLabel:"按 {column} 排序",filterLabel:"按 {column} 过滤"},tag:{close:"关闭此标签"},tour:{next:"下一步",previous:"上一步",finish:"结束导览",close:"关闭此对话框"},tree:{emptyText:"暂无数据"},transfer:{noMatch:"无匹配数据",noData:"无数据",titles:["列表 1","列表 2"],filterPlaceholder:"请输入搜索内容",noCheckedFormat:"共 {total} 项",hasCheckedFormat:"已选 {checked}/{total} 项"},image:{error:"加载失败"},pageHeader:{title:"返回"},popconfirm:{confirmButtonText:"确定",cancelButtonText:"取消"},carousel:{leftArrow:"上一张幻灯片",rightArrow:"下一张幻灯片",indicator:"幻灯片切换至索引 {index}"},inputOTP:{groupLabel:"一次性密码输入框",defaultLabel:"请输入第 {index} 位 OTP 字符"}}};const pc={common:{previous:"Previous",next:"Next",pageOf:"Page {current} of {pages}",save:"Save",cancel:"Cancel",requiredShort:"Required",mustBePositive:"Must be > 0",maxTwoDecimals:"Max 2 decimals",close:"Close",confirm:"Confirm",search:"Search",reset:"Reset",detail:"Detail",view:"View",noPermissionToView:"You do not have permission to view these records",kpiGo:"View →",back:"Back",edit:"Edit",delete:"Delete",refresh:"Refresh",actions:"Actions",moreActions:"More actions",viewDetails:"View details",viewAuditLog:"View audit log",status:"Status",keyword:"Keyword",createdAt:"Created at",updatedAt:"Updated at",owner:"Owner",none:"—",projectFilter:"Project: {code}",traceId:"Trace ID",empty:"No data",emptyOwned:"Nothing here for the customers you are responsible for",emptyFiltered:"Nothing matches these filters",legacy:"Legacy",months:"{n} months",selectPlaceholder:"Please select",saved:"Saved",created:"Created",deleted:"Deleted",requestFailed:"Request failed",networkError:"Network error",placeholderPage:"Skeleton placeholder — this module is not built yet"},confirm:{consequencesLead:"This will:",affectedLead:"Affected ({n}):",irreversible:"This cannot be undone.",reasonRequired:"Please say why — it goes into the audit trail",reasonOptional:"Reason (optional)",reasonTooLong:"The reason can be at most {max} characters; it is {n} now",typeWord:"Type {word} to confirm",wordMismatch:"Type {word} exactly as shown (case-sensitive)"},globalSearch:{trigger:"Search",shortcutHint:"Global search ({key})",placeholder:"Search organizations, quotations, contracts, projects, claims...",jumpTo:"Jump to",recent:"Recently viewed",recentEmpty:"Nothing viewed yet. Organizations, quotations, contracts, projects, entitlements and claims you open will appear here.",searching:"Searching…",showingTop:"Showing {n} of {total}",groupFailed:"This type couldn't be loaded. The others are unaffected.",noResult:'No matches. Try "companies", "claims", "projects"...',noSearchable:"You don't have permission to view any of organizations, quotations, contracts, projects, entitlements or claims.",keyMove:"to move",keyOpen:"to open",keyClose:"to close",type:{company:"Organization",quotation:"Quotation",contract:"Contract",project:"Project",instance:"Product entitlement",claim:"Billing claim"}},editConflict:{title:"Someone else changed this record while you were editing. Compared with the latest version:",taken:"Changed by them, untouched by you, now updated to their values: {fields}",merged:"Changed by both of you. Their additions and removals are merged into yours: {fields}",clashed:"Changed by both of you. Saving keeps your values and overwrites theirs: {fields}",noOverlap:"Their changes don't touch anything you edited. Everything you entered is kept.",saveAgain:"Check the form, then save again.",separator:", ",goneTitle:"Someone else deleted this record, so it can't be saved. What you entered is still here to copy before closing.",failedTitle:"Someone else changed this record, and the latest version couldn't be loaded. What you entered is kept; try saving again later."},menu:{inventory:"Hardware Inventory",systemGuide:"System Guide",authPolicy:"Auth & SSO",orgGeneral:"General",dashboard:"Dashboard",analytics:"Analytics",myTasks:"My Tasks",inbox:"Inbox",crm:"Customer Lifecycle",companies:"Organizations",quotations:"Quotations",contracts:"Contracts",delivery:"Delivery",projects:"Projects",projectDetail:"Project Detail",productInstances:"Product Entitlements",productInstanceDetail:"Product Entitlement",provisioning:"Provisioning",products:"Products",role_templates:"Role templates",workflowTemplates:"Workflow Templates",notificationTemplates:"Notification Templates",pipelines:"Provisioning templates",onboarding:"Onboarding",onboardingDetail:"Onboarding Detail",billing:"Finance",claims:"Billing Claims",invoices:"Invoices",claimDetail:"Claim Detail",invoiceDetail:"Invoice Detail",handover:"Closure",handovers:"Handovers",handoverDetail:"Handover Detail",companyDetail:"Organization Detail",quotationDetail:"Quotation Detail",contractDetail:"Contract Detail",provisioningDetail:"Provisioning Run",productDetail:"Product Detail",hardwareDetail:"Hardware Model",overInstallationDetail:"Over-installation",roleTemplateDetail:"Role Template",terms:"Commercial Terms",termDetail:"Term",login:"Sign in",system:"System",users:"Users",userDetail:"User Detail",roles:"Roles",profile:"Personal Settings",audit:"Audit Log",compliance:"Compliance",accessGrants:"Temporary customer access",accessGrantDetail:"Access grant",auditEvents:"Business audit",accessLogs:"Access logs"},shell:{unread:"Unread",openNav:"Open navigation",brand:"BES BOSS",brandSub:"Internal Platform",breadcrumb:"Breadcrumb",group:{workspace:"Workspace",commercial:"Organizations & Commercial",delivery:"Delivery",products:"Products & Automation",hardware:"Hardware Operations",finance:"Finance",access:"Access & Security"},accessCenter:"Access Center",auditLog:"Audit Log",orgSettings:"Organization Settings",accountSettings:"Account settings",tab:{general:"General",auth:"Auth & SSO",staffPolicy:"Internal staff policy",customerAccess:"Temporary customer access",businessAudit:"Business audit",accessLogs:"Access logs",compliance:"Compliance"}},locale:{label:"Language",en:"English","zh-CN":"简体中文"},theme:{toLight:"Switch to light",toDark:"Switch to dark",light:"Light",dark:"Dark",auto:"Auto"},prefs:{title:"Display Preferences",subtitle:"Customize how BES BOSS looks for you",language:"Language",timeZone:"Time zone",dateFormat:"Date format",timeFormat:"Time format",theme:"Theme",sidebarDensity:"Sidebar density",date:{iso:"2026-05-20 (ISO)",dmy:"20/05/2026 (DD/MM/YYYY)",mdy:"05/20/2026 (MM/DD/YYYY)",long:"20 May 2026"},time:{"24h":"24-hour (14:30)","12h":"12-hour (2:30 PM)"},density:{compact:"Compact",comfortable:"Comfortable",spacious:"Spacious"},inZone:"Time in {zone}",sgtDate:"Dates in Singapore time"},mfa:{codeLabel:"Verification code",appHint:"Open the authenticator app on your phone to see the code.",lostTitle:"Lost access to your second factor?",lostBody:"Contact your administrator to reset your MFA. Reset requests are logged and reviewed.",verifyTitle:"Two-factor authentication",verifySubtitle:"Enter the 6-digit code from your authenticator app.",codePlaceholder:"6-digit code or a backup code",codeRequired:"Enter the code",verifySubmit:"Verify and continue",oneShotHint:"This challenge is single-use: if the code is wrong you will be signed out and have to enter your password again. That is deliberate — it makes guessing codes pointless.",backToLogin:"Back to sign in",setupTitle:"Set up two-factor authentication",setupSubtitle:"Scan this with an authenticator app, then enter the code it shows.",requiredBy:"This has to be set up by {date}.",qrAlt:"Authenticator setup QR code",scanHint:"Google Authenticator, 1Password, Authy — any TOTP app will do.",cannotScan:"Can't scan? Enter the key by hand",copySecret:"Copy key",secretHint:"Same key as the QR code — use one or the other, not both. It is shown only during setup.",setupCodePlaceholder:"6-digit code",setupSubmit:"Confirm and sign in",setupWrongCodeHint:"If the code keeps being rejected, check that your phone's clock is set automatically — TOTP codes are derived from the current time.",copied:"Copied",copyFailed:"Could not copy — select the text and copy it manually",backupTitle:"Save your backup codes",backupOnceTitle:"Shown once, right now",backupOnceHint:"These are stored only as hashes, so they cannot be shown again — close this page and they are gone for good. Each one works once, and they are the only way in if you lose your phone. Keep them somewhere other than that phone.",copyAll:"Copy all",download:"Download as .txt",savedAck:"I have saved these codes somewhere safe",enterConsole:"Continue"},stepUp:{title:"Confirm it's you in BES",subtitle:"This action is high-risk",step1:'Click "Open BES confirmation" and confirm your identity in the window that opens (password or two-step verification, done in BES).',step2:`Come back here and click "Continue". The action runs once you've confirmed.`,expires:"Confirm before {time}.",restartHint:'If the confirmation page failed, expired or was closed, click "Start again" for a new one.',pending:`BES hasn't accepted the confirmation yet. Finish it on the confirmation page, then click "Continue" — or "Start again" if it failed.`,renewed:"The earlier confirmation is no longer valid. A new one has been started — open the confirmation page again.",open:"Open BES confirmation",continue:"Continue",restart:"Start again",mfaTitle:"Set up two-step verification first",mfaBody:"Your account has no two-step verification, so BES can't confirm this high-risk action. Set it up on your BES account page, then try the action again.",mfaOpen:"Open account settings"},login:{control:{SIGN_IN:{title:"Sign in",body:"Sign in with your BES account. Your password and two-step verification are handled on the BES sign-in page.",action:"Continue with BES account"},NOT_STAFF:{title:"This account can't use BOSS",body:"The BES account you signed in with has no BOSS staff record, or its email address hasn't been verified. Sign in with your staff account, or ask an administrator to add you.",action:"Sign in with another account"},ACCOUNT_NOT_ACTIVE:{title:"Your account is suspended",body:"Your BOSS staff account has been suspended. Ask an administrator to reactivate it.",action:"Sign in with another account"},LOGIN_FAILED:{title:"Sign-in didn't complete",body:"The sign-in was interrupted or expired before it finished. Start again.",action:"Sign in again"},NO_ACCESS:{title:"No access to BOSS",body:"You're signed in, but your account doesn't currently have access to BOSS. Ask an administrator to check your roles.",action:"Sign out"},UNAVAILABLE:{title:"Can't reach the sign-in service",body:"BOSS or the BES identity service is temporarily unavailable. Try again in a moment.",action:"Try again"},secureTitle:"Signed in through BES",secureBody:"BOSS never sees your password. Manage your password, two-step verification and signed-in browsers from your BES account page."},secureTitle:"Secure sign in",secureBody:"All authentication attempts are logged. Two-factor authentication is required for all accounts.",footCopyright:"© 2026 Global BES Pte. Ltd.",footSecure:"Encrypted connection · All authentication events are audited",title:"Sign in to your account",subtitle:"Welcome back. Enter your credentials to continue.",username:"Username",password:"Password",submit:"Sign in",hint:"Signed in as the seeded account {account} — credentials are prefilled for local development",guideAccountLocked:"This account is locked — repeated wrong passwords trigger that protection. It clears itself once the time above has passed; ask an administrator to reset it if you need in sooner.",guideAccountNotActive:"This account cannot sign in right now, and retrying will not help. Ask an administrator to check its status.",missingCredentials:"Please enter username and password"},dashboard:{roleDesc:{sales:"Sales view — pipeline, conversions and renewals that need a decision.",operations:"Operations view — onboarding, provisioning and handover blockers.",finance:"Finance view — billing claims, invoices and receivables.",products:"Products view — instances and provisioning.",admin:"Admin view — access requests, break-glass, inactive staff and audit alerts."},kpiChip:{critical:"Critical",clear:"None",quotesAwaitingFollowUp:"Act",contractsAwaitingActivation:"Act",renewalRisk:"30 days",overdueReceivables:"Watch",accessRequestsPending:"Review",auditAlerts:"Triage",activeOnboardings:"In flight",breakGlassActive:"Active now",inactiveUsers:"Review"},pipelineTitle:"Lifecycle pipeline",pipelineSub:"Customers moving from quote to live across the platform",viewCompanies:"View companies",stageQuotes:"Quotes",stageQuotesSub:"open",stageContracts:"Contracts",stageContractsSub:"active",stageProvisioning:"Provisioning",stageProvisioningSub:"{n} failed",stageLive:"Live",stageLiveSub:"instances",stageRenewals:"Renewals",stageRenewalsSub:"next 90 days",recentTitle:"Recent Activity",recentSub:"Latest events across the platform",viewAuditLog:"View audit log",recentEmpty:"No events yet.",recentFailed:"Couldn't load recent events. Open the audit log to see them.",pageTitle:"BOSS Work Dashboard",pageSubtitle:"Internal action centre for BES sales, operations, finance, products and admin teams.",provFailedTitle:"{n} provisioning run failed — needs Ops | {n} provisioning runs failed — needs Ops",provFailedHint:"Customer set-ups stuck mid-way. Investigate the cause, then retry.",provFailedCta:"Open Provisioning Monitor",quickActions:"Quick Actions",qaNewCompany:"New Company",qaNewQuotation:"New Quotation",qaStartOnboarding:"Start Onboarding"},error:{loadFailed:"Could not load this",loadFailedHint:'The request failed — this is not "no data".',retry:"Try again",notFound:"Page not found",notFoundDesc:"This page does not exist, or your account has no permission to open it.",backHome:"Back to dashboard"},user:{removeMenu:"Remove user",removeTitle:"Remove {name}?",removeSubtitle:"Audit log retained",removeChecking:"Checking what this person still owns…",removeBlockedLead:"Reassign these first — Remove stays disabled until they're cleared:",removeBlockerCompanies:"Account owner of {n} customer(s). Change the owner on each customer.",removeBlockerProjects:"Owner of {n} active project(s). Change the owner on each project.",removeBlockerTasks:"{n} open task(s) assigned to them. Have them handled or reassigned.",removeBlockerSelf:"You can't remove your own account.",removeBlockerLastAdmin:"They're the last active user who can manage staff. Give another active user that permission first.",removeBlockerAlready:"This person has already been removed.",removeBlockerOther:"Blocked by the server: {code}",removeViewCompanies:"View these customers",removeViewProjects:"View these projects",removeConsequenceList:"take them off the staff list — audit records and their name on documents stay",removeConsequenceRoles:"revoke all their roles and end their sessions right away",removeConsequenceControl:"deactivate their BES account; this email can't be used for a new invite",removeConsequenceDocs:"keep them as owner on quotations, contracts, onboardings and handovers — change those on each record",removeConsequenceFinal:"be permanent — a removed user can't be reactivated",removeConfirmWord:"Type {word} to confirm",removeConfirmMismatch:"Type {word} exactly",removeAction:"Remove",removed:"{name} removed",removedReadOnly:"This person has been removed. The record is kept for audit and references; it can no longer be changed.",inviteCreate:"Invite user",inviteTitle:"Invite user to BES BOSS",inviteLead:"Creates the person in BES and assigns the roles. They set their password and two-step verification through a first sign-in link.",inviteSubmit:"Send invite",firstName:"First name",lastName:"Last name",firstNamePlaceholder:"e.g. Sarah",lastNamePlaceholder:"e.g. Chen",emailPlaceholder:"user{'@'}bes.sg",firstNameRequired:"Enter the first name",lastNameRequired:"Enter the last name",rolesRequired:"Select at least one role",emailRequired:"Enter the email",inviteEmailHint:"They sign in to BES with this email. It becomes their BOSS username and can't be changed here later.",accountType:"Account type",sendInvite:"Send welcome email immediately",sendInviteOn:"Sends a first sign-in link, valid for 48 hours.",sendInviteOff:`No email is sent now. Use "Resend setup link" when they're ready.`,invited:"Invited — first sign-in link sent",invitedNoEmail:"Created — no email sent yet",emailManagedInBes:"Email is managed in BES; the person changes it on their BES account page.",rolesNotInControl:"This person hasn't signed in through BES yet, so roles can't be changed until they do.",resendInvite:"Resend setup link",resendInviteTitle:"Resend first sign-in link?",resendInviteAction:"Resend",resendInviteConsequenceSend:"send {name} ({email}) a new first sign-in email to set a password and two-step verification",resendInviteConsequenceExpiry:"make the new link valid for 48 hours",resendInviteConsequenceOld:"invalidate the link sent before",resendInviteDone:"First sign-in link sent",sendReset:"Send password reset",sendResetTitle:"Send password reset email?",sendResetAction:"Send reset",sendResetConsequenceEmail:"send a one-time password reset link to {name}'s verified email",sendResetConsequenceExpiry:"make the link valid for 10 minutes",sendResetConsequenceSignOut:"sign them out of BES everywhere right away, BOSS included",sendResetConsequenceNoPassword:"leave the new password to them — BOSS never sees it",sendResetDone:"Password reset email sent",logout:"Sign out",fallbackName:"User",selectOwner:"Select owner",title:"Users",create:"New user",editTitle:"Edit user",createTitle:"New user",searchPlaceholder:"Username / display name",username:"Username",usernameImmutable:"Username cannot be changed — it is the identity anchor in audit records",displayName:"Display name",email:"Email",department:"Department",seniority:"Seniority",roles:"Roles",noRoles:"No role assigned",lastLogin:"Last sign-in",neverLoggedIn:"Never signed in",pageSubtitle:"BES internal staff accounts. Not to be confused with customer-side users (managed in product platforms).",tabAll:"All",userColumn:"User",roleColumn:"Role",footTitle:"BES internal users only.",footBody:"Customer end-users are managed by their Company Admin in the product platforms (BOSP, AIVA, etc) — not here. Suspended accounts retain audit history but cannot log in.",autoSuspendIn:"Auto-suspend in {days}d",autoSuspendDue:"Auto-suspend pending",autoSuspendHint:"No sign-in for {days} days suspends the account automatically. Counting from {since}.",password:"Initial password",passwordHint:"There is no mail service — hand the initial password over offline; the user changes it after signing in.",suspend:"Suspend",suspendMenu:"Suspend user",activate:"Reactivate user",resetPassword:"Reset password",resetMfa:"Reset MFA",suspendConsequenceLogin:"stop {name} from signing in — from the next attempt on",suspendConsequenceSession:"terminate their active sessions right away — the audit log and account record are retained",suspendConsequenceReversible:"be reversible — you can reactivate the account at any time",activateTitle:"Reactivate account",activateConsequenceLogin:"let {name} sign in again with their current password",activateConsequenceRoles:"restore everything their roles allow — the roles themselves are unchanged",resetConsequenceLogin:"replace {name}'s password with the one you type next",resetConsequenceNoNotify:"not notify them — BOSS does not send mail, so you have to pass it on yourself",resetConsequenceMfaKept:"leave their MFA binding alone — they still need their authenticator code",resetMfaConsequenceUnbind:"unbind {name}'s authenticator and void their backup codes",resetMfaConsequenceSingleFactor:"leave that account on the password alone until they bind a new authenticator — it is single-factor in the meantime",resetMfaConsequenceRebind:"make them set up MFA again the next time they sign in",resetMfaDone:"MFA reset — they will be asked to set it up again at next sign-in",suspendTitle:"Suspend account",suspended:"Account suspended",activated:"Account activated",resetTitle:"Reset password",resetPrompt:'Set a new password for "{name}". {rule} They will be forced to sign in again.',resetDone:"Password reset — the user must sign in again",usernameRequired:"Username is required",displayNameRequired:"Display name is required",passwordRequired:"Password is required",internalStaff:"BES Internal Staff",joined:"Joined {date}",kpiOwnedCompanies:"Owned Companies",kpiActiveProjects:"Active Projects",kpiOpenTasks:"Open Tasks",kpiLastActive:"Last Active",neverActive:"Never",tabOverview:"Overview",tabActivity:"Activity",personalInfo:"Personal Information",editPersonalTitle:"Edit Personal Information",fullName:"Full Name",jobTitle:"Job Title",employeeType:"Employee Type",reportsTo:"Reports To",selectReportsTo:"Select manager",activitySummary:"Recent Activity Summary",last30Days:"Last 30 days",summary:{quotationsCreated:"Quotations created",contractsSigned:"Contracts signed",onboardingsLed:"Onboardings led",systemActions:"System actions"},activityTimeline:"Activity Timeline",colTime:"Timestamp",colEvent:"Event",colResource:"Resource",colDetails:"Details",activityEmpty:"No activity yet",viewFullAudit:"View full audit log →",tabAccess:"Access & Roles",customerOwnership:"Customer Ownership",customerOwnershipSub:"Companies whose account team this user is on",customerOwnershipEmpty:"Not on any customer's account team yet",assignCustomerButton:"Assign customer",assignInactive:"Only active staff can be assigned to a customer",colCompany:"Company",colRelationship:"Role",colStage:"Stage",colActiveProjects:"Active Projects",colSince:"Since",showingCompanies:"Showing {n} of {total} companies · ",viewAll:"View all →",removeFromTeam:"Remove",removeFromTeamTitle:"Remove from account team",removeFromTeamConsequence1:"{name} will no longer be {role} for {company}",removeFromTeamConsequence2:'Staff with "Owned customers" data scope lose sight of this customer right away; quotations, contracts and audit records they handled stay visible to them',removeFromTeamDone:"Removed from the account team",assignCustomerTitle:"Assign customer to {name}",assignCustomerSubtitle:"Choose a customer and {name}'s role on its account team",assignCustomer:"Customer",assignCustomerPlaceholder:"— Select customer —",assignCustomerRequired:"Select a customer",assignRole:"Role",assignRoleRequired:"Select a role",assignSubmit:"Assign",assignDone:"Customer assigned",assignReplacesOwner:"The current Primary Account Owner, {owner}, will be replaced and will no longer be on this customer's account team",assignAlreadyOwner:"{name} is already the Primary Account Owner of this customer",assignOwnerCannotJoin:"{name} is the Primary Account Owner of this customer. Assign the Primary Account Owner to someone else first",passwordRule:"12–64 characters, including an uppercase letter, a lowercase letter, a digit and a symbol."},role:{kpiTotal:"Total Permissions",kpiModules:"{n} modules",kpiUsers:"{n} user | {n} users",kpiSystem:"System",kpiEditable:"Editable",title:"Roles",create:"New role",createTitle:"New role",editTitle:"Edit role",code:"Code",codeHint:"Converted to lowercase. Starts with a letter; letters, digits, _ . - only; up to 48 characters; must be unique; cannot be changed later",codeFormat:"Start with a letter; use only letters, digits, _ . -; up to 48 characters",codeReserved:"staff-base is reserved for the base role every staff member has",name:"Name",userCount:"Members",permissions:"Permissions",grants:"Granted",denies:"Denied",denyHint:"Denies override grants from every other role — when someone holds several roles, an explicit deny must win.",dataScope:"Data scope",dataScopeHint:"Orthogonal to permission points: permissions decide what you can do, data scope decides whose data you can see. On OWNED a user only sees the customers they own — plus quotations, contracts and audit records they handled themselves.",dataScopeLocked:"The admin role is always on All data and cannot be changed.",systemLocked:"System role",systemLockedHint:"The admin role is system-locked: its permissions always equal the full set and cannot be edited or deleted here.",deleteTitle:"Delete role",deleteConsequenceGone:'delete the role "{name}" and the permission set it carries',deleteConsequenceInUse:"be refused while any staff member still holds this role — reassign them first",catalogEmpty:"No permission points",codeRequired:"Code is required",nameRequired:"Name is required",replaceHint:"Permissions are replaced wholesale — what you check here becomes the role's full set."},profile:{changeConfirmTitle:"Change password?",changeConsequenceReplace:"replace your password — the old one stops working from your next sign-in",changeConsequenceSessions:"keep this and any other signed-in session open — nobody is signed out",changeConsequenceAudit:"be written to the audit log — no email is sent, so if you didn't make this change, contact your Admin",title:"Personal Settings",tabProfile:"Profile",tabPassword:"Password",pageSubtitle:"Your account preferences. These settings apply only to you and can be changed anytime.",profileSubtitle:"Basic information visible to other BES staff",tabDisplay:"Display",tabNotifications:"Notifications",changePassword:"Change password",accountTitle:"Password & two-step verification",accountBody:"Your password, two-step verification, recovery codes and signed-in browsers are managed on your BES account page. BOSS never sees your password.",accountOpen:"Open BES account page",passwordTitle:"Change Password",oldPassword:"Current password",newPassword:"New password",confirmPassword:"Confirm new password",changed:"Password updated",mismatch:"The two passwords do not match",oldRequired:"Current password is required",photoTitle:"Profile photo",photoHint:"JPG, PNG or GIF. Max 2 MB.",uploadNew:"Upload new",removePhoto:"Remove",avatarUploaded:"Profile photo updated",avatarRemoved:"Avatar removed — reverted to initials.",fullName:"Full name",displayName:"Display name",email:"Email",emailReadOnly:"(read-only · contact Admin to change)",emailReadOnlyControl:"(read-only · change it on your BES account page)",phone:"Phone",phoneOnAccount:"Managed on your BES account page",jobTitle:"Job title",department:"Department",departmentSetByAdmin:"(set by Admin)",discard:"Discard",discarded:"Changes discarded.",saveChanges:"Save changes",noChanges:"Nothing has changed",saveConfirmTitle:"Save changes?",saveConsequenceUpdate:"update your profile — other BES staff see the change immediately",saveConsequenceAudit:"record the change in your staff history",saved:"Profile saved",displayNameRequired:"Display name is required",conflictReloaded:"Your profile was changed elsewhere. The latest version is loaded — your edits are kept; check them and save again."},analytics:{pageTitle:"Business Overview",desc:{sales:"Sales performance — pipeline, conversion and recurring revenue.",operations:"Operations — onboarding, provisioning and handover health.",finance:"Finance — billing, collections and receivables.",products:"Products — live instances, product mix and provisioning.",admin:"Admin — access requests, break-glass, inactive staff and audit activity."},viewAsRole:"View as role",view:{sales:"Sales",operations:"Operations",finance:"Finance",products:"Products",admin:"Admin"},range:{TODAY:"Today",YESTERDAY:"Yesterday",LAST_7:"Last 7 days",LAST_30:"Last 30 days",LAST_90:"Last 90 days",THIS_QUARTER:"This quarter",YTD:"Year to date",CUSTOM:"Custom range…"},from:"From",to:"To",apply:"Apply",rangeTooLong:"Pick a range of 366 days or less",export:"Export",exportTitle:"Export overview",exportFormat:"Format",exportScope:"Scope",scopeCurrent:"Current role view",scopeAll:"All role views",download:"Download",noData:"No data in this period",noPermission:"No permission to view",daysValue:"{n} days",changePt:"{n}pt",changeDays:"{n} days",lastSixMonths:"Last 6 months",quotationsIn:"Quotations · {range}",kpi:{openPipeline:"Open pipeline",winRate:"Win rate",mrr:"MRR",quotationsSent:"Quotations sent",quotesAwaitingFollowUp:"Quotes awaiting follow-up",contractsAwaitingActivation:"Contracts awaiting activation",renewalRisk:"Renewal risk",activeOnboardings:"Active onboardings",blockedOnboardings:"Blocked",provisioningSuccessRate:"Provisioning success",handoverOverdue:"Handover overdue",provisioningFailed:"Provisioning failed",arr:"ARR",collected:"Collected",collectedIn:"Collected · {range}",overdueReceivables:"Overdue receivables",dso:"DSO",invoicesOverdue:"Invoices overdue",claimsPending:"Billing claims pending",liveInstances:"Live instances",provisioningFailures:"Provisioning failures",accessRequestsPending:"Access requests pending",breakGlassActive:"Break-glass active",inactiveUsers:"Inactive users · 30d",auditAlerts:"Audit alerts"},sales:{mrrTitle:"Monthly Recurring Revenue",yoy:"{arrow} {n}% YoY",funnelTitle:"Sales Funnel",funnel:{sent:"Sent",opened:"Opened",negotiation:"Negotiation",accepted:"Accepted"},conversionTitle:"Quotation Conversion",conversionSub:"Sent vs accepted vs lost",accepted:"Accepted",lost:"Lost",open:"Open",topTitle:"Top Customers by ACV",topSub:"Annual contract value",lossTitle:"Loss Reasons"},operations:{throughputTitle:"Implementation Throughput",throughputSub:"Onboardings completed vs started · per month",started:"Started",completed:"Completed",statusTitle:"Onboarding & Handover",statusSub:"Lifecycle status · {n} in total",completedShort:"Completed",inProgress:"In progress",overdue:"Overdue",total:"Total",provTitle:"Provisioning Success by Product"},finance:{trendTitle:"Billed vs Collected",mom:"{arrow} {n}% MoM",billed:"Billed",collected:"Collected",agingTitle:"Receivables Aging",agingSub:"Outstanding · {amount}",aging:{notDue:"Not due",d1to30:"1–30d overdue",d31to60:"31–60d",d61to90:"61–90d",d90plus:"90+ d"},claimsTitle:"Billing Claim Pipeline",claimsSub:"By status · count"},products:{mixTitle:"Product Mix",mixSub:"Active instances",instances:"instances"},admin:{accessTitle:"Access Requests & Break-glass",accessSub:"Granted vs denied vs break-glass · per month",granted:"Granted",denied:"Denied",breakGlass:"Break-glass",auditTitle:"Audit Events by Type",trendTitle:"Sensitive Action Trend",trendSub:"Break-glass · 6 months"}},audit:{eventDialogTitle:"Audit event",sourceIp:"Source IP",maskedIp:"Masked IP",description:"Description",payload:"Payload",hashChain:"Hash chain",hashPrev:"Previous:",hashThis:"This:",readOnlyFoot:"Read-only · cannot be edited or deleted",keywordHint:"Search event, trace ID, actor, resource, or masked IP",allCategories:"All event types",allSeverities:"All severities",allTenants:"All tenants",kpi90:"Events (Last 90d)",kpi90Hint:"In your data scope",kpi30:"Events (Last 30d)",kpi30Hint:"Avg {n}/day",kpiSensitive:"Sensitive Events (24h)",kpiSensitiveBadge:"Review",kpiSensitiveHint:"Warning and critical: identity and permission changes, lockouts, IP blocks",kpiRetention:"Retention",kpiRetentionValue:"Permanent",kpiRetentionHint:"Append-only, never expires · ISO 27001",readOnlyLead:"Read-only.",eventsTitle:"Events",eventsSub:"Showing {shown} of {total} {range} · Sorted newest first",presetIn:{d7:"in the last 7 days",d30:"in the last 30 days",d90:"in the last 90 days",custom:"in the selected range"},colTimestamp:"Timestamp",colEvent:"Event",colActor:"Actor",colDetails:"Details",trailTitle:"Audit Trail",autoGenerated:"Auto-generated",pageSubtitle:"Immutable record of all BES BOSS events, kept permanently for ISO 27001 / PDPA compliance.",readOnlyChain:"Entries cannot be edited or deleted. Every state-changing action in BES BOSS produces an audit event. Hash chain ensures tamper-evidence — see {link} to verify chain integrity.",complianceLink:"Settings → Compliance",actorFilter:"All users",preset:{d7:"Last 7 days",d30:"Last 30 days",d90:"Last 90 days",custom:"Custom range"},targetDetails:"Target / Details",events:"Audit trail",accessLogs:"Access logs",occurredAt:"Occurred at",eventType:"Event",eventHeaderHint:"Event codes like PROVISIONING.COMPLETED or CLAIM.APPROVED are machine-readable labels in the form type.action. Every state change writes one automatically, immutably, for compliance.",eventTypeHint:"Event code, e.g. ORGANIZATION.UPDATED",siemExport:"SIEM export status",siemExportHint:"The endpoint and token are set on the server via environment variables, not here — this opens the read-only forwarding status.",aggregate:"Object",objectFilter:"{type} {id}",aggregateType:"Object type",aggregateId:"Object ID",actor:"Actor",actorType:"Actor type",risk:"Risk",traceId:"Trace ID",detail:"Payload",allCustomers:"All customers",tenantId:"Tenant ID",allProducts:"All products",allProjects:"All projects",from:"From",to:"To",dateRange:"Time range",viewTrace:"View full chain",traceTitle:"Causal chain",traceRequests:"Triggering request",traceEvents:"Resulting events",traceEmpty:"Nothing found for this trace",noTrace:"This record has no trace ID — access logs only carry one from 2026-08-25 onwards",history:"Activity",customerTimeline:"Activity timeline",historyEmpty:"No activity yet",historyLoadMore:"Load earlier ({n} more)",createdAt:"Time",username:"Username",actionType:"Type",method:"Method",uri:"URI",status:"Code",statusHint:"Business code, not the HTTP status — e.g. 20002 finds everything blocked by permissions",costMs:"Cost",ip:"IP",querySummary:"Params",minCostMs:"Slower than (ms)",dateHint:"Without a start time the backend narrows to the last 7 days — access logs are partitioned by month.",changes:"Field changes",field:"Field",before:"Before",after:"After",permissionsAdded:"Permissions added",permissionsRemoved:"Permissions removed",deniesAdded:"Denies added",deniesRemoved:"Denies removed",rawPayload:"Raw payload",empty:"(empty)",ownedScopeEvents:'Your account is scoped to "Owned only": this page shows records for the customers you own, plus actions you performed yourself.',ownedScopeAccess:'Your account is scoped to "Owned only": this page shows your own access records only.',readOnly:"Audit data is read-only and can never be modified."},company:{filterOwner:"Owner: {name}",filterTeamMember:"Account team: {name}",kpiTotal:"Total Organizations",kpiTotalSub:"vs last 30 days",kpiTotalHint:"Total active organizations in BES BOSS (customers, prospects, suppliers and partners).",kpiLeads:"Active Leads",kpiLeadsBadge:"PRIORITY",kpiQualified:"Qualified",kpiNew:"New",kpiCustomers:"Customers",kpiActive:"Active",kpiDormant:"Dormant",kpiSuppliers:"Suppliers",kpiSuppliersSub:"Equipment + Material",tabAll:"All",tabCustomer:"Customer",tabLeads:"Leads",tabSupplier:"Supplier",tabDeveloper:"Developer",tabSubCon:"Sub Con",tabConsultant:"Consultant",tabArchived:"Archived",lastActivity:"Last Activity",industryPlaceholder:"Select an industry",notes:"Notes",notesPlaceholder:"Any context about this company…",noNotes:"No notes yet",editNotesTitle:"Edit notes",createdBy:"by {name}",editTitleNamed:"Edit organization — {name}",editSubtitle:"Update organization information. Changes are audited.",editFootnote:"All changes are recorded in audit log",saveChanges:"Save changes",legalNamePlaceholder:"e.g. ABC Construction Pte Ltd",shortNamePlaceholder:"e.g. ABC",uenPlaceholder:"e.g. 201234567K",companyType:"Company Type",companyTypeHint:"— Select all that apply",corporateRelationship:"Corporate Relationship",corporateRelationshipHint:"— If this company is part of a group",relationshipTypeShort:"Relationship type",parentPartner:"Parent / partner company",selectCompany:"— Select company —",corporateRelationshipNote:"Used when a large contractor has a main entity acting as primary, and sub-entities (JV / Subsidiary) acting on specific projects.",relOption:{NONE:"— None (independent entity) —",SUBSIDIARY:"Subsidiary of",JV_PARTNER:"JV Partner with",BRANCH:"Branch of",DIVISION:"Division of"},billingAddressLabel:"Billing Address",optionalHint:"— Optional",entGlossary:"Entitlement = what the customer is contractually allowed to use — the exact products and modules they paid for. The system enables only this, nothing more.",created:"Created",owner:"Owner",entSummaryTitle:"Product Entitlements",entSummarySub:"Entitlements actually provisioned for this customer",viewAllN:"View all ({n}) →",recentActivity:"Recent Activity",colSigned:"Signed",selectPlaceholder:"Select an organization",pageSubtitle:"A single business-party directory for customers, suppliers, developers and consultants. Only customer/service-recipient relationships can own a tenant.",createTitle:"New organization",createSubtitle:"Add a new business counterpart. All creations are audited.",createFootnote:"All creations are recorded in audit log",createSubmit:"Create organization",columnCompany:"Company",columnStage:"Stage",columnOwner:"Owner",registeredAddress:"Registered Address",registeredAddressPlaceholder:"Street, building, postal code…",billingAddress:"Billing address (optional)",billingAddressPlaceholder:"Leave blank if same as registered",sameAsRegistered:"Same as registered",addressNotSaved:"The organization was created, but its address was not saved — add it on the organization's Addresses",roleShort:{MAIN_CON:"Main Con",SUB_CON:"Sub Con",EQUIPMENT:"Equipment"},editTitle:"Edit organization",create:"New Organization",searchPlaceholder:"Search organizations, UEN, relationship or owner",orgNo:"No.",legalName:"Legal Name",shortName:"Short Name",uen:"UEN",country:"Country/Region",countryPlaceholder:"Defaults to Singapore (SG)",industry:"Industry",website:"Website",roles:"Roles",accountOwner:"Account owner",parentOrg:"Parent organization",relationshipType:"Group relationship",tags:"Tags",tagsPlaceholder:"Press Enter to add a tag",lifecycleStage:"Lifecycle",customerSince:"Customer since",qualify:"Mark Qualified",archiveCompany:"Archive organization",archive:"Archive",restore:"Restore",qualified:"{name} is now Qualified",archived:"Archived",restored:"Restored",qualifyTitle:"Mark organization as Qualified",qualifyConsequenceStage:'move "{name}" from Lead to Qualified',qualifyConsequenceOnce:"take this button away — only a Lead can be qualified, so it cannot be done a second time",qualifyConsequenceReversible:"be reversible — you can set the stage back to Lead by editing the organization",restoreTitle:"Restore organization?",restoreConsequenceListed:'put "{name}" back on the customer list',restoreConsequenceEditable:"make it editable again, and allow new quotations against it",archiveTitle:"Archive organization?",archiveConsequenceHidden:'take "{name}" off the customer list — you have to filter for Archived to find it',archiveConsequenceReadonly:"make it read-only: no edits, no new quotations against it",archiveConsequenceRunning:"leave its contracts and projects running: contracts still expire or end as before, claims and invoices are raised as usual, and renewal quotations, revisions and amendment quotes carry on",archiveConsequenceReversible:"be reversible — you can restore the customer at any time",deleteCompany:"Delete company",deleteTitle:"Delete company?",deleteSubmit:"Delete permanently",deleteConsequenceGone:'delete "{name}" permanently: it disappears from lists, dropdowns and search, and can no longer be picked as the customer of a new quotation',deleteConsequenceRecords:"keep its quotations, contracts, projects and invoices, which still show its name",deleteConsequenceAttached:"hide its contacts, addresses, meeting notes, customer team and billing accounts along with it",deleteConsequenceAudit:"keep its audit history — its events can still be found in the audit log",deleteConsequenceBlocked:"be refused if this customer still has a live contract, an unpaid invoice, or a draft or sent quotation",deleted:"Company deleted",customerGone:"This customer doesn't exist or has been deleted",archivedAlert:"This organization is archived. Archived organizations cannot be edited — restore it first.",legalNameRequired:"Legal name is required",relationshipRequired:'Group relationship is required when a parent organization is set, and cannot be "None"',stageWorkflowOnly:"{stage} — this stage is driven by the sales/contract workflow and cannot be set manually",relatedQuotations:"Quotations",relatedContracts:"Contracts",noQuotations:"No quotations",noContracts:"No contracts",noProjects:"No projects",tabOverview:"Overview",tabAudit:"Audit",tabAccess:"Customer Access",tabEntitlements:"Product Entitlements",tabActivity:"Activity",grantExpiry:"Expiry",viewAllInProjects:"View all in Projects →",viewAllInContracts:"View all in Contracts →",viewAllInQuotations:"View all in Quotations →",colProject:"Project",colContract:"Contract",colExpires:"Expires",colValue:"Value",viewProject:"View project",entIntro:"Product entitlements are the live entitlements provisioned from this customer's contracts — each carries its own tenant, provisioning state and renewal. See the full register in {link}.",activityAutoHint:"Auto-generated by system events",lifecycleStageLabel:"Lifecycle Stage",lifecycleStageHint:"— Active / Dormant / Churned are reached via sales workflow, not set manually",grantsTitle:"Temporary BES access · Break-glass",grantsSubtitle:"Time-boxed BES support access into the customer's deployed system — fully audited, revocable early",grantsAll:"Access requests →",grantReasonScope:"Reason · Scope",grantRequestedBy:"Requested by",grantApprovedBy:"Approved by",noGrants:"No temporary access for this customer",entTenant:"Tenant",entProject:"Project",entTerm:"Term",entOpen:"Open instance →",noEntitlements:"No live entitlements for this customer",infoTitle:"Company Information",parentRestricted:"This organization has a parent that is outside your data scope",primaryContact:"Primary Contact",contactsLoadFailed:"Contacts could not be loaded — see the Contacts tab",noContacts:"No contacts yet",viewAllContacts:"View all contacts ({n})",addTag:"+ Add",noTags:"No tags yet",addTagTitle:"Add tag",addTagPlaceholder:"Type a tag name…",addTagSubmit:"Add tag",addTagSuggestions:"Suggestions",addTagRequired:"Type a tag name",addTagDuplicate:"This organization already has that tag",addTagConflict:"Someone else just changed this organization — it has been reloaded, please add the tag again",tagAdded:"Tag added",workflowOwnership:"Operational workflow ownership",workflowBesTitle:"BES side — Implementation workflow",workflowBesBody:"The onboarding and implementation steps, defined in {templates}. This is how BES delivers the system.",workflowCustomerTitle:"Customer side — Operational workflow",workflowCustomerBody:"How the customer runs their day-to-day site operations (inspection flows, approval chains, etc.). Defined by the customer's Company Admin in their own system — not in BOSS. BES has no visibility here by design.",period:"Period",relatedShown:"Showing {shown} of {total}",relatedViewAll:"View all →",openFullAuditLog:"Open full audit log →"},billingAccount:{title:"Billing accounts",subtitle:"Who the invoice is made out to — may be a different company from the customer",create:"New billing account",createTitle:"New billing account",editTitle:"Edit billing account",empty:"No billing account yet",legalName:"Legal name",legalNameHint:"The billing entity's own registered name — it may differ from the customer's",legalNameRequired:"Legal name is required",uen:"UEN",currency:"Currency",currencyRequired:"Currency is required",paymentTermsRequired:"Payment terms are required — enter 30 to go back to the default",gstRateRequired:"GST rate is required — enter 9 to go back to the default",paymentTerms:"Payment terms",paymentTermsDays:"{n} days",days:"days",gstRate:"GST rate",gstRateHint:"Enter as a percentage, e.g. 9 for 9%",contact:"Billing contact",contactName:"Contact name",contactEmail:"Email",contactEmailInvalid:"Enter a valid email address",contactPhone:"Phone",address:"Billing address",addrLine1:"Address line 1",addrLine2:"Address line 2",addrPostal:"Postal code",addrCountry:"Country/Region",remark:"Remark",isDefault:"Default",defaultTag:"Default",setAsDefault:"Make this the default billing account",firstIsDefaultHint:"The customer's first active billing account always becomes the default, whether or not this is ticked — otherwise new documents would have nothing to pre-fill.",setDefault:"Set as default",setDefaultTitle:"Set as default billing account",setDefaultConsequenceThis:`invoices issued for this customer's claims will take their header and payment terms from "{name}"`,setDefaultConsequenceOther:"clear the default flag on whichever one holds it now",setDefaultConsequenceExisting:"leave documents that already exist alone — they keep the billing account they were issued with",archiveConsequenceHidden:'take "{name}" out of the picker — new documents can no longer be issued to it',archiveConsequenceExisting:"leave existing references valid — documents already issued to it are unaffected",restoreConsequenceSelectable:'put "{name}" back in the picker for new documents',restoreConsequenceNotDefault:"not make it the default again — another one may have taken that place while it was off, and quietly swapping the invoice header back would go unnoticed",setDefaultDone:"Default billing account updated",archive:"Deactivate",archiveTitle:"Deactivate billing account",archiveLosesDefault:"This is the current default — deactivating it also clears the default. Until you set another one, this customer has no default billing account and its claims cannot be approved (no invoice can be issued).",archived:"Deactivated",restore:"Restore",restored:"Restored",restoreTitle:"Restore billing account",archivedReadonly:"Deactivated billing accounts are read-only — restore it first to edit.",notNullHint:'Currency, payment terms and GST rate always hold a value — there is no "not set" state for them. To go back to the defaults, enter SGD / 30 days / 9%.',notWiredHint:"Invoices take their header and payment terms from the default billing account here at the moment of issue; without a default, claims cannot be approved. Quotations and contracts cannot pick a billing account yet (BESDEV-52).",noPermission:"You do not have permission to view billing accounts"},companyContact:{title_:"Title",editContact:"Edit contact",deleteContact:"Delete contact",contactType:"Type",title:"Contacts",subtitle:"Who to reach at this organization — separate from the billing contact on a billing account",create:"Add Contact",createTitle:"Add contact",editTitle:"Edit contact",empty:"No contact yet",name:"Name",firstName:"First name",lastName:"Last name",firstNameRequired:"First name is required",lastNameRequired:"Last name is required",emailRequired:"Email is required",jobTitle:"Job title",email:"Email",emailInvalid:"Enter a valid email address",phone:"Phone",primaryTag:"Primary",setAsPrimary:"Make this the primary contact",firstIsPrimaryHint:"The first contact for a customer always becomes the primary one, whether or not this is ticked.",noPrimaryHint:"This customer has no primary contact — pick one so it is clear who to reach first.",setPrimary:"Set as primary",setPrimaryTitle:"Set as primary contact",setPrimaryConsequenceThis:'make "{name}" the first person to reach at this customer',setPrimaryConsequenceOther:"clear the primary flag on whoever holds it now",setPrimaryDone:"Primary contact updated",deleteTitle:"Delete contact",deleteConsequenceRemoved:`remove "{name}" from this customer's contacts`,primaryCannotDelete:"Primary contact cannot be deleted. Set another contact as primary first.",deleted:"Contact deleted",archivedReadonly:"This customer is archived — contacts are read-only. Restore the customer first to edit them."},meetingNote:{create:"Add meeting note",createTitle:"Add meeting note",editTitle:"Edit meeting note",titleLabel:"Title",titlePlaceholder:"e.g. Q3 AIVA rollout discussion",titleRequired:"Title is required",content:"Notes",contentPlaceholder:"What was discussed, decisions and follow-ups",contentRequired:"Notes are required",attendees:"Attendees",attendeesHint:"— this customer's contacts, up to 20",attendeesPlaceholder:"Select contacts",nameSep:", ",attendeesLine:"Attendees: {names}",edit:"Edit meeting note",delete:"Delete meeting note",deleteTitle:"Delete meeting note",deleteConsequence:'remove the meeting note "{title}" from this customer; the activity timeline keeps only its title',deleted:"Meeting note deleted",goneHint:"This meeting note has been deleted.",goneHintNamed:'The meeting note "{title}" has been deleted.',snapshotHint:"Could not load the current version — showing the notes as first saved."},inventory:{pageSubtitle:"Internal BES hardware stock, purchasing and receiving. (Not customer-site material inventory.)",newPo:"New PO",howItWorksLabel:"How it works:",howItWorks:`{label} hardware models (catalog & price) are defined once in {link}. Here you manage stock of those models — buy (PO), receive, dispatch to sites. Need a model that doesn't exist yet? Use "New model not listed?" inside New PO — it creates the catalog entry too, so you don't do it twice.`,howItWorksLink:"Products → Hardware",kpiInStock:"In Stock",kpiInStockSub:"across {n} model | across {n} models",kpiOnOrder:"On Order",kpiOnOrderSub:"{n} open PO | {n} open POs",kpiAllocated:"Allocated",kpiAllocatedSub:"reserved for sites",kpiInstalled:"Installed",kpiInstalledSub:"in the field",kpiLow:"Low Stock",kpiLowSub:"below safety level",kpiOutSub:"{n} out of stock | {n} out of stock",lifecycleLabel:"Stock lifecycle:",lifecycle:{purchase:"Purchase (PO)",receive:"Receive (GRN)",store:"Store (In stock)",dispatch:"Dispatch (to site)",install:"Install (on project)"},tabStock:"Stock",tabOrders:"Purchase orders",searchStock:"Search model, SKU or supplier",colProductVariant:"Product / Variant",colInStock:"In stock",colAllocated:"Allocated",colOnOrder:"On order",variantsN:"{n} variants",noVariants:"No variants yet",modelOut:"{n} variant out | {n} variants out",modelLow:"{n} variant low | {n} variants low",lowBelowSafety:"Low — below safety ({n})",expandHint:"expand →",viewUnits:"View units",reorder:"Reorder",noModels:"No hardware models yet — add them in Products → Hardware",searchPo:"Search PO number or supplier",colPoNo:"PO #",colSupplier:"Supplier",colItems:"Items",colEta:"ETA",receivedOf:"{received} / {total} received",receive:"Receive",receiveNeedsTransit:"Mark the PO as in transit before receiving",done:"Done",markInTransit:"Mark in transit",editPo:"Edit PO",cancelPo:"Cancel PO",noPos:"No purchase orders yet",shipTitle:"Mark as in transit",shipConsequenceReceive:"mark {no} as shipped by the supplier, so goods can be received against it",shipConsequenceLocked:"lock its lines — a PO in transit can no longer be edited",shipped:"Marked as in transit",cancelTitle:"Cancel purchase order",cancelConsequenceOnOrder:"cancel {no} — its {n} unit(s) stop counting as On Order",cancelConsequenceFinal:"keep it in the list as Cancelled; it cannot be reopened",cancelled:"Purchase order cancelled",poCreateTitle:"New purchase order",poCreateSub:"Order hardware from a supplier",poEditTitle:"Edit purchase order {no}",poLines:"Items",poAddLine:"Add item",poVariantPlaceholder:"Hardware model / variant",poVariantRequired:"Pick a variant",poQty:"Quantity",poQtyInvalid:"Whole number, at least 1",poUnitCost:"Unit cost (SGD)",poUnitCostInvalid:"0 or more, up to 2 decimals",poLinesHint:"One supplier per PO. Each variant can appear once; unit cost is optional.",poSupplierRequired:"Supplier is required",poExpectedDate:"Expected delivery",poLinkTo:"Link to (optional)",poLinkNone:"Stock replenishment (no project)",poLinkContract:"Contract",poLinkQuotation:"Quotation",poLinkHint:"Linking to a contract ties this purchase to a customer order. It is for reference only and does not reserve stock; with a contract linked, goods can be shipped direct to that contract's project on receive.",poLinkPick:"Pick the contract or quotation to link, or choose stock replenishment",poNote:"Note",poCreate:"Create PO",poCreated:"Purchase order {no} created",poDetailTitle:"Purchase order {no}",poDetailTitleBare:"Purchase order",poCreatedAt:"Created",poReceivedTotal:"Received",poReceived:"Received",poReceipts:"Receipts",poNoReceipts:"Nothing received yet",receiveTitle:"Receive goods (GRN)",receiveOrdered:"Ordered",receiveOutstanding:"Outstanding",receiveNow:"Received now",receiveQtyInvalid:"Whole number from 0 to {n}",receiveSerials:"Serial numbers",receiveSerialsHint:"— optional, one per line",receiveSerialsPlaceholder:"Leave empty to add them later in View units",receiveSerialsCount:"Enter {n} serial numbers, or leave it empty",receiveSerialsDup:"Serial numbers must not repeat",warehouse:"Warehouse",warehouseRequired:"Pick a warehouse",bin:"Bin",binPlaceholder:"e.g. A-03",qualityCheck:"Quality check",qcQuantity:"Quantity matches PO",qcDamage:"No visible damage",qcSerials:"Serial numbers logged",qcNone:"no checks ticked",listSep:", ",receiveHint:"On receive, {n} units enter In stock and an inbound movement is logged for each line.",receiveConfirm:"Confirm receipt",received:"{n} units received",unitsTitle:"{model} · {variant} — units",unitsSub:"Serial numbers belong to this variant (SKU {sku})",unitsLifecycleLabel:"Lifecycle:",unitsLifecycle:{onOrder:"On order",received:"Received",inStock:"In stock",dispatched:"Dispatched",onSite:"On site",installed:"Installed"},searchSerial:"Search serial number",colSerial:"Serial",colLocation:"Location",colUpdated:"Updated",noSerial:"No serial yet",noUnits:"No units for this variant yet",locationRestricted:"A project outside your data scope",unitFromPo:"Received on {no}",unitFromInitial:"Initial stock",unitNoMovements:"No movements yet",unitEditTitle:"Edit unit",unitNote:"Note",unitInstalledAt:"installed {time}",dispatchToSite:"Dispatch to site",tabAllocation:"Allocation",tabDispatch:"Dispatch",tabDeployment:"Deployment",colModel:"Model",colQty:"Qty",colProject:"Project",colContract:"Contract",colDate:"Date",colClaim:"Billing claim",customer:"Customer",allocationHint:"Hardware each contract needs installed on a project, created when the contract is activated, and how far each is installed.",colAllocatedTo:"Allocated to",allocInstalledOf:"{installed} of {total} installed",nInTransit:"{n} in transit",nOnSite:"{n} on site",allocShortage:"{n} short — reserve or order more",allocBlocked:"Blocked",allocBlockedTip:"The onboarding Hardware Installation step has not started yet, so nothing can be dispatched",dispatch:"Dispatch",release:"Customer won't install",noAllocations:"Nothing to install yet — allocations are created when a contract with catalog hardware is activated",releaseTitle:"Customer won't install",releaseQty:"Units the customer won't install",allocContracted:"Contracted",allocInstalled:"Installed",allocOverInstalled:"Over contract",allocReleased:"Won't install",allocRemaining:"Still to install",allocDispatched:"In transit",allocOnSite:"On site",allocReserved:"Reserved",allocShortageLabel:"Short",allocReturned:"Returned from site",releaseReason:"Reason",releaseReasonPlaceholder:"e.g. variation order reduced the quantity",releaseHint:"These units are taken off what still has to be installed and will not be billed. The project's reservation is not reduced — change it below if needed.",releaseQtyMax:"At most {n} — the units still to install",released:"{n} units recorded as not to install",allocDetailTitle:"Allocation",allocOnboarding:"Onboarding",fromAmendment:"From amendment",allocUnits:"Units",allocNoUnits:"No units dispatched yet",allocDispatches:"Dispatches",allocOverInstallations:"Over-installations",reservationsTitle:"Reservations",reservationsHint:"Units kept in the warehouse for a project. Only a count — the actual units are picked on dispatch.",addReservation:"Add reservation",colReserved:"Reserved",colOpenRemaining:"Still to install on project",reservationStale:"Nothing left to install — consider clearing",changeReservation:"Change",clearReservation:"Clear reservation",noReservations:"No reservations",clearReservationTitle:"Clear reservation",clearReservationConsequenceQty:"set the reservation of {sku} for {project} from {n} to 0",clearReservationConsequenceStock:"make those {n} unit(s) available to other projects again",reservationCleared:"Reservation cleared",addReservationTitle:"Add reservation",changeReservationTitle:"Change reservation",reservationDialogSub:"Keep units in the warehouse for a project",nAvailable:"{n} available",reserveQty:"Reserved units",availableInStock:"Available in stock",reservationReason:"Reason",reservationProjectRequired:"Pick a project",reserveQtyInvalidZero:"Whole number, 0 or more",addReservationHint:"The number is the total kept for this project. If the project already has a reservation for this variant, it is replaced. Only units available in stock can be added.",changeReservationHint:"Currently {n} reserved. Enter the new total; 0 clears the reservation. Only units available in stock can be added.",reservationSaved:"Reservation set to {n}",locEnRoute:"En route · {project}",locOnSite:"On site · {project}",dispatchHint:"Units shipped to site for installation — dispatched for an allocation while its onboarding {step} is in progress, then settled unit by unit.",dispatchHintStep:"Hardware Installation step",searchDispatch:"Search dispatch number",colDispatchNo:"Dispatch #",colDestination:"Destination",markInstalled:"Mark installed",markDelivered:"Mark delivered",cancelDispatch:"Cancel dispatch",delivered:"Marked as delivered",cancelDispatchTitle:"Cancel dispatch",cancelDispatchConsequenceUnits:"return the {n} unit(s) taken from the warehouse on {no} to stock",cancelDispatchConsequenceReservation:"give back the {n} unit(s) of the project's reservation it used",cancelDispatchConsequenceOnSite:"leave the {n} unit(s) brought along from site on site again",cancelDispatchConsequenceFinal:"keep {no} in the list as Cancelled; it cannot be reopened",dispatchCancelled:"Dispatch cancelled",noDispatches:"No dispatches yet",nBroughtFromSite:"{n} brought from site",nInstalled:"{n} installed",nFaulty:"{n} faulty",nSurplus:"{n} surplus",settledOf:"{parts} (of {total})",confirmTitle:"Settle dispatch",confirmOnDispatch:"On this dispatch",confirmUnitsLabel:"What happened to each unit",confirmSetAll:"Set all to",broughtFromSite:"From site",colOutcome:"Outcome",confirmCountsLabel:"How many of the {total} units — they have no serial numbers",confirmCountsInvalid:"Whole numbers, 0 or more",confirmCountsSum:"The four numbers must add up to {total} (now {sum})",faultyReason:"Fault",faultyReasonPlaceholder:"e.g. lens cracked on arrival",faultyReasonRequired:"Describe the fault — it becomes the reason on the return",overInstallTitle:"{n} unit(s) beyond the contract",overInstallTitleBare:"Units beyond the contract",overInstallBody:"More units are installed than this allocation still needs. Confirming creates an over-installation record and a separate draft claim at the contract unit price, outside the payment plan. The signed DO for this dispatch serves as the customer's acceptance.",overInstallConfirm:"The customer accepted the extra units",overInstallNote:"Note",overInstallNotePlaceholder:"Why more units were installed, e.g. customer added two entrances on site",overInstallConfirmRequired:"Confirm the over-installation, or change the outcomes",overInstallNoteRequired:"Explain the over-installation",otherAllocationTitle:"Contract {contract} still needs {n} of this variant on the same onboarding",otherAllocationBody:"More units are marked installed than this allocation still needs ({r}). Install up to {r} here and leave the rest on site, then dispatch from the {contract} allocation and bring them along. Only units beyond that count as over-installation.",otherAllocationFix:"Mark the extra as on site",tabReturns:"Returns / RMA",returnsHint:"Units returned from site, under repair, or sent back to supplier under warranty. Restocked units are added back to Stock on hand.",searchReturns:"Search RMA # or serial no.",colRmaNo:"RMA #",colFrom:"From",colReason:"Reason",noReturns:"No returns yet",returnTitle:"Return {no}",returnSourceLabel:"Source",returnSplitFrom:"Split from",returnNote:"Note",returnCreatedAt:"Created",returnClosedAt:"Closed",returnUnits:"Units ({n})",returnHistory:"History",returnSplitOff:"split off {no}",returnSplitOffFrom:"split from {no}",actReceive:"Receive",actCancel:"Cancel return",actRepair:"Send for repair",actSendToSupplier:"Send to supplier",actRestock:"Restock",actScrap:"Scrap",actionUnits:"Units to process ({n} / {total})",actionUnitsRequired:"Pick at least one unit",actionSplitHint:"Only some units are picked: they are split into a new return and processed there. The rest stay on this return, unchanged.",restockWarehouseHint:"Leave empty to keep the units in their current warehouse",actionDone:"{action} done · {no}",consequenceReceive:"The units go back to the warehouse and leave the project. The allocation's installed count, claims and onboarding steps are unchanged.",consequenceCancel:"The units on site stay in use. This return stays in the list as Cancelled and cannot be reopened.",consequenceRepair:"The units move to Under repair and stay in their warehouse.",consequenceSendToSupplier:"The units go back to the supplier under warranty; their warehouse and bin are cleared.",consequenceRestock:"The units return to stock and can be dispatched again. They do not go back to their earlier allocation or project.",consequenceScrap:"The units are scrapped, become read-only and cannot be restored; their serial numbers are freed.",siteReturn:"Return",siteReturnTitle:"Return from site",warehouseReturnTitle:"Return for inspection",createReturnUnits:"Units to return ({n} / {total})",createReturnNoUnits:"No units on this project can be returned (units already on an open return are not listed)",returnReasonPlaceholder:"e.g. Faulty sensor, project closed",returnReasonRequired:"Enter a reason",createReturnHintSite:"After creating, the units stay installed on the project and show Needs check until received back into the warehouse. Nothing is re-installed, and claims and onboarding steps are unchanged.",createReturnHintWarehouse:"The units move to Returned, awaiting inspection, and no longer count as in stock.",createReturn:"Create return",returnCreated:"Return {no} created",unitsSelected:"{n} selected",unitsReturn:"Return for inspection",unitsTransfer:"Move",unitsReturnDisabled:"Only in-stock units not on an open return can be returned",unitsTransferDisabled:"Selected units must be in the same warehouse and be in stock, returned or under repair",unitOnReturn:"On {no}",transferTitle:"Move units",transferSub:"{n} unit(s) · from {warehouse}",transferTo:"To warehouse",transferBinSame:"Within the same warehouse, enter a different bin",transferHint:"Only the location changes; status stays the same. Reservations are counted per project and are not affected.",transferred:"{n} unit(s) moved",poQuickToggle:"New model not listed?",poQuickHint:"Quick-add a hardware model — also creates its catalog entry in Products, no need to leave this page",poQuickName:"Model name (e.g. Turnstile Gate)",poQuickSku:"Model no. (e.g. TG-X2)",poQuickSupplier:"Supplier",poQuickCost:"Unit cost",poQuickAdd:"Add model & select",poQuickFull:"Full product form →",poQuickNameRequired:"Enter a model name",poQuickSkuRequired:"Enter a model no.",poQuickAdded:"Model {name} added. Its sell price is empty — set it in Products before quoting.",receiveDirectShip:"Ship direct to site",receiveDirectShipHint:"Skip the warehouse: units go straight to contract {contract}'s project as on site, settled when brought along on the next dispatch",receiveHintDirect:"On receive, {n} unit(s) enter In stock and {m} go straight to the project as on site. Each line logs a receive movement; direct-ship lines also log a dispatch movement.",receiptDirect:"direct",receiveHintAllDirect:"On receive, {m} unit(s) go straight to the project as on site and do not enter In stock. Each line logs a receive and a dispatch movement.",needsCheckQty:"{n} on a return, awaiting pickup",printDo:"Print DO",registerDo:"Register signed DO",changeDo:"Change",signedDo:"Signed DO",signedDoMissing:"Not registered",signedDoAt:"registered {time}",doFileName:"File name",doFileNamePlaceholder:"e.g. {no}-signed.pdf",doFileRef:"Link",doFileNameRequired:"Enter the file name",doFileRefRequired:"Enter a link starting with http:// or https://",doHint:"The DO the customer signed is the acceptance for this batch. There is no file storage yet, so register the file name and a link; registering again overwrites it.",doHintOver:"This dispatch has an over-installation: its claim can be submitted once this is registered, and the DO cannot be changed after that claim is submitted.",doHintAmendment:"This batch comes from an add-hardware amendment: its claim at the amendment's unit price can be submitted once this is registered, and the DO cannot be changed after that claim is submitted.",doRegistered:"Signed DO registered",installedDate:"Installed on",dateDefaultToday:"Today",dispatchNote:"Note",confirmHintInstalled:"{n} unit(s) become Installed on the project; a draft billing claim is created for this batch.",confirmHintOnSite:"{n} unit(s) stay on site to be installed later — bring them along on the next dispatch.",confirmHintFaulty:"{n} faulty unit(s) go back to the warehouse they came from, and a return is created for them.",confirmHintSurplus:"{n} surplus unit(s) go back to stock.",confirmHintNoClaim:"Nothing installed: no billing claim is created.",confirmInstall:"Settle",confirmed:"Dispatch settled — {n} units installed",confirmedWithClaim:"Dispatch settled — {n} units installed, billing claim {claim} created",dispatchDetailTitle:"Dispatch {no}",dispatchDetailTitleBare:"Dispatch",installedOfQty:"{installed} of {total} installed",dispatchDate:"Dispatch date",deliveredAt:"Delivered",reservationUsed:"From reservation",overInstalledLabel:"Over contract",faultyReturn:"Return for faulty units",dispatchUnits:"Units",deploymentHint:"Installed units in operation, linked to a project and product deployment.",colAsset:"Asset",colProductDeployment:"Product deployment",colDeployed:"Deployed",noInstallations:"No hardware installed yet",dispatchTitle:"Dispatch to site",dispatchSub:"Ship units to a project for installation",dispatchAllocation:"Allocation (project / onboarding step)",dispatchAllocationPlaceholder:"Pick the allocation to dispatch for",dispatchAllocationRequired:"Pick an allocation",dispatchNoChoices:"Nothing can be dispatched right now — an allocation becomes dispatchable once its onboarding Hardware Installation step starts.",nRemaining:"{n} still to install",dispatchFromStock:"Units from the warehouse",dispatchOnSite:"Units left on site to settle with this dispatch ({n} of {total})",dispatchQtyInvalid:"Whole number, 0 or more",dispatchNothing:"Take at least one unit from the warehouse or bring one along from site",dispatchHintBox:"Units come from this project's reservation first, then from available stock (oldest received first), and move to Dispatched with a −qty movement. Extra units are fine — they go back to stock as surplus when the dispatch is settled.",dispatched:"Dispatch {no} created",oviAcceptanceMissingTitle:"No acceptance yet",oviAcceptanceMissingBody:"The signed DO for dispatch {dispatch} has not been registered. The over-installation claim cannot be submitted until it is.",oviOverQty:"Units over contract",oviUnitPrice:"Contract unit price",oviUnitPriceHint:"From the quotation line, before the overall discount",oviAmount:"Amount",oviAcceptance:"Acceptance (signed DO)",oviConfirmed:"Confirmed",oviNote:"Note",colOviNo:"Over-installation #"},companyAddress:{siteSectionTitle:"Site addresses",siteSectionHint:"— project locations",addSiteLink:"+ Add site address",label:"Label",labelPlaceholder:"e.g. Jurong East Industrial",linkedProject:"Linked project",linkedProjectPlaceholder:"— None —",linkedTo:"Linked to project",title:"Addresses",subtitle:"Registered, billing and site addresses on file for this organization",create:"Add address",createTitle:"Add address",editTitle:"Edit address",empty:"No address yet",addrType:"Type",addrTypeRequired:"Type is required",line1:"Address line 1",line1Required:"Address line 1 is required",line2:"Address line 2",postal:"Postal code",country:"Country/Region",countryRequired:"Country/Region is required",countryNotNullHint:'An address always holds a country — there is no "not set" state for it. It defaults to Singapore.',multipleSiteHint:"A customer can have several site addresses (one per site), so types are not restricted to one each.",deleteTitle:"Delete address",deleteConsequenceRemoved:"remove this {type} address from the organization file",deleted:"Address deleted",archivedReadonly:"This customer is archived — addresses are read-only. Restore the customer first to edit them.",companySection:"Company addresses",siteSection:"Site addresses — project locations",registered:"Registered Address",billing:"Billing Address",primaryTag:"Primary",add:"Add",addSite:"Add site address",registeredEmpty:"No registered address yet",sameAsRegistered:"Same as registered",billingMirrors:"Mirrors the registered address. Add one here to bill to a separate address.",siteEmpty:"No site address yet"},projectLink:{label:"Related project",none:"— None / will be created at contract signing —",createNew:"+ Create new project after quote acceptance",newOnSign:"Create new project on counter-sign",linkExisting:"Link to existing: {name} ({code})",newName:"New project name",newNamePlaceholder:"e.g. TOPAZ HDB Sengkang — Phase 2",newNamePlaceholderShort:"New project name",newNameRequired:"Enter the new project name",newType:"Project type",newCountry:"Site country",newAddress:"Site address",newAddressPlaceholder:"e.g. Block 5 Tampines Street 32, Singapore 528700",notCreatedNow:"The project is not created now — it is provisioned automatically once the customer signs / accepts this quotation.",noneAvailable:"This customer has no project that can take another contract. Only Setup and Active projects are listed.",noPermission:"You don't have access to projects, so only a new project can be chosen.",acceptLabel:"Project link",acceptHint:"A contract can share a project with other contracts (implementation + maintenance). The project is created on counter-sign.",consequenceNew:"create project “{name}” when the contract is activated, and start its onboarding",consequenceExisting:"add the contract to the selected project as an add-on when it is activated — only the new products are provisioned, no onboarding is created, and it ends together with the project's primary contract",existingShort:"existing project",later:"Decide later",laterPlan:"Decide later — link it to a project after activation",consequenceLater:"activate the contract without a project — its products are provisioned, no onboarding is created, and you link it to a project later from the project's Related Contracts",notVisible:"A project outside your data scope",newOnActivation:"New project on activation: {name}"},quotation:{inStockN:"{n} in stock",selectPlaceholder:"Search by quotation no.",termMonthsLabel:"Term (months)",termMonthsPlaceholder:"e.g. 12",projectLinesTitle:"Project Lines",projectLinesHint:"Projects covered by this quotation",plProject:"Project",plDuration:"Duration",plSiteAddress:"Site Address",plMonths:"{n} month | {n} months",plTbd:"To be decided",reviseWarning:"Current version will be archived as Superseded. Customer must accept the new revision to proceed. Line items and referenced terms are copied as they read on this version.",customerOrgHint:"— Billing entity (signs contract)",serviceEntity:"Service entity",serviceEntityHint:"— who actually receives services (if different from billing)",serviceEntityPlaceholder:"Same as billing entity (default)",serviceEntityNote:"Common when a large customer contracts via parent but services run through a subsidiary or JV.",serviceEntityNoPermission:"You cannot view organizations, so only the default is available.",quoteTitle:"Quote title",validityDaysLabel:"Validity (days)",createdAsDraft:"Quote will be created in Draft status.",acceptSubtitle:"Customer confirmed. This converts the quotation into a contract.",whatHappensNext:"What happens next:",reviseSubtitle:"New version {no} will be created from current",loseButton:"Mark lost",reviseButton:"Create revision",kpiFollowUp:"FOLLOW UP",kpiWinRateLabel:"Win rate {rate}",tabAll:"All",colQuote:"Quote",colValue:"Value",colValidUntil:"Valid Until",sendTo:"Send to (optional)",versionPill:"Version {n}",awaitingResponse:"Awaiting Response",sendToPlaceholder:"customer{'@'}example.com — recorded on the quotation, no email is sent",metaSentTo:"Sent to",acceptedDate:"Acceptance date",acceptedDatePlaceholder:"Leave blank for today",acceptedDateHint:"The day the customer accepted. Cannot be before the quotation was sent or later than today.",confirmedBy:"Confirmed by (customer side)",confirmedByPlaceholder:"e.g. PM Lee",confirmedByShort:"confirmed by {name}",lossReasonLabel:"Loss reason",lossReasonPlaceholder:"Select a reason",lossReasonRequired:"Select a loss reason",lossDetails:"Details (optional)",lossDetailsPlaceholder:"Add context for future learning",revisionReasonLabel:"Reason for revision",revisionReasonPlaceholder:"Select a reason (optional)",revisionNotes:"Notes",revisionNotesPlaceholder:"Internal note for the audit trail",revisionAlert:"Revised: {reason}",notes:"Notes (internal)",notesPlaceholder:"Context for the team — not shown to the customer",customerStageHint:"Only companies with the Customer role appear here — Lead, Qualified, Converted, Active or Dormant.",kpiOpen:"Total Open",kpiOpenSub:"{amount} potential",kpiSent:"Sent · Awaiting",kpiSentSub:"{n} overdue response",kpiAccepted:"Accepted · 30d",kpiWinRate:"Win rate {rate}",kpiAvgDeal:"Avg. Deal Size",kpiAvgDealSub:"Accepted in the last 30 days",signed:"Signed",pageSubtitle:"Track quotations from draft to acceptance.",daysLeft:"{n} day left | {n} days left",daysRemaining:"{n} day remaining | {n} days remaining",stepContract:"Contract",amountSummary:"Amount Summary",discountWithPct:"Discount ({pct}%)",gstWithRate:"GST ({rate}%)",inclGst:"{currency} · incl. GST",validUntilOn:"Valid until {date}",contactLoadFailed:"The customer's contacts could not be loaded",noPrimaryContact:"This customer has no primary contact",viewCompany:"View company →",nextSteps:"Next steps",nextStep1:"The customer accepts on the accept link — or mark it Accepted here when they reply",nextStep2:"Contract created automatically as Draft",nextStep3:"Contract activated once signed",nextStep4:"Projects pre-created in Setup",daysOverdue:"{n} day overdue | {n} days overdue",createTitle:"New quotation",createSubtitle:"Quote ID will be auto-generated on save",createAndOpen:"Create & open",editTitle:"Edit quotation",create:"New Quotation",searchPlaceholder:"No. / title",submitApproval:"Submit for approval",submitApprovalTitle:"Submit this discount for approval",submitApprovalConsequenceLocked:"will lock the quotation while it waits — no line item or amount can be changed until it is decided",submitApprovalConsequenceCleared:"will clear any earlier decision on this quotation, so a previous rejection note disappears",submitApprovalConsequenceBlocked:"will keep the quotation unsendable until someone approves it",approvalSubmitted:"Submitted for approval",approveDiscount:"Approve discount",approveDiscountTitle:"Approve this discount",approveConsequenceSendable:"will let this quotation be sent to the customer at this discount",approveConsequenceAudited:"records you as the approver, with the time and your note",approveNoteLabel:"Why is this discount acceptable? (optional)",approveNotePlaceholder:"Note (optional) — e.g. cleared with the CFO",discountApproved:"Discount approved",rejectDiscount:"Reject discount",rejectDiscountTitle:"Reject this discount",rejectConsequenceBlocked:"will keep this quotation from being sent at this discount",rejectConsequenceResubmit:"lets the owner change the amount and submit again — your reason is what they will work from",rejectNoteLabel:"Why are you rejecting it? The owner will work from this.",rejectNotePlaceholder:"Reason (required) — e.g. 8% is the most we can give here",discountRejected:"Discount rejected",editBlockedByApproval:"Cannot edit while the discount is awaiting approval — changing the amount would leave the approval pointing at a different quotation",sendBlockedByApproval:"The discount needs approval before this quotation can be sent",approvalNeededAlert:"This discount is over your limit, so the quotation cannot be sent until it is approved. Submit it for approval first.",approvalPendingAlert:"This discount is waiting for approval. The quotation cannot be edited or sent until it is decided.",approvalRequestedAt:"Submitted",approvalRejectedAlert:"Discount rejected — {reason}",approvalApprovedAlert:"Discount approved by {who} on {at}",approvalApprovedAlertNoWho:"Discount approved",approvalNote:"Note",discountVsLimit:"discount {pct}%, your limit {limit}%",discountPctOnly:"discount {pct}%",quotationNo:"No.",title:"Title",titlePlaceholder:"e.g. BOSP + Vision · 12 months",titleRequired:"Title is required",customerRequired:"Please select a customer",customerOrg:"Customer",serviceOrg:"Service recipient",serviceOrgPlaceholder:"Empty = same as billing entity",sameAsBilling:"Same as billing entity",currency:"Currency",validityDays:"Valid for (days)",validUntil:"Valid until",metaCreated:"Created",metaValidity:"Valid for",metaValidityDays:"{n} days",metaSent:"Sent",metaAccepted:"Accepted",discountAmount:"Discount",gstRate:"GST rate",termsTemplate:"Terms template",termsTemplateLegacy:"A legacy free-text field, kept read-only for older quotations. Commercial terms are now referenced through the Commercial terms panel below.",termsTemplatePlaceholder:"e.g. GL0001 (free text)",revision:"Revision",sentAt:"Sent at",acceptedAt:"Accepted at",lossReason:"Loss reason: {reason}",lines:"Line items",lineNo:"#",lineType:"Type",product:"Product",licence:"Licence",label:"Description",labelPlaceholder:"Line description",lineDescriptionPlaceholder:"Description (optional)",customHardware:"Custom hardware",noSellableVariant:"No sellable hardware variants",singleVariant:"single variant",variantNotInCatalog:"No longer in the catalog",catalogPriceSgdOnly:"Catalog price is in SGD — enter the price for this currency.",catalogPrice:"Catalog {price}",qty:"Qty",qtyUnit:"Unit",unitPrice:"Unit price",periodType:"Billing",subtotal:"Subtotal",required:"Required",addSoftware:"+ Software",addHardware:"+ Hardware",addService:"+ Service",noLines:"No line items yet — at least one is required before sending",noSellableProduct:"No sellable product — check the product catalogue (deprecated products cannot be quoted)",softwareProductAlert:"A software line must have a product selected, otherwise the contract gets no entitled products and activation will not start any provisioning pipeline. The list only offers products that can still be sold; the licence is fixed to ENTERPRISE by the backend.",amountSubtotal:"Subtotal",amountDiscount:"Discount",amountGst:"GST",amountTotal:"Total",previewNote:"(preview — the server calculates the final amounts)",perOccurrenceSubtotal:"Per occurrence",period:"Period",perMonthSuffix:"/mo",perMonthHint:"Per month",lineMonthsPlaceholder:"Months",lineMonthsDefault:"{n} (default)",lineMonthsRequired:"Set months or the term above",lineMonthsMismatch:"Recurring lines of the same product must have the same number of months",perOccurrenceNote:"Per-occurrence services are charged by the actual number of occurrences and are not included in the total above.",perOccurrenceUnitRequired:"Enter the unit for each occurrence (e.g. visit)",send:"Send",accept:"Mark Accepted",reject:"Mark Lost",revise:"Revise",sent:"Sent",sendNeedsLines:"At least one line item is required before sending",sendNeedsTerm:"Set the term (months) before sending — it sets the amounts and cannot be changed on the contract",acceptNeedsTerm:"This quote has no term (months). Revise it and set the term before accepting",sendNeedsHardwareTerm:"Set the term (months) on every hardware line before sending",acceptNeedsHardwareTerm:"Some hardware lines have no term (months). Revise the quote and set them before accepting",hardwareTermLine:"Term: {n} months",hardwareTermMissing:"Term: not set",hardwareTermPlaceholder:"Term (months)",hardwareTermInvalid:"1–120",hardwareTermMismatch:"Hardware lines of the same model (and all custom hardware lines) must have the same term",sendTitle:"Send this quotation",sendConsequenceStatus:"move the quotation to Sent and stamp the time it was sent",sendConsequenceValidUntil:"set the expiry date to {n} days from today, from the validity period on this quotation",sendConsequenceLocked:"stop the line items and terms from being edited directly — changing them afterwards means issuing a revision, which supersedes this version",sendConsequenceNoEmail:"⚠ NOT email anything to the customer — the system only records that it was sent. You still have to send the document yourself.",softwareNeedsProduct:"A software line must have a product selected, otherwise the contract gets no entitled products and no provisioning pipeline",softwareNeedsProductShort:"A software line needs a product",lineLabelRequired:"Line name is required",lineUnitPriceNegative:"Unit price cannot be negative",discountTooLarge:"Discount cannot exceed the line subtotal",acceptTitle:"Accept quote → create contract",acceptButton:"Accept & create contract →",acceptConsequenceContract:"create a draft contract from this quotation — that is what the customer will sign",acceptConsequenceLocked:"lock this quotation: prices and line items can no longer be edited",acceptConsequenceFinal:"make this the final version — an accepted quotation can no longer be revised",rejectConsequenceStatus:"mark this quotation Rejected — it stops being a live offer",rejectConsequenceRevise:"still let you revise it into a new version later if the customer comes back",reviseConsequenceNew:"create a new version of this quotation, copying every line item and the referenced terms as they read on this version — not upgraded to newer term versions",reviseConsequenceSuperseded:"mark this version Superseded — it stays readable but can no longer be sent or accepted",deleteConsequenceGone:"permanently remove quotation {no} and all its revisions, together with their line items",acceptedUndeletable:"Accepted quotations cannot be deleted.",supersededUndeletable:"This version has been superseded by a revision. Delete the quote from its latest version.",duplicate:"Duplicate",duplicateTitle:"Duplicate quote",duplicateSubtitle:"A new draft will be created with copied line items",duplicateSource:"Source quote",duplicateTarget:"Target customer",duplicateKeepCustomer:"— Keep same customer —",duplicateCopyLines:"Copy line items",duplicateCopyTerms:"Copy terms & conditions",duplicateCopyNotes:"Copy internal notes",duplicateSubmit:"Duplicate & open",duplicated:"Duplicated as {no}",deleteConsequenceAudit:"keep its activity timeline in the audit log",accepted:"Accepted — creating the contract…",contractReady:"Contract {no} created",contractPending:"The contract is still being created, check the contract list shortly",contractNoPermission:"The contract will be created automatically; you do not have permission to view contracts, so there is no link to it here.",acceptedAlert:"This quotation is closed won. The contract is created automatically by the system.",viewContract:"View contract",contractCreating:"The contract is being created — you can find it in the contract list shortly.",rejectTitle:"Mark as lost?",rejectPrompt:"Please enter the loss reason (required)",rejectPlaceholder:"e.g. Price too high",rejected:"Marked as lost",reviseTitle:"Create revision",revised:"Revision {no} created",deleteTitle:"Delete quotation"},claimFiles:{title:"Supporting Documents",empty:"No supporting documents yet",full:"A claim can have at most {n} supporting documents",uploadTitle:"Upload supporting document",docType:"Document type",uploaded:"Uploaded",deleted:"Deleted",deleteTitle:"Delete this supporting document?",deleteConsequenceGone:'remove "{name}" from this claim — it can no longer be viewed or downloaded',deleteConsequenceAudit:"record the deletion in the claim's history"},claimVo:{title:"Raise Variation Order",sub:"For scope/quantity changes found during claim review",note:"A VO triggers a contract Amendment (and may produce a mini-quotation). Once approved, the adjusted amount flows back into this claim — apply it from the Variation Orders list on this page.",reason:"VO reason",reasonPlaceholder:"e.g. Additional 4 cameras requested on-site beyond contracted scope",reasonRequired:"Enter the VO reason",amount:"Amount delta ({currency})",amountPlaceholder:"e.g. 11,200",amountPositive:"Enter an amount greater than 0 — choose Deductive for less scope",direction:"Type",additive:"Additive (more scope)",deductive:"Deductive (less scope)",submit:"Create VO → Amendment",raised:"Amendment {no} created",listTitle:"Variation Orders",colAmendment:"Amendment",colDelta:"Amount delta",colApply:"Adjustment",apply:"Apply to this claim",applied:"Added a VO adjustment line for {no}",appliedOn:"Applied {date}",waitActive:"Can be applied once the amendment takes effect",waitEditable:"Return the claim to draft to apply it",noPermission:"Needs claim edit permission"},miniQuote:{acceptButton:"Mark accepted",nextStep1:"The customer accepts on the accept link — or mark it Accepted here when they reply",nextStep2:"Send amendment {no} for signature on its contract",nextStep3:"Record the signature once both sides have signed",acceptTitle:"Accept mini-quotation",acceptSubtitle:"Customer confirmed. Amendment {no} can then be sent for signature.",amends:"Amendment {no} ·",noProject:"None — a mini-quotation does not create a contract or a project",acceptedAlert:"This mini-quotation is accepted. Amendment {no} can now be sent for signature on its contract.",acceptConsequence:"not create a contract — instead amendment {no} can be sent for signature"},renewal:{title:"Renew contract",subtitle:"Create a renewal quotation based on current contract terms",sourceContract:"Source contract",term:"Renewal term",termDefault:"{n} months (default)",termMonths:"{n} months",priceUplift:"Price uplift",termRequired:"Pick a renewal term",priceUpliftRequired:"Pick a price uplift",customPercent:"Custom uplift (%)",customPercentPlaceholder:"e.g. 7.5, or -3 to lower",customPercentHint:"Applied to recurring line prices. 5 means +5%; a negative number lowers the price.",customPercentRequired:"Enter the uplift percentage",customPercentDecimals:"At most two decimal places",carryOver:"Carry over all current amendments to the renewal",carryOverHint:"Signed amendments are listed in the renewal quote's internal notes; lines and amounts are not changed.",submit:"Create renewal quote",created:"Renewal quote {no} created",menu:"Renew contract",menuNoteExpired:"Contract has ended. Renew to continue service.",alreadyRenewed:"Already renewed by {no}. To renew again, start from that contract.",terminationBlocked:"Can't terminate while a renewal is taking over: the renewal contract is active and this contract has not expired yet. Either contract can be terminated after the original expires.",renews:"Renews",renewedBy:"Renewed by",headButton:"Renewal Quote",opportunityTitle:"Renewal opportunity",opportunityBody:"{customer} has no other active contracts with us. Consider proposing a renewal before contract expires. | {customer} has 1 other active contract with us. Consider proposing a renewal before contract expires. | {customer} has {n} other active contracts with us. Consider proposing a renewal before contract expires.",opportunityBodyNone:"Consider proposing a renewal before contract expires.",opportunityCta:"Create Renewal Quote →",opportunityNotRenewable:"This contract is {status}; only expiring or expired contracts can be renewed.",projectFixed:"Renewal — stays on the project of {no}",projectFixedHint:"The project link of a renewal is set by the system from the original contract and can't be changed.",activateTakeOver:"take over from {no} as the project's primary contract — the tenant, project and instances stay; no new onboarding run is opened (if that project is already closing or archived, a new project is set up instead)",activatePush:"create this contract's entitlements as Pending and push a new licence period for each to Control — they turn Active, and the instances move over, when the original contract expires",activateHandover:"cancel the open handover of the original contract, if there is one",activateNoTerminate:"until the original contract expires, neither contract can be terminated",acceptConsequence:"make the contract a renewal of {no} — once activated it takes over as the project's primary contract, keeping the same tenant, project and instances"},amendment:{fromClaim:"Raised from claim",linkedArtifacts:"Linked artifacts",miniQuotation:"Mini-quotation {no}",generateMiniQuotation:"Generate mini-quotation",miniQuotationCreated:"Mini-quotation {no} created — edit it and send it to the customer",waitingQuoteHint:"Mini-quotation {no} has not been accepted yet. Send it to the customer and record the acceptance first.",createTitle:"Create amendment",createButton:"Create Amendment",createMenu:"Create amendment",createSubList:"For contract {no}",createSubDetail:"Changes will require new signature from both parties",type:"Amendment type",typeOption:{list:{SCOPE_ADDITION:"Scope addition (more sites / users / cameras)",SCOPE_REDUCTION:"Scope reduction",PRICE_ADJUSTMENT:"Price adjustment",TERM_EXTENSION:"Term extension",VO_DRIVEN:"VO-driven (from field variation order)"},detail:{SCOPE_ADDITION:"Scope addition (add product / projects)",PRICE_ADJUSTMENT:"Price adjustment",TERM_EXTENSION:"Term extension",CONTACT_BILLING_CHANGE:"Contact / billing change",OTHER:"Other"}},sourceVo:"Source VO (if VO-driven)",sourceVoPlaceholder:"e.g. VO-2026-007",changeDescription:"Change description",descriptionOfChange:"Description of change",descriptionPlaceholder:"What changes, and why",costDelta:"Cost delta",costDeltaPlaceholder:"e.g. 36000 or -5000 ({currency})",effectiveFrom:"Effective from",effectiveDate:"Effective date",typeRequired:"Pick an amendment type",descriptionRequired:"A description is required",effectiveDateRequired:"Pick an effective date",costDeltaDecimals:"At most two decimal places",costDeltaTooLarge:"The amount is too large",createNoteList:"Will create AMD-YYYY-NNN in Draft status.",createNoteDetail:"Amendment is a new sub-document linked to {no}. Original contract remains in force until both sign the amendment.",created:"{no} created in Draft status",cardTitle:"Amendments & Change Orders",cardSub:"Scope adds, price adjustments, term extensions",empty:"No amendments yet",cardFoot:"VO (Variation Order) and Amendment are the same object — use «VO-driven» type when the change originates from a field change request.",contractRef:"Contract {no}",createdBy:"Created by",voTitle:"Source VO (Variation Order)",voBody:"Field-originated change — this amendment was triggered by a Variation Order raised on site.",voBodyClaim:"Raised during claim review — for scope/quantity changes found while reviewing the claim.",voRef:"Source VO:",sentAt:"Sent for signature {time}",signedOn:"Signed {date}",sendForSignature:"Send for signature",sendTitle:"Send {no} for signature",sendConsequenceStatus:"move the amendment to Pending Sig, waiting for both parties to sign",sendConsequenceNoMail:"not email anyone — collect the signatures yourself, then record them with «Mark as signed»",sendConsequenceNoChange:"leave the contract itself unchanged",sent:"Sent for signature",markSigned:"Mark as signed",markSignedTitle:"Mark amendment as signed",markSignedHint:"Record that both parties have signed this amendment. It becomes Active; it does not change the contract's amount, term or products.",signedDate:"Signed on",signedDatePlaceholder:"Leave blank for today",signed:"Amendment marked as signed — it is now Active",hwTitle:"Add hardware",hwSub:"Creates an amendment on primary contract {no}",hwLines:"Hardware to add",hwQty:"Qty",hwUnitPrice:"Unit price ({currency})",hwLinesRequired:"Add at least one hardware line",hwTotal:"Total {amount} — this becomes the amendment's cost delta",hwTermMonths:"Term (months)",hwTermMonthsInvalid:"1–120 months",hwTermDate:"Effective on",hwTermDateRequired:"Pick a date",hwModeRequired:"Choose one",hwStepUnavailable:"No step in the hardware workflow template starts the term, so “At workflow milestone” is unavailable.",hwNote:"Next, in the contract: to have the customer confirm the price, generate a mini quotation (not possible when the total is 0) and send for signature once it is accepted; or send for signature directly. After both signatures are recorded, allocations are created a moment later — from the catalog hardware lines of the accepted mini quotation if there is one, otherwise from these lines. Then dispatch and settle as usual; each batch is claimed at the unit price, and the claim can be submitted once the signed DO is registered.",hwTypeHint:"Only Scope addition and VO-driven amendments can add hardware",hwGoContract:"Open contract",hwCreatedGo:"{no} created (draft) — generate the mini quotation and send for signature in the contract",addHardware:"Add hardware",addHardwareClosing:"The project is closing or archived; hardware can no longer be added",addHardwareNoPrimary:"The project has no primary contract",addHardwareContractInactive:"Primary contract {no} is not active or expiring; amendments cannot be created",hwSection:"Hardware lines",hwSectionCount:"{lines} line(s) · {qty} unit(s)",hwSectionNote:"If there is a mini quotation, the accepted one wins on activation and these lines are not updated; service lines and custom hardware added to it create no allocations, and Finance raises claims for them by hand.",hwAllocations:"Allocations created",hwSubtotal:"Subtotal",hwAllocationsPending:"No allocations yet: they are created a moment after activation — reopen this in a while. None are created if the accepted mini quotation has no catalog hardware lines.",markSignedHintHardware:"Records that both parties signed this amendment. It becomes active, and allocations are created a moment later — from the accepted mini quotation if there is one, otherwise from the hardware lines — with a new hardware onboarding if the project has none in progress for that model. The contract's amount, term and products do not change."},contract:{partyHintBilling:"Primary · signs",partyHintRecipient:"Runs project",partyHintRecipientSub:"Subsidiary · runs project",partyHintBes:"Seller · provider",viewAll:"View all →",viewCompanyProfile:"View company profile →",kpiRenewalBadge:"RENEWAL",colContract:"Contract",colValue:"Value",colExpires:"Expires",tabExpiring:"Expiring",linkPrimary:"Primary",allowedProjects:"Allowed Projects",linkAddOn:"Add-on",planLinkExisting:"Added to this project when the contract is activated",planNewProject:"New project, created when the contract is activated",planLater:"Decide later — not linked to a project yet",planLaterNote:"Link it from a project's Related Contracts once the contract is active",pageSubtitle:"Central source of truth for all customer commitments. Contracts authorize provisioning.",noCreateLead:"Contracts are auto-generated as Draft when a Quotation is Accepted.",menuNoteDraft:"Draft contracts have limited actions until counter-signed.",menuNotePending:"Awaiting customer signature.",menuNoteExpired:"Contract has ended.",noCreateAlert:"{lead} Manual creation is disabled to ensure traceability from sales cycle. Go to {quotations} to start a new sales cycle.",searchPlaceholder:"Contract no.",selectPlaceholder:"Search by contract no.",oneProject:"1 project",metaFromQuotation:"From quotation",metaSigned:"Signed",metaEffective:"Term",termsCard:"Terms & Effective Dates",termsCardSub:"Each product and hardware item runs its own term from its own effective date",termsEmpty:"No product or hardware with its own term — the contract takes effect on signing.",termsEmptyActive:"No product or hardware with its own term — the contract took effect on signing.",termModesEdit:"Set effective modes",termCustomHardware:"Custom hardware",termFromAmendment:"From {no}",termModeLine:"Starts: {mode}",termModeDateLine:"Starts: {mode} ({date})",termSourceLine:"Effective from: {source}",termStepGone:"The matching workflow template no longer has a step that starts the term — choose another mode before sending for signature.",termStepUnavailable:"No step in the matching workflow template starts the term",termSetDate:"Set effective date",termChangeDate:"Change effective date",termModesTitle:"Effective modes",termModesHint:"Choose how each item's term starts. The modes are locked once the contract is sent for signature.",termColItem:"Item",termColMode:"Takes effect",termColDate:"Date",termModesDateRequired:"Pick the date for {name}",termModesModeRequired:"Choose how {name} takes effect",termModesSaved:"Effective modes saved",termDateTitleSet:"Set effective date — {name}",termDateTitleChange:"Change effective date — {name}",termDateCurrent:"Now: {line}",termDateLabel:"Effective date",termDateHint:"From the signing date ({date}) up to today. The term runs {n} months from this date.",termDateRequired:"Pick the effective date",termDateReason:"Reason",termDateReasonPlaceholder:"Why the effective date is being set or changed — recorded in the audit log",termDateReasonRequired:"Enter a reason",termDateSoftwareNote:"A later date extends the customer's access in Control to the new end of term. An earlier date cannot shorten access that was already granted yet; reconciliation will flag the period mismatch.",termDateSaved:"Effective date saved",metaCreated:"Created",viewProvisioning:"View provisioning",counterParties:"Counter-parties",counterPartiesSub:"Who signs vs who receives services — important when group entities are involved",filterTerm:"Uses term {code}",kpiActive:"Total Active",kpiActiveSub:"{amount} total value",kpiExpiring:"Expiring ≤ 90d",kpiExpiringSub:"{amount} at risk",kpiPending:"Pending Signature",kpiPendingSub:"{n} customer",kpiAvg:"Avg. Duration",kpiAvgValue:"{n} mo",kpiAvgSub:"{n}-month dominant",tabAll:"All",tabPendingSig:"Pending Sig",projectsUnder:"Projects Under This Contract",viewAllProjects:"View all {n} →",colProject:"Project",colProducts:"Products",colPeriod:"Period",noProjects:"No projects under this contract yet.",partyRelationOf:"{relation} of {parent}",partyDescBilling:"Legal signatory · Invoices addressed here",partyDescRecipient:"Operates at the project site · Receives provisioning & training",partyAccountOwner:"Account owner: {name}",terminateNotesLine:"Internal notes: {notes}",signedBy:"Signed by {name} · {date}",authScope:"Authorization Scope",authScopeSub:"Products and projects authorized by this contract",allowedProducts:"Allowed Products",contractValue:"Contract Value",customer:"Customer",notYetActive:"Not yet active",awaitingSignature:"Awaiting signature",contractNo:"No.",termMonths:"Term",billingCycle:"Billing Cycle",billingCyclePlaceholder:"e.g. Quarterly",nextInvoiceDate:"Next Invoice",editTitle:"Edit contract",termMonthsLabel:"Term (months)",amountFixed:"Amounts are inherited from the quotation and cannot be changed here.",amountFixedShort:"Inherited from quotation, read-only",notSigned:"Not signed",noProducts:"No entitled products — none of the quotation lines had a productId, so activation will not start any provisioning pipeline",tenant:"Tenant",tenantOutOfScope:"This contract's tenant is outside your data scope",project:"Project",sendForSignature:"Send for signature",activate:"Activate",terminate:"Terminate",termRequiredAlert:"This draft was created before monthly pricing and has no term (months). Fill it in once before sending for signature.",termLockedHint:"Copied from the quotation and sets the amounts — revise the quotation to change it.",termFillOnceHint:"Can be filled in once; it cannot be changed afterwards and does not change the amounts.",termRequired:"Please edit the contract and fill in the term (months) first",sentForSignature:"Sent for signature",sendTitle:"Send for signature",sendConsequenceLocked:"move the contract to awaiting customer signature — it can no longer be edited",sendConsequenceTerms:"freeze the bound terms — they can only be changed while the contract is a draft",activateTitle:"Activate contract",activateButton:"Activate",activateConsequenceProvision:"kick off provisioning for every product entitlement on this contract — tenants and deployments get created for real",activateConsequenceOnboarding:"open one onboarding per product (each hardware model gets its own): site work, training and handover, typically 6–10 weeks",activateConsequenceReserve:"record the catalog hardware on this contract as an allocation in Inventory — units are taken from stock when they are dispatched",activateConsequenceTermStart:"start the term of items set to start on signing from the signed date, and of items set to a date on that date",activateConsequenceUndo:'to undo it you have to terminate the contract and then run a handover to decommission — there is no "activate again" button',activateConsequenceEntitlement:"create the entitlements as Pending and start provisioning them — they only turn Active once the pipeline finishes",activated:"Contract activated — starting provisioning…",runsStarted:"{n} provisioning pipeline(s) started",runsPending:"Provisioning is still starting, check the provisioning monitor shortly",runsNone:"This contract has no entitled products, so no provisioning pipeline will run",terminateTitle:"Terminate contract?",terminatePrompt:"Termination reason",terminateReasonPlaceholder:"Select a reason",terminateReasonRequired:"Select a termination reason",terminateNotes:"Internal notes",terminatePlaceholder:"Optional — context for the team",terminateButton:"Terminate contract",terminateEffectiveDate:"Effective date",terminateEffectiveDatePlaceholder:"Leave blank for today",terminateEffectiveDateHint:"Today or earlier terminates it now (earlier records a termination that already happened); a later date schedules it, and the contract shows as Terminating until then.",terminateIrreversible:"Cannot be undone — only reversed via a new contract.",terminateLead:"This will trigger the handover workflow.",terminateConsequenceEntitlement:"Active provisioning stops on the effective date: every entitlement on this contract is terminated and the customer loses access. Until then, delivery, claims and invoicing carry on as normal.",terminateConsequencePdpa:"The customer has 30 days after the effective date to download their data (PDPA).",terminateConsequenceHandover:"A handover workflow (5 steps) is created right away; if one is already open, its contract end moves to the effective date.",terminateConsequenceBilling:"Unpaid invoices stay open — terminating does not write them off.",terminated:"Contract terminated — entitlements terminated accordingly",terminationScheduled:"Termination scheduled — the contract ends on {date}; until then delivery carries on",terminatedAlert:"Terminated: {reason} (effective {date})",terminatingAlert:"Terminating on {date}: {reason}. Entitlements and delivery carry on until then; this cannot be withdrawn.",earlyTermination:"Early termination",paymentPlan:"Payment plan",paymentPlanBase:"Node amounts are based on the contract amount excl. GST, {base}",paymentPlanEdit:"Edit payment plan",paymentPlanEditTitle:"Edit payment plan",paymentPlanEditHint:"Each payment node is a percentage of the contract amount excl. GST ({base}); claims are raised against a node and capped by it. You can save a plan that adds up to less than 100%, but it must be exactly 100% before sending for signature.",paymentPlanIncomplete:"The payment plan adds up to {pct}% — it must be exactly 100% before sending for signature.",paymentPlanMissing:"No payment plan yet — set up payment nodes adding up to exactly 100% before sending for signature.",paymentNodeSeq:"#",paymentNodeName:"Payment node",occurrenceTitle:"Per-occurrence services",occurrenceSub:"Priced per occurrence — not included in the contract value; record each batch to raise a draft claim",occurrenceService:"Service",occurrenceUnitPrice:"Unit price",occurrenceRegistered:"Recorded",occurrenceRegisteredValue:"{n} {unit} · {claims} claim | {n} {unit} · {claims} claims",occurrenceRecord:"Record occurrences",occurrenceNotActive:"Occurrences can be recorded once the contract is active",projectClosingNoNew:"The project is in its closing period: no new claims, VOs, or amendments can be created",projectArchivedNoNew:"The project is archived: no new claims, VOs, or amendments can be created",occurrenceRecordTitle:"Record occurrences",occurrenceCount:"Number of occurrences ({unit})",occurrenceCountShort:"Occurrences",occurrenceCountInvalid:"Whole number from 1 to 9999",occurrencePeriod:"Date range",occurrencePeriodFrom:"From",occurrencePeriodTo:"To",occurrencePeriodRequired:"Pick the dates these occurrences happened",occurrenceNote:"Note",occurrenceNotePlaceholder:"e.g. 3 extra site visits for the lift inspection",occurrenceNoteRequired:"Describe what was done",occurrenceHint:"Creates a draft claim of {amount} (before GST). Finance reviews and submits it.",occurrenceRecorded:"Recorded — draft claim {no} created",occurrenceClaim:"Claim",occurrenceAmount:"Amount",occurrenceNoHistory:"Nothing recorded for this service yet",paymentNodeProduct:"Product",paymentNodeStep:"Milestone step",paymentNodeNoLink:"Not linked",paymentNodeStepPlaceholder:"Pick a milestone step",paymentNodeStepNoPerm:"You cannot view workflow templates, so steps cannot be listed. Leave the product empty to keep the node unlinked.",paymentNodeStepGone:"{name} (not in the current template)",paymentNodeLinkIncomplete:"Pick both a product and a step for a linked node, or clear both",paymentNodeNamePlaceholder:"e.g. Deposit on signing, Go-live acceptance",paymentNodePercentage:"Percentage",paymentNodeAmount:"Node amount (excl. GST)",paymentNodeAmountEstimate:"Node amount (estimate)",paymentNodeClaimed:"Claimed",paymentNodeRemaining:"Remaining",paymentNodeAdd:"Add node",paymentPlanEmptyDraft:"No payment nodes yet",paymentPlanEmptyLegacy:"This contract has no payment plan (it left draft before payment plans existed); claims are capped by the contract amount excl. GST as a whole.",paymentPlanDraftNote:"Editable while the contract is a draft; it freezes with the contract once sent for signature.",paymentPlanFrozenNote:"The payment plan is frozen with the contract. Claimed and remaining follow the claims live; draft claims do not count as claimed.",paymentPlanTotal:"Total {pct}%",paymentPlanTotalEstimate:"Total {pct}% (estimate)",paymentPlanTotal_over:"Over 100% — it cannot be saved.",paymentPlanTotal_under:"You can save it below 100%, but it must be exactly 100% before sending for signature.",paymentPlanTotal_exact:"Exactly 100%.",paymentNodeNameRequired:"Every payment node needs a name",paymentNodePercentageRequired:"Every payment node needs a percentage above 0",paymentPlanSaved:"Payment plan saved",sendNeedsPaymentPlan:"The payment plan must add up to exactly 100% before sending for signature",sendConsequencePaymentPlan:"freeze the payment plan — claims are then raised against these nodes and capped by them",sendConsequenceTermModes:"lock how each item's term starts — once active, only the effective date can be set or changed by hand"},files:{dropTitle:"Click to browse or drag a file here",dropHint:"{types} up to {size} MB",remove:"Remove",typeNotAllowed:"Only {types} files can be uploaded here",empty:"The file is empty",tooLarge:"The file is larger than {size} MB",noPreview:"This file type can't be previewed here — download it to open",previewFailed:"The file couldn't be loaded for preview",download:"Download",view:"View",upload:"Upload",replace:"Replace",delete:"Delete",sizeAndDate:"{size} · Uploaded {date}",uploadedBy:"{size} · Uploaded {date} by {name}"},acceptLink:{title:"Customer Accept Link",copy:"Copy",copied:"Link copied",copyFailed:"Couldn't copy — select the link above and copy it manually",email:"Email",emailUnavailable:"Emailing the link isn't available yet — copy it and send it to the customer yourself",expires:"Expires",endOfDay:"End of {date}",opened:"Opened",openedTimes:"{n} time | {n} times",lastOpened:"Last {time}",notOpened:"Not opened yet",created:"Created",noUrl:{ACTIVE:"",EXPIRED:"This link has expired — the customer can no longer open it.",REVOKED:"This link was revoked — the customer can no longer open it.",SUPERSEDED:"This version was revised — its link no longer opens.",DECIDED:"A decision has been made and the link has expired."},decidedAccepted:"Accepted by the customer online",decidedRejected:"Declined by the customer online",reasonIs:"Reason: {reason}",regenerate:"Regenerate link",regenerateTitle:"Regenerate the accept link?",regenerateOldStops:"stop the current link at once — anyone holding it can no longer open the quotation",regenerateNew:"create a new link that stays valid until the end of {date}",regenerateCount:"restart the open count from zero for the new link",regenerated:"New link created — copy it and send it to the customer",revoke:"Revoke link",revokeTitle:"Revoke the accept link?",revokeStops:"stop the link at once — the customer can no longer open, accept or decline the quotation",revokeRegenerate:"leave the quotation as Sent — regenerate a link to give the customer access again",revoked:"Link revoked",expiresOnLabel:"Accept link expires on (optional)",expiresOnPlaceholder:"Defaults to the last valid day ({date})",sendConsequenceLink:"create a customer accept link — copy it from the quotation and send it yourself"},quotationFiles:{title:"Attachments",subtitle:"Signed paper quotation scans, customer PO, email confirmations",full:"This quotation already has {n} attachments — delete one before uploading another",autoGenerated:"Auto-generated",pdfTag:"Quote PDF",tag:{SIGNED_SCAN:"Signed",CUSTOMER_PO:"PO",EMAIL_CONFIRMATION:"Email",REFERENCE:"Reference",OTHER:"Other"},uploadTitle:"Upload attachment",docType:"Attachment type",uploaded:"Attachment uploaded",deleteTitle:"Delete this attachment?",deleteGone:'remove "{name}" from this quotation — it can no longer be viewed or downloaded',deleteAudit:"record the deletion in the quotation's activity",deleted:"Attachment deleted"},productFiles:{photoTitle:"Product photo",photoPlaceholder:"Product image",replacePhoto:"Replace photo",uploadPhoto:"Upload photo",photoUploaded:"Photo uploaded",datasheetsTitle:"Datasheets & manuals",datasheetsEmpty:"No datasheets or manuals yet.",datasheetsFull:"This model already has {n} files — delete one before uploading another",uploadDatasheet:"Upload datasheet / manual",uploadDatasheetTitle:"Upload datasheet / manual",docType:"Document type",datasheetUploaded:"File uploaded",deleteDatasheetTitle:"Delete this file?",deleteDatasheetGone:'remove "{name}" from this hardware model — it can no longer be viewed or downloaded',deleteAudit:"record the deletion in the model's history",datasheetDeleted:"File deleted",newPhotoFailed:"The hardware model was created, but the photo wasn't uploaded. Upload it again on the detail page."},serviceTerm:{daysLeft:"Last day | {n} day left | {n} days left",monthsLeft:"{n} month left | {n} months left",expiredDaysAgo:"Expired {n} day ago | Expired {n} days ago",expiredMonthsAgo:"Expired {n} month ago | Expired {n} months ago",pending:"Pending effective",pendingFor:"Pending effective · {n} months",effectiveOn:"{date} · {n} months",effectiveOnShort:"Effective {date}",takesEffectOn:"Takes effect {date} · {n} months",takesEffectOnShort:"Takes effect {date}",months:"{n} month | {n} months",endsOn:"Ends {date}"},termBinding:{titleQuotation:"Terms & Conditions",titleContract:"Bound Terms",subtitleContract:"Standardized clauses referenced by this contract",versionN:"Version {v}",langBilingual:"Bilingual",langEn:"English",langZh:"Chinese",showSnapshot:"Show bound wording",hideSnapshot:"Hide bound wording",boundAtTip:"Bound at {at}",title:"Commercial terms",subtitle:"The wording this document references — copied in as a snapshot when it was bound",setTerms:"Set terms",setTermsTitle:"Set the referenced commercial terms",saved:"Commercial terms updated",empty:"No commercial term is referenced yet",sourceState:"Source version",boundAt:"Bound at",staleHint:"{n} of the terms below came from a version that is no longer the current one. Those references are still valid — the snapshot is exactly what the customer saw — but the library has a newer version.",lockedQuotation:"The referenced terms can only be changed while the quotation is a Draft or has been Sent — changing them on an accepted or expired quotation would serve no purpose.",lockedContract:"The referenced terms can only be changed while the contract is a Draft. Once it is out for signature the customer's PDF already carries the wording, so changing it would mean the signed and the stored copy are not the same document.",pickerTitle:"Pick commercial terms",pickerOnlyCurrent:"Only the active version can be referenced, so that is all this list shows. Drafts and superseded versions are rejected by the server.",selectedCount:"{n} selected",consequenceReplace:"replace the whole set of referenced terms with the {n} you picked — this is not an addition",consequenceRemoved:"unbind {n} that you did not pick ({codes})",consequenceAdded:"bind {n} newly referenced term(s) ({codes}), copying the wording in as it is now",consequenceRebound:"⚠ re-snapshot {n} already-referenced term(s) ({codes}) — the wording changes to the current version, and nothing on this screen would show that afterwards",consequenceSnapshot:"leave every wording already copied into signed documents untouched — this only affects this one document"},term:{createDraftNote:"Term will be created in Draft status. Publish it when the wording is final — only published versions can be bound.",pdfLangBilingual:"Bilingual EN/ZH (current view)",pdfLangEn:"English only",pdfLangZh:"中文 only",lockTitle:"Version locking",lockBody:"Editing a published term means creating a new version. Contracts and quotations already bound keep the wording they were bound with.",versionPill:"Version {n}",footNote:"Terms are bound by reference to a version, and the wording is snapshotted at binding. Changes to a term do not retroactively apply to existing contracts — each contract keeps the wording it was bound with.",codeAutoHint:"Term ID will be auto-generated on save",adjustmentMonths:"Term adjustment (months)",adjustmentMonthsPlaceholder:"e.g. 3 or -2",adjustmentMonthsHint:"Positive extends, negative shortens the service period of every licensed product. Amounts are not affected. Required before publishing.",adjustmentMonthsNonZero:"Must not be 0",namePlaceholder:"e.g. Payment Terms — Annual Subscription",categoryPrefixHint:"Changing the category does not change the code prefix.",languageField:"Language",langBilingual:"Bilingual EN/ZH",langEnOnly:"English only",langZhOnly:"Chinese only",lang:{BILINGUAL:"Bilingual EN/ZH",EN:"English",ZH:"Chinese"},shortDescription:"Short description",shortDescriptionPlaceholder:"e.g. Quarterly · Net 30",jurisdiction:"Jurisdiction",jurisdictionPlaceholder:"e.g. Singapore",governingLaw:"Governing law",governingLawPlaceholder:"e.g. Laws of Singapore",contentPlaceholder:"Term clause text…",createAndOpen:"Create & open",newVersionTitle:"Create new version",newVersionSub:"{code} · current {from} → new {to}",newVersionReason:"Reason for new version",newVersionReasonPlaceholder:"Select a reason",newVersionReasonRequired:"Select a reason for the new version",changeSummary:"Change summary",changeSummaryPlaceholder:"Describe what changed for the version history log…",newVersionNote:"The new version starts as a draft. {from} stays in force for the {n} contract already using this term; new contracts use {to} once it is published. | The new version starts as a draft. {from} stays in force for the {n} contracts already using this term; new contracts use {to} once it is published.",newVersionButton:"Create {to} (draft)",newDraftLong:"Create New Version",duplicate:"Duplicate",duplicateTitle:"Duplicate term",duplicateFrom:"From {code} {name}",duplicateName:"New term name",duplicateDefaultName:"Copy of {name}",duplicateNote:"A new term is created as Draft v1 with the body and metadata copied. The original term is unaffected.",duplicated:"Created {code}",kpiTotal:"Total Terms",kpiTotalSub:"Across {n} categories",kpiActive:"Active",kpiActiveSub:"In use by contracts",kpiDraft:"Draft",kpiDraftSub:"Under legal review",kpiNeedUpdate:"Need Update",kpiNeedUpdateSub:"Not updated 6+ months",usedBy:"Used By",usedByHint:"Contracts bound to any version of this term (quotations not counted). Counts every contract, including ones you cannot see.",usedByUnit:"contract | contracts",lastUpdated:"Last Updated",approvedBy:"Approved by",inUseBy:"In use by",inUseByValue:"{n} contract | {n} contracts",termInfo:"Term Info",languages:"Languages",contractsUsing:"Contracts Using This Term",colContract:"Contract",colCustomer:"Customer",colLockedVersion:"Locked Version",viewAllContracts:"View all {n} contracts →",usageCount:"{n} contract references this term. | {n} contracts reference this term.",usageFirst:"{n} contracts reference this term. Showing first {shown}.",usageScoped:"{n} contracts reference this term; {visible} of them are in your data scope.",noContractReferences:"No contract uses this term yet.",versionTitle:"Version {n}",versionTitleCurrent:"Version {n} (current)",versionViewing:"Viewing",versionContracts:"{n} contract | {n} contracts",versionContractsLocked:"{n} contract (locked) | {n} contracts (locked)",pageSubtitle:"Template library of reusable commercial clauses — payment terms, support & SLA terms, warranty terms and renewal terms. Quotations and contracts keep a snapshot of the wording when they bind a term.",tabCurrent:"Active",tabAll:"All",keywordPlaceholder:"Code or name",code:"Code",colTerm:"Term",codeHint:"Letters, digits, hyphen and underscore. Every version of this term shares it, and it cannot be changed later.",codeImmutableHint:"The code cannot be changed — references already point at it.",codeRequired:"Please enter a code",codeFormat:"Only letters, digits, hyphen and underscore",name:"Title",nameRequired:"Please enter a title",category:"Category",categoryRequired:"Please pick a category",language:"Written in",version:"Version",references:"References",referenceCountHint:"Counts every quotation and contract, including documents outside your data scope.",create:"New Term",createTitle:"New term",editTitle:"Edit term",content:"Wording",contentDraftHint:"Both languages may be left empty while drafting. Publishing requires at least one of them.",contentEn:"English",contentZh:"Chinese",noContentEn:"No English wording",noContentZh:"No Chinese wording",noContent:"No wording in either language yet",tabContent:"Content",tabUsage:"Usage",tabHistory:"Version History",tabAudit:"Audit",langBoth:"Bilingual",langEn:"English",langZh:"中文",wordCountEn:"~{n} words",charCountZh:"{n} Chinese characters",showAll:"Show all",collapse:"Show less",emptyCurrent:"No active term. Drafts and archived versions are under All versions.",emptyFiltered:"No term matches these filters",emptyAll:"No commercial terms yet",publishedAt:"Published",retiredAt:"Archived",metaCreated:"Created",metaUpdated:"Updated",notPublished:"Not published",noteDraftTitle:"Draft",noteDraft:"Not selectable on quotations or contracts yet. Publish it once the wording is final — after that it can no longer be edited.",noteCurrentTitle:"Active",noteCurrent:"New quotations and contracts will reference this version.",noteSupersededTitle:"Superseded by a newer version",noteSuperseded:"New documents reference the newer version instead. Documents already bound to this one are unaffected — they hold a snapshot of the wording taken when they were bound.",noteRetiredTitle:"Archived",noteRetired:"No longer offered when picking terms. Documents that already reference it are unaffected — they hold their own snapshot.",publish:"Publish",publishTitle:"Publish this version",publishDiffAgainst:"Compared with {v}, this version changes:",publishNoChange:"Identical to {v} — nothing changes except the version number. Publish anyway?",publishNoBaseline:"Nothing to compare — this is the first version of this code.",publishDiffUnavailable:"The differences could not be loaded. That does not mean there are none — check the version history before publishing.",diffLines:"+{add} / -{del} lines",publishConsequenceSupersede:"{v} will become superseded, and new documents will reference this version instead.",publishConsequenceBind:"New quotations and contracts will reference this version.",publishConsequenceSnapshot:"Documents already signed keep the wording they were bound with — nothing changes for them.",publishConsequenceImmutable:"This version becomes read-only; changing the wording again means publishing a new version.",published:"Published",retire:"Archive",retireTitle:"Archive this term",retireConsequenceHidden:"The term will no longer appear when someone picks terms for a quotation or contract.",retireConsequenceExisting:"The {n} document(s) already referencing it keep their snapshot and are unaffected.",retireConsequenceNewVersion:"Archiving is not the same as superseding — if the wording simply changed, publish a new version instead.",retired:"Archived",newDraft:"Create new version",draftCreated:"Draft created",deleteTitle:"Delete this draft",deleteConsequenceGone:"The draft and its wording will be permanently deleted.",deleteConsequenceOnlyDraft:"Only unreferenced drafts can be deleted — published versions never can.",deleteOnlyDraftHint:"Only unreferenced drafts can be deleted.",actionTarget:"Term:",versionHistory:"Version history",versionHistoryHint:"Each binding keeps the wording of the version it was bound to. Older contracts retain their original version.",compare:"Compare",compareTitle:"Compare versions",changed:"Changed",unchanged:"Unchanged",columnUnchanged:"No change between these two versions.",columnEmptyBoth:"Neither version has wording in this language.",contentIdentical:"The wording of both versions is identical.",contentIdenticalUnknown:"One of these versions is still a draft, so the server cannot say whether the wording is identical — read the lines below.",referencedBy:"Referenced by",referencesScopedHint:"Showing {shown} of {total} — the rest are outside your data scope.",referencesAllScoped:"All {total} references are on documents outside your data scope.",noReferences:"Not referenced by any quotation or contract yet",refType:"Document",refNo:"Number",boundAt:"Bound at"},product:{colInventory:"Inventory",stockOut:"Out of stock",stockWithOut:"{n} · {k} variant out | {n} · {k} variants out",stockLowSingle:"{n} low stock",stockWithLow:"{n} · {k} variant low | {n} · {k} variants low",stockIn:"{n} in stock",title:"Products",pageSubtitle:"BES product portfolio. Each product is the basic unit sold in quotations and authorized via contracts.",kpiTotal:"Total Products",kpiSoftwareN:"{n} software",kpiHardwareN:"{n} hardware",kpiServiceN:"{n} service",kpiMostSold:"Most Sold",kpiMostSoldSub:"{n} active deployments",kpiDeployments:"Active Deployments",kpiDeploymentsSub:"Across {n} projects",tabAll:"All",viewGrid:"Grid view",viewList:"List view",colProduct:"Product",colDescription:"Description",colPermissions:"Permissions",colDeployments:"Deployments",colCode:"Code",manage:"Manage",colModel:"Model",colSupplier:"Supplier",colUnitPrice:"Unit price",variantsN:"No variants | {n} variant | {n} variants",modelsN:"No models | {n} model | {n} models",hwSectionSub:"— third-party machines & devices sold by BES",hwTableHint:"Hardware uses a compact table — scales to dozens of models. Full catalog and pricing on each model's page.",requiresHardware:"Requires hardware",customerCanSelfProvide:"customer can self-provide",footNoteLead:"Products define what BES sells.",footNote:"Each product exposes a set of permission points which Company Admins assign via default roles. Quotations and contracts bind to specific product editions.",createSubtitle:"Product code will be auto-assigned on save",formType:"Product type",typeSoftwareDesc:"BOSP, AIVA, SHELL — recurring subscription",typeHardwareDesc:"Cameras, workstations, robots — one-off + maintenance",typeServiceDesc:"Consulting, training, custom dev — billed per engagement",formName:"Product name",namePlaceholder:"e.g. BOSP",shortTitle:"Short title",shortTitlePlaceholder:"e.g. Build Operation & Site Platform",descriptionPlaceholder:"What does this product do...",initialStatus:"Initial status",initialStatusRequired:"Initial status is required",prefixPlaceholder:"e.g. bosp",prefixFixedHint:"Fixed after creation — it is the namespace of this product's Layer 2 permission points.",scopeLevel:"Entitlement scope",scopeLevelRequired:"Choose an entitlement scope",scopeLevelHint:"Per project: each project is licensed separately; its first entitlement period is created when the project is provisioned. Per tenant: licensed per customer tenant, shared by all its projects. Fixed after creation.",scopeFixedHint:"Fixed after creation — it decides how entitlements for this product are created in Control.",controlSync:"Control registration",controlSyncHint:"Software products are registered in Control after they are created, renamed or change status. It runs in the background and failed attempts are retried automatically — nothing to do here.",controlSyncFailed:"Registration in Control failed — it will be retried automatically",hwDeps:"Hardware Dependencies",hwDepsSoftwareOnly:"— Software products only",hwDepsHint:"Software like AIVA requires hardware to run (cameras, workstations). Mark required vs recommended. Customers can opt to provide their own hardware.",hwCandidatesEmpty:"No sellable hardware products yet",allowCustomerHardware:'Allow customers to use their own hardware (marked "customer-provided" in quotation)',createFootnote:"Editions, permission points, default roles, and onboarding template will be configured on the product detail page after creation.",editFootnote:"Editions, permission points, default roles, and onboarding template are edited from their respective tabs.",createAndConfigure:"Create & configure",create:"New Product",createTitle:"New product",editTitle:"Edit product",searchPlaceholder:"Code / name",productCode:"Code",name:"Name",productType:"Type",permissionPrefix:"Permission prefix",permissionPrefixHint:"Software only, lowercased automatically. It defines the namespace of the entire Layer 2 registry and is fixed after creation.",description:"Description",permissionCount:"Permission points",roleTemplateCount:"Role templates",belongsTo:"Product",countScopeHint:"Counts are for this product alone — the platform-wide figure is the sum across every product.",nameRequired:"Name is required",typeRequired:"Type is required",changeStatus:"Change status",changeStatusTitle:"Change product status",currentStatus:"Current:",reason:"Reason",updateStatus:"Update",statusDesc:{ACTIVE:"sellable, supported",BETA:"early access, limited support",DEPRECATED:"no new sales, existing supported"},changeStatusLabel:"New status",statusChanged:"Status changed",kpiActiveDeployments:"Active Deployments",kpiPermissionPoints:"Permission Points",kpiRoleTemplates:"Role Templates",navViews:"Views",section:{setup:"Product setup",access:"Access & roles",delivery:"Delivery"},view:{surfaces:"Product surfaces",permissions:"Permission Points",templates:"Role Templates",pipeline:"Provisioning template",projects:"Projects"},appPages:"{n} pages",appIncluded:"Included",appsVerbatim:"App blurbs are synced verbatim from {name}.",appsSyncedAtValue:"Last synced {time}",projectsUsing:"Projects using {name}",projectsShowing:"Showing {shown} of {n} projects with {name} deployed",viewAllProjects:"View all projects",colProject:"Project",colEdition:"Edition",editionEnterprise:"Enterprise",noDeployedProjects:"No project has {name} deployed yet.",layer2Alert:"Permission points and role templates on this page are Layer 2: they are handed to customer tenants and enforced by the product side. BOSS never uses them for its own access control.",placeholderAlert:"The permission points loaded today are placeholder data pending confirmation from the product side — most codes were derived from naming patterns, not documented. Verify them before anything is rolled out to a customer.",unpublishedTemplatesAlert:"{n} role template(s) have never been published. Provisioning only rolls out published snapshots, so tenants get nothing from them.",neverSynced:"Never synced",appCode:"App code",appName:"Name",appPageCount:"Pages",appSortNo:"Order",syncApps:"Sync applications",syncAppsTitle:"Sync application mirror",syncAppsHint:"Names and descriptions are mirrored verbatim from the product side, so this is a wholesale replacement rather than an edit: any app missing from this list is removed. Permission points under a removed app are kept and fall back to grouping by their raw app code.",addRow:"+ Add row",appsEmpty:"No applications synced yet",appRowIncomplete:"Every row needs an app code and a name",appsRequired:"The list cannot be empty — that would wipe the mirror rather than change nothing",synced:"Synchronised",resultAdded:"Added",resultUpdated:"Updated",resultUnchanged:"Unchanged",resultOrphaned:"Orphaned",resultPruned:"Deleted",resultKeptInUse:"Kept (in use)",resultUnknownApps:"Unknown app codes",resultOrphanedHint:"Present locally but missing from the list you submitted — usually the product side retired them.",resultKeptInUseHint:"Still referenced by a role template, so they were not deleted. Change the templates first.",resultUnknownAppsHint:"Not found in the application mirror. They were imported anyway and are grouped by their raw app code.",importPoints:"Import permission points",importPointsTitle:"Import Layer 2 permission points",importPointsHint:"Paste the list exported from the product side. The import is idempotent — re-importing the same list only refreshes the display text.",importJsonLabel:"Points (JSON)",importJsonInvalid:"Not valid JSON",importJsonShape:"Expected a JSON array whose entries each have a code",importCount:"{n} point(s) parsed",pruneOrphans:"Delete points that are missing from this list",pruneOrphansHint:"Off by default — missing points are only reported. Even when on, points referenced by a role template are never deleted.",pointCode:"Code",pointName:"Name",pointRisk:"Risk",pointsEmpty:"No permission points yet — import them from the product side",ungrouped:"Not in the application mirror",imported:"Imported",templateCode:"Template code",templateCodeHint:"Globally unique across all products and fixed after creation — provisioned tenants identify the role by it.",templateName:"Name",templatePermissions:"Permissions",publishedRevision:"Published version",revisionNoValue:"r{n}",neverPublished:"Never published",neverPublishedHint:"Never published — provisioning skips this template entirely.",unpublishedChanges:"Unpublished changes",unpublishedChangesAlert:"This template has unpublished changes. Tenants keep receiving the last published snapshot until you publish it.",systemTemplate:"Preset",createTemplate:"New role template",createTemplateTitle:"New role template",editTemplateTitle:"Edit role template",isSystem:"Product preset",isSystemHint:"Preset templates cannot be deleted. This can only be set when creating — allowing it later would let anyone unset it and delete the template.",templateCodeRequired:"Template code is required",templateNameRequired:"Name is required",deleteTemplateTitle:"Delete role template",deleteTemplateConsequenceGone:'delete the role template "{name}" and every published revision of it',deleteTemplateConsequenceProvision:"leave tenants that already received it untouched — but no future provisioning will seed this role",templatesEmpty:"No role templates — the seed_roles provisioning step will be skipped for this product",publish:"Publish",publishTitle:"Publish role template",publishConsequenceSnapshot:"freeze the current working copy into a new, read-only revision",publishConsequenceTenant:"make that revision the one every future provisioning hands to tenants",publishConsequenceServerCopy:"publish what is saved on the server — anything you changed here but did not save is not included",publishPrompt:"Publishing freezes the working copy as a new version and rolls it out to every tenant holding this product. Note (optional):",publishPlaceholder:"e.g. added sealant permissions",published:"Published as revision {n}",workingCopy:"Working copy",workingCopyHint:"Editable. Tenants never see this until it is published.",publishedSnapshot:"Published snapshot",publishedSnapshotHint:"Read-only, frozen at revision {n}. This is what tenants actually have.",pendingDiff:"Pending: +{added} / -{removed} against the published snapshot",unsavedChanges:"You have unsaved changes. Publishing freezes the copy saved on the server, not what is on screen — save first.",revisions:"Version history",revisionNo:"Revision",revisionNote:"Note",publishedAt:"Published at",publishedBy:"Published by",revisionPermissions:"Permission points",revisionsEmpty:"No published version yet",registryEmpty:"This product has no Layer 2 permission points yet — import them before configuring templates",pipelineTitle:"{name} Provisioning Pipeline",pipelineSubtitle:"Automated system steps when activating {name} for a new customer · {n} steps",currentlyVersion:"Currently {v}",provVsOnbTitle:"Provisioning vs Onboarding",provVsOnbBody:"This pipeline runs automatically by system workers when a contract activates. It sets up the technical side (tenant, entitlements, access) for this product. The manual implementation steps that BES staff follow with the customer (survey, install, training, handover) are defined per implementation type in Workflow Templates, not here.",provNotOnboardingLead:"Provisioning ≠ Onboarding.",provNotOnboarding:"This is the automated technical pipeline for this product — what system workers do when a contract activates. The manual implementation flow that BES staff run with the customer lives in",addStep:"Add step",addStepTitle:"Add provisioning step",addStepSubtitle:"Add an automated step to the {name} provisioning pipeline",editStepTitle:"Edit provisioning step",stepDescription:"Description",stepNamePlaceholder:"e.g. Seed sample sites",handlerPlaceholder:"provisioning.seed_sites",estimatedDuration:"Estimated duration",estimatedDurationPlaceholder:"e.g. 5s",insertPosition:"Insert position",insertLast:"After step {n} (last)",insertFirst:"Before step 1",insertCustom:"Custom (drag after creation)",stepNameRequired:"Step name is required",handlerRequired:"Handler function is required",handlerDuplicate:"Another step already uses this handler",stepTypeRequired:"Type is required",stepBehaviorRequired:"Behavior is required",insertPositionRequired:"Insert position is required",systemWorker:"System (worker)",handlerValue:"handler: {h}",dragToReorder:"Drag to reorder",draftUnsaved:"Unsaved changes to the steps — nothing takes effect until you save a new version.",discardDraft:"Discard changes",deleteStepTitle:"Delete this step?",deleteStepConsequenceDraft:'remove "{name}" from the steps on this page — nothing is published until you save a new version',deleteStepConsequenceRuns:"leave existing customer provisioning runs on {v}",deleteStepConsequenceRequired:"drop a Required step — provisioning for new customers may break without it; consider editing it instead",pipelineSummary:"Pipeline summary",totalSteps:"Total steps",avgExecution:"Avg execution",successRate30d:"Success rate (30d)",durationSeconds:"~{n}s",durationMinutes:"~{n} min",durationHours:"~{n} h",history:"History",activeRunsUseVersion:"{n} active runs use this version",historicalRuns:"{n} historical runs",lastUpdated:"Last updated {date}",lastUpdatedBy:"Last updated {date} by {name}",noVersionYet:"No version published yet",saveAsNewVersion:"Save as new version",saveVersionNoChanges:"No changes to the steps yet",provisioningEventsLead:"See execution logs of past runs at",provisioningEventsLink:"Provisioning Events →",saveVersionTitle:"Save as new pipeline version",saveVersionSubtitle:"{from} → {to} · Existing runs continue with {from}",saveVersionFirst:"First version of this pipeline",versionLabel:"Version label",changeSummary:"Change summary",changeSummaryPlaceholder:"Briefly describe what changed and why...",changeSummaryRequired:"Change summary is required",saveVersionButton:"Save {version}",historyTitle:"Provisioning pipeline history",historySubtitle:"{name} · {n} versions",historyEmpty:"No version published yet",versionActive:"Active",versionArchived:"Archived",stepCountN:"{n} steps",compare:"Compare",compareTitle:"Compare versions",compareSubtitle:"Step changes between two pipeline versions",compareBase:"Base",compareTo:"Compare to",compareCurrent:"{v} (current)",comparePick:"Pick two versions to compare",diff:{added:"ADDED",removed:"REMOVED",changed:"CHANGED",same:"SAME"},diffField:{stepNo:"Position",stepName:"Name",stepType:"Type",behavior:"Behavior",description:"Description",estimatedDuration:"Estimated duration"},diffUnchanged:"Other steps unchanged: {n}",diffIdentical:"The two versions have the same steps",leaveDraftTitle:"Leave with unsaved pipeline changes?",leaveDraftAction:"Leave",leaveDraftConsequence:"discard the step changes on this page — nothing was published",pipelineVersion:"Version",pipelineNoneAlert:"No provisioning template configured. When a contract with this product activates, provisioning is skipped for it — nothing is set up and no error is raised.",stepName:"Step name",stepType:"Type",stepBehavior:"Behavior",handlerFn:"Handler function",handlerMissing:"Not implemented",handlerMissingAlert:"{n} required step(s) point at a handler that does not exist on the server — every provisioning run for this product will fail there.",requiredCount:"Required",optionalCount:"Optional",versionRequired:"A version identifier is required",versionDuplicate:"This product already has a version with that name",requiredHandlerHint:"Required steps must have a working handler on the server, otherwise the backend rejects the publish. Optional steps are not checked — the orchestrator skips ones it cannot run.",pipelinePublished:"Provisioning template {version} published"},hardware:{manageInventory:"Manage inventory",kpiInStock:"In Stock",kpiDeployed:"Deployed",tabInventory:"Inventory",tabDeployments:"Deployments",tabDatasheet:"Datasheet",deploymentsTitle:"Where this hardware is deployed",deploymentsSub:"Units installed per project site",colProject:"Project",colCustomer:"Customer",colUnits:"Units",noDeployments:"Not installed on any project yet",dispatch:"Dispatch",colInStock:"In stock",inventorySnapshot:"Snapshot for this model. Open the full {link} for everything.",inventoryModule:"Inventory module",reorderNewPo:"Reorder (New PO)",invInStock:"In stock",invAllocated:"Allocated",invOnOrder:"On order",invInstalled:"Installed",recentMovements:"Recent stock movements",openInventory:"Open inventory →",colMovement:"Movement",colQty:"Qty",colReference:"Reference",colDate:"Date",noMovements:"No stock movements yet",initialStock:"Initial stock",safetyStock:"Safety stock alert",wholeNumber:"Whole number, 0 or more",inventoryRecordHint:"Saving creates a catalog entry and an Inventory record. Stock is then managed in the Inventory module.",kpiUnitPrice:"Unit Price",kpiMargin:"Margin",tabCatalog:"Catalog",tabPricing:"Pricing & Supplier",variantsTitle:"Variants",variantsTitleSku:"(SKUs)",variantsSub:"Each variant is a sellable spec. Pricing is tracked per variant.",addVariant:"Add variant",addVariantTitle:"Add variant",editVariantTitle:"Edit variant",colVariant:"Variant",colSku:"SKU",colPrice:"Price",default:"Default",noVariants:"No variants yet. Add one so this model can be quoted.",singleSpecHint:"A single-spec product would simply have one variant here.",firstVariantTitle:"Hardware details",firstVariantSub:"— first variant",firstVariantHint1:"A product can have multiple variants (specs). Add more after creating.",firstVariantHint2:"Pricing is tracked per variant. Single-spec products just keep one variant — e.g. a workstation with i5/i7/i9 configs would be one product with three variants. Leave these empty to add variants later.",sharedSpecs:"Shared specifications",sharedSpecsSub:"— common to all variants",noSpecs:"No shared specifications yet",noDescription:"No description yet",bundledTitle:"Bundled with software",defaultCompanionOf:"Default companion of",notBundled:"No software product lists this hardware as a dependency.",pricingTitle:"Pricing",pricingOf:"Variant {name} · {sku}",pricingHint:"Amounts are in SGD. Bulk price and maintenance are catalog reference only — quotations do not apply them automatically.",supplierTitle:"Supplier",supplier:"Supplier",supplierPlaceholder:"e.g. Hikvision",warranty:"Warranty",warrantyMonths:"Warranty (months)",warrantyPlaceholder:"e.g. 36",warrantyMonthsInvalid:"1–120 months",warrantyYears:"{n} year | {n} years",sku:"Variant SKU / model no.",skuPlaceholder:"e.g. AIVA-CAM-4MP",skuRequired:"SKU is required",variantName:"Variant name",variantNamePlaceholder:"e.g. 4MP Standard",specNote:"Spec note",specNotePlaceholder:"e.g. 2.8mm lens · day-only",sellPrice:"Sell price (unit)",sellPriceRequired:"Sell price is required",unitPriceSell:"Unit price (sell)",costPrice:"Cost price (buy)",margin:"Margin",bulkPrice:"Bulk price",bulkPriceN:"Bulk price ({n}+)",bulkMinQty:"Bulk from (units)",bulkMinQtyPlaceholder:"At least 2",bulkUnitPrice:"Bulk unit price",bulkPairRequired:"Fill in both bulk fields, or neither",maintenancePerYear:"Maintenance / yr",variantFootnote:"Amounts are in SGD. Quotations copy the SKU, name and price when a line is saved, so later edits don't change existing quotes.",specNamePlaceholder:"e.g. Power",specValuePlaceholder:"e.g. PoE (802.3af)",specNameRequired:"Name required",specValueRequired:"Value required",addSpec:"Add specification",specsMax:"Up to {n} specifications",moveUp:"Move up",moveDown:"Move down",createFootnote:"Add more variants, shared specifications and pricing on the model page after creation.",editFootnote:"Variants and their prices are edited on the model page.",deleteVariantTitle:"Delete variant",deleteVariantConsequence:"Removes SKU {sku} from the catalog; new quotation lines can no longer pick it. Existing quotation lines keep the SKU and price they saved.",deleteDefaultConsequence:"{name} becomes the default variant — the model's SKU, unit price and margin will show its values."},provisioning:{pageTitle:"Provisioning Monitor",pageSubtitle:"Customer set-ups that are in progress or failed. Successful runs live on each instance's page.",kpiInProgress:"In Progress",kpiInProgressBadge:"LIVE",kpiInProgressHint:"Running now — no action needed",kpiFailed:"Failed · needs Ops",kpiFailedBadge:"ATTENTION",kpiFailedHint:"Investigate root cause, then retry",tabAll:"All",rolledBackAtStep:"Rolled back at step {current} of {total}",failedAtStep:"Failed at step {current} of {total}",footTitle:"All provisioning events also produce audit log entries.",footBody:" Every event is idempotent — safe to retry from the failed step. See {link} for the broader event history.",searchPlaceholder:"Run no.",runNo:"Run no.",entitlementNo:"Entitlement",progress:"Progress",stepProgress:"Step {current} of {total}",pipelineVersionValue:"Template {version}",startedAt:"Started at",finishedAt:"Finished at",took:"Took {d}",entitlementStatus:"Entitlement",product:"Product",contract:"Contract",deploymentId:"Deployment ID",traceId:"Trace ID",steps:"Steps",noSteps:"No steps",attempt:"Attempt {n}",runningAlert:"The pipeline is running — this page refreshes every 2 seconds.",errorBeforeRollback:"Error from before the rollback — this step was skipped when the run was rolled back",rolledBackAlert:"Rolled back: the entitlement was terminated before provisioning finished. The remaining steps were skipped and the deployment never went live. This run can't be retried.",projectLevelAlert:"Project-level deprovision after handover — there is no entitlement or product on this run.",termExtendedAlert:"Extends the authorization period in Control: a new period is added right after the one already granted, so access runs to the end of the service term (or by another term while the product has not taken effect). Nothing else is rebuilt.",failedAlert:"The pipeline failed at step {step} and stopped (failures are never retried automatically). Once you have found the root cause, click Retry — it resumes from the failed step and never re-runs steps that already succeeded or were skipped.",retry:"Retry",retryTitle:"Retry provisioning?",retryConsequenceResume:"resume this run from the step that failed, not from the beginning",retryConsequenceIdempotent:"re-run that step against the tenant — the steps are written to be safe to repeat",retryConsequenceAgain:"be repeatable — if it fails again you can retry again",retryPrompt:"Root cause confirmation — recorded in the audit log (required, max 500 characters)",retryPlaceholder:"e.g. CMDB handler was not deployed with this release, now patched",retryReasonTooLong:"Root cause must not exceed 500 characters",retryButton:"Retry",triggeredBy:"Triggered by",retryFromStep:"Retry from step {n}",retrySuccess:"All steps completed successfully",retryStillFailed:"Still failing at step {step}, please keep investigating",retryRestarted:"Pipeline restarted",reconcileScope:"All tenants pushed to Control",reconcileSummary:"Tenants {tenants} · Discrepancies {n}",reconcileInSync:"Tenants {tenants} · in sync with Control",reconcileAlert:"Daily reconciliation with Control: reads back every tenant's entitlement periods and compares them with BOSS. It only reports differences — nothing is changed in BOSS or in Control. The next run checks again, so fixed items drop off by themselves.",tenantCount:"Tenants read",discrepancyCount:"Discrepancies",discrepancies:"Discrepancies",discrepancyKind:"Discrepancy",discrepancyLocal:"BOSS",discrepancyControl:"Control",controlEntitlementId:"Control entitlement ID",period:"{start} → {end}",noDiscrepancies:"No discrepancies — BOSS and Control agree",discrepanciesPending:"Discrepancies appear once the read-back finishes",discrepanciesFailed:"The read-back failed, so there is no result. Retry to read every tenant again from the beginning.",discrepancyHint:{NOT_PUSHED:"Retry this entitlement's provisioning run",MISSING_IN_CONTROL:"Check in Control — the period BOSS recorded is gone",INACTIVE_IN_CONTROL:"Check in Control — the customer has no access while BOSS says active",ACTIVE_IN_CONTROL:"Retry this entitlement's deprovision run — the customer still has access",PERIOD_MISMATCH:"Check the period in Control",UNKNOWN_IN_CONTROL:"Check in Control — BOSS has no record of this period"},reconcileFailedAlert:"The read-back failed and stopped (failures are never retried automatically). Once you have found the root cause, click Retry — it reads every tenant again from the beginning.",retryReconcileConsequenceRead:"read back every tenant from Control again, from the beginning",retryReconcileConsequenceNoChange:"change nothing in BOSS or in Control — it only reports differences"},notes:{add:"Add note",onboardingTitle:"Add note to onboarding",handoverTitle:"Add note to handover",placeholder:"Note will appear under Notes for the team…",internalOnly:"Visible to BOSS staff only — notes can't be edited or deleted once added.",required:"Write the note first",added:"Note added",title:"Notes",empty:"No notes yet"},onboarding:{title:"Onboarding",fromAmendment:"Added hardware · amendment {no}",pageSubtitle:"Track project onboarding tasks from contract activation to full deployment. Auto-created from active contracts.",completedLast30d:"{n} last 30d",viewAllCompleted:"View all {n} completed →",footTitle:"Onboarding is the operational workflow that runs after a contract is signed.",footBody:"It is auto-created when the contract becomes Active and follows the workflow template that matches what was sold:",footDefault:"default",footClaim:"A step can be set to trigger a claim (financial milestone) and/or notify Sales (upsell opportunity).",priorityBadge:"{level} Priority",metaStarted:"Started",metaTarget:"Target",implementationType:"Implementation Type",stepsCount:"{n} step | {n} steps",slaTotal:"SLA {n} working days",overallProgress:"Overall Progress",currentlyOn:"Currently on",progressTriggers:"Each step completion can trigger a Claim and/or notify Sales",usesLabel:"This onboarding uses:",usesHint:"— instantiated from the contract's product mix when it became Active",compareFlows:"Compare flow types",editDefinitions:"Edit definitions →",editDefinitionsLong:"Edit workflow definitions →",compareTitle:"Implementation flow types",gotIt:"Got it",customerContacts:"Customer Contacts",primaryContact:"Primary contact",noContacts:"This customer has no contacts yet",searchPlaceholder:"Onboarding no.",noCreateAlert:"Onboarding runs cannot be created by hand — activating a contract starts one, the same way it starts provisioning. Provisioning is the system opening the tenant in minutes; this is the 6–10 weeks of people going on site, installing, training and handing over.",boardView:"Board",listView:"List",boardMore:"{n} more →",onboardingNo:"No.",customer:"Customer",contract:"Contract",project:"Project",product:"Product",definition:"Workflow",currentMilestone:"Current milestone",progress:"Progress",progressValue:"{done} / {total} steps",progressHint:"Continuous phases (such as maintenance) are excluded from the denominator — they never complete, and counting them would keep the run below 100% forever.",targetDate:"Target date",overdueParen:"({n}d overdue)",overdueDays:"{n}d overdue",viewLog:"View log",stepLogTitle:"Step activity log",stepLogSub:"{step} · all events",startedAt:"Started at",completedAt:"Completed at",timelineCompleted:"Completed {time}",timelineSkipped:"Skipped {time}",timelineStarted:"Started {time}",timelineTarget:"Target {date}",priority:"Priority",owner:"Owner",noOwner:"Unassigned",blockedReason:"Blocked: {reason}",blockedAlert:"This run is blocked — no step can be started, completed or skipped until it is unblocked. Reason: {reason}",emptyColumn:"Nothing here",steps:"Steps",stepOwnerRole:"Suggested role",stepOwnerRoleHint:"Comes from the workflow template — a suggestion, not an assignment.",durationDays:"Took {n} day(s)",milestone:"Milestone",milestoneHint:"Completing a milestone step is what a claim is raised against — treat it as a billing event, not a status tick.",continuous:"Continuous phase",continuousHint:"A continuous phase never completes and is not counted in the progress. It starts by itself once the last normal step is done (delivery finished → maintenance begins), so it has neither a Start nor a Complete button — only Skip, for when the customer does not renew.",skippedReason:"Skipped: {reason}",pendingRequiredHint:"{n} required item(s) still outstanding — complete them first.",autoNextHint:"Only the first step needs starting by hand: completing or skipping a step starts the next one automatically.",items:"Checklist & deliverables",itemRequired:"Required",itemOptional:"Optional",itemDoneBy:"Done by {name} · {time}",itemLockedHint:"This step is already closed, so its items can no longer be changed — reopen the step first if something really has to change.",checklistTitle:"Checklist",checklistCount:"{done} of {total} done",deliverablesTitle:"Deliverables",deliverablesCount:"{done} of {total} required uploaded",deliverableMissing:"required, not yet uploaded",legacyLink:"Earlier link:",itemFileUploaded:"Uploaded",itemFileReplaced:"Replaced",itemFileDeleted:"Deleted",itemFileDeleteTitle:"Delete this file?",itemFileDeleteGone:'remove "{name}" from this item — it can no longer be viewed or downloaded',itemFileDeleteUndone:'mark "{label}" as not done',itemFileDeleteUndoneRequired:`mark "{label}" as not done — it is required, so the step can't be completed until a file is uploaded again`,signOffHint:"Upload the file the customer signed. The step can't be completed until this item is done.",customHardware:"Custom hardware",allProjectProducts:"All project products",colDeliveredProduct:"Delivers",deliversLabel:"Delivers",hardwareDispatchHint:"Hardware is dispatched and settled against this step in batches; it can only be completed once every unit is installed (or recorded as not to install) and none is left on site.",startsTermHint:"Completing this step starts the contract term of what this onboarding delivers (items set to take effect at the workflow milestone). Skipping it does not.",hardwareNotInstalledHint:"Hardware still to install: {n} unit(s). Settle every dispatch (bring units left on site along on the next one), or record what the customer will not install, before completing this step.",hardwareNotInstalledHintSite:"Hardware still to install: {n} unit(s); left on site: {site}. Settle every dispatch (bring units left on site along on the next one), or record what the customer will not install, before completing this step.",hardwareNotInstalledTip:"Some hardware is not installed yet, a dispatch is still open, or units are left on site",skipConsequenceRelease:"record the {n} hardware unit(s) still to install as not to be installed — they will not be billed",skipHardwareInTransit:"{n} dispatch(es) still open — settle or cancel them before skipping this step",skipHardwareOnSite:"{n} unit(s) left on site — bring them along on a dispatch and settle it before skipping this step",hwBadge:"Inventory dispatch",hwInstalledOf:"{installed} of {total} installed",hwInTransit:"{n} dispatched",hwOnSite:"{n} on site",hwReserved:"{n} reserved",hwReleased:"{n} not to install",hwOverInstalled:"{n} over contract",hwShort:"{n} short",hwNoAllocations:"Custom hardware — not tracked in Inventory. This step bills like a normal milestone.",hwClaim:"Claim",hwOverClaim:"Over-installation claim",hwViewInventory:"View in Inventory",salesHint:"This step prompts the team to notify Sales for upsell follow-up. Use Notify Sales once the step is in progress or done.",notifySales:"Notify Sales (upsell opportunity)",actionsTitle:"Available actions:",claimCreated:"Claim created · {no}",triggered:"Triggered: ",notified:"Notified: ",notifiedOpen:" (",notifiedClose:")",notifiedNameSep:", ",notifiedGroupSep:", ",claimRef:"Claim {no}",actionsMilestoneReached:"🎯 {label} reached — Available actions:",notifySalesTitle:"Notify Sales for follow-up",notifySalesSubtitle:"Flag this step as an upsell / cross-sell opportunity for the Sales team",notifySalesTo:"Notify (Sales team member)",notifySalesOwnerSuffix:"current account owner (default)",notifySalesToRequired:"Select who to notify",opportunityType:"Opportunity type",opportunityTypeRequired:"Select an opportunity type",notifySalesContext:"Context for Sales",notifySalesContextPlaceholder:"What the customer said or did that suggests an upsell opportunity...",notifySalesContextRequired:"Explain the opportunity when the type is Other",notifySalesUrgency:"Urgency",notifySalesUrgencyRequired:"Select an urgency",notifySalesFollowUpBy:"Suggested follow-up by",notifySalesDraftQuotation:"Auto-create a draft quotation pre-filled with the customer + context",notifySalesSelf:"You picked yourself — no notification is sent to you. Everything else is still recorded.",notifySalesSubmit:"Notify Sales",notifySalesDone:"Sales notified",notifySalesDoneQuotation:"Sales notified. Draft quotation {no} created.",notifySalesDoneSelf:"Recorded. No notification was sent, because you picked yourself.",notifySalesDoneSelfQuotation:"Recorded, and draft quotation {no} created. No notification was sent, because you picked yourself.",definitionRevision:"v{n}",definitionRevisionHint:"The template version this onboarding was created from. Publishing a new version doesn't change it.",start:"Start",complete:"Complete",skip:"Skip",reopen:"Reopen",reassign:"Reassign",block:"Mark as Blocked",unblock:"Unblock",startDone:"Step started",completeTitle:"Mark step complete?",completeConfirm:"Mark complete",completeConsequenceStep:'mark step {seq} · "{step}" as complete',completeConsequenceLocked:"lock this step's checklist and deliverables — changing them later needs a reopen",completeConsequenceNext:"start the next pending step automatically",completeConsequenceClaim:'generate a draft billing claim for milestone "{label}"',completeConsequenceTerm:"start the contract term today for what this onboarding delivers that is set to take effect at the workflow milestone and not yet effective",completeDone:"Step completed — the next step is now in progress",completeAllDone:"Step completed — all steps are done",linkedRecords:"Linked Records",cantCompleteHint:"Step can't be marked Complete until all checklist items are ticked and required deliverables uploaded ({n} still outstanding).",progressComplete:"{done} / {total} steps complete",currentStepLabel:"Step {n}: {name}",whenDone:"Done {date}",whenSkipped:"Skipped {date}",whenTarget:"Target: {date}",whenStarted:"Started {date}",whenDays:"{n} day | {n} days",skipTitle:"Skip step?",skipPrompt:"Reason for skipping — this delivery step will not be done at all (required, recorded in the audit log)",skipPlaceholder:"e.g. customer supplied their own cameras, no installation needed",skipDone:"Step skipped",reopenTitle:"Reopen step",reopenWarning:"Reopening «{step}» also resets the {n} step(s) after it back to Not started, and moves the run itself back to In progress. Those steps may already have been billed — a claim raised against a milestone does not disappear when the step is reopened.",reopenNoFollowing:"Reopening «{step}» moves the run back to In progress.",reopenItemsKept:"Checklist items and deliverables are deliberately kept — they carry who ticked them and when. Untick manually whatever really has to be redone.",reopenPrompt:"Please state why (required, goes into the audit trail):",reopenPlaceholder:"e.g. survey report has to be reissued",reopenReasonRequired:"A reason is required",reopenDone:"Step reopened",blockTitle:"Mark onboarding as blocked",blockSubtitle:"Pauses SLA · escalates to manager",blockNotify:"Notify owner & manager",blockConsequenceSla:"pause the SLA — days left stop counting down, and target dates move back by the blocked working days on unblock",blockConfirm:"Mark blocked",skipConsequenceNotDone:'mark "{step}" as skipped, not done — whatever that step was meant to produce does not exist',skipConsequenceProgress:"still count it towards progress, so the run can reach 100%",skipConsequenceNext:"start the next step automatically",blockConsequenceFrozen:"freeze every step: nothing can be started, completed or skipped until you unblock it",blockConsequenceBoard:"move this run to the Blocked column, where someone is expected to pick it up",blockConsequenceUnblock:"be reversible — unblocking puts the run back where it was",blockPrompt:"Blocked runs sit in their own column for someone to pick up — state what is holding it up (required):",blockPlaceholder:"e.g. customer has not nominated a Company Admin yet",blockDone:"Run blocked",unblockDone:"Run unblocked",blockReasonLabel:"Block reason",blockReasonRequired:"Choose a block reason",blockDetails:"Details",blockDetailsPlaceholder:"What exactly is holding it up",blockedAlertDetails:"This run is blocked — no step can be started, completed or skipped until it is unblocked. Reason: {reason} — {details}",completeNoteLabel:"Completion notes (optional)",completionNote:"Completion note: {note}",cancelRun:"Cancel onboarding",cancelTitle:"Cancel onboarding?",cancelSubStatus:"Project stays {status}",cancelSubUnknown:"The project stays as it is",cancelReasonLabel:"Reason",cancelReasonRequired:"Choose a reason",cancelNoteLabel:"Note (optional)",cancelConsequenceFinal:"This is final — the run can't be reopened; only notes can be added afterwards.",cancelConsequenceScope:"Only this run changes: the project, its tenants and entitlements, and any claims already raised stay as they are.",cancelConsequenceNoNew:"No new onboarding will be created for this project, and BOSS sends no email to the customer.",cancelConfirmWord:"Type {word} to confirm",cancelConfirmMismatch:"Type {word} exactly",keepRun:"Keep onboarding",cancelDone:"Onboarding cancelled",cancelledAlert:"This onboarding was cancelled {date} — reason: {reason}. Steps can no longer move; notes can still be added.",cancelledAlertNote:"This onboarding was cancelled {date} — reason: {reason}. Note: {note}. Steps can no longer move; notes can still be added.",reassignTitle:"Reassign",reassignStepTitle:"Reassign step",reassignDone:"Reassigned",related:"Related records",viewContract:"View contract",viewCustomer:"View customer",kpiInProgress:"In Progress",colOnboarding:"Onboarding",kpiBlockedBadge:"ACTION NEEDED",kpiBlocked:"Blocked",kpiCompleted30d:"Completed (30d)",kpiAvgDays:"Avg. time to complete",kpiDaysValue:"{n} d"},billing:{from:"From",paymentInstructions:"Payment instructions",bankTransferTo:"Bank transfer to {bank}",accountName:"Account name: {name}",paymentReference:"Reference: {ref}",termsNet:"Terms: NET {n}",lastReminder:"Last reminder recorded {at} ({n} in total)",sendReminder:"Send reminder",reminderTitle:"Send payment reminder",reminderNoEmail:"BOSS does not send emails. This only records who you reminded and in what tone — send the email yourself.",reminderRecipient:"Recipient",reminderFinanceContact:"Finance contact",reminderPrimaryContact:"Primary contact",reminderCustom:"Custom email…",reminderCustomEmail:"Email",reminderEmailRequired:"Enter the recipient's email",reminderRecipientRequired:"Choose a recipient",reminderToneRequired:"Choose a reminder tone",reminderEmailInvalid:"Enter a valid email address",reminderTone:"Reminder tone",reminderMessage:"Message (not saved)",reminderCc:"CC (not saved)",reminderCcPlaceholder:"e.g. Finance lead",reminderPrevious:"Previous reminder recorded {at} · {n} in total",reminderSubmit:"Record reminder",reminderRecorded:"Reminder recorded",currentlyWith:"Currently with:",holderWithName:"{role} ({name})",submittedByLine:"— submitted by {name}",actionsCount:"{n} action: {list} | {n} actions: {list}",noActions:"No actions for you",autoCreatedTitle:"Auto-created when billing milestone was reached",autoCreatedBody:"This claim was generated automatically when {step} of onboarding {run} was completed{date}. Finance reviews the claim, adds the breakdown, then submits it to the customer.",autoCreatedOn:" on {date}",autoCreatedBodyDispatch:"This claim was generated automatically when dispatch {dispatch} was settled under {step} of onboarding {run}. Finance reviews the claim, then submits it to the customer.",autoCreatedBodyAmendment:"This claim was generated automatically when dispatch {dispatch} of onboarding {run} was settled: the units installed in this batch are billed at the unit price of amendment {amd}, outside the payment plan. It can be submitted once the signed DO is registered on the dispatch.",autoCreatedBodyOverInstall:"This claim was generated automatically for the units installed beyond the contract: over-installation {ovi} was confirmed when dispatch {dispatch} of onboarding {run} was settled. It is billed at the contract unit price, outside the payment plan, and can be submitted once the signed DO is registered on the dispatch.",triggeringOps:"Triggering operations",triggeringOpsSub:"Onboarding steps completed → triggered this claim",triggeredClaim:"Triggered claim",nextPaymentNode:"Next payment node: {name} ({pct}%)",nextPaymentNodeSub:"{amount} left to claim",claimant:"Claimant",claimantOwner:"Owner: {name}",claimantOwnerDept:"Owner: {name} ({dept})",counterpartiesSub:"Claim is issued to Billing Party; service delivered to Service Recipient",partyBilling:"Billing",partyService:"Service",partyBes:"BES",paysInvoice:"Pays invoice",paysInvoiceWithRoles:"{roles} · pays invoice",runsProject:"runs {name}",sameAsBillingParty:"Same as billing party",customerContact:"Customer Contact",customerContactNone:"No primary contact on the paying company, or you cannot view this customer.",stepperApprovedInvoiced:"Approved & invoiced",claimsSubtitle:"Milestone billing claims generated from contract payment plans and onboarding milestones.",claimsSubtitleMuted:"(Not BOSP construction claims.)",invoicesSubtitle:"Invoices generated when a Claim is approved. Sent to customer for payment.",customerColumn:"Customer",submittedColumn:"Submitted",claimFlowTitle:"Claim → Invoice → Payment workflow.",claimFlowBody:"Completing a milestone step creates a Claim. Once it is approved, an {link} is issued automatically; when payment arrives, the Invoice and Claim are marked Paid.",claimFlowInvoice:"Invoice",createSubtitle:"For exceptional cases only — claims are usually auto-created",createHintTitle:"Claims should normally be auto-created",createSubmit:"Create draft claim",subBilling:"Billing:",subService:"Service:",subContract:"Contract",subMilestone:"Milestone: {name}",claimSummary:"Claim Summary",flowCardTitle:"Claim → Invoice → Payment",flowDraft:"Draft",flowDraftSub:"Not submitted yet",flowSubmitted:"Claim submitted",flowAwaitingApproval:"Awaiting approval",flowDisputed:"Disputed",flowApproved:"Approved",flowApprovalSub:"Approve to auto-generate invoice",flowInvoiced:"Invoice issued",flowAwaitingReissue:"Awaiting re-invoice",flowPaid:"Payment received",flowDue:"Due {date}",disputeSubmit:"Raise dispute",kpiUnpaidAcross:"Across {n} invoices",statusOverdueDays:"Overdue {n}d",statusDueIn:"Due in {n}d",statusDueToday:"Due today",statusOverdueDaysLong:"Overdue {n} days",statusSent:"Sent",amountColumn:"Amount",dueDateColumn:"Due Date",linkedClaim:"Linked Claim",fromClaim:"From Claim",invoicePaper:"INVOICE",creditNotePaper:"CREDIT NOTE",dateIssued:"Date issued",lineDescription:"Description",lineRate:"Rate",gstWithRate:"GST ({rate}%)",paymentStatus:"Payment Status",invoiceTotalLabel:"Invoice total",overdueDaysLong:"{n} days overdue",paymentHistory:"Payment History",sourceClaimCard:"Source Claim",approvedOn:"Approved {date}",paymentAmountWithCurrency:"Amount received ({currency})",paymentPaidNote:"If amount equals outstanding, invoice will be marked {paid}. Partial payment will keep invoice open with reduced balance.",outstandingSub:"Outstanding {amount}",methodDefault:"{method} (default)",claimsTitle:"Claims",invoicesTitle:"Invoices",noCreateAlert:"Claims are raised by themselves — completing a milestone step of an onboarding run creates one, and only one per milestone. The work here is filling in the breakdown, not creating claims; «New claim» is for exceptional cases only.",claimNo:"Claim #",invoiceNo:"Invoice #",contract:"Contract",project:"Project",milestone:"Milestone",claimType:"Type",amount:"Amount",period:"Period",periodFrom:"Period (from)",periodTo:"Period (to)",source:"Source",autoCreated:"Auto",manualCreated:"Manual",triggerStep:"Triggered by «{step}»",createdBy:"Raised by",sourceFilter:"How raised",searchClaimPlaceholder:"Claim no. or milestone",searchInvoicePlaceholder:"Invoice no. or claim no.",tabAll:"All",tabDraft:"Draft",tabSubmitted:"Submitted",tabUnderReview:"Under review",tabInvoiced:"Approved & invoiced",tabPaid:"Paid",tabDisputed:"Disputed",tabIssued:"Issued",tabOverdue:"Overdue (collections)",tabAwaitingReinvoice:"Awaiting re-invoice",tabCredited:"Credited",tabCreditNotes:"Credit notes",reissueInvoice:"Re-issue invoice",awaitingReinvoiceAlert:"This claim's invoice was credited — it has no valid invoice right now. Check the lines, then re-issue; the new invoice takes its amount from the current lines.",invoiceHistory:"Invoice history",reissueConsequenceNew:"Issues a new invoice (a new INV number, dated today)",reissueConsequenceAmount:"The amount comes from this claim's current lines: {amount} (before GST, which is added at the contract rate)",reissueConsequenceDue:"The due date is recalculated as NET 30 from today",reissueConsequenceStatus:"This claim goes back to «Approved & invoiced»; the credited invoice and its credit note stay in the invoice history",reissueDone:"Re-issued: {no}",reissueDoneNoNo:"Invoice re-issued",creditNote:"Credit note",creditNoteTitle:"Credit {no}",creditNeedsReversal:"This invoice has payments. Reverse them in the payments list below until nothing is collected, then credit it.",creditNeedsInvoicedClaim:"The source claim is «{status}». Only an «Approved & invoiced» claim can be credited — withdraw the dispute first if there is one.",creditedAlert:"This invoice has been credited and no longer counts as receivable. Credited by:",billTo:"Bill to",billToMissing:"This invoice was issued before invoices took their header from a billing account, so no bill-to header was recorded.",billToLine:"Bill to: {name}",viewBillingAccounts:"View customer's billing accounts",paymentTermsValue:"{n} days",noDefaultBillingAccount:`The payer "{name}" has no default billing account, so approving or re-issuing now will be blocked: the invoice takes its header and payment terms from it. Create a billing account in the customer's details (the first one becomes the default), or set an existing one as the default.`,noDefaultBillingAccountShort:"The payer has no default billing account, so no invoice can be issued",goSetBillingAccount:"Set up billing account",noDefaultBillingAccountNoPerm:"Ask a colleague who can maintain billing accounts to set this up.",creditNoteOfAlert:"This is a credit note (negative amount) — it takes no payments and never goes overdue. It credits:",creditReasonIs:"Reason: {reason}",creditConsequenceNote:"Issues a credit note (a new CN number) for {amount}, cancelling this invoice out",creditConsequenceOriginal:"This invoice itself is kept as is (number, amounts and lines); its status becomes «Credited» and it no longer counts as receivable",creditConsequenceClaim:"Claim {no} goes back to «Awaiting re-invoice» for Finance to re-issue",creditReasonLabel:"Why are you crediting this invoice?",creditReasonPlaceholder:"e.g. wrong amount, wrong customer (recorded on the credit note)",creditNoteDone:"Credit note {no} issued",creditNoteDoneNoNo:"Invoice credited",paymentReversal:"Reversal",paymentReversed:"Reversed",reversalReasonIs:"Reason: {reason}",reversePayment:"Reverse",reversePaymentTitle:"Reverse this payment",reverseConsequenceRecord:"Adds a reversal record of {amount} dated today; the original record is kept",reverseConsequencePaid:"The amount collected on this invoice goes down accordingly",reverseConsequenceStatus:"The invoice goes from «Paid» back to «Issued» or «Overdue» by its due date, and the claim from «Paid» back to «Approved & invoiced»",reversalReasonLabel:"Why are you reversing this payment?",reversalReasonPlaceholder:"e.g. wrong amount recorded, refunded to the customer",reversePaymentDone:"Payment reversed",approvedTabHint:"Approving a claim issues its invoice in the same transaction, so approved claims sit under «Approved & invoiced». «Awaiting re-invoice» holds claims whose invoice was credited and not yet re-issued.",collectionsHint:"Collections is not a separate module and not a separate state: it is the overdue invoices, under the tab below.",kpiOutstanding:"Awaiting approval",kpiOutstandingHint:"Submitted and under review — not «invoiced but unpaid», which is counted on the Invoices page.",kpiUnderReview:"Under review",kpiApprovedThisMonth:"Approved (MTD)",kpiAvgApproval:"Avg Approval Time",kpiDaysValue:"{n} d",kpiUnpaid:"Outstanding total",kpiOverdue:"Overdue",kpiDueSoon:"Due ≤ 30d",kpiDueSoonHint:"Issued invoices due between today and 30 days from now (both ends included), as outstanding balance. Overdue ones are not counted here — they are under Overdue.",kpiPaidThisMonth:"Paid (MTD)",kpiPaidThisMonthHint:"Payments received from the 1st of this month to today, by payment date rather than when they were recorded — a late entry for last month counts in last month.",kpiScope:"Across every claim and invoice — these totals ignore the filters and paging below.",kpiMixedCurrency:"Amounts are added at face value with no FX conversion, so no currency is shown while the underlying documents are in more than one.",zeroAmountAlert:"This claim was raised at 0 — that is expected, not a fault: milestones are not mapped to payment nodes automatically, so Finance fills it in. Click Edit to add the lines (pick a payment node first if the contract has a payment plan); the amount is their sum and cannot be entered directly.",paymentNode:"Payment node",paymentNodeLabel:"{name} ({pct}%)",paymentNodeNone:"No node",paymentNodeNoPermission:"Picking a payment node reads the contract's payment plan, which needs contract view permission (boss.contracts.view).",paymentNodePickContract:"Pick a contract first",paymentNodeLoadFailed:"Failed to load the contract's payment plan.",paymentNodeNoPlan:"This contract has no payment plan; claims are capped by the contract amount excl. GST as a whole.",paymentNodeNonePlaceholder:"No node (outside the plan)",paymentNodeRequiredPlaceholder:"Pick a payment node",paymentNodeRemainingShort:"{amount} left",paymentNodeNoneHint:"No node: an exceptional charge outside the plan — it uses no node's allowance and is not capped.",paymentNodeRequiredHint:"This contract has a payment plan: an auto-created claim must be linked to a payment node before it can be submitted.",nodeAmount:"Node amount",nodeClaimed:"Claimed so far",nodeRemaining:"Remaining",nodeQuotaHint:"All amounts exclude GST (added at invoicing); draft claims do not count as claimed.",claimLimit:"Max for this claim",claimLimitShort:"This claim can be at most {amount} (excl. GST).",claimLimitContract:"This claim can be at most {amount} (excl. GST): the contract amount excl. GST minus the contract's other claims already raised.",claimLimitDisputedHint:"All amounts exclude GST. This claim is disputed and already counted in the node's claimed total, so its max is the remaining plus its own original amount.",claimLimitNone:"No payment node — not capped",claimLimitPickNode:"Pick a payment node first — the claim is then capped by it",fillFromLimit:"Fill one line from the max",overLimitDraft:"The lines add up to more than this claim's max of {amount}: you can save the draft, but submitting will be rejected.",overLimitBlocked:"The lines add up to more than this claim's max of {amount}: a disputed claim is capped when saved, so adjust the lines.",submitNeedsAcceptance:"The signed DO for this dispatch has not been registered yet — it is the customer's acceptance of the over-installation. Register it on the over-installation record or the dispatch, then submit.",submitNeedsAcceptanceAmendment:"The signed DO for this dispatch has not been registered yet — it is the customer's acceptance of this batch. Register it on the dispatch, then submit.",submitNeedsNode:"Click Edit and pick a payment node first — this contract has a payment plan, so an auto-created claim must be linked to a node before submitting.",submitOverLimit:"The amount exceeds this claim's max of {amount} (excl. GST); submitting will be rejected.",nodeRequiredAlert:"This contract has a payment plan: click Edit and pick a payment node before submitting.",zeroAmountShort:"Awaiting breakdown",submitNeedsAmount:"Add at least one line first — a claim cannot be submitted at 0.",editableStatesHint:"Only draft and disputed claims can be edited: once it is with the customer, changing the amount would put the two out of step. Adjusting the amount is one of the ways a dispute gets resolved, which is why it is allowed there.",counterparties:"Counter-parties (from contract)",billingParty:"Claim issued to",serviceRecipient:"Work performed for",breakdown:"Milestone breakdown",lineLabel:"Description",lineLabelRequired:"Description is required",qty:"Qty",unitPrice:"Unit price",subtotal:"Subtotal",noLines:"No lines yet — the claim amount stays 0 until something is added.",addLine:"Add line",linesTotal:"Claim total",linesTotalHint:"Server-calculated from the lines; the total itself is never sent.",approvalTimeline:"Approval Timeline",createdStep:"Raised",submittedStep:"Submitted",approvedStep:"Approved & invoiced",paidStep:"Paid",disputedStep:"Disputed",byWhom:"by {name}",pending:"Pending",description:"Description",justification:"Justification",claimReason:"Reason",invoice:"Invoice",viewInvoice:"View invoice",viewClaim:"View claim",create:"New Claim",createTitle:"New manual claim",editTitle:"Edit claim",createHint:"When an onboarding step marked as a billing milestone is completed, the system auto-generates the corresponding milestone claim. Only use this manual form for off-cycle scenarios (extra trips, custom services, dispute corrections, etc.). The reason and justification both go into the audit trail.",formSourceContract:"Source contract",formClaimReason:"Claim reason",formPeriodCovered:"Period covered",justificationPlaceholder:"Why a manual claim is needed instead of auto-creation. Include reference to VO / amendment / customer email if relevant.",claimReasonOption:{EXTRA_SITE_TRIP:"Extra site trip (VO-driven)",ADJUSTMENT:"Adjustment / correction to a prior claim",CUSTOM_SERVICE:"Custom service outside standard milestones",EXTRA_MAINTENANCE:"Maintenance trip beyond contracted count",OTHER:"Other (specify in description)"},contractRequired:"Pick a contract",contractProjectClosing:"Project closing · no new claims",contractProjectArchived:"Project archived · no new claims",reasonRequired:"A reason is required",justificationRequired:"A justification is required",milestoneNamePlaceholder:"e.g. Ad-hoc site visit",submit:"Submit",submitDone:"Claim submitted",submitTitle:"Submit claim",submitConsequenceLocked:"lock the line items and amount — only draft or disputed claims can be edited",submitConsequenceApproval:"hand it to Finance for review; approval issues the invoice",startReview:"Start review",startReviewDone:"Claim under review",startReviewHint:"Optional — a claim can be approved straight from Submitted.",approve:"Approve & invoice",approveTitle:"Approve claim & generate invoice",approveTwoActions:"This will perform two actions:",approveActionMark:"Mark claim {no} as {status}",approveActionApproved:"Approved",approveActionInvoice:"Generate an invoice addressed to {name} (Billing Party)",approveConfirm:"Approve & create invoice",invoiceDueDate:"Invoice due date",invoiceNotesOptional:"Invoice notes (optional)",invoiceNotesPlaceholder:"Internal notes for the invoice...",dueDate:"Due date",dueDateHint:"Leave empty to use the payment terms of the payer's default billing account.",dueDateHintTerms:"Leave empty to use the payer's default billing account terms: approval date + {n} days.",notes:"Notes",sendImmediately:"Mark as sent to the customer",sendImmediatelyHint:"No email is sent — there is no mail infrastructure yet, this only records a timestamp. Do not let anyone read it as «the customer has it».",approveDone:"Claim approved — invoice {no} issued",approveDoneNoNo:"Claim approved and invoice issued",dispute:"Dispute",disputeTitle:"Raise a dispute",disputeSub:"Flag a disagreement on this claim for multi-department coordination",disputeParty:"Disputed by",disputePartyHint:"Any of the three sides can raise one — it is not only the customer.",disputeType:"Dispute type",disputeReason:"Details",disputePartyCustomer:"Customer ({name})",disputePartyInternal:"{party} (internal)",disputeReasonPlaceholder:"Describe the disagreement...",disputeMovesTo:"The claim moves to {status} status. Resolve by adjusting the amount, raising a Variation Order, or withdrawing the dispute.",disputeReasonRequired:"A reason is required",disputeDone:"Dispute raised",disputeAlert:"Disputed by {party} — {type}. {reason}",withdrawDispute:"Withdraw dispute",withdrawOccurrence:"Withdraw registration",withdrawOccurrenceConsequenceFinal:"mark {no} as Withdrawn — it stays on record but can no longer be edited or submitted",withdrawOccurrenceConsequenceCount:'take its {n} occurrence(s) off "{line}" on the contract',withdrawOccurrenceReason:"Reason (optional)",withdrawOccurrenceDone:"Registration withdrawn",withdrawnAlert:"This per-occurrence registration was withdrawn on {time}. The claim is kept for the record.",paymentNodeOccurrence:"Per-occurrence claims are not linked to a payment node and do not use any node's budget.",paymentNodeOverInstall:"Over-installation claims are not linked to a payment node and do not use any node's budget.",paymentNodeAmendment:"Added-hardware claims are billed at the amendment's unit price; they are not linked to a payment node and do not use any node's budget.",occurrenceLineLocked:"Recorded occurrences — withdraw and record again to change",withdrawConsequenceReview:"put this claim back under review, where it was before the dispute",withdrawConsequenceInvoiced:"put this claim back to Approved & invoiced — it cannot go back to review, because the invoice has already been issued and approving it again would be blocked",withdrawConsequenceReopen:"still let anyone raise the dispute again if it is not actually settled",markSentConsequenceStamp:"record the time you sent the invoice, on this invoice",markSentConsequenceNoEmail:"not email anything — BOSS does not send mail. You still have to send the invoice to the customer yourself",withdrawDone:"Dispute withdrawn",reject:"Return",rejectTitle:"Return claim to draft",rejectConsequenceDraft:"send the claim back to draft for the preparer to fix and resubmit",rejectConsequenceQuota:"stop counting it as claimed, releasing the payment-node allowance it held",rejectConsequenceReapprove:"Once it is fixed, resubmitted and approved again, the approval issues the new invoice by itself — no need to re-issue",rejectConsequenceReason:"show the reason on the claim and record it in the audit trail",rejectReasonLabel:"Why is it being returned? The preparer will fix it based on this",rejectReasonPlaceholder:"e.g. The adjustment lacks support — please attach an explanation",rejectDone:"Returned to draft",rejectedAlert:"Returned: {reason} ({by}, {at}). Please fix it and resubmit.",rejectedStep:"Returned",rejectedTag:"Returned",rejectedAtHint:"Returned on {at}, waiting to be fixed and resubmitted",contractClaimed:"Contract claimed to date",contractClaimedHint:"Sum of this contract's claims that have been submitted or gone further (excl. GST), including this one once submitted; drafts are not counted.",approvalNote:"Approval note",approvalNoteHint:"Kept on the claim and also copied to the invoice notes.",customerFilter:"Customer (billing party)",createdFrom:"Created from",createdTo:"Created to",customer:"Customer",issuedDate:"Issued",dueFrom:"Due from",dueTo:"Due to",invoiceTotal:"Total",amountPaid:"Amount paid",outstanding:"Outstanding",sentAt:"Marked sent",notSent:"Not marked sent",markSent:"Mark as sent",markSentDone:"Marked as sent",noEmailHint:"Sending is manual for now: «mark as sent» and «mark as sent on approval» both only write a timestamp, no mail is sent by the system.",recordPayment:"Record payment",remittanceOptional:"Remittance advice (optional)",remittance:"Remittance advice",uploadRemittance:"Attach remittance advice",replaceRemittance:"Replace",replaceRemittanceTitle:"Replace the remittance advice?",replaceRemittanceGone:'replace "{name}" — the old file is no longer shown on this payment',replaceRemittanceAudit:"record the replacement in the invoice's history",remittanceUploaded:"Remittance advice attached",remittanceNotAttached:"The payment is recorded, but the remittance advice wasn't attached. Attach it on the payment in Payment History.",recordPaymentTitle:"Record payment received",paymentAmountPlaceholder:"Amount received this time",fillOutstanding:"Fill outstanding",paidDate:"Payment date",method:"Payment method",reference:"Reference / transaction ID",referencePlaceholder:"e.g. TXN-001",paymentHint:"Payments can be recorded in parts. Overpaying is rejected outright — money that does not belong to this invoice would turn into an unexplainable difference at reconciliation.",outstandingIs:"Outstanding on this invoice: {amount}",overpayError:"That is more than the {amount} still outstanding.",amountRequired:"Amount must be greater than 0",paymentDone:"Payment recorded",paymentSettled:"Payment recorded — invoice settled and the claim marked paid",noPayments:"No payments recorded yet.",recordPaymentButton:"Record Payment",recordedBy:"Recorded by {name}"},workflow:{subtitle:"Templates that define the onboarding step sequence for each implementation type. When a contract becomes Active, the matching workflow is instantiated automatically.",create:"New Workflow",createTitle:"New workflow definition",createSubtitle:"Define a custom onboarding step sequence",editTitle:"Edit template details",editSubtitle:"Name, description and auto-match aren't versioned — saving applies them right away.",editInfo:"Edit details",nameEn:"Workflow name (English)",nameZh:"Workflow name (Chinese)",namePlaceholder:"e.g. Express SW Onboarding",zhPlaceholder:"In Chinese (optional)",descriptionEn:"Description (English)",descriptionZh:"Description (Chinese)",nameRequired:"Enter the English name",matchCondition:"Auto-match condition",matchRequired:"Choose an auto-match condition",matchHint:"Each product's onboarding is matched by what it delivers (software or hardware); Hardware + software is no longer matched automatically. Only published templates take part; a template that has never been published does not hold its condition yet.",manualHint:"Never picked automatically, and there is no way to pick it by hand yet.",baseOn:"Base on existing",startFromScratch:"Start from scratch",copyOf:"Copy: {name} ({n} step) | Copy: {name} ({n} steps)",createInfo:"After creation you can add/remove/reorder steps and configure claim triggers and Sales notifications per step.",createInfoMatch:" Publish it once so matching contracts can pick it.",createSubmit:"Create & edit steps",createdHint:"Template created. Add or adjust its steps, then publish it once so matching contracts can pick it.",createdHintManual:"Template created. Add or adjust its steps next.",stepsCount:"{n} step | {n} steps",revisionValue:"v{n}",neverPublished:"Never published",statusActive:"Active · Published",default:"Default",defaultHint:"Used when a contract matches no template. There is exactly one default and it cannot be changed here.",unpublished:"Unpublished changes",pillUnpublished:"Unpublished",autoMatch:"Auto-match: ",neverPublishedAlert:"This template has never been published: it does not take part in auto-matching, so no contract will use it. Publish it once the steps are ready.",workingCopy:"Working copy",workingCopyHint:"You are editing the working copy: changes don't affect any onboarding until you publish.",noSteps:"No steps yet.",addStep:"+ Add step",moveUp:"Move up",moveDown:"Move down",duplicate:"Duplicate",copySuffix:" (copy)",stepMenu:"Step actions",slaValue:"SLA {n} working days",checklistCount:"{n} checklist item | {n} checklist items",deliverableCount:"{n} deliverable | {n} deliverables",stepTitleAdd:"Add step",stepTitleEdit:"Edit step",stepTypeContinuous:"Continuous phase",stepTypeContinuousDesc:"Runs for the duration of the maintenance contract: never completes, doesn't count toward progress and always sits after the normal steps. It can't trigger a claim or require a sign-off.",stepNameEn:"Step name (English)",stepNameZh:"Step name (Chinese)",stepNamePlaceholder:"e.g. Pre-Survey",descPlaceholder:"What happens in this step...",stepNameRequired:"Enter the English step name",stepNameDuplicate:"Another step in this template already has this name",responsibility:"Responsibility & timing",ownerRole:"Owner role",ownerRoleSuffix:" (hint only)",sla:"SLA (working days)",slaHint:"Planned dates count Monday to Friday; public holidays are not skipped.",slaRange:"Between 1 and 365",completion:"Completion requirements",completionSuffix:" — what makes this step “done”",deliverables:"Required deliverables",deliverablesSuffix:" (must be uploaded)",checklist:"Checklist",checklistSuffix:" (required items must be ticked)",newDeliverable:"New deliverable…",newChecklistItem:"New checklist item…",itemLabelZh:"(Chinese)",addDeliverable:"+ Add deliverable",addChecklistItem:"+ Add checklist item",itemLabelRequired:"Enter the English label",itemRequired:"Required",removeItem:"Remove",autoActions:"Automatic actions on completion",milestone:"Trigger a milestone claim",milestoneHint:"Auto-generate a draft claim when marked done. If the contract's payment plan links a node to this step, the amount is filled in; otherwise Finance fills it in.",milestoneLabelEn:"Milestone name (English)",milestoneLabelZh:"Milestone name (Chinese)",milestoneLabelRequired:"Enter the English milestone name",salesPrompt:"Prompt Sales notification",salesPromptHint:"Flag upsell opportunity for Sales — the step on the onboarding gets Notify Sales, which sends the chosen salesperson an in-app notification.",signOff:"Require customer sign-off",signOffHint:"Step can't complete until the customer's signed file is uploaded.",hardwareDispatch:"Trigger hardware dispatch",hardwareDispatchHint:"Dispatch hardware from Inventory for install — hardware onboardings dispatch and settle installation against this step.",hardwareDispatchTaken:"Another step already triggers hardware dispatch; a template can have only one.",startsTerm:"Start contract term",startsTermHint:"Contract items set to take effect at the workflow milestone start their term on the day this step completes.",startsTermTaken:"Another step already starts the contract term; a template can have only one.",continuousDisabled:"Not available for a continuous phase.",saveStep:"Save step",deleteStepTitle:"Delete step",deleteStepConsequence:"Removes “{name}” with its checklist and deliverables from the working copy.",deleteStepRecover:"Published versions don't change; “Discard changes” restores the working copy to the current version.",deleteStepRecoverNever:"This template has never been published, so there is no version to restore it from.",stepConflict:"Someone else changed this template and the steps behind this dialog have been refreshed. Your input is still here — check it against the latest steps before saving again.",stepConflictEdit:"Saving will overwrite step {n} “{name}” in the latest list.",stepConflictAppend:"The step you were editing is no longer there; saving will add yours at the end.",versions:"Version & Publishing",versionsLead:"{count} runs on v{v}. Publishing a new version does {not} change it. | {count} run on v{v}. Publishing a new version does {not} change them.",versionsLeadCount:"{n} active onboarding | {n} active onboardings",versionsLeadNot:"not",versionsNone:"Nothing published yet.",publishedOn:"Published {date}",revisionActive:"{n} active",revisionTooltip:"Published by {name} · {time}",revisionTooltipNone:"No publisher (created by migration) · {time}",compare:"Compare",publish:"Publish new",publishFirst:"Publish",publishNoChanges:"There are no unpublished changes.",publishNoSteps:"Add at least one normal step first.",publishTitle:"Publish v{n}",publishConsequenceNew:"Onboardings created from now on will copy these steps.",publishConsequenceKeep:"Existing onboardings keep the version they were created with.",publishConsequenceNext:"Contracts activated after publishing will use v{n}.",publishConsequenceStay:"Active onboardings stay on v{n}; they are not migrated.",publishConsequenceFirst:"The template starts taking part in auto-matching ({condition}).",publishConsequenceManual:"Its condition is Manual selection only, so no contract will pick it automatically.",publishNoteLabel:"What changed in this version? (optional)",publishNotePlaceholder:"e.g. + AI credits step",publishChangesLead:"Compared with v{n}:",publishStepsLead:"Steps in this first version:",published:"Published v{n}",takeOverTitle:"Take over the match condition",takeOverConsequenceHolder:"“{other}” currently holds “{condition}”; it will be switched to “{manual}” in the same step.",takeOverConsequenceNext:"Contracts activated from now on that match this condition will use “{name}”.",takeOverUnknown:"Another published template",takeOverAction:"Take over",discard:"Discard changes",discardTitle:"Discard unpublished changes",discardConsequence:"The working copy goes back to v{n}; the unpublished step changes are lost.",discarded:"Working copy restored to v{n}",legend:"Step configuration legend",badgeClaim:"$ Claim",badgeSales:"Sales",badgePhase:"Phase",badgeSign:"Sign",badgeInventory:"Inventory",badgeTerm:"Term",legendClaim:"Step auto-generates a draft milestone claim on completion.",legendSales:"Step prompts the team to notify Sales for upsell follow-up.",legendSign:"Step can't complete without customer signature.",legendInventory:"Hardware is dispatched from Inventory at this step.",legendTerm:"Completing this step starts the contract term of what the onboarding delivers.",legendPhase:"Continuous phase — runs for the duration of the maintenance contract.",usage:"Usage",usageActive:"Active onboardings using this",usageCompleted:"Completed (all-time)",usageAvg:"Avg duration",usageAvgValue:"{n} weeks",usageScopeHint:"Counted within your data scope, the same as the onboarding list.",matchingTitle:"How matching works: ",matchingText:"each product on a contract gets its own onboarding, and the template is picked by what it delivers. Software → {sw}. Hardware (a catalog model or custom hardware) → {hw}. When no template holds the condition → {fallback}. Hardware + software is no longer matched automatically.",vsProvisioningTitle:"Workflow vs Provisioning. ",vsProvisioningText:"This page defines the {manual} BES staff run with the customer, by implementation type. The {auto} for each product (create tenant, push entitlement to Control, configure SSO) is defined separately as that product's Provisioning Template, on the product page.",vsManual:"manual implementation steps",vsAuto:"automated technical setup",compareTitle:"Compare versions",compareFrom:"From",compareTo:"To",compareHeader:"{from} → {to}",workingCopyOption:"Working copy (unpublished)",compareSame:"No differences.",comparePick:"Pick a version on both sides to compare.",compareReordered:"The order of the steps changed.",changeLine:"{kind}: {name}",changeAdded:"Added",changeRemoved:"Removed",changeChanged:"Changed",addedAfter:"after “{name}”",addedAtTop:"at the top",renamedFrom:"was “{name}”",titleWith:"{name} {extra}",valueChange:"{field} {from} → {to}",listChange:"{field} +{plus} / −{minus}",valueOn:"on",valueOnWith:"on ({name})",valueOff:"off",valueNone:"none",field:{stepName:"Name",description:"Description",stepType:"Type",ownerRole:"Owner role",slaWorkingDays:"SLA (working days)",milestone:"Milestone claim",salesPrompt:"Sales prompt",signOffRequired:"Customer sign-off",hardwareDispatch:"Hardware dispatch",startsTerm:"Start contract term",checklist:"Checklist",deliverables:"Deliverables"},noTemplates:"No workflow templates."},handover:{scopeNote:"Closing a project when its contract ends: hand the data back, hand the tenant over, then deprovision.",noCreateAlert:"Handovers are raised automatically — 90 days before a contract expires, or the moment one is terminated early. A contract has at most one open (non-cancelled) handover at a time, and none at all for contracts without a project (a hardware-only order has no system to hand over). There is no «new handover» button.",pdpaNote:"PDPA: customer data is kept for 30 days after the contract ends and is then deleted irreversibly. Everything here exists to make sure the customer has their data before that window closes.",handoverNo:"Handover no.",customer:"Customer",project:"Project",contract:"Contract",trigger:"Raised by",owner:"Owner",noOwner:"Unassigned",reassign:"Reassign",reassignTitle:"Reassign handover owner",reassignHint:"The owner gets this handover's tasks in My Tasks. Clear the field to leave it unassigned.",reassigned:"Owner updated",unassigned:"Owner removed",searchPlaceholder:"Handover no.",product:"Product",kpiInProgress:"In Progress",kpiPendingExport:"Pending Data Export",kpiCompleted90d:"Completed (90d)",kpiAvgClosure:"Avg. Closure Time",kpiDaysValue:"{n} d",kpiOverdue:"Overdue",kpiOverdueHint:"Contract has ended but the handover has not — not the same as Overdue on the invoices page",pageSubtitle:"Project closure handovers. Auto-created 90 days before a contract expires, or as soon as it is terminated early.",metaStarted:"Handover Started",daysShort:"{n}d",skipStep:"Skip step",markStepComplete:"Mark Step Complete",stepShort:{1:"Notice Sent",2:"Data Prepared",3:"Customer Download",4:"Acceptance",5:"Deprovisioning"},stepTitle:"Step {n} · {name}",stepLocked:"Locked",retentionWindow:"Retention Window",retentionDays:"{n} days",importantLabel:"Important:",importantBody:"Customer must download all data before {date}. After this date, all customer-specific data is irreversibly deleted per PDPA.",cancelSubtitle:"For when the contract is renewed instead of terminated",cancelTypeToConfirm:"Type {word} to confirm",keepHandover:"Keep handover",reminderSend:"Send",kpiInProgressSub:"Contract ending within 90 days or already ended",kpiPendingExportSub:"Data export not recorded yet",kpiActionBadge:"ACTION",kpiCompletedSub:"All five steps closed",kpiAvgClosureSub:"Last 90 days",menuReadOnly:"Completed and cancelled handovers are read-only.",footTitle:"Handovers auto-trigger 90 days before contract expiry, or when a contract is terminated early.",footBody:"5 standard steps: Notice → Data export → Customer download → Acceptance → Deprovisioning.",tabActive:"Active",tabAll:"All",progress:"Progress",progressValue:"{done} / {total} steps",colHandover:"Handover",startedOn:"Started {date}",completedOn:"Completed {date}",linkedRecords:"Linked Records",linkedProject:"Project",linkedContract:"Contract",linkedCustomer:"Customer",closed:"Closed",contractEnds:"Contract Ends",daysLeft:"{n} days left",overdueDays:"{n} days overdue",autoDeletion:"Data deleted on",deletionCountdown:"in {n} days",deletionPassed:"deletion window has passed",stepDesc:{1:"Closure notice sent to the customer when the handover starts",2:"Customer data exported and its location recorded",3:"Customer must download their data within PDPA retention window",4:"Customer signs the Handover Acceptance Note · 14-day window from download date",5:"Tenants deactivated · Data marked for retention then automatic deletion"},completedLine:"Completed {time}",skippedLine:"Skipped {time}",downloadStatus:"Customer Download Status",downloadedOn:"Customer downloaded the data on {time}",notDownloadedYet:"Customer hasn't downloaded yet",notDownloadedBody:"After contract expiry, data is retained for {n} days only per PDPA before automatic deletion.",stepCurrentHint:"Use «Skip step» or «Mark Step Complete» at the top of the page when this step is done.",steps:"Closure steps",stepLockedHint:"Finish the previous step first — steps have to be done in order.",deprovisionNotYet:"Deprovisioning stops the customer's instances and revokes access, so it can only be completed or skipped once the contract has ended ({date}).",stepCurrent:"Do this next",stepName:{1:"Closure Notice",2:"Data Prepared",3:"Customer Data Download",4:"Acceptance & Sign-off",5:"Deprovisioning"},stepNote:"Note",stepSkipReason:"Skipped: {reason}",doneBy:"by {name} · {time}",notStarted:"Not started",complete:"Complete",skip:"Skip",markDataExported:"Mark data exported",sendReminder:"Send reminder",cancel:"Cancel handover",completeTitle:"Mark step complete?",markComplete:"Mark complete",completeNote:"Confirmation note",completeNotePlaceholder:"What happened, in one line",step2ExportHint:"«Record export» completes this step for you and leaves behind where the data actually went; completing it directly closes the step with nothing recorded. If BES is not producing a package at all, skip the step instead so the reason is on file.",exportOnSkippedHint:"«Data Prepared» was skipped, so recording an export here only stores the metadata — the step stays skipped. That is deliberate: a package handed over after the fact is still worth having on file.",step3NoteHint:"The customer has not been recorded as having downloaded the data, so completing this step is a statement that it reached them some other way. Say how it was delivered — this is what the audit trail will show.",step3NoteRequired:"Say how the data was delivered",effectStep3:"Completing this records the customer as having the data and gives them 14 days to sign off.",effectStep4:"Completing this signs the project off and moves it into its closing period.",effectStep5:"Completing this deprovisions: the tenant is archived, its instances are stopped, and open temporary access grants on this project or its entitlements are revoked. Data is not deleted here — that happens when the retention window ends.",completeDone:"Step completed",completeAllDone:"Step completed — the handover is now closed",skipTitle:"Skip step?",skipSubtitle:"Requires a written reason · audited as high risk",skipWarning:"Skipping means this step is not being done. The step is marked Skipped rather than Done, and its side effects do NOT run — the flow simply moves on.",skipNoSideEffect4:"Skipping this will NOT move the project into its closing period.",skipNoSideEffect5:"Skipping this will NOT archive the tenant or stop its instances.",skipReason:"Reason for skipping",skipReasonPlaceholder:"e.g. customer exported it themselves from BOSP, no package needed",skipReasonRequired:"A reason is required",skipDone:"Step skipped",exportTitle:"Mark data export complete",markExported:"Mark exported",exportFormatDefault:"SQL dump + CSV (default)",exportFormatCustomer:"Customer-requested format",exportLocation:"Export location",exportLocationPlaceholder:"s3://… · SFTP path · handover directory",exportLocationRequired:"A location is required",exportFormat:"Format",exportFormatPlaceholder:"Pick one or type a format",exportSha256:"SHA-256 hash",exportSha256Placeholder:"For the customer to verify the package",notifyCustomer:"Mark the customer as notified",exportDone:"Export recorded",exportMeta:"Export",noExport:"Nothing recorded yet",exportedAt:"Recorded at",reminderTitle:"Send download reminder",reminderTypeLabel:"Reminder type",recipient:"Recipient",recipientPlaceholder:"pm{'@'}customer.com",message:"Message",reminderHint:"This does not send anything — no mail infrastructure yet. It records that a reminder went out, and who it was meant for.",reminderDone:"Reminder recorded",reminders:"Reminders",reminderCount:"{n} sent",lastReminder:"Last",neverReminded:"None sent",reject:"Reject",rejectTitle:"Reject this handover and send it back",rejectDone:"Sent back for rework",rejectReasonLabel:"What is wrong with it?",rejectReasonPlaceholder:"e.g. the export is missing inspection records after June 2026 — please add them and provide it again",rejectConsequenceStatus:"put the handover back to Data exporting — it is not cancelled, it goes back for rework",rejectConsequenceStep:"reset step 3 (Customer Data Download) to Pending so it has to be done again",rejectConsequenceDeadline:"clear the 14-day acceptance deadline — a new one is calculated when step 3 is completed again",rejectConsequenceDownloaded:"keep the record that the customer did download the data — rejecting does not undo something that already happened",cancelTitle:"Cancel handover?",cancelWarning:"Usually because the contract was renewed and there is nothing to hand over. The handover becomes read-only. Data already exported is NOT deleted — those packages stay in storage and have to be cleared through data retention separately.",cancelReuseHint:"Cancelling does not use up the contract: if it approaches expiry again, a fresh handover is raised.",cancelReasonLabel:"Reason",cancelDone:"Handover cancelled",customerDownloaded:"Customer got the data",notDownloaded:"Not recorded",acceptanceDeadline:"Sign-off due",signedOffAt:"Signed off",related:"Related records",timeline:"PDPA Retention Timeline",noEmailHint:"Nothing here sends email — closure notice, «data ready» and reminders all just record a timestamp. Do not read them as «the customer has it».",noExportPackages:"There is no export package list (BOSP project data / photos / reports with row counts and sizes) — that needs the file service, which does not exist yet. What is recorded here is the metadata above.",accessRevocation:"Temporary access",revokedGrantCount:"{n} grant(s) revoked",revokedGrantDone:"Revoked at deprovisioning: pending and approved grants on this project or its entitlements were all closed.",revokedGrantNone:"Deprovisioning ran, but there was no open grant to revoke at the time.",revokedGrantSnapshot:"This is a snapshot taken at deprovisioning, not a live count. A grant requested after that is not reflected here.",revokedGrantPending:"Not deprovisioned yet",revokedGrantPendingHint:"Temporary access is revoked when step 5 Deprovisioning completes. Until then there is no result to show — this is not the same as “nothing was revoked”."},task:{pageSubtitle:"Actions assigned to you across quotations, contracts, onboardings, and handovers. Sorted by urgency.",snoozeView:"Snooze view",hideTasksFor:"Hide tasks for",snooze1h:"1 hour",snooze4h:"4 hours",snoozeTomorrow:"Until tomorrow 9am",snoozeCustom:"Custom…",snoozeFoot:"Snoozed tasks return after this period.",snoozedUntil:"Snoozed until {time}. Tasks you already had are hidden until then; new ones still show.",showNow:"Show now",snoozed:"Tasks hidden until {time}. New tasks will still show up.",unsnoozed:"All tasks are showing again",snoozeCustomTitle:"Snooze view",snoozeUntil:"Hide tasks until",snoozeUntilPlaceholder:"Pick a date and time",snoozeCustomHint:"Up to 30 days from now. Tasks that appear in the meantime still show.",snoozeApply:"Snooze",kpiOverdue:"Overdue",kpiUrgent:"URGENT",kpiOverdueHint:"Need immediate action",kpiDueToday:"Due Today",kpiToday:"TODAY",kpiDueTodayHint:"Before EOD",kpiThisWeek:"This Week",kpiThisWeekHint:"Due by Sunday",kpiCompleted:"Completed (7d)",kpiCompletedHint:"In the last 7 days",kpiTrend:"{arrow} {pct}% vs prev week",tabAll:"All",tab:{QUOTATION:"Quotations",CONTRACT:"Contracts",ONBOARDING:"Onboarding",HANDOVER:"Handover"},sortedBy:"Sorted by",sortedByDue:"due date ↑",titleDiscount:"Approve discount on {no} ({pct}% off)",titleOnboarding:"{step} for {project}",titleHandover:{2:"Prepare the data export for {customer}",3:"Confirm data download with {customer} before deprovisioning",4:"Get acceptance sign-off from {customer}",5:"Deprovision {customer} after the retention window"},stepOf:"Step {seq}/{count}",descDiscount:"{name} requested a {pct}% discount. Requires approval.",descDiscountLimit:"{name} requested a {pct}% discount (above {limit}% threshold). Requires approval.",descOnboardingStep:"Step {seq} of {count} in onboarding.",descHandoverStep:"Step {seq} of {count} in the closure handover: {step}.",overdueDays:"{n} day overdue | {n} days overdue",dueToday:"Due today",noDueDate:"No due date",dueOn:"Due {date}",requestedBy:"Requested by {name}",pctOff:"{pct}% off",approveTitle:"Approve discount",approveSubtitleLimit:"{off} (above {limit}% threshold)",requestedByLabel:"Requested by",original:"Original",afterDiscount:"After {pct}% discount",approveReason:"Reason",optional:"(optional)",approvePlaceholder:"Add a note for the audit log…",approveFoot:"Approval is logged to audit log with your user, timestamp, and reason.",confirmApprove:"Confirm approve",denyTitle:"Deny discount request",denySubtitle:"{no} · Requested by {name}",denyReason:"Reason for denial",denyPlaceholder:"This will be visible to {name} and logged…",denyReasonRequired:"Enter a reason for denial",denyFoot:"Reason is required for denials. {name} can resubmit with adjustments.",confirmDeny:"Confirm deny",theRequester:"the requester",approve:"Approve",deny:"Deny",openOnboarding:"Open onboarding",alreadyHandled:"Someone else already handled this request. The list has been refreshed.",emptyAll:"Nothing assigned to you right now. Tasks appear here automatically from quotations, onboarding and handovers.",emptyTab:"No tasks in this category.",emptySnoozed:"Your tasks are hidden for now. Use «Show now» above to see them again.",footLead:"Tasks are system-generated from business events",footBody:"discount approval requests, onboarding steps, handover checkpoints. You cannot create tasks manually; they appear automatically based on workflow state."},notificationTpl:{pageSubtitle:"Configure per-event-type notifications: who gets notified, on which channels, with what wording.",create:"New template",infoLead:"Templates fire automatically on matching events.",infoBody:"Each template binds to a boss.* event type and defines: enabled channels, recipient rules (owner / role / individual / Slack channel), and per-channel message body with {'{'}variable{'}'} substitution. System events (audit, provisioning) cannot be disabled — only the channels and recipients can change.",kpiActive:"Active Templates",kpiActiveHint:"Across {n} category | Across {n} categories",kpiDisabled:"Disabled",kpiDisabledHint:"Not firing",tabAll:"All",searchPlaceholder:"Search template name or event code",cannotDisable:"Cannot disable",active:"Active",disabled:"Disabled",emptyTab:"No templates in this category.",emptySearch:"No templates match your search.",selectHint:"Select a template to see its configuration.",enabledSwitch:"Enabled",triggerCondition:"Trigger condition",noConditions:"(fires on every event of this type)",recipients:"Recipients",roleLabel:"Role: {role}",roleMembers:"All users with {role} role ({n} user) | All users with {role} role ({n} users)",staffMember:"Staff member",slackChannel:"Slack channel",noRecipients:"No recipients yet.",channelTemplate:"{channel} Template",preview:"Preview",noContent:"No message yet.",subject:"Subject:",to:"To:",availableVariables:"Available Variables",updatedBy:"Last changed by {name} · {time}",created:"Template created. Set up its messages and recipients, then enable it.",saved:"Template saved",enabledMsg:"Template enabled",disabledMsg:"Template disabled",disableTitle:"Disable this template",disable:"Disable",disableConsequence:"will stop this template from being used for {event} notifications",disableReversible:"can be turned back on at any time; its messages and recipients are kept",prereq:{NO_CHANNEL:"Pick at least one channel.",CHANNEL_CONTENT_MISSING:"Write the {channel} message.",NO_RECIPIENT:"Add at least one recipient.",NO_SLACK_CHANNEL:"Slack is selected, so add a Slack channel recipient."},createTitle:"New notification template",name:"Template name",namePlaceholder:"e.g. Contract activated",nameRequired:"Enter a template name",category:"Category",categoryPlaceholder:"Defaults to the event's category",categoryRequired:"Pick a category",eventCode:"Event code",eventPlaceholder:"Pick an event",eventRequired:"Pick an event",description:"Description",channels:"Channels",createHint:"New templates start disabled. Set up the messages and recipients, then enable it.",createAndConfigure:"Create & configure",editTitle:"Edit template",conditionHint:"All conditions must match. Leave empty to fire on every event of this type.",conditionField:"Field",conditionOperator:"Operator",conditionValue:"Value",conditionValues:"Values (press Enter after each)",addCondition:"Add condition",ownerPlaceholder:"Pick an owner",rolePlaceholder:"Pick a role",addRecipient:"Add recipient",messages:"Messages",tokenHintPre:"Use",tokenHintPost:"tokens. Hover a variable to see its sample value.",noChannelHint:"Pick a channel above to write its message.",emailSubject:"Email subject",inAppTitle:"In-app title",bodyOf:"{channel} body",unknownVariables:"Not available for this event: {vars}",fixBeforeSave:"Fix these before saving",problemCondition:"Every trigger condition needs a field, an operator and a value.",problemRecipient:"Every recipient needs to be filled in; Slack channels look like #sales-wins.",problemUnknown:"The {channel} message uses variables this event doesn't have: {vars}",previewTitle:"Template preview",previewSubtitle:"Rendered with sample data",previewEmpty:"No channel to preview.",optionalVar:"may be empty when sent"},inbox:{pageSubtitle:"System notifications and alerts. Tasks requiring action go to",quickSelect:"Quick select",customRange:"Custom range",from:"From",to:"To",toWord:"to",apply:"Apply",range:{TODAY:"Today",LAST_7:"Last 7 days",LAST_30:"Last 30 days",LAST_90:"Last 90 days",THIS_YEAR:"This year"},markAllRead:"Mark all as read",preferences:"Preferences",kpiUnread:"Unread",kpiUnreadHint:"In this range",kpiCritical:"Critical Alerts",kpiUnreadBadge:"UNREAD",kpiCriticalNone:"Nothing critical unread",kpiToday:"Today",kpiTodayHint:"{read} read · {unread} unread",kpiAvg:"Avg {n}/day",tabAll:"All",tabUnread:"Unread",showing:"Showing",group:{TODAY:"Today",YESTERDAY:"Yesterday",THIS_WEEK:"Earlier this week",EARLIER:"Earlier"},minAgo:"{n} min ago",hAgo:"{n}h ago",emptyAll:"No notifications in this range.",emptyUnread:"You're all caught up — nothing unread in this range.",emptyTab:"No notifications of this kind in this range.",footLead:"Notifications are informational; actionable items go to My Tasks.",footBody:"What you receive is configured per event type — see",footAnd:"for system-wide defaults and",footSettings:"Settings → Notifications",footTail:"for your personal channels (email / Slack / in-app)."},notifPrefs:{channelsTitle:"Channels by category",channelsSubtitle:"Choose which kinds of business notifications reach you, and on which channels.",category:"Category",outboundPendingShort:"After outbound goes live",alwaysOn:"These always reach your Inbox, whatever you choose here: {events}.",listSep:", ",deliveryTitle:"Delivery",deliverySubtitle:"How email, Slack and SMS reach you.",outboundPending:"Email, Slack and SMS are not sent yet. These settings are saved now and take effect once outbound messaging goes live.",preferredChannel:"Preferred channel",preferredHint:"When a notification could go out on several channels, it uses this one.",urgentOverride:"Urgent alerts break through quiet hours",urgentHint:"Applies to: {events}.",quietHours:"Quiet hours",from:"From",to:"to",timeZone:"Time zone",quietHint:"During quiet hours, email, Slack and SMS wait until the period ends. In-app notifications are not affected.",needPreferred:"Pick a preferred channel.",needQuiet:"Fill in the quiet hours and time zone.",sameTimes:"Quiet hours can't start and end at the same time.",save:"Save preferences",saved:"Notification preferences saved",conflict:"These preferences were changed elsewhere (another tab?). The latest version has been loaded — check it and save again."},project:{filterOwner:"Customer owner: {name}",linkExisting:"Link existing",linkTitle:"Link existing contract",linkSubtitle:"A project can be covered by multiple contracts (implementation + maintenance + add-ons)",linkRule:"Listed here: active contracts of this customer that are not linked to any project yet. They join this project as add-ons and end together with its primary contract.",linkSigned:"Signed {date}",linkEmpty:"No active contract of this customer is waiting for a project. Contracts get here when “Decide later” was chosen on acceptance or in the contract draft.",linkNoContractPermission:"You don't have access to contracts, so the candidates can't be listed.",linkSubmit:"Link selected",linkSubmitN:"Link selected ({n})",linked:"Linked {n} contract(s) to this project",linkDisabled:"Only Setup or Active projects can take another contract",selectPlaceholder:"Search a project",pageSubtitle:"Site projects, pre-created when a contract is activated, or imported from a contract activated without one.",footLead:"Projects are auto-created in Setup state when a Contract becomes Active.",footBody:" A Project moves to Active automatically once its Company Admin is assigned and all product bindings are provisioned.",outOfScope:"This project is outside your data scope",projectCode:"Project code",name:"Project name",colProject:"Project",editInfo:"Edit project info",nameRequired:"A project name is required",customer:"Customer",projectType:"Type",tenant:"Tenant",primaryContract:"Main contract",site:"Site",siteCountry:"Country",siteAddress:"Site address",period:"Project period",internalNotes:"Internal notes",internalNotesPlaceholder:"Only BES staff see this — the customer never does",searchPlaceholder:"Project code or name",viaContract:"via {no}",periodColumn:"Period",contractNotSigned:"Contract not signed",productsColumn:"Products",filterContract:"Contract {no}",tabOverview:"Overview",tabEntitlements:"Product Entitlements",tabLifecycle:"Lifecycle",tabAudit:"Audit",info:"Project Information",sourceChain:"Source Chain",sourceChainHint:"This project was created from the following chain (primary source)",chainQuotation:"Quotation",chainContract:"Contract",chainProject:"Project",chainSigned:"Signed {date}",chainAccepted:"Accepted · {date}",chainYouAreHere:"(you are here)",openInstance:"Open instance →",lifecycleTitle:"Project lifecycle",lifecycleHint:"Where this project stands in its lifecycle. Each status change is recorded under Audit.",lifecycleBlocked:"This project is blocked during setup and will not move on until it is unblocked.",trackOnboardings:" Track open onboardings in {link}.",superAdmin:"Company Admin",superAdminPending:"Awaiting assignment",superAdminPlaceholder:"ops.lead{'@'}customer.com",superAdminRequired:"A Company Admin reference is required",superAdminRefHint:"This is the customer's own identifier — their email or their username on the product side. BOSS does not create a user for it, which is why this is a plain field rather than a staff picker.",kpiActive:"Total Active",kpiActiveSub:"Across {n} contracts",kpiSetup:"In Setup",kpiSetupBadge:"ONBOARDING",kpiSetupSub:"Awaiting Company Admin activation",kpiLive:"Active",kpiLiveSub:"Daily operational",kpiEndingSoon:"Ending Soon",kpiEndingSoonSub:"Next 90 days",overdueClosingAlert:"{n} project(s) passed their archive date and are still closing. This number is normally zero — it is the only sign that the nightly archive scanner has stopped working, so report it to ops.",tabAll:"All",tabSetup:"Setup",tabLive:"Active",tabBlocked:"Blocked",tabPendingContract:"Pending Contract",tabEnding:"Ending",tabArchived:"Archived",importButton:"Import from Contract",importTitle:"Import from Contract",importSubtitle:"Select an active contract; BES pre-fills the project from its product mix and entitlements.",importContract:"Contract",importContractPlaceholder:"Search by contract no.",importContractRequired:"Select a contract",importContractHint:"Only active contracts not yet linked to any project",importNoCandidate:"No contract to import. Only active contracts not yet linked to a project can be imported.",importName:"Project name",importNamePlaceholder:"Leave blank to use the source quotation's title",importFixedHint:"Type and country can't be changed after the project is created — set them here.",importSubmit:"Import",importDone:"Project {code} created",importRetryHint:"{n} provisioning run(s) for this contract failed. Retry them in Provisioning.",closingAlert:"In its closing period until {date}",closingRemaining:"Closing period — {n} of {total} days remaining (auto-archive {date})",extendClosing:"Extend closing period",archiveNow:"Archive now (skip remaining days)",archiveProject:"Archive project",extendClosingTitle:"Extend closing period",extendClosingRemaining:"Currently {n} of {total} days remaining",extendBy:"Extend by",extendByDays:"+{n} days",extendByRequired:"Pick how many days to extend by",extendReason:"Reason",extendReasonPlaceholder:"Why the closing period needs extension",extendClosingNote:"Extending keeps the project editable longer (claims/VOs still blocked). Logged in audit trail.",extendSubmit:"Extend",extended:"Closing period extended — auto-archive {date}",archiveTitle:"Archive project?",archiveTarget:"Project:",archiveSubmit:"Archive",archiveBlocked:"Contract {no} is still active. Archive will fail — terminate it or wait for it to expire first.",archiveConsequenceReadOnly:"Moves the project to the read-only archive: its details can no longer be edited, and its contracts can no longer take new claims, VOs or amendments",archiveConsequenceSkipClosing:"Ends the closing period now instead of auto-archiving on {date}",archiveConsequenceExisting:"Claims and VOs already raised can still be processed to completion",archiveConsequenceNoDeprovision:"Does not deprovision the customer tenant or stop any instance — that is part of the handover",archiveConsequenceHandover:"A handover still in progress carries on; signing it off will not bring the project back into closing",archivedDone:"Project archived",editTitle:"Edit project info",editImmutableHint:"Contract reference, period, products, and Company Admin assignment can only be changed via their dedicated workflows.",assignSuperAdmin:"Assign Company Admin",reassignSuperAdmin:"Change Company Admin",assignSuperAdminTitle:"Assign the customer's Company Admin",reassignSuperAdminTitle:"Change the customer's Company Admin",assignHint:"This is the way out of Setup: once a Company Admin is on file and every entitlement has been provisioned, the project becomes Active.",reassignWarning:"This replaces {ref} as the registered customer-side Company Admin. The change is recorded in the audit trail.",assignNotAllowed:"A Company Admin can only be assigned while the project is in Setup, Blocked or Active.",assignNote:"Note",assignNotePlaceholder:"e.g. the previous one left the company",assignNoteHint:"Worth filling in when replacing someone — it is what the audit trail will show.",assignActivationHint:"Assigning the same person again changes nothing and is recorded as nothing — only an actual change is written to the audit trail.",assignNoInviteHint:"Nothing is sent to the customer: this records who their Company Admin is. Inviting them on the product side needs the integration adapter, which is not connected yet.",assigned:"Company Admin assigned",assignedAndActive:"Company Admin assigned — the project is now Active",contracts:"Contracts",contractNo:"Contract no.",linkType:"Link",primaryTag:"Primary",expiresDate:"Expires",contractsHint:"A project can be covered by several contracts — the implementation contract plus maintenance or add-ons signed later.",relatedContractsTitle:"Related Contracts",relatedContractsSubtitle:"All contracts covering this project — implementation + maintenance + amendments",activeContracts:"{n} active",contractTerm:"{n}-month term",contractSigned:"Signed {date}",signedOn:"Signed on",entitlementTerm:"Term",termInfo:"Term",timelineRemaining:"Time remaining",contractRecipient:"Service Recipient: {name}",inclAmendments:"incl. {n} amendment | incl. {n} amendments",perMonth:"{amount}/mo",contractRestricted:"This contract is outside your data scope",entitlements:"Entitlements",entitlementNo:"Entitlement no.",product:"Product",instance:"Instance",noInstance:"No instance to monitor",entitlementsHint:"Each card pairs an entitlement with its running instance, so the question «is this product actually up on this site» has one answer. Not every entitlement has one.",linkedRecords:"Linked Records",linkedRecordsHint:"Everything connected to this project",linkedCompany:"Company",linkedContract:"Contract",linkedQuotation:"Quotation",linkedEntitlements:"Product entitlements",linkedOnboarding:"Onboarding",linkedHandover:"Handover",linkedInvoices:"Invoices",linkedClaims:"Billing claims",linkedRuns:"Provisioning events",linkedLoadFailed:"Failed to load — retry",infoSiteCountry:"Site Country",headPeriod:"Period",activeBannerTitle:"Project is active and fully operational",activeBannerBody:"Delivery, claims and provisioning all run as normal. The project stays active until the implementation handover is signed off, after which its closing period begins.",closingBannerBody:"Handover has been signed off and the project is winding down: no new claims, VOs, or amendments can be created, and it can no longer take another contract or change its Company Admin. Existing records are still editable. When the closing period ends it is archived automatically and becomes fully read-only.",archivedBannerTitle:"Archived & read-only",archivedBannerTitleDate:"Archived & read-only since {date}",archivedBannerBody:"This project is closed. Nothing on it can be edited any more; every record is kept and can still be browsed.",readOnlyStripLead:"Read-only mode.",readOnlyStripBody:" All edit buttons and action menus on this page are disabled while archived.",timelineTitle:"Timeline — Contract vs Project",timelineHint:"Legal contract period (what was sold) vs actual project execution dates (what's happening on the ground)",timelineContract:"Contract {no} (legal)",timelineContractActive:"Contract active",timelineExecution:"Project execution (operational)",timelineImplementation:"Implementation",timelineMaintenance:"Maintenance (under {no})",timelineSigned:"Contract signed",timelineImplStart:"Implementation start",timelineHandoverTarget:"Handover target",timelineNotStarted:"Implementation not started",timelineImplSuffix:"(Implementation)",timelineThenMaint:"· then Maintenance phase",tabUsers:"Users",accessTitle:"Customer Access Requests",accessHint:"Temporary BES access granted at the customer's request for short-term operations",accessHow:"How it works",accessBandLead:"Customer-initiated only.",accessBandBody:" BES staff do not grant themselves access unasked: the customer raises a request → BES reviews and approves → the grant expires on its own.",accessSubmitted:"Submitted {time}",accessEmpty:"No access requests on this project",accessHowTitle:"How Customer Access Requests work",accessHowSub:"Why BES does not enter customer systems on its own initiative",accessStep1Title:"The customer asks",accessStep1Body:"The customer's Company Admin asks for help, with a reason and the scope needed. The request records who asked.",accessStep2Title:"BES reviews and approves",accessStep2Body:"Staff who hold the approval permission check the reason and approve or reject it, and name the BES operator who will do the work.",accessStep3Title:"Access is time-boxed",accessStep3Body:"Every grant has a fixed expiry and closes on its own; it can also be revoked early. BOSS records the authorisation only — it never creates accounts or hands out passwords.",accessStep4Title:"Everything is audited",accessStep4Body:"Each request, approval, revocation and expiry is written to the audit trail with the people involved.",accessHowWhy:"Why this design: BES never enters a customer system unasked. This prevents abuse, satisfies audit requirements and respects customer data sovereignty."},entitlement:{pageSubtitle:"Monitor what each customer is contractually allowed to use, which tenant owns the data boundary, and whether the technical deployment is healthy.",viewActivationQueue:"View activation queue",colCustomerTenant:"Customer · Tenant",colEntitlementId:"Entitlement ID",colAiQuota:"AI / Quota",linkedRecords:"Linked records",quotation:"Quotation",tenantId:"Tenant ID",companyAdmin:"Company Admin",creditLine:"{used} / {grant} credits this month",scopeNote:"Organization → Tenant → Product Entitlement → Projects.",scopeBody:"Contract activation creates the entitlement and starts an idempotent deployment. A tenant is the security boundary; projects live inside it. A technical instance is shown only when there is a real deployment to monitor.",customerFilter:"Customer: {name}",provisioningBtn:"Provisioning",moreActions:"More options",copySystemId:"Copy system ID",viewAuditTrail:"View audit trail",openMonitor:"Open Provisioning Monitor",systemIdCopied:"System ID copied",copyFailed:"Could not copy — select the text and copy it manually",runTitle:"Provisioning run",runSub:"Most recent run",runCount:"{n} runs in total",runTriggeredBy:"Triggered by contract",runViewLog:"View raw technical log →",noRun:"No provisioning run for this entitlement yet",entitlementNo:"Entitlement no.",customer:"Customer",tenant:"Tenant",product:"Product",contract:"Contract",project:"Project",term:"Term",kpiActive:"In use",kpiLive:"Live",kpiPending:"Pending",kpiPendingHint:"Waiting on provisioning — a growing number means that pipeline is stuck",kpiRenewingSoon:"Renewing in 90 days",kpiStaleRoleGrant:"On an old role version",kpiStaleHint:"Zero does not mean all clear: entitlements whose provisioning never reached the role step are not counted",tabActive:"In use",tabStaleRole:"On an old role version",tabAll:"All",instance:"Deployment",systemId:"System ID",deploymentState:"Deployment",provisioningStatus:"Provisioning",accessStatus:"Access",accessStatusHint:"Whether the machine is up (Deployment) and whether anyone on the customer side has taken it over (Access) are two different questions — Live plus «awaiting Company Admin» is exactly «the system is ready and nobody is running it». «Registered, awaiting customer confirmation» only means the customer-side Company Admin's identifier was recorded; BOSS cannot yet tell whether the customer is actually running the tenant.",noInstance:"No deployment",noInstanceHint:"This entitlement has no deployment to monitor — not every one does.",roleGrant:"Role permissions granted",versionLabel:"Version",current:"Latest",notCurrent:"Superseded",granted:"Permission points",grantedUnknown:"Cannot be determined",notCurrentHint:"The template has been published again since this was granted, and the hash in the version label cannot be reversed — so how many points went out at the time cannot be recovered. Showing today's count instead would answer «what did they get» wrongly, which is exactly the question an audit asks.",noOutboundHint:"Roles are currently snapshotted and version-stamped on the BOSS side only; there is no outbound push yet (it needs the integration adapter). Once there is, each push is recorded separately and this becomes exact.",noRoleGrant:"No role version on record",noRoleGrantHint:"Provisioning has not reached the role-seeding step for this entitlement yet, so nothing has been stamped.",wfTemplate:"Onboarding template",credit:"AI credits",creditGrant:"Granted",creditTopup:"Topped up",creditUsed:"Used",creditBalance:"Balance",creditNotSyncedTitle:"Not synced yet — these are not real balances",creditNotSyncedHint:"Credit figures mirror what the product side reports, and that inbound channel is not connected yet, so they sit at zero. Zero here means «nothing has come back», not «the customer has used it all up»."},accessPlanes:{pageSubtitle:"Three deliberately separate authorization planes for internal work, customer product roles, and temporary cross-tenant support. Every grant has an explicit boundary and audit trail.",staffKicker:"BOSS internal",staffBadge:"Active policy",staffTitle:"Internal staff access",staffDesc:"Roles determine which BOSS modules a person can use; data scope (All / Owned) limits which customers and projects they can reach.",staffFoot:"Roles × data scope",productKicker:"Customer products",productBadge:"Tenant-scoped",productTitle:"Product role templates",productDesc:"Company Admin, Project Manager and other roles live inside each product tenant. They never grant access to BOSS.",productFoot:"Open product roles →",customerKicker:"Cross-tenant support",customerBadge:"{n} pending",customerTitle:"Temporary customer access",customerDesc:"Just-in-time access requires a reason, customer and tenant scope, approver, expiry time and immutable audit event.",customerFoot:"Review requests →",boundaryTitle:"Authorization boundaries never inherit across planes.",boundaryBody:"A BES role cannot enter a customer tenant, and a customer product role cannot open BOSS. Temporary access is a separate, expiring grant layered on top of a named customer and tenant."},accessGrant:{introLead:"Access boundaries are kept separate.",introBody:"This tab is only for temporary BES support access and break-glass access into a customer's tenant. BES staff roles inside BOSS live on the other tab; a customer's own product roles (Company Admin, project roles) are managed inside each {tenant}.",introTenant:"tenant",cardTitle:"Temporary & break-glass access",cardSub:"Requests for BES staff to access a customer's live tenant for support. Every grant is scoped, time-boxed and written to the audit log.",colExpiry:"Expiry",colAction:"Action",footAudit:"Every grant, extension and revocation is recorded in the {link}.",review:"Review",revokeEarly:"Revoke early",viewAudit:"View audit",intro:"Authorisation records for BES support staff entering a customer system: who asked, who approved, which project, why, and until when. BOSS records the authorisation only — it never issues passwords, tokens or connection strings, and an approved grant gives nobody any extra permission inside BOSS.",tabOpen:"Still open",tabAll:"All records",keywordPlaceholder:"Request no., operation or scope",requestNo:"Request",grantType:"Type",grantTypeRequired:"Please pick a type",carHint:"Raised by the customer's system administrator. Lasts at most 7 days.",breakGlassHint:"Emergency intervention. No fixed limit — the duration is the approver's call, and it goes through the same approval.",scope:"Scope",scopeType:"Scope is",scopeProject:"A project",scopeEntitlement:"A product entitlement",scopeRequired:"Pick what this grant covers",scopeDesc:"Scope detail",project:"Project",entitlement:"Product entitlement",entitlementPlaceholder:"Search by instance no.",operationType:"Operation",operationTypePlaceholder:"e.g. DB read-only",tenant:"Target tenant",tenantUnknown:"Read from the project — not available for projects outside your data scope.",who:"People",besOperator:"BES operator",besOperatorHint:"Who is designated to do the work. This does not hand them any credentials.",besOperatorRequired:"Please pick who will do the work",requestedByRef:"Requested by",requestedByRefPlaceholder:"SA email or ticket no.",requestedByRefHint:"Who on the customer side asked for it. BES cannot create customer accounts.",reason:"Reason",reasonHint:"This is what the audit trail will show when someone asks why a customer system was entered.",reasonRequired:"A reason is required",reasonPlaceholder:"Say what happened and why this access is needed",approvedBy:"Approved by",notApprovedYet:"Not approved yet",expiresAt:"Expires",expiresAtPlaceholder:"Pick date and time",expiresAtRequired:"Please set when it expires",expiryCarHint:"A CAR grant lasts at most 7 days. The server has the final say.",expiryFreeHint:"No fixed limit for BREAK_GLASS — keep it as short as the work needs.",expiredTag:"Past expiry",expiresInHours:"Expires in {n}h",expiresInDays:"Expires in {n}d",expiresWithinHour:"Expires within 1h",expiredOn:"Expired {date}",durationHours:"{n} hour | {n} hours",durationDays:"{n} day | {n} days",create:"New request",createTitle:"Request temporary access",createNote:"This creates a PENDING request. Asking for access is not the same as having it — someone still has to approve.",submitRequest:"Submit request",requested:"Request submitted",emptyOpen:"No grants are waiting approval or approved right now",emptyAll:"No access grants yet",expiredAlertTitle:"Past its expiry time",expiredAlert:"The expiry scanner runs hourly, so the status can still read Approved for a while after the time has passed. Treat this grant as no longer valid.",pendingAlertTitle:"Waiting for approval",pendingAlert:"A pending request carries no access at all. Nobody can enter on the strength of it.",noCredentialNote:"This record is not a key. BOSS stores who was authorised, for what and until when — passwords, tokens and connection strings are handled elsewhere.",approve:"Approve",approveTitle:"Approve this access",approveConsequenceActive:"{who} becomes authorised to enter the customer system until {until}.",approveConsequenceScope:"The authorisation covers {scope} only, nothing else.",approveConsequenceAudit:"The approval is written to the audit trail at HIGH risk — it will always be traceable to you.",approveConsequenceRevocable:"You can revoke it later, but any access that has already happened cannot be taken back.",approved:"Approved",reject:"Reject",rejectTitle:"Reject this request",rejectConsequence:"The requester gets no access at all and the request ends here.",rejectConsequenceFinal:"A rejected request cannot be approved later — a new one has to be raised.",rejectReasonLabel:"Why are you rejecting it?",revokeReasonLabel:"Why are you revoking it?",rejected:"Rejected",revoke:"Revoke",revokeTitle:"Revoke this access",revokeConsequenceActive:"This grant is revoked immediately and is no longer valid.",revokeConsequencePending:"The pending request is voided — nobody needs to act on it any more.",revokeConsequenceFinal:"This cannot be undone; a new request has to be raised.",revokeConsequenceAudit:'Your reason goes into the audit trail — it is what answers "why was this access stopped".',revoked:"Revoked"},compliance:{dailyVerification:"Daily verification",automated:"Automated",siemExport:"SIEM export",enabledValue:"Enabled",chainTitle:"Audit log chain integrity",verifyNow:"Verify now",verified:"Chain re-verified",status:"Status",verifiedAt:"Last verified",entries:"Audit rows",breaks:"Breaks",lastHash:"Chain head hash",lastHashHint:"Send this off-box regularly (SIEM or printed record) — the chain only proves that tampering cannot be silent; whoever can edit the data can also recompute the whole chain.",neverVerifiedHint:"This chain has never been verified — that is not the same as intact.",brokenHint:"The chain is broken. Every break below needs investigating.",breakList:"Breaks (first 20)",breakId:"Audit row",tamper:"How it was tampered with",contentAltered:"Row altered",contentAlteredHint:"This row's own content was changed",predecessorMissing:"Predecessor gone",predecessorMissingHint:"The row itself is untouched — the row before it was deleted or one was inserted",prevHash:"Recorded predecessor",expectedPrevHash:"Expected predecessor",off:"Off"},authPolicy:{control:{title:"Sign-in & security are managed in BES",sub:"Staff sign in to BOSS through BES",body:"Password rules, two-step verification, session length and single sign-on are set in BES, not in BOSS. Each person changes their own password and two-step verification on their BES account page.",open:"Open your BES account page"},readOnly:"These rules are built into the system and shown here for reference — they cannot be changed on this page.",mfa:{title:"Multi-Factor Authentication",sub:"Required for every account",require:{label:"Require MFA for all users",desc:"Everyone sets up an authenticator app (TOTP) the first time they sign in. Three wrong codes in a row lock the account for 15 minutes.",value:"On"},backup:{label:"Backup codes",desc:"10 single-use codes generated when the authenticator is set up",value:"Allowed"},sms:{label:"SMS as fallback",desc:"Codes by text message are not offered",value:"Not available"},webauthn:{label:"WebAuthn / Passkeys",desc:"Hardware keys and platform passkeys are not offered",value:"Not available"}},password:{title:"Password Policy",sub:"Applies to new accounts, admin resets and changing your own password",length:{label:"Minimum length",desc:"12–64 characters, with an uppercase letter, a lowercase letter, a digit and a symbol",value:"12 characters"},expiration:{label:"Expiration",desc:"Passwords do not expire",value:"Not enforced"},history:{label:"Password history",desc:"Earlier passwords can be reused",value:"Not enforced"},failures:{label:"Max failed attempts",desc:"Lock account after 5 wrong passwords in a row (15 min cooldown)",value:"5"}},sso:{title:"SSO Identity Providers",sub:"SAML 2.0 / OIDC providers · Not configured",emptyTitle:"No SSO providers configured",emptyBody:"Everyone signs in with username, password and an authenticator code. Sign-in moves to the company SSO once it is connected."},session:{title:"Session Policy",sub:"How long a sign-in lasts",timeout:{label:"Inactive session timeout",desc:"Sign users out after a period of inactivity; a session lasts 24 hours at most",value:"30 minutes"},autoSuspend:{label:"Auto-suspend inactive accounts",desc:"Suspend if no sign-in for 90 days; an admin can reactivate the account",value:"90 days"}}},orgSettings:{keepEditing:"Keep editing",invoicingTitle:"Invoicing",invoicingNote:"Printed on invoices as the issuer's GST number and the payment instructions. Copied onto each invoice when it is issued — changing them here does not alter invoices already issued.",gstRegistrationNo:"GST registration no.",bankName:"Bank",bankNamePlaceholder:"e.g. DBS",bankAccountName:"Account name",bankAccountNo:"Account no.",subtitle:"BES company-wide configuration. Only Owner / Admin roles can modify these settings. For your own profile and preferences, see",personalSettings:"Personal Settings",adminOnly:"Admin only",infoTitle:"Organization Information",infoSub:"Legal entity details used in contracts and invoices",legalName:"Legal Name",uen:"UEN",displayName:"Display Name",country:"Country",registeredAddress:"Registered Address",legalNameRequired:"Legal name is required — it heads every quotation, contract and term PDF",countryRequired:"Please choose a country",incompleteHint:"UEN or registered address is still empty. PDFs sent to customers will show only the legal name and country in the letterhead until they are filled in.",save:"Save changes",saveTitle:"Save settings?",saveConfirm:"Save",saveConsequenceImmediate:"Changes will take effect immediately",saveConsequenceDocs:"Every quotation, contract and term PDF downloaded from now on will carry the new details in its letterhead",saveConsequenceAudit:"An audit log entry will be created",discardTitle:"Discard changes?",discard:"Discard",discardConsequence:"Unsaved changes will be lost"},document:{downloadPdf:"Download PDF",exportPdf:"Export PDF",quotationTitle:"Download quotation PDF",contractTitle:"Download contract PDF",termTitle:"Export term as PDF",includeCoverLetter:"Include cover letter",includeTerms:"Include Terms & Conditions",includeSignaturePage:"Include signature page",contractIncludeTerms:"Include T&Cs",version:"Version",versionOriginal:"Original (pre-counter-sign)",versionOriginalHint:"Signed copies are not stored in BOSS yet, so the system-generated original is the only version available.",englishOnly:"The document is always generated in English, whatever language this interface is in.",language:"Language",langBilingual:"Bilingual EN/ZH",langEn:"English only",langZh:"中文 only",termNoContent:"This version has no text yet, so there is nothing to export.",thisVersion:"this page",includeVersionHistory:"Include version history footnote",draftWatermark:'Watermark "DRAFT" on cover',download:"Download",export:"Export"},provisioningLog:{title:"Provisioning log",live:"live",viewLive:"View live log",viewFull:"View full log",autoRefresh:"Auto-refreshing every 2s",empty:"No log lines yet",pollFailed:"Couldn't fetch the latest lines — retrying every 2 seconds"},companyExport:{title:"Export company data",section:{company:"Company info + contacts + addresses",quotations_contracts:"Quotations & contracts",projects_subscriptions:"Projects & subscriptions",activity_audit:"Activity & audit log"},noPermission:"You don't have permission to export this part",format:"Format",formatRequired:"Pick a format",formatOption:{zip:"ZIP (CSV files)",xlsx:"Excel (.xlsx)",pdf:"PDF report"},generate:"Generate export"},dataExport:{button:"Export",asCsv:"Export as CSV",asXlsx:"Export as Excel",asPdf:"Export as PDF",asJson:"Export as JSON",currentFilter:"Exports current filter ({n} row) | Exports current filter ({n} rows)",tooManyRows:"{n} rows match the current filter — one export can hold at most {max}. Narrow the filter and try again.",nothingToExport:"No rows match the current filter, so there is nothing to export.",dialogTitle:"Export data",format:"Format",scope:"Scope",scopeCurrent:"Current filtered view ({n} row) | Current filtered view ({n} rows)",scopeAll:"All records",includeHeaders:"Include column headers",includeHeadersPdfHint:"PDF always has column headers",download:"Download"},enum:{companyRole:{CUSTOMER:"Customer",SERVICE_RECIPIENT:"Service recipient",MAIN_CON:"Main Contractor",SUB_CON:"Sub Con",DEVELOPER:"Developer",CONSULTANT:"Consultant",SUPPLIER:"Supplier",EQUIPMENT:"Equipment Vendor"},lifecycleStage:{LEAD:"Lead",QUALIFIED:"Qualified",CUSTOMER:"Converted",ACTIVE:"Active",DORMANT:"Dormant",CHURNED:"Churned"},companyStatus:{ACTIVE:"Active",ARCHIVED:"Archived"},billingAccountStatus:{ACTIVE:"Active",ARCHIVED:"Deactivated"},relationshipType:{NONE:"None",SUBSIDIARY:"Subsidiary",JV_PARTNER:"JV Partner",BRANCH:"Branch",DIVISION:"Division"},discountApprovalStatus:{NOT_REQUIRED:"Not submitted",PENDING:"Awaiting approval",APPROVED:"Approved",REJECTED:"Rejected"},acceptLinkStatus:{ACTIVE:"Active",EXPIRED:"Expired",REVOKED:"Revoked",SUPERSEDED:"Superseded",DECIDED:"Decided"},quotationStatus:{DRAFT:"Draft",SENT:"Sent",ACCEPTED:"Accepted",REJECTED:"Rejected",EXPIRED:"Expired",SUPERSEDED:"Superseded"},lineType:{SOFTWARE:"Software",HARDWARE:"Hardware",SERVICE:"Service"},periodType:{RECURRING:"Recurring",ONE_TIME:"One-time",PER_OCCURRENCE:"Per occurrence"},deliveryType:{SOFTWARE:"Software",HARDWARE:"Hardware",MIXED:"Whole project (earlier onboarding)"},productType:{SOFTWARE:"Software",HARDWARE:"Hardware",SERVICE:"Service"},stockStatus:{HEALTHY:"Healthy",LOW:"Low",OUT:"Out of stock"},hardwareUnitStatus:{IN_STOCK:"In stock",DISPATCHED:"Dispatched",ON_SITE:"On site",INSTALLED:"Installed",RETURNED:"Returned",UNDER_REPAIR:"Under repair",AT_SUPPLIER:"At supplier",SCRAPPED:"Scrapped"},purchaseOrderStatus:{ORDERED:"Ordered",IN_TRANSIT:"In transit",PARTIALLY_RECEIVED:"Partially received",RECEIVED:"Received",CANCELLED:"Cancelled"},stockMovementType:{INITIAL:"Initial stock",RECEIVE:"Received",ALLOCATE:"Reserved",RELEASE:"Released",DISPATCH:"Dispatched",RECALL:"Back to stock",INSTALL:"Installed",HOLD_ON_SITE:"Left on site",RETURN:"Returned",REPAIR:"Sent for repair",TO_SUPPLIER:"Sent to supplier",RESTOCK:"Restocked",SCRAP:"Scrapped",TRANSFER:"Transferred"},allocationStatus:{PENDING_ONBOARDING:"Pending onboarding",RESERVED:"Reserved",FULFILLED:"Fulfilled"},dispatchStatus:{IN_TRANSIT:"In transit",DELIVERED:"Delivered",CONFIRMED:"Settled",CANCELLED:"Cancelled"},dispatchOutcome:{INSTALLED:"Installed",ON_SITE:"Left on site",FAULTY:"Faulty",SURPLUS:"Surplus"},installationStatus:{NEEDS_CHECK:"Needs check",INSTALLING:"Installing",OPERATIONAL:"Operational"},returnStatus:{REPORTED:"Awaiting pickup",RETURNED:"Awaiting inspection",UNDER_REPAIR:"Under repair",AT_SUPPLIER:"Sent to supplier",RESTOCKED:"Restocked",SCRAPPED:"Scrapped",CANCELLED:"Cancelled"},returnSource:{SITE:"Site",WAREHOUSE:"Warehouse",INSTALLATION:"Faulty at install"},returnHistoryAction:{CREATE:"Created",RECEIVE:"Received",REPAIR:"Sent for repair",SEND_TO_SUPPLIER:"Sent to supplier",RESTOCK:"Restocked",SCRAP:"Scrapped",CANCEL:"Cancelled",SPLIT:"Split"},productStatus:{ACTIVE:"Active",BETA:"Beta",DEPRECATED:"Deprecated"},productScopeLevel:{PROJECT:"Per project",TENANT:"Per tenant"},controlSyncStatus:{NOT_APPLICABLE:"Not registered",PENDING:"Pending",SYNCED:"Registered",FAILED:"Failed"},hardwareRequirement:{REQUIRED:"Required",RECOMMENDED:"Recommended"},revisionStatus:{CURRENT:"Current",SUPERSEDED:"Superseded"},stepType:{REQUIRED:"Required",OPTIONAL:"Optional"},amendmentType:{SCOPE_ADDITION:"Scope addition",SCOPE_REDUCTION:"Scope reduction",PRICE_ADJUSTMENT:"Price adjustment",TERM_EXTENSION:"Term extension",VO_DRIVEN:"VO-driven",CONTACT_BILLING_CHANGE:"Contact / billing change",OTHER:"Other"},amendmentStatus:{DRAFT:"Draft",PENDING_SIGNATURE:"Pending Sig",ACTIVE:"Active"},contractStatus:{DRAFT:"Draft",PENDING_CUSTOMER_SIGNATURE:"Pending Customer Signature",ACTIVE:"Active",EXPIRING:"Expiring in 90d",EXPIRED:"Expired",TERMINATING:"Terminating",TERMINATED:"Terminated"},termStatus:{DRAFT:"Draft",CURRENT:"Active",SUPERSEDED:"Superseded",RETIRED:"Archived"},termCategory:{GENERAL:"General",PAYMENT:"Payment",DPA:"DPA",SLA:"SLA",INDUSTRY_SPECIFIC:"Industry-specific",TERM_ADJUSTMENT:"Term adjustment"},termSourceState:{CURRENT:"Latest version",SUPERSEDED:"A newer version exists",RETIRED:"Source archived",GONE:"Source deleted"},termLanguage:{EN:"English",ZH:"Chinese"},termRefType:{QUOTATION:"Quotation",CONTRACT:"Contract"},partyRole:{BILLING:"Billing Party",SERVICE_RECIPIENT:"Service Recipient",BES:"BES Counterpart"},effectiveMode:{IMMEDIATE:"On signing",STEP:"At workflow milestone",DATE:"On a set date"},effectiveSource:{IMMEDIATE:"On signing",DATE:"Set date",STEP:"Workflow milestone",MANUAL:"Set manually",RENEWAL:"Renewal"},effectiveState:{PENDING:"Pending effective",PARTIAL:"Partially effective",EFFECTIVE:"Effective"},entitlementStatus:{PENDING:"Pending",ACTIVE:"Active",SUSPENDED:"Suspended",EXPIRED:"Expired",TERMINATED:"Terminated"},runStatus:{RUNNING:"Running",SUCCESS:"Success",FAILED:"Failed",ROLLED_BACK:"Rolled back"},runType:{PROVISION:"Provision",DEPROVISION:"Deprovision",RECONCILE:"Reconcile"},runTrigger:{CONTRACT_ACTIVATED:"Contract activated",CONTRACT_RENEWED:"Contract renewed",TERM_EXTENDED:"Authorization extended",ENTITLEMENT_TERMINATED:"Contract ended",HANDOVER_VACATED:"Handover vacated",SCHEDULED:"Scheduled"},discrepancyKind:{NOT_PUSHED:"Not pushed",MISSING_IN_CONTROL:"Missing in Control",INACTIVE_IN_CONTROL:"Inactive in Control",ACTIVE_IN_CONTROL:"Still active in Control",PERIOD_MISMATCH:"Period mismatch",UNKNOWN_IN_CONTROL:"Unknown in Control"},controlEntitlementStatus:{PENDING:"Pending",ACTIVE:"Active",REVOKED:"Revoked",EXPIRED:"Expired"},stepStatus:{PENDING:"Pending",RUNNING:"Running",SUCCESS:"Success",SKIPPED:"Skipped",FAILED:"Failed"},stepBehavior:{IDEMPOTENT:"Idempotent",RETRYABLE:"Retryable",CONDITIONAL:"Conditional"},userRemovalBlocker:{OWNS_COMPANIES:"Owns customers",HAS_ACTIVE_PROJECTS:"Owns active projects",HAS_OPEN_TASKS:"Has open tasks",SELF:"Your own account",LAST_ADMIN:"Last administrator",ALREADY_REMOVED:"Already removed"},loginStatus:{INVITED:"Invited",INVITE_EXPIRED:"Invite expired",ACTIVE:"Signed up"},userStatus:{Active:"Active","MFA Pending":"MFA pending",Suspended:"Suspended",Removed:"Removed"},dataScope:{ALL:"All data",OWNED:"Owned only"},permissionRisk:{STANDARD:"Standard",SENSITIVE:"Sensitive",HIGH_RISK:"High risk"},actorType:{USER:"User",SYSTEM:"System",EXTERNAL:"External"},auditCategory:{AUTHENTICATION:"Authentication",SALES:"Sales (companies, quotations, contracts)",DELIVERY:"Delivery (projects, onboarding)",ACCESS:"Access (users, roles, permissions)",SYSTEM_BILLING:"System & billing"},auditSeverity:{INFO:"Info",WARNING:"Warning",CRITICAL:"Critical"},auditRisk:{NORMAL:"Normal",HIGH:"High risk"},action:{export:"Export",view:"View",create:"Create",update:"Update",delete:"Delete",archive:"Archive",restore:"Restore",qualify:"Qualify",accept:"Accept",send:"Send",revise:"Revise",submit_approval:"Submit for discount approval",approve_discount:"Approve discount",reject_discount:"Reject discount",update_payment_plan:"Update payment plan",send_for_signature:"Send for signature",create_amendment:"Create amendment",quote_amendment:"Amendment quoted",raise_variation_order:"Raise variation order from claim",apply_variation_order:"Apply variation order to claim",duplicate:"Duplicate",send_amendment_for_signature:"Send amendment for signature",activate_amendment:"Amendment signed",renew:"Renewal quoted",activate:"Activate",terminate:"Terminate",retry:"Retry",roll_back:"Roll back",manage:"Manage",suspend:"Suspend",auto_suspend:"Auto-suspend",change_roles:"Change roles",change_permissions:"Change permissions",reset_password:"Reset password",start:"Start",complete:"Complete",go_live:"Go live",reject:"Reject",expire:"Expire",supersede:"Supersede",mark_expiring:"Mark expiring",mark_expired:"Mark expired",start_term:"Term started",set_effective_date:"Set effective date",mark_active:"Back to active",extend_authorization:"Extend authorization",advance_contract_end:"Contract end brought forward",fail:"Fail",change_password:"Change password",lock:"Lock",unlock:"Unlock",ship:"Mark in transit",receive:"Receive goods",record_movement:"Record stock movement",reserve:"Reserve",deliver:"Mark delivered",confirm_installation:"Settle installation",register_delivery_receipt:"Register signed DO",change:"Change",repair:"Send for repair",send_to_supplier:"Send to supplier",restock:"Restock",scrap:"Scrap",split:"Split",withdraw:"Withdraw",record_occurrences:"Record occurrences",change_stage:"Change stage",change_status:"Change status",sync:"Sync",start_step:"Start step",complete_step:"Complete step",skip_step:"Skip step",reopen_step:"Reopen step",block:"Block",unblock:"Unblock",reassign:"Reassign",assign_staff:"Assign to account team",remove_staff:"Remove from account team",notify_sales:"Notify Sales",publish:"Publish",publish_pipeline:"Publish pipeline",discard:"Discard changes",release_match_condition:"Release match condition",sync_apps:"Sync applications",import_permissions:"Import permissions",submit:"Submit",start_review:"Start review",approve:"Approve",dispute:"Raise dispute",withdraw_dispute:"Withdraw dispute",settle:"Settle",issue_invoice:"Issue invoice",record_payment:"Record payment",mark_sent:"Mark as sent",mark_overdue:"Mark overdue",credit:"Credit invoice",issue_credit_note:"Issue credit note",reverse_payment:"Reverse payment",revert_to_approved:"Back to awaiting re-invoice",reissue_invoice:"Re-issue invoice",revert_to_invoiced:"Back to approved & invoiced",mark_data_exported:"Record data export",send_reminder:"Send reminder",sign_off:"Sign off",deprovision:"Deprovision",cancel:"Cancel",start_closing:"Start closing period",stop:"Stop",assign_super_admin:"Assign Company Admin",extend_closing:"Extend closing period",link_contract:"Link contract",add_note:"Add note",enable_mfa:"Enable MFA",reset_mfa:"Reset MFA",send_invite:"Send first sign-in link",send_password_reset:"Send password reset link",remove:"Remove user",skip:"Skip",reopen:"Reopen",payment:"Record payment",release:"Release",set_default:"Set as default",set_primary:"Set as primary",update_item:"Update checklist item",upload_item_file:"Upload deliverable file",replace_item_file:"Replace deliverable file",delete_item_file:"Delete deliverable file",upload_attachment:"Upload attachment",delete_attachment:"Delete attachment",create_accept_link:"Create accept link",revoke_accept_link:"Revoke accept link",open_accept_link:"Customer opened accept link",upload_photo:"Upload photo",replace_photo:"Replace photo",upload_datasheet:"Upload datasheet / manual",delete_datasheet:"Delete datasheet / manual",upload_remittance:"Upload remittance advice",replace_remittance:"Replace remittance advice",upload_avatar:"Upload avatar",replace_avatar:"Replace avatar",remove_avatar:"Remove avatar",update_profile:"Update own profile",download:"Download",reject_infected:"Reject (malicious content)",request:"Request",revoke:"Revoke",new_version:"New version",retire:"Archive"},addrType:{REGISTERED:"Registered",BILLING:"Billing",SITE:"Site"},onboardingStatus:{NOT_STARTED:"Not Started",IN_PROGRESS:"In Progress",BLOCKED:"Blocked",COMPLETED:"Completed",CANCELLED:"Cancelled"},blockedReason:{CUSTOMER_UNRESPONSIVE:"Customer unresponsive",AWAITING_SIGNATURE:"Awaiting customer signature",AWAITING_INFRASTRUCTURE:"Awaiting customer infrastructure",CUSTOMER_PAUSE:"Customer requested pause",INTERNAL_PROVISIONING:"Internal — provisioning issue",OTHER:"Other"},onboardingCancelReason:{CONTRACT_TERMINATED:"Contract terminated before activation",CUSTOMER_WITHDREW:"Customer withdrew",RESTART_NEEDED:"Restart needed — major scope change",OTHER:"Other"},onboardingStepStatus:{PENDING:"Pending",IN_PROGRESS:"In Progress",COMPLETED:"Complete",SKIPPED:"Skipped"},onboardingStepType:{NORMAL:"Normal",CONTINUOUS:"Continuous"},projectSetupStage:{ONBOARDING:"Setup · Onboarding",BLOCKED:"Setup · Blocked"},priority:{NORMAL:"Normal",HIGH:"High",URGENT:"Urgent"},opportunityType:{CROSS_SELL:"Cross-sell",UPSELL_SCALE:"Upsell: additional sites / cameras",UPSELL_TERM:"Upsell: extended maintenance term",RENEWAL_PREVIEW:"New: module renewal preview",OTHER:"Other (explain below)"},employeeType:{FULL_TIME:"Full-time staff",CONTRACTOR:"Contractor",PART_TIME:"Part-time"},staffRelationship:{PRIMARY_OWNER:"Primary Account Owner",CSM:"Customer Success Manager",SECONDARY_CONTACT:"Secondary contact"},notifiedAudience:{FINANCE:"Finance",SALES:"Sales"},opportunityUrgency:{NORMAL:"Normal",HIGH:"High (act this week)",LOW:"Low"},itemType:{CHECKLIST:"Checklist",DELIVERABLE:"Deliverable",SIGN_OFF:"Customer sign-off"},matchCondition:{HW_SOFTWARE:"Contract has hardware + software",SOFTWARE_ONLY:"Contract has software only",HARDWARE_ONLY:"Contract has hardware only",MANUAL:"Manual selection only"},workflowOwnerRole:{PM:"Project Manager (PM)",FE:"Field Engineer (FE)",OPS:"Ops Coordinator",CS:"Customer Success"},claimStatus:{DRAFT:"Draft",SUBMITTED:"Submitted",UNDER_REVIEW:"Under review",APPROVED:"Awaiting re-invoice",INVOICED:"Approved & invoiced",PAID:"Paid",DISPUTED:"Disputed",WITHDRAWN:"Withdrawn"},claimReason:{EXTRA_SITE_TRIP:"Extra site trip",ADJUSTMENT:"Adjustment",CUSTOM_SERVICE:"Custom service",EXTRA_MAINTENANCE:"Extra maintenance",OTHER:"Other",PER_OCCURRENCE:"Per-occurrence service",OVER_INSTALLATION:"Over-installation",AMENDMENT_HARDWARE:"Amendment hardware"},claimHolder:{CREATOR:"Creator",FINANCE:"Finance",CUSTOMER:"Customer",OPERATIONS:"Operations"},claimAction:{edit:"Edit",submit:"Submit",start_review:"Start review",approve:"Approve",reject:"Return",issue_invoice:"Re-issue invoice",dispute:"Dispute",withdraw_dispute:"Withdraw dispute",withdraw:"Withdraw registration"},disputeParty:{CUSTOMER:"Customer",FINANCE:"Finance",OPERATIONS:"Operations"},disputeType:{AMOUNT_DISCREPANCY:"Amount / quantity discrepancy",SCOPE_NOT_AS_AGREED:"Scope not as agreed",MISSING_EVIDENCE:"Missing supporting evidence",PRICING_DISAGREEMENT:"Pricing disagreement"},invoiceStatus:{DRAFT:"Draft",ISSUED:"Issued",DUE:"Due",OVERDUE:"Overdue",PAID:"Paid",CREDITED:"Credited"},invoiceDocType:{INVOICE:"Invoice",CREDIT_NOTE:"Credit note"},claimAttachmentDocType:{SITE_REPORT:"Site report",PROVISIONING_EVIDENCE:"Provisioning evidence",TRAINING_SIGNOFF:"Training signoff",DELIVERY_ORDER:"Delivery order",OTHER:"Other"},productDatasheetDocType:{DATASHEET:"Technical specifications",MANUAL:"Installation manual"},quotationAttachmentDocType:{SIGNED_SCAN:"Signed quotation scan",CUSTOMER_PO:"Customer PO",EMAIL_CONFIRMATION:"Email confirmation",REFERENCE:"Reference document",OTHER:"Other"},paymentMethod:{BANK_TRANSFER:"Bank transfer",PAYNOW:"PayNow / FAST",CHEQUE:"Cheque",CARD:"Credit card / Stripe",OTHER:"Other"},notificationCategory:{SALES:"Sales",DELIVERY:"Delivery",ACCESS:"Access",SECURITY:"Security",SYSTEM:"System"},notificationChannel:{EMAIL:"Email",SLACK:"Slack",SMS:"SMS",IN_APP:"In-app"},notificationVariableType:{STRING:"Text",NUMBER:"Number",DATE:"Date",DATETIME:"Date & time",URL:"Link"},notificationOperator:{EQ:"equals",NE:"not equal",GT:"greater than",GTE:"at least",LT:"less than",LTE:"at most",IN:"is one of",NOT_IN:"is none of"},notificationRecipientType:{OWNER:"Owner",ROLE:"Role",USER:"Staff member",SLACK_CHANNEL:"Slack channel"},inboxCategory:{ALERTS:"Alerts",CUSTOMER:"Customer replies",SYSTEM:"System"},inboxBadge:{CRITICAL:"Critical",WIN:"Win",SECURITY:"Security"},inboxLinkKind:{QUOTATION:"View quotation",CONTRACT:"Open contract",PROVISIONING_RUN:"View event",HANDOVER:"Open handover",ONBOARDING:"Open onboarding",CLAIM:"View claim",OVER_INSTALLATION:"View over-installation",ROLE:"View role",MY_TASKS:"Review in tasks",AUDIT_LOG:"View audit log"},taskType:{DISCOUNT_APPROVAL:"Discount approval",ONBOARDING_STEP:"Onboarding step",HANDOVER_STEP:"Handover step"},taskCategory:{QUOTATION:"Quotation",CONTRACT:"Contract",ONBOARDING:"Onboarding",HANDOVER:"Handover"},taskPriority:{P0:"P0",P1:"P1",P2:"P2",P3:"P3"},taskDueBucket:{OVERDUE:"Overdue",TODAY:"Due Today",THIS_WEEK:"This Week",LATER:"Later"},handoverStatus:{NOTICE_SENT:"Notice Sent",DATA_EXPORTING:"Data Exporting",AWAITING_CONFIRMATION:"Awaiting Confirmation",COMPLETED:"Completed",CANCELLED:"Cancelled"},handoverStepStatus:{PENDING:"Pending",DONE:"Completed",SKIPPED:"Skipped"},tenantStatus:{ACTIVE:"Active",SUSPENDED:"Suspended",ARCHIVED:"Archived"},licenceCode:{ENTERPRISE:"Enterprise"},projectStatus:{PENDING_CONTRACT:"Pending contract",SETUP:"Setup",BLOCKED:"Blocked",ACTIVE:"Active",CLOSING:"Closing",ARCHIVED:"Archived"},reminderTone:{FRIENDLY:"Friendly nudge (1st reminder)",FIRM:"Firm reminder (overdue 7-30 days)",ESCALATION:"Escalation notice (30+ days)",FINAL:"Final notice (before legal action)"},linkType:{IMPLEMENTATION:"Implementation",MAINTENANCE:"Maintenance",ADD_ON:"Add-on",RENEWAL:"Renewal"},priceUplift:{NONE:"No change (carry over current pricing)",CPI_5:"+5% CPI adjustment",MARKET_10:"+10% market adjustment",CUSTOM:"Custom"},deploymentState:{PROVISIONING:"Provisioning",LIVE:"Live",RISK:"At risk",STOPPED:"Stopped"},provisioningStatus:{NOT_STARTED:"Not started",RUNNING:"Running",FAILED:"Failed",LIVE:"Live",ROLLED_BACK:"Rolled back"},accessStatus:{CUSTOMER_MANAGED:"Registered, awaiting customer confirmation",BES_TEMP:"BES temporary access",PENDING_SUPER_ADMIN:"Awaiting Company Admin",PENDING:"Pending",NOT_PROVISIONED:"Not provisioned"},triggerType:{TERMINATION:"Contract ending",IMPLEMENTATION:"Implementation"},cancelReason:{CONTRACT_RENEWED:"Contract renewed — handover no longer needed",CUSTOMER_REQUESTED_PAUSE:"Customer requested pause",CREATED_IN_ERROR:"Created in error",OTHER:"Other"},reminderType:{POLITE_FOLLOW_UP:"Polite follow-up",APPROACHING_DEADLINE:"Approaching deadline (final 14 days)",FINAL_NOTICE:"Final notice (final 7 days)"},aggregateType:{OrganizationProfile:"Organization profile",NotificationTemplate:"Notification template",PurchaseOrder:"Purchase order",StockMovement:"Stock movement",HardwareUnit:"Hardware unit",Warehouse:"Warehouse",Allocation:"Hardware allocation",Dispatch:"Hardware dispatch",Reservation:"Hardware reservation",OverInstallation:"Over-installation",HardwareReturn:"Hardware return",File:"File",MeetingNote:"Meeting note",NotificationPreference:"Notification preferences",DataExport:"Data export",Organization:"Organization",Quotation:"Quotation",Contract:"Contract",Tenant:"Tenant",ProductEntitlement:"Entitlement",Project:"Project",Deployment:"Deployment",ProvisioningRun:"Provisioning run",User:"User",Role:"Role",Product:"Product",ProductRoleTemplate:"Role template",ProvisioningPipeline:"Provisioning template",WorkflowDefinition:"Workflow template",OnboardingRun:"Onboarding",BillingClaim:"Claim",Invoice:"Invoice",Handover:"Handover",IpBlock:"IP block",BillingAccount:"Billing account",CommercialTerm:"Commercial terms",StaffAccessGrant:"Staff access grant",Contact:"Contact",Address:"Address"},grantType:{CAR:"Temp support",BREAK_GLASS:"Break-glass"},accessGrantStatus:{PENDING:"Pending",ACTIVE:"Active",AUTO_DELETED:"Expired",REJECTED:"Rejected",REVOKED:"Revoked",DORMANT:"Dormant"},chainStatus:{INTACT:"Intact",BROKEN:"Broken",NEVER_VERIFIED:"Never verified"},accessAction:{API:"API call",LOGIN:"Sign in",LOGIN_FAIL:"Sign-in failed",LOGOUT:"Sign out",KICKOUT:"Forced sign-out"}}},mc={common:{previous:"上一页",next:"下一页",pageOf:"第 {current} / {pages} 页",save:"保存",cancel:"取消",requiredShort:"必填",mustBePositive:"须大于 0",maxTwoDecimals:"最多两位小数",close:"关闭",confirm:"确认",search:"查询",reset:"重置",detail:"详情",view:"查看",noPermissionToView:"你没有查看这类记录的权限",kpiGo:"查看 →",back:"返回",edit:"编辑",delete:"删除",refresh:"刷新",actions:"操作",moreActions:"更多操作",viewDetails:"查看详情",viewAuditLog:"查看审计记录",status:"状态",keyword:"关键词",createdAt:"创建时间",updatedAt:"更新时间",owner:"负责人",none:"—",projectFilter:"项目:{code}",traceId:"追踪 ID",empty:"暂无数据",emptyOwned:"你负责的客户暂无相关记录",emptyFiltered:"没有符合筛选条件的记录",legacy:"旧字段",months:"{n} 个月",selectPlaceholder:"请选择",saved:"已保存",created:"已创建",deleted:"已删除",requestFailed:"请求失败",networkError:"网络异常",placeholderPage:"骨架占位页 —— 该业务模块待落地"},confirm:{consequencesLead:"这个操作会:",affectedLead:"受影响的对象({n}):",irreversible:"此操作无法撤销。",reasonRequired:"请说明原因 —— 它会进审计记录",reasonOptional:"原因(选填)",reasonTooLong:"原因最多 {max} 字,现在是 {n} 字",typeWord:"输入 {word} 以确认",wordMismatch:"请照原样输入 {word}(区分大小写)"},globalSearch:{trigger:"搜索",shortcutHint:"全局搜索({key})",placeholder:"搜索组织、报价、合同、项目、产品权益、请款单,或跳到某个页面",jumpTo:"跳转到",recent:"最近访问",recentEmpty:"还没有访问记录。打开过的组织、报价、合同、项目、产品权益、请款单会出现在这里。",searching:"搜索中…",showingTop:"显示前 {n} 条,共 {total} 条",groupFailed:"这一类没能加载,其他类不受影响。",noResult:"没有匹配的结果。试试输入「companies」「claims」「projects」…",noSearchable:"你没有查看组织、报价、合同、项目、产品权益、请款单中任何一类的权限。",keyMove:"选择",keyOpen:"打开",keyClose:"关闭",type:{company:"组织",quotation:"报价",contract:"合同",project:"项目",instance:"产品权益",claim:"请款单"}},editConflict:{title:"这条记录在你编辑期间被其他人改过,已对照最新版本:",taken:"对方改了、你没动过的,已换成对方的新值:{fields}",merged:"你和对方都改了的,已把对方的增减并入你的修改:{fields}",clashed:"你和对方都改了的,保存将以你填的为准,会覆盖对方的修改:{fields}",noOverlap:"对方改的地方与你填的内容不冲突,你填的都还在。",saveAgain:"核对无误后再点保存。",separator:"、",goneTitle:"这条记录已被其他人删除,无法保存。你填的内容还在,可以复制后再关闭。",failedTitle:"这条记录在你编辑期间被其他人改过,但没能取到最新版本。你填的内容还在,请稍后再点保存重试。"},menu:{inventory:"硬件库存",systemGuide:"系统指南",authPolicy:"认证与 SSO",orgGeneral:"常规",dashboard:"工作台",analytics:"业务指标",myTasks:"我的待办",inbox:"收件箱",crm:"客户生命周期",companies:"组织",quotations:"报价",contracts:"合同",delivery:"交付供应",projects:"工地项目",projectDetail:"项目详情",productInstances:"产品权益",productInstanceDetail:"产品权益详情",provisioning:"供应监控",products:"产品目录",role_templates:"角色模板",workflowTemplates:"流程模板",notificationTemplates:"通知模板",pipelines:"供应流水线模板",onboarding:"实施跟进",onboardingDetail:"实施详情",billing:"财务",claims:"请款单",invoices:"发票",claimDetail:"请款单详情",invoiceDetail:"发票详情",handover:"收尾",handovers:"交接",handoverDetail:"交接详情",companyDetail:"组织详情",quotationDetail:"报价详情",contractDetail:"合同详情",provisioningDetail:"供应流水线详情",productDetail:"产品详情",hardwareDetail:"硬件型号详情",overInstallationDetail:"超装记录",roleTemplateDetail:"角色模板详情",terms:"商务条款",termDetail:"条款详情",login:"登录",system:"系统管理",users:"员工账号",userDetail:"员工详情",roles:"角色管理",profile:"个人设置",audit:"审计日志",compliance:"合规",accessGrants:"临时客户访问",accessGrantDetail:"访问授权",auditEvents:"业务审计",accessLogs:"访问日志"},shell:{unread:"有未读",openNav:"打开导航",brand:"BES BOSS",brandSub:"内部平台",breadcrumb:"面包屑",group:{workspace:"工作区",commercial:"客户与商务",delivery:"交付",products:"产品与自动化",hardware:"硬件运营",finance:"财务",access:"访问与安全"},accessCenter:"访问中心",auditLog:"审计日志",orgSettings:"组织设置",accountSettings:"账户设置",tab:{general:"常规",auth:"认证与 SSO",staffPolicy:"内部员工权限",customerAccess:"临时客户访问",businessAudit:"业务审计",accessLogs:"访问日志",compliance:"合规"}},locale:{label:"语言",en:"English","zh-CN":"简体中文"},theme:{toLight:"切换到浅色",toDark:"切换到深色",light:"浅色",dark:"深色",auto:"自动"},prefs:{title:"显示偏好",subtitle:"按你的习惯调整 BES BOSS 的显示",language:"语言",timeZone:"时区",dateFormat:"日期格式",timeFormat:"时间格式",theme:"主题",sidebarDensity:"侧栏密度",date:{iso:"2026-05-20(ISO)",dmy:"20/05/2026(日/月/年)",mdy:"05/20/2026(月/日/年)",long:"20 May 2026"},time:{"24h":"24 小时制(14:30)","12h":"12 小时制(2:30 PM)"},density:{compact:"紧凑",comfortable:"适中",spacious:"宽松"},inZone:"按 {zone} 时间",sgtDate:"按新加坡日期"},mfa:{codeLabel:"验证码",appHint:"打开手机上的验证器应用查看验证码。",lostTitle:"无法使用第二因素了?",lostBody:"请联系管理员重置两步验证。重置请求会被记录并复核。",verifyTitle:"两步验证",verifySubtitle:"请输入验证器 App 上的 6 位验证码。",codePlaceholder:"6 位验证码,或一个备份码",codeRequired:"请输入验证码",verifySubmit:"验证并继续",oneShotHint:"本次验证只有一次机会:输错会退回登录页、需要重新输入口令。这是有意的——让逐个试验证码变得没有意义。",backToLogin:"返回登录",setupTitle:"绑定两步验证",setupSubtitle:"用验证器 App 扫描下方二维码,然后输入它显示的验证码。",requiredBy:"请在 {date} 之前完成绑定。",qrAlt:"两步验证绑定二维码",scanHint:"Google Authenticator、1Password、Authy 等任意 TOTP 应用都可以。",cannotScan:"扫不了码?手动输入密钥",copySecret:"复制密钥",secretHint:"与二维码是同一把密钥,用其中一种即可。它只在绑定时出现这一次。",setupCodePlaceholder:"6 位验证码",setupSubmit:"确认并登录",setupWrongCodeHint:"如果验证码一直不对,先检查手机时间是否为自动校准——TOTP 验证码是按当前时间算出来的。",copied:"已复制",copyFailed:"复制失败,请手动选中文本复制",backupTitle:"保存备份码",backupOnceTitle:"只在此刻显示这一次",backupOnceHint:"备份码在库里只存哈希,因此无法再次显示——关掉这个页面就再也拿不回来了。每个码只能用一次,它们是手机丢失时唯一的登录方式。请存在手机以外的地方。",copyAll:"全部复制",download:"下载为 .txt",savedAck:"我已把这些备份码保存到安全的地方",enterConsole:"继续"},stepUp:{title:"在 BES 确认身份",subtitle:"这是高风险操作",step1:"点「打开 BES 确认页」,在弹出的窗口里确认身份(口令或两步验证都在 BES 完成)。",step2:"回到这里点「继续」,确认通过后这个操作才会执行。",expires:"请在 {time} 前完成确认。",restartHint:"确认页失败、过期或被关掉了,点「重新确认」换一个新的。",pending:"BES 还没认可这次确认。在确认页完成后再点「继续」;如果确认页已经失败,点「重新确认」。",renewed:"之前的确认已失效,已发起新的确认,请重新打开确认页。",open:"打开 BES 确认页",continue:"继续",restart:"重新确认",mfaTitle:"需要先设置两步验证",mfaBody:"你的账号还没有可用的两步验证,BES 无法确认这个高风险操作。先到 BES 账户页设置两步验证,再重做这个操作。",mfaOpen:"打开账户设置"},login:{control:{SIGN_IN:{title:"登录",body:"使用 BES 账号登录。口令与两步验证在 BES 登录页完成。",action:"使用 BES 账号登录"},NOT_STAFF:{title:"这个账号不能使用 BOSS",body:"你登录的 BES 账号没有对应的 BOSS 员工档案,或邮箱还没有验证。请换用员工账号登录,或请管理员为你建档。",action:"换个账号登录"},ACCOUNT_NOT_ACTIVE:{title:"账号已停用",body:"你的 BOSS 员工账号已被停用,请联系管理员恢复。",action:"换个账号登录"},LOGIN_FAILED:{title:"登录没有完成",body:"登录过程被中断或已过期,请重新登录。",action:"重新登录"},NO_ACCESS:{title:"没有 BOSS 访问权限",body:"你已经登录,但账号目前不能使用 BOSS。请联系管理员检查你的角色。",action:"退出登录"},UNAVAILABLE:{title:"暂时连不上登录服务",body:"BOSS 或 BES 身份服务暂时不可用,请稍后重试。",action:"重试"},secureTitle:"经 BES 登录",secureBody:"BOSS 不经手你的口令。口令、两步验证与已登录的浏览器都在 BES 账户页管理。"},secureTitle:"安全登录",secureBody:"所有登录尝试都会记录。所有账号都要启用两步验证。",footCopyright:"© 2026 Global BES Pte. Ltd.",footSecure:"加密连接 · 所有认证事件都会记入审计",title:"登录你的账号",subtitle:"欢迎回来,请输入账号与口令继续。",username:"用户名",password:"密码",submit:"登录",hint:"本地开发已预填联调账号 {account}",guideAccountLocked:"账号已被锁定——连续多次口令错误会触发这个保护。等提示的时间过去会自动解除;急用请联系管理员重置。",guideAccountNotActive:"这个账号当前不能登录,自己重试没有用。请联系管理员确认账号状态。",missingCredentials:"请输入用户名和密码"},dashboard:{roleDesc:{sales:"销售视图:在途报价、转化,以及需要拍板的续约。",operations:"运营视图:实施、开通与交接中的阻碍。",finance:"财务视图:请款、发票与应收。",products:"产品视图:实例与开通。",admin:"管理视图:访问申请、紧急访问、未登录员工与审计告警。"},kpiChip:{critical:"严重",clear:"无",quotesAwaitingFollowUp:"待处理",contractsAwaitingActivation:"待处理",renewalRisk:"30 天内",overdueReceivables:"关注",accessRequestsPending:"待审",auditAlerts:"待排查",activeOnboardings:"进行中",breakGlassActive:"生效中",inactiveUsers:"待复核"},pipelineTitle:"生命周期漏斗",pipelineSub:"客户从报价到上线的整体进度",viewCompanies:"查看组织",stageQuotes:"报价",stageQuotesSub:"进行中",stageContracts:"合同",stageContractsSub:"生效中",stageProvisioning:"供应",stageProvisioningSub:"{n} 条失败",stageLive:"上线",stageLiveSub:"个实例",stageRenewals:"续约",stageRenewalsSub:"90 天内到期",recentTitle:"近期动态",recentSub:"全平台最新的业务事件",viewAuditLog:"查看审计日志",recentEmpty:"还没有事件。",recentFailed:"近期动态加载失败,可到审计日志查看。",pageTitle:"BOSS 工作台",pageSubtitle:"BES 销售、运营、财务、产品与管理团队的内部行动中心。",provFailedTitle:"{n} 个开通运行失败,需要 Ops 处理",provFailedHint:"客户开通卡在半路。先查清原因,再重试。",provFailedCta:"打开供应监控",quickActions:"快捷入口",qaNewCompany:"新建组织",qaNewQuotation:"新建报价",qaStartOnboarding:"开始实施"},error:{loadFailed:"没能加载出来",loadFailedHint:"请求失败了 —— 这不是「没有数据」。",retry:"重试",notFound:"页面不存在",notFoundDesc:"该页面不存在,或当前账号没有访问权限。",backHome:"返回工作台"},user:{removeMenu:"移除员工",removeTitle:"移除 {name}?",removeSubtitle:"审计记录保留",removeChecking:"正在检查他名下还有什么…",removeBlockedLead:"先移交以下几项,处理完之前不能移除:",removeBlockerCompanies:"他是 {n} 家客户的负责人,到各客户页改负责人。",removeBlockerProjects:"他负责 {n} 个进行中的项目,到各项目页改负责人。",removeBlockerTasks:"还有 {n} 条派给他的待办没处理,先处理或改派。",removeBlockerSelf:"不能移除自己的账号。",removeBlockerLastAdmin:"他是最后一个能管理员工的在职员工,先给另一位在职员工这项权限。",removeBlockerAlready:"这名员工已经移除。",removeBlockerOther:"后端拦下:{code}",removeViewCompanies:"查看这些客户",removeViewProjects:"查看这些项目",removeConsequenceList:"从员工列表移除,审计记录和单据上的名字都保留",removeConsequenceRoles:"撤掉他的全部角色,立即结束他的登录",removeConsequenceControl:"停用他的 BES 账号,这个邮箱不能再用来邀请",removeConsequenceDocs:"报价、合同、实施单、交接单上他仍是负责人,之后到各自页面改",removeConsequenceFinal:"不能撤销,移除的员工无法重新启用",removeConfirmWord:"输入 {word} 确认",removeConfirmMismatch:"请准确输入 {word}",removeAction:"移除",removed:"已移除 {name}",removedReadOnly:"这名员工已移除。记录为审计与引用保留,不能再修改。",inviteCreate:"邀请员工",inviteTitle:"邀请员工加入 BES BOSS",inviteLead:"在 BES 建档并分配角色。员工经首次登录链接自己设口令与两步验证。",inviteSubmit:"发送邀请",firstName:"名",lastName:"姓",firstNamePlaceholder:"如 Sarah",lastNamePlaceholder:"如 Chen",emailPlaceholder:"user{'@'}bes.sg",firstNameRequired:"请填写名",lastNameRequired:"请填写姓",rolesRequired:"至少选一个角色",emailRequired:"请填写邮箱",inviteEmailHint:"员工用这个邮箱登录 BES,它也会成为 BOSS 的用户名,之后不能在这里改。",accountType:"账号类型",sendInvite:"立即发送欢迎邮件",sendInviteOn:"会发一封首次登录链接,48 小时内有效。",sendInviteOff:"现在不发邮件,之后用「重发首次登录链接」。",invited:"已邀请,首次登录链接已发出",invitedNoEmail:"已建档,还没有发邮件",emailManagedInBes:"邮箱以 BES 为准,员工在 BES 账户页自己改。",rolesNotInControl:"这名员工还没有经 BES 登录过,登录一次之后才能改角色。",resendInvite:"重发首次登录链接",resendInviteTitle:"重发首次登录链接?",resendInviteAction:"重发",resendInviteConsequenceSend:"给 {name}({email})发一封新的首次登录邮件,用来设口令与两步验证",resendInviteConsequenceExpiry:"新链接 48 小时内有效",resendInviteConsequenceOld:"之前发出的链接作废",resendInviteDone:"首次登录链接已发出",sendReset:"发送重置口令邮件",sendResetTitle:"发送重置口令邮件?",sendResetAction:"发送",sendResetConsequenceEmail:"给 {name} 的已验证邮箱发一个一次性的重置口令链接",sendResetConsequenceExpiry:"链接 10 分钟内有效",sendResetConsequenceSignOut:"立即结束他在 BES 各处的登录,包括 BOSS",sendResetConsequenceNoPassword:"新口令由他自己设,BOSS 不经手",sendResetDone:"重置口令邮件已发出",logout:"退出登录",fallbackName:"用户",selectOwner:"选择负责人",title:"员工账号",create:"新建员工账号",editTitle:"编辑员工账号",createTitle:"新建员工账号",searchPlaceholder:"用户名 / 显示名",username:"用户名",usernameImmutable:"用户名不可修改 —— 它是审计记录里的身份锚点",displayName:"显示名",email:"邮箱",department:"部门",seniority:"职级",roles:"角色",noRoles:"未分配角色",lastLogin:"上次登录",pageSubtitle:"BES 内部员工账号。不是客户侧的用户(那些在各产品平台里管理)。",tabAll:"全部",userColumn:"员工",roleColumn:"角色",footTitle:"这里只管 BES 内部员工。",footBody:"客户的终端用户由各自的 Company Admin 在产品平台(BOSP、AIVA 等)里管理,不在这里。停用的账号保留审计记录,但不能登录。",neverLoggedIn:"从未登录",autoSuspendIn:"{days} 天后自动停用",autoSuspendDue:"待自动停用",autoSuspendHint:"连续 {days} 天未登录会被系统自动停用,从 {since} 起算。",password:"初始密码",passwordHint:"系统没有邮件基建,初始密码请线下转达,员工登录后自行修改。",suspend:"停用",suspendMenu:"停用员工",activate:"重新启用",resetPassword:"重置密码",resetMfa:"重置两步验证",suspendConsequenceLogin:"从下一次尝试起,{name} 登不进来",suspendConsequenceSession:"立即结束他当前的会话 —— 审计记录与账号信息都保留",suspendConsequenceReversible:"可以撤销:随时能把账号重新启用",activateTitle:"启用账号",activateConsequenceLogin:"{name} 可以用现有口令重新登录",activateConsequenceRoles:"恢复其角色的全部权限 —— 角色本身没有变化",resetConsequenceLogin:"把 {name} 的口令换成你接下来输入的那个",resetConsequenceNoNotify:"不会通知他 —— BOSS 不发邮件,新口令要你自己转达",resetConsequenceMfaKept:"不动他的 MFA 绑定,他仍然需要验证器上的动态码",resetMfaConsequenceUnbind:"解除 {name} 的验证器绑定,并作废他的全部备份码",resetMfaConsequenceSingleFactor:"在他重新绑定之前,那个账号只靠口令就能进 —— 这段时间它是单因素的",resetMfaConsequenceRebind:"他下次登录时会被要求重新绑定 MFA",resetMfaDone:"已重置,该账号下次登录时会被要求重新绑定",suspendTitle:"停用账号",suspended:"账号已停用",activated:"账号已启用",resetTitle:"重置密码",resetPrompt:"为「{name}」设置新密码。{rule} 重置后该账号会被强制重新登录。",resetDone:"密码已重置,该账号需重新登录",usernameRequired:"请填写用户名",displayNameRequired:"请填写显示名",passwordRequired:"请填写密码",internalStaff:"BES 内部员工",joined:"入职 {date}",kpiOwnedCompanies:"负责的客户",kpiActiveProjects:"进行中的项目",kpiOpenTasks:"待办",kpiLastActive:"最近活跃",neverActive:"从未",tabOverview:"概览",tabActivity:"活动",personalInfo:"个人信息",editPersonalTitle:"编辑个人信息",fullName:"全名",jobTitle:"职位",employeeType:"雇佣类型",reportsTo:"汇报对象",selectReportsTo:"选择汇报对象",activitySummary:"近期活动",last30Days:"近 30 天",summary:{quotationsCreated:"新建报价",contractsSigned:"签约合同",onboardingsLed:"参与的实施",systemActions:"系统操作"},activityTimeline:"活动记录",colTime:"时间",colEvent:"事件",colResource:"对象",colDetails:"详情",activityEmpty:"还没有操作记录",viewFullAudit:"查看完整审计日志 →",tabAccess:"访问与角色",customerOwnership:"客户归属",customerOwnershipSub:"这名员工所在客户团队的客户",customerOwnershipEmpty:"还没有加入任何客户的客户团队",assignCustomerButton:"指派客户",assignInactive:"只有在职的员工能指派给客户",colCompany:"客户",colRelationship:"角色",colStage:"阶段",colActiveProjects:"进行中的项目",colSince:"起始日期",showingCompanies:"显示 {n} / 共 {total} 家客户 · ",viewAll:"查看全部 →",removeFromTeam:"移除",removeFromTeamTitle:"移出客户团队",removeFromTeamConsequence1:"{name} 不再是 {company} 的{role}",removeFromTeamConsequence2:"数据范围是「我的客户」的员工会立刻看不到这家客户的数据,只保留自己经手的报价、合同与审计",removeFromTeamDone:"已移出客户团队",assignCustomerTitle:"给 {name} 指派客户",assignCustomerSubtitle:"选择客户,以及 {name} 在其客户团队中的角色",assignCustomer:"客户",assignCustomerPlaceholder:"— 选择客户 —",assignCustomerRequired:"请选择客户",assignRole:"角色",assignRoleRequired:"请选择角色",assignSubmit:"指派",assignDone:"已指派",assignReplacesOwner:"当前主负责人 {owner} 将被替换,之后不再属于这家客户的客户团队",assignAlreadyOwner:"{name} 已经是这家客户的主负责人",assignOwnerCannotJoin:"{name} 是这家客户的主负责人。要换成别的角色,先把主负责人指派给别人",passwordRule:"12–64 位,且需同时包含大写字母、小写字母、数字与符号。"},role:{kpiTotal:"权限总数",kpiModules:"{n} 个模块",kpiUsers:"{n} 人",kpiSystem:"系统",kpiEditable:"可编辑",title:"角色管理",create:"新建角色",createTitle:"新建角色",editTitle:"编辑角色",code:"角色编码",codeHint:"自动转小写。字母开头,只能用字母、数字、_ . -,最长 48 个字符;不可重复,建后不可修改",codeFormat:"须以字母开头,只能用字母、数字、_ . -,最长 48 个字符",codeReserved:"staff-base 留给所有员工都有的基础角色,不能使用",name:"角色名称",userCount:"成员数",permissions:"权限点",grants:"授予",denies:"拒绝",denyHint:"拒绝会压过其它所有角色的授予 —— 一人身兼数职时,显式拒绝必须生效。",dataScope:"数据范围",dataScopeHint:"与权限点正交:权限点决定「能不能做」,数据范围决定「能看到谁的数据」。OWNED 档只看得到自己负责的客户,以及自己经手过的报价、合同与审计记录。",dataScopeLocked:"admin 角色恒为「全部数据」,不可修改。",systemLocked:"系统角色",systemLockedHint:"admin 是系统锁定角色:权限恒等于全部权限点,不可在此编辑或删除。",deleteTitle:"删除角色",deleteConsequenceGone:"删掉角色「{name}」以及它携带的那套权限",deleteConsequenceInUse:"只要还有员工挂着这个角色就会被拒绝 —— 先把他们改到别的角色",catalogEmpty:"暂无权限点",codeRequired:"请填写角色编码",nameRequired:"请填写角色名称",replaceHint:"权限为整体替换 —— 这里勾选的即为该角色的全部权限。"},profile:{changeConfirmTitle:"确认修改口令?",changeConsequenceReplace:"把你的口令换成新的,下次登录起旧口令不再可用",changeConsequenceSessions:"保留当前与其他已登录的会话,不会把谁登出",changeConsequenceAudit:"记入审计日志;不会发邮件,如果不是你本人操作,请联系管理员",title:"个人设置",tabProfile:"个人资料",tabPassword:"密码",pageSubtitle:"你的账户偏好。这些设置只对你生效,随时可以改。",profileSubtitle:"其他 BES 员工能看到的基本信息",tabDisplay:"显示",tabNotifications:"通知",changePassword:"修改密码",accountTitle:"口令与两步验证",accountBody:"口令、两步验证、恢复码与已登录的浏览器都在 BES 账户页管理,BOSS 不经手你的口令。",accountOpen:"打开 BES 账户页",passwordTitle:"修改密码",oldPassword:"当前密码",newPassword:"新密码",confirmPassword:"确认新密码",changed:"密码已修改",mismatch:"两次输入的密码不一致",oldRequired:"请填写当前密码",photoTitle:"头像",photoHint:"JPG、PNG 或 GIF,最大 2 MB。",uploadNew:"上传新头像",removePhoto:"删除",avatarUploaded:"头像已更新",avatarRemoved:"头像已删除,改回姓名首字母。",fullName:"全名",displayName:"显示名",email:"邮箱",emailReadOnly:"(只读 · 要改请联系管理员)",emailReadOnlyControl:"(只读 · 在 BES 账户页修改)",phone:"电话",phoneOnAccount:"在 BES 账户页管理",jobTitle:"职位",department:"部门",departmentSetByAdmin:"(由管理员设置)",discard:"放弃修改",discarded:"已放弃修改。",saveChanges:"保存修改",noChanges:"没有改动",saveConfirmTitle:"保存修改?",saveConsequenceUpdate:"更新你的个人资料,其他 BES 同事立即看到",saveConsequenceAudit:"修改会记进你的员工变更历史",saved:"资料已保存",displayNameRequired:"请填写显示名",conflictReloaded:"你的资料刚在别处被改过,已载入最新版本,你填的内容保留着,请核对后再保存。"},analytics:{pageTitle:"业务总览",desc:{sales:"销售表现:在途报价、成交转化与经常性收入。",operations:"交付运营:实施、开通与交接的健康度。",finance:"财务:开票、回款与应收。",products:"产品:在用实例、产品构成与开通。",admin:"管理:访问申请、紧急访问、未登录员工与审计动态。"},viewAsRole:"按角色查看",view:{sales:"销售",operations:"运营",finance:"财务",products:"产品",admin:"管理"},range:{TODAY:"今天",YESTERDAY:"昨天",LAST_7:"最近 7 天",LAST_30:"最近 30 天",LAST_90:"最近 90 天",THIS_QUARTER:"本季度",YTD:"今年以来",CUSTOM:"自定义范围…"},from:"开始",to:"结束",apply:"应用",rangeTooLong:"范围不能超过 366 天",export:"导出",exportTitle:"导出总览",exportFormat:"格式",exportScope:"范围",scopeCurrent:"当前角色视图",scopeAll:"全部角色视图",download:"下载",noData:"这段时间没有数据",noPermission:"无权限查看",daysValue:"{n} 天",changePt:"{n} 个百分点",changeDays:"{n} 天",lastSixMonths:"最近 6 个月",quotationsIn:"报价 · {range}",kpi:{openPipeline:"在途报价金额",winRate:"成交率",mrr:"月经常性收入",quotationsSent:"发出的报价",quotesAwaitingFollowUp:"待跟进的报价",contractsAwaitingActivation:"待生效的合同",renewalRisk:"续约风险",activeOnboardings:"进行中的实施",blockedOnboardings:"受阻",provisioningSuccessRate:"开通成功率",handoverOverdue:"交接逾期",provisioningFailed:"开通失败",arr:"年经常性收入",collected:"回款",collectedIn:"回款 · {range}",overdueReceivables:"逾期应收",dso:"应收周转天数",invoicesOverdue:"逾期发票",claimsPending:"待批请款",liveInstances:"在用实例",provisioningFailures:"开通失败",accessRequestsPending:"待批访问申请",breakGlassActive:"生效中的紧急访问",inactiveUsers:"30 天未登录员工",auditAlerts:"审计告警"},sales:{mrrTitle:"月经常性收入",yoy:"同比 {arrow} {n}%",funnelTitle:"销售漏斗",funnel:{sent:"已发出",opened:"已打开",negotiation:"谈判中",accepted:"已接受"},conversionTitle:"报价转化",conversionSub:"发出、接受与丢单",accepted:"已接受",lost:"丢单",open:"在途",topTitle:"年合同额最高的客户",topSub:"年合同额",lossTitle:"丢单原因"},operations:{throughputTitle:"实施吞吐",throughputSub:"每月开始与完成的实施",started:"开始",completed:"完成",statusTitle:"实施与交接",statusSub:"生命周期状态 · 共 {n}",completedShort:"已完成",inProgress:"进行中",overdue:"已逾期",total:"合计",provTitle:"各产品开通成功率"},finance:{trendTitle:"开票与回款",mom:"环比 {arrow} {n}%",billed:"开票",collected:"回款",agingTitle:"应收账龄",agingSub:"未收 · {amount}",aging:{notDue:"未到期",d1to30:"逾期 1–30 天",d31to60:"31–60 天",d61to90:"61–90 天",d90plus:"90 天以上"},claimsTitle:"请款单分布",claimsSub:"按状态 · 单数"},products:{mixTitle:"产品构成",mixSub:"在用实例",instances:"个实例"},admin:{accessTitle:"访问申请与紧急访问",accessSub:"每月批准、驳回与紧急访问",granted:"批准",denied:"驳回",breakGlass:"紧急访问",auditTitle:"审计事件分类",trendTitle:"敏感操作趋势",trendSub:"紧急访问 · 最近 6 个月"}},audit:{eventDialogTitle:"审计事件",sourceIp:"来源 IP",maskedIp:"打码 IP",description:"描述",payload:"事件数据",hashChain:"哈希链",hashPrev:"前一条:",hashThis:"本条:",readOnlyFoot:"只读 · 不可修改或删除",keywordHint:"搜索事件码、链路 ID、操作人、对象或打码 IP",allCategories:"全部类别",allSeverities:"全部严重度",allTenants:"全部租户",kpi90:"事件数(近 90 天)",kpi90Hint:"你的数据范围内",kpi30:"事件数(近 30 天)",kpi30Hint:"日均 {n} 条",kpiSensitive:"敏感事件(24 小时)",kpiSensitiveBadge:"待查看",kpiSensitiveHint:"警告与严重:身份与权限变化、账号锁定、IP 封禁",kpiRetention:"保留期",kpiRetentionValue:"永久保存",kpiRetentionHint:"只插不改,不会到期 · ISO 27001",readOnlyLead:"只读。",eventsTitle:"事件",eventsSub:"{range}共 {total} 条,本页 {shown} 条 · 按时间倒序",presetIn:{d7:"近 7 天",d30:"近 30 天",d90:"近 90 天",custom:"所选时间范围内"},colTimestamp:"时间",colEvent:"事件",colActor:"操作人",colDetails:"详情",trailTitle:"审计记录",autoGenerated:"自动生成",pageSubtitle:"BES BOSS 全部事件的不可改记录,为 ISO 27001 / PDPA 合规永久保存。",readOnlyChain:"记录不能编辑或删除。BES BOSS 里每个改变状态的操作都会写一条审计事件,哈希链保证可发现篡改——到{link}校验链完整性。",complianceLink:"设置 → 合规",actorFilter:"全部人员",preset:{d7:"近 7 天",d30:"近 30 天",d90:"近 90 天",custom:"自定义"},targetDetails:"对象 / 详情",events:"审计日志",accessLogs:"访问日志",occurredAt:"发生时间",eventType:"事件",eventHeaderHint:"事件码(如 PROVISIONING.COMPLETED、CLAIM.APPROVED)是「类型.动作」形式的机读标签。每次状态变更都会自动写入一条,不可修改,用于合规留证。",eventTypeHint:"事件码,如 ORGANIZATION.UPDATED",siemExport:"SIEM 转发状态",siemExportHint:"端点与 token 由后端环境变量配置,不在界面上改 —— 这里查看只读的转发状态。",aggregate:"对象",objectFilter:"{type} {id}",aggregateType:"对象类型",aggregateId:"对象 ID",actor:"操作者",actorType:"操作者类型",risk:"风险",traceId:"Trace ID",detail:"事件内容",allCustomers:"全部客户",tenantId:"租户 ID",allProducts:"全部产品",allProjects:"全部项目",from:"开始时间",to:"结束时间",dateRange:"时间范围",viewTrace:"查看完整链路",traceTitle:"因果链",traceRequests:"触发请求",traceEvents:"引发的事件",traceEmpty:"该链路没有查到记录",noTrace:"该记录没有 Trace ID —— 访问日志自 2026-08-25 起才带此字段",history:"操作历史",customerTimeline:"客户动态",historyEmpty:"暂无操作记录",historyLoadMore:"加载更早的记录(还有 {n} 条)",createdAt:"时间",username:"用户名",actionType:"类型",method:"方法",uri:"接口",status:"业务码",statusHint:"是业务码不是 HTTP 状态码 —— 例如 20002 可查出所有被权限拦下的请求",costMs:"耗时",ip:"IP",querySummary:"参数",minCostMs:"耗时超过(ms)",dateHint:"不指定开始时间时后端会收敛到最近 7 天 —— 访问日志按月分区。",changes:"字段变更",field:"字段",before:"修改前",after:"修改后",permissionsAdded:"新增权限",permissionsRemoved:"移除权限",deniesAdded:"新增拒绝",deniesRemoved:"移除拒绝",rawPayload:"原始内容",empty:"(空)",ownedScopeEvents:"你的账号是「仅本人负责」范围:这里只显示你负责客户的记录,以及你自己经手的操作。",ownedScopeAccess:"你的账号是「仅本人负责」范围:这里只显示你自己的访问记录。",readOnly:"审计数据只读,永远不提供修改入口。"},company:{filterOwner:"负责人:{name}",filterTeamMember:"客户团队:{name}",kpiTotal:"组织总数",kpiTotalSub:"近 30 天新增",kpiTotalHint:"BES BOSS 中的有效组织总数(客户、潜在客户、供应商与合作方)。",kpiLeads:"潜在客户",kpiLeadsBadge:"优先",kpiQualified:"已确认",kpiNew:"新线索",kpiCustomers:"客户",kpiActive:"活跃",kpiDormant:"休眠",kpiSuppliers:"供应商",kpiSuppliersSub:"设备 + 材料",tabAll:"全部",tabCustomer:"客户",tabLeads:"潜在客户",tabSupplier:"供应商",tabDeveloper:"开发商",tabSubCon:"分包商",tabConsultant:"顾问",tabArchived:"已归档",lastActivity:"最近动态",industryPlaceholder:"选择行业",notes:"备注",notesPlaceholder:"这家公司的背景信息……",noNotes:"还没有备注",editNotesTitle:"编辑备注",createdBy:"由 {name} 创建",editTitleNamed:"编辑组织 — {name}",editSubtitle:"更新组织信息,所有修改都会记入审计。",editFootnote:"所有修改都会记入审计日志",saveChanges:"保存修改",legalNamePlaceholder:"如 ABC Construction Pte Ltd",shortNamePlaceholder:"如 ABC",uenPlaceholder:"如 201234567K",companyType:"组织类型",companyTypeHint:"— 可多选",corporateRelationship:"集团关系",corporateRelationshipHint:"— 这家组织属于某个集团时填写",relationshipTypeShort:"关系类型",parentPartner:"上级 / 合作方组织",selectCompany:"— 选择组织 —",corporateRelationshipNote:"用于大型承包商:主体作为主要签约方,子实体(合资 / 子公司)负责具体项目。",relOption:{NONE:"— 无(独立实体)—",SUBSIDIARY:"子公司,隶属于",JV_PARTNER:"合资方,合作于",BRANCH:"分支,隶属于",DIVISION:"事业部,隶属于"},billingAddressLabel:"账单地址",optionalHint:"— 选填",entGlossary:"权益 = 客户按合同可以使用的东西,即他们付费的具体产品与模块。系统只开通这些,不多不少。",created:"创建",owner:"负责人",entSummaryTitle:"产品权益",entSummarySub:"这家客户实际开通的权益",viewAllN:"查看全部({n})→",recentActivity:"最近动态",colSigned:"签署日期",selectPlaceholder:"选择组织",pageSubtitle:"客户、供应商、开发商与顾问统一在这里建档。只有客户或服务接收方关系的组织才能拥有租户。",createTitle:"新建组织",createSubtitle:"新增一个业务往来方,每次新建都会记入审计。",createFootnote:"新建操作都会记入审计日志",createSubmit:"创建组织",columnCompany:"公司",columnStage:"阶段",columnOwner:"负责人",registeredAddress:"注册地址",registeredAddressPlaceholder:"街道、楼宇、邮编…",billingAddress:"账单地址(选填)",billingAddressPlaceholder:"与注册地址相同就留空",sameAsRegistered:"同注册地址",addressNotSaved:"组织已创建,但地址没有保存 —— 请到该组织的地址里补上",roleShort:{MAIN_CON:"总包",SUB_CON:"分包",EQUIPMENT:"设备"},editTitle:"编辑组织",create:"新建组织",searchPlaceholder:"搜索组织、UEN、上级主体或负责人",orgNo:"编号",legalName:"法定名称",shortName:"简称",uen:"UEN",country:"国家/地区",countryPlaceholder:"缺省新加坡(SG)",industry:"行业",website:"网站",roles:"角色",accountOwner:"负责人",parentOrg:"上级组织",relationshipType:"集团关系",tags:"标签",tagsPlaceholder:"回车创建标签",lifecycleStage:"生命周期",customerSince:"成为客户时间",qualify:"标记 Qualified",archiveCompany:"归档组织",archive:"归档",restore:"恢复",qualified:"{name} 已标记为 Qualified",archived:"已归档",restored:"已恢复",qualifyTitle:"标记为 Qualified",qualifyConsequenceStage:"把「{name}」的阶段从 Lead 推进到 Qualified",qualifyConsequenceOnce:"让这个按钮消失 —— 只有 Lead 能被标记,所以点不了第二次",qualifyConsequenceReversible:"可以回退 —— 在编辑客户里把阶段改回 Lead",restoreTitle:"恢复组织?",restoreConsequenceListed:"把「{name}」放回客户列表",restoreConsequenceEditable:"让它重新可编辑,并可以对它开新报价",archiveTitle:"归档组织?",archiveConsequenceHidden:"把「{name}」从客户列表里收起来 —— 要筛「已归档」才找得到",archiveConsequenceReadonly:"它转为只读:不能编辑,也不能给它开新报价",archiveConsequenceRunning:"进行中的合同与项目照常运行:合同照常到期或终止,请款单与发票照常开,续约报价、修订版与变更单小报价照常走",archiveConsequenceReversible:"可以撤销:随时能把客户恢复回来",deleteCompany:"删除公司",deleteTitle:"删除公司?",deleteSubmit:"永久删除",deleteConsequenceGone:"永久删除「{name}」:之后在列表、下拉与搜索里都找不到它,也不能再选作新报价的客户",deleteConsequenceRecords:"保留以它为客户的报价、合同、项目与发票,照常显示原来的名称",deleteConsequenceAttached:"它的联系人、地址、会议记录、客户团队与账单主体随之一起看不到",deleteConsequenceAudit:"审计记录照常保留,审计页仍能查到它的事件",deleteConsequenceBlocked:"如果这个客户还有进行中的合同、未付清的发票,或草稿、已发送的报价,操作会被拒绝",deleted:"公司已删除",customerGone:"客户不存在或已删除",archivedAlert:"该组织已归档,归档态禁止编辑;恢复后可继续维护。",legalNameRequired:"请填写法定名称",relationshipRequired:"指定上级组织时必须选择集团关系,且不能为「无」",stageWorkflowOnly:"{stage} —— 该阶段由销售/合同工作流推进,不可手工修改",relatedQuotations:"关联报价",relatedContracts:"关联合同",noQuotations:"暂无报价",noContracts:"暂无合同",noProjects:"暂无项目",tabOverview:"概览",tabAudit:"审计",tabAccess:"客户访问",tabEntitlements:"产品权益",tabActivity:"动态",grantExpiry:"到期",viewAllInProjects:"在项目列表查看全部 →",viewAllInContracts:"在合同列表查看全部 →",viewAllInQuotations:"在报价列表查看全部 →",colProject:"项目",colContract:"合同",colExpires:"到期",colValue:"金额",viewProject:"查看项目",entIntro:"产品权益是从这家客户的合同开通出来的在用权益,每条有自己的租户、开通状态与续期日。完整清单见{link}。",activityAutoHint:"由系统事件自动生成",lifecycleStageLabel:"生命周期阶段",lifecycleStageHint:"— 活跃、休眠、流失由销售流程推进,不能手工设置",grantsTitle:"临时 BES 访问 · 应急账号",grantsSubtitle:"BES 支持人员限时进入客户已部署系统的授权,全程审计、可提前收回",grantsAll:"全部访问申请 →",grantReasonScope:"原因 · 范围",grantRequestedBy:"申请人",grantApprovedBy:"批准人",noGrants:"这家客户没有临时访问授权",entTenant:"租户",entProject:"项目",entTerm:"期限",entOpen:"打开权益 →",noEntitlements:"这家客户没有在用的产品权益",infoTitle:"公司信息",parentRestricted:"该组织有上级主体,但不在你的数据范围内",primaryContact:"主联系人",contactsLoadFailed:"联系人没有加载出来 —— 到「联系人」页签查看",noContacts:"还没有联系人",viewAllContacts:"查看全部联系人({n})",addTag:"+ 添加",noTags:"还没有标签",addTagTitle:"添加标签",addTagPlaceholder:"输入标签名…",addTagSubmit:"添加标签",addTagSuggestions:"建议",addTagRequired:"请输入标签名",addTagDuplicate:"这个组织已经有这个标签了",addTagConflict:"有人刚改过这个组织,已重新加载,请再加一次",tagAdded:"标签已添加",workflowOwnership:"流程归属",workflowBesTitle:"BES 侧 —— 实施流程",workflowBesBody:"上线与实施的各个步骤,定义在{templates}里。这是 BES 交付系统的方式。",workflowCustomerTitle:"客户侧 —— 运营流程",workflowCustomerBody:"客户日常怎么跑工地运营(巡检流程、审批链等)。由客户的 Company Admin 在他们自己的系统里定义,不在 BOSS 里。BES 按设计看不到这部分。",period:"周期",relatedShown:"这里只列 {shown} 条,共 {total} 条",relatedViewAll:"查看全部 →",openFullAuditLog:"查看完整审计日志 →"},billingAccount:{title:"账单主体",subtitle:"发票开给谁 —— 可以与客户不是同一家公司",create:"新建账单主体",createTitle:"新建账单主体",editTitle:"编辑账单主体",empty:"暂无账单主体",legalName:"法定名称",legalNameHint:"账单主体自己的法定名称,可与客户不同",legalNameRequired:"请填写法定名称",uen:"税号(UEN)",currency:"币种",currencyRequired:"请选择币种",paymentTermsRequired:"请填写账期 —— 想改回默认就填 30",gstRateRequired:"请填写税率 —— 想改回默认就填 9",paymentTerms:"账期",paymentTermsDays:"{n} 天",days:"天",gstRate:"默认税率",gstRateHint:"按百分比填,如 9 表示 9%",contact:"账单联系人",contactName:"联系人",contactEmail:"邮箱",contactEmailInvalid:"请填写有效的邮箱地址",contactPhone:"电话",address:"账单地址",addrLine1:"地址行 1",addrLine2:"地址行 2",addrPostal:"邮编",addrCountry:"国家/地区",remark:"备注",isDefault:"默认",defaultTag:"默认",setAsDefault:"设为该客户的默认账单主体",firstIsDefaultHint:"该客户的第一个启用中的账单主体一定会成为默认,勾不勾都一样 —— 否则新建单据时没有可带出的默认值。",setDefault:"设为默认",setDefaultTitle:"设为默认账单主体",setDefaultConsequenceThis:"此后该客户的请款单批准开票时,发票抬头与账期取「{name}」",setDefaultConsequenceOther:"取消当前那一个的默认标记",setDefaultConsequenceExisting:"已经开出的单据不受影响,它们仍挂着开票时的那个账单主体",archiveConsequenceHidden:"把「{name}」从选择列表里拿掉,新单据不能再开给它",archiveConsequenceExisting:"已有引用照旧有效,已经开给它的单据不受影响",restoreConsequenceSelectable:"「{name}」重新出现在新建单据的选择列表里",restoreConsequenceNotDefault:"不会自动夺回默认位 —— 停用期间可能已经有别的顶上,悄悄把发票抬头换回来没有人会察觉",setDefaultDone:"默认账单主体已更新",archive:"停用",archiveTitle:"停用账单主体",archiveLosesDefault:"它当前是默认账单主体 —— 停用会同时让出默认位。在你另设一个之前,该客户没有默认账单主体,名下的请款单批准不了(开不出发票)。",archived:"已停用",restore:"恢复",restored:"已恢复",restoreTitle:"恢复账单主体",archivedReadonly:"已停用的账单主体是只读的,需先恢复才能编辑。",notNullHint:"币种、账期、税率三个字段永远有值,它们没有「未设置」这个状态。想改回默认就填 SGD / 30 天 / 9%。",notWiredHint:"发票签发时取这里的默认账单主体,把抬头与账期复制到发票上;没有默认时请款单批准不了。报价 / 合同还不能选账单主体(BESDEV-52)。",noPermission:"你没有查看账单主体的权限"},companyContact:{title_:"职位",editContact:"编辑联系人",deleteContact:"删除联系人",contactType:"类型",title:"联系人",subtitle:"这个组织找谁对接 —— 与账单主体上的账单联系人是两回事",create:"新增联系人",createTitle:"新增联系人",editTitle:"编辑联系人",empty:"还没有联系人",name:"姓名",firstName:"名",lastName:"姓",firstNameRequired:"请填写名",lastNameRequired:"请填写姓",emailRequired:"请填写邮箱",jobTitle:"职务",email:"邮箱",emailInvalid:"请填写正确的邮箱地址",phone:"电话",primaryTag:"主联系人",setAsPrimary:"设为主联系人",firstIsPrimaryHint:"该客户的第一个联系人无论是否勾选都会成为主联系人。",noPrimaryHint:"该客户当前没有主联系人,请指定一位,让人知道优先找谁。",setPrimary:"设为主联系人",setPrimaryTitle:"设为主联系人",setPrimaryConsequenceThis:"让「{name}」成为该客户优先联系的人",setPrimaryConsequenceOther:"清掉当前那位的主联系人标记",setPrimaryDone:"主联系人已更新",deleteTitle:"删除联系人",deleteConsequenceRemoved:"把「{name}」从该客户的联系人里移除",primaryCannotDelete:"主联系人不能删除,请先把其他联系人设为主联系人。",deleted:"联系人已删除",archivedReadonly:"该客户已归档,联系人只读。要修改请先恢复客户。"},meetingNote:{create:"添加会议记录",createTitle:"添加会议记录",editTitle:"编辑会议记录",titleLabel:"标题",titlePlaceholder:"如:Q3 AIVA 上线讨论",titleRequired:"请填写标题",content:"内容",contentPlaceholder:"讨论了什么、定了什么、后续要跟进什么",contentRequired:"请填写内容",attendees:"参与人",attendeesHint:"— 这家客户的联系人,至多 20 位",attendeesPlaceholder:"选择联系人",nameSep:"、",attendeesLine:"参与人:{names}",edit:"编辑会议记录",delete:"删除会议记录",deleteTitle:"删除会议记录",deleteConsequence:"会从这家客户删除会议记录「{title}」,动态里只保留它的标题",deleted:"会议记录已删除",goneHint:"这条会议记录已删除。",goneHintNamed:"会议记录「{title}」已删除。",snapshotHint:"取不到当前版本,下面是首次保存时的内容。"},inventory:{pageSubtitle:"BES 自有硬件的库存、采购与收货。(不是客户工地的物料库存。)",newPo:"新建采购单",howItWorksLabel:"怎么用:",howItWorks:"{label}硬件型号(目录与价格)在 {link} 里定义一次。这里管理这些型号的库存——采购(PO)、收货、出库到现场。要一个还没有的型号?在新建采购单里点「目录里没有这个型号?」——它会顺带建好产品目录,不用做两遍。",howItWorksLink:"产品 → 硬件",kpiInStock:"在库",kpiInStockSub:"分布在 {n} 个型号",kpiOnOrder:"待到货",kpiOnOrderSub:"{n} 张未完结采购单",kpiAllocated:"已预留",kpiAllocatedSub:"已为项目预留",kpiInstalled:"已安装",kpiInstalledSub:"已在现场",kpiLow:"库存偏低",kpiLowSub:"低于安全库存",kpiOutSub:"{n} 个缺货",lifecycleLabel:"库存流程:",lifecycle:{purchase:"采购(PO)",receive:"收货(GRN)",store:"入库(在库)",dispatch:"出库(到现场)",install:"安装(在项目上)"},tabStock:"库存",tabOrders:"采购单",searchStock:"搜索型号、SKU 或供应商",colProductVariant:"型号 / 变体",colInStock:"在库",colAllocated:"已预留",colOnOrder:"待到货",variantsN:"{n} 个变体",noVariants:"还没有变体",modelOut:"{n} 个变体缺货",modelLow:"{n} 个变体偏低",lowBelowSafety:"偏低——低于安全库存({n})",expandHint:"展开 →",viewUnits:"查看单件",reorder:"补货",noModels:"还没有硬件型号——先到「产品 → 硬件」里添加",searchPo:"搜索采购单号或供应商",colPoNo:"采购单号",colSupplier:"供应商",colItems:"明细",colEta:"预计到货",receivedOf:"已收 {received} / {total}",receive:"收货",receiveNeedsTransit:"先把采购单标记为在途才能收货",done:"已完成",markInTransit:"标记在途",editPo:"编辑采购单",cancelPo:"取消采购单",noPos:"还没有采购单",shipTitle:"标记为在途",shipConsequenceReceive:"会把 {no} 标记为供应商已发货,之后才能按它收货",shipConsequenceLocked:"会锁定明细——在途的采购单不能再编辑",shipped:"已标记为在途",cancelTitle:"取消采购单",cancelConsequenceOnOrder:"会取消 {no},它的 {n} 件不再计入待到货",cancelConsequenceFinal:"会以「已取消」留在列表里,不能恢复",cancelled:"采购单已取消",poCreateTitle:"新建采购单",poCreateSub:"向供应商采购硬件",poEditTitle:"编辑采购单 {no}",poLines:"明细",poAddLine:"添加一行",poVariantPlaceholder:"硬件型号 / 变体",poVariantRequired:"请选择变体",poQty:"数量",poQtyInvalid:"请填不小于 1 的整数",poUnitCost:"单价(新加坡元)",poUnitCostInvalid:"不小于 0,最多两位小数",poLinesHint:"一张采购单对一个供应商;同一变体只能出现一次;单价选填。",poSupplierRequired:"请填写供应商",poExpectedDate:"预计到货",poLinkTo:"关联(选填)",poLinkNone:"补库存(不关联项目)",poLinkContract:"合同",poLinkQuotation:"报价",poLinkHint:"关联合同表示这次采购对应一笔客户订单。关联只作记录,不会预留库存;关联了合同,收货时可以选到货直发,不进仓直接记到那份合同的项目上。",poLinkPick:"请选择要关联的合同或报价,或改选补库存",poNote:"备注",poCreate:"创建采购单",poCreated:"已创建采购单 {no}",poDetailTitle:"采购单 {no}",poDetailTitleBare:"采购单",poCreatedAt:"创建时间",poReceivedTotal:"已收",poReceived:"已收",poReceipts:"收货记录",poNoReceipts:"还没有收货",receiveTitle:"收货(GRN)",receiveOrdered:"订购",receiveOutstanding:"未收",receiveNow:"本次收到",receiveQtyInvalid:"请填 0 到 {n} 的整数",receiveSerials:"序列号",receiveSerialsHint:"— 选填,一行一个",receiveSerialsPlaceholder:"不填也可以,之后在「查看单件」里补",receiveSerialsCount:"请填 {n} 个序列号,或者留空",receiveSerialsDup:"序列号不能重复",warehouse:"仓库",warehouseRequired:"请选择仓库",bin:"库位",binPlaceholder:"如 A-03",qualityCheck:"质检",qcQuantity:"数量与采购单一致",qcDamage:"外观无损",qcSerials:"已登记序列号",qcNone:"未勾选质检项",listSep:"、",receiveHint:"收货后,{n} 件进入在库,每行记一条入库流水。",receiveConfirm:"确认收货",received:"已收货 {n} 件",unitsTitle:"{model} · {variant} —— 单件",unitsSub:"序列号属于这个变体(SKU {sku})",unitsLifecycleLabel:"单件流程:",unitsLifecycle:{onOrder:"待到货",received:"已收货",inStock:"在库",dispatched:"已出库",onSite:"现场待装",installed:"已安装"},searchSerial:"搜索序列号",colSerial:"序列号",colLocation:"位置",colUpdated:"更新于",noSerial:"还没有序列号",noUnits:"这个变体还没有单件",locationRestricted:"不在你数据范围内的项目",unitFromPo:"由 {no} 收货",unitFromInitial:"初始库存",unitNoMovements:"还没有流水",unitEditTitle:"编辑单件",unitNote:"备注",unitInstalledAt:"{time} 安装",dispatchToSite:"出库到现场",tabAllocation:"需求与预留",tabDispatch:"出库",tabDeployment:"已部署",colModel:"型号",colQty:"数量",colProject:"项目",colContract:"合同",colDate:"日期",colClaim:"请款单",customer:"客户",allocationHint:"各合同要在项目上装的硬件:合同激活时自动建,下面是每条装到哪了。",colAllocatedTo:"装到",allocInstalledOf:"已装 {installed} / {total}",nInTransit:"在途 {n}",nOnSite:"现场待装 {n}",allocShortage:"缺 {n} 件——预留或补货",allocBlocked:"未开始",allocBlockedTip:"实施单的硬件安装步骤还没开始,暂时不能出库",dispatch:"出库",release:"客户不装",noAllocations:"还没有要装的硬件——含目录硬件的合同激活时会自动建",releaseTitle:"客户不装",releaseQty:"客户不装的件数",allocContracted:"合同数量",allocInstalled:"已验收",allocOverInstalled:"超出合同",allocReleased:"客户不装",allocRemaining:"还要装",allocDispatched:"在途",allocOnSite:"现场待装",allocReserved:"项目预留",allocShortageLabel:"缺货",allocReturned:"现场退回",releaseReason:"原因",releaseReasonPlaceholder:"例如变更单减了数量",releaseHint:"这些件数从「还要装」里扣掉,不再请款。项目的预留不会自动减,需要的话在下面的预留里改。",releaseQtyMax:"最多 {n} 件——还要装的件数",released:"已记为客户不装 {n} 件",allocDetailTitle:"需求",allocOnboarding:"实施单",fromAmendment:"来源变更单",allocUnits:"单件",allocNoUnits:"还没有出库的单件",allocDispatches:"出库单",allocOverInstallations:"超装记录",reservationsTitle:"预留",reservationsHint:"给项目在仓库里留着的件数。只记数量,出库时才挑具体的件。",addReservation:"新增预留",colReserved:"预留数",colOpenRemaining:"项目上还要装",reservationStale:"项目上已没有要装的——可以考虑清掉",changeReservation:"修改",clearReservation:"清掉预留",noReservations:"还没有预留",clearReservationTitle:"清掉预留",clearReservationConsequenceQty:"会把 {project} 对 {sku} 的预留从 {n} 改成 0",clearReservationConsequenceStock:"会让这 {n} 件重新可供其他项目使用",reservationCleared:"预留已清掉",addReservationTitle:"新增预留",changeReservationTitle:"修改预留",reservationDialogSub:"给项目在仓库里留几件",nAvailable:"可用 {n}",reserveQty:"预留件数",availableInStock:"可用在库",reservationReason:"原因",reservationProjectRequired:"请选择项目",reserveQtyInvalidZero:"填 0 或正整数",addReservationHint:"填的是给这个项目留的总数;这个项目对这个变体已经有预留的,会改成这个数。只能从可用在库里加。",changeReservationHint:"现在预留 {n} 件。填改成的总数,填 0 就是清掉。只能从可用在库里加。",reservationSaved:"预留已改为 {n} 件",locEnRoute:"在途 · {project}",locOnSite:"现场待装 · {project}",dispatchHint:"出往现场安装的批次——实施单的{step}进行中时为一条需求出库,装完后逐件结算。",dispatchHintStep:"硬件安装步骤",searchDispatch:"搜索出库单号",colDispatchNo:"出库单号",colDestination:"去向",markInstalled:"结算",markDelivered:"标记已到场",cancelDispatch:"取消出库",delivered:"已标记为到场",cancelDispatchTitle:"取消出库",cancelDispatchConsequenceUnits:"会把 {no} 从仓库出的 {n} 件退回在库",cancelDispatchConsequenceReservation:"会把它用掉的 {n} 件项目预留加回去",cancelDispatchConsequenceOnSite:"会让从现场带上的 {n} 件回到现场待装",cancelDispatchConsequenceFinal:"会让 {no} 以「已取消」留在列表里,不能恢复",dispatchCancelled:"出库已取消",noDispatches:"还没有出库单",nBroughtFromSite:"其中 {n} 件从现场带上",nInstalled:"装好 {n}",nFaulty:"坏件 {n}",nSurplus:"冗余 {n}",settledOf:"{parts}(共 {total})",confirmTitle:"结算出库单",confirmOnDispatch:"本单件数",confirmUnitsLabel:"每一件的结果",confirmSetAll:"全部设为",broughtFromSite:"从现场带上",colOutcome:"结果",confirmCountsLabel:"{total} 件各有几件(这些件没有序列号)",confirmCountsInvalid:"填 0 或正整数",confirmCountsSum:"四个数加起来要等于 {total}(现在是 {sum})",faultyReason:"故障",faultyReasonPlaceholder:"例如到货时镜头已裂",faultyReasonRequired:"请写明故障——会作为退回单的原因",overInstallTitle:"超出合同 {n} 件",overInstallTitleBare:"超出合同的件",overInstallBody:"装好的件数比这条需求还要装的多。确认后会建一条超装记录,并按合同单价另出一张请款单草稿,不在付款计划里。这张出库单签好的 DO 就是客户的验收单。",overInstallConfirm:"客户已同意多装的件",overInstallNote:"说明",overInstallNotePlaceholder:"为什么多装,例如客户在现场加了两个出入口",overInstallConfirmRequired:"请确认超装,或改每件的结果",overInstallNoteRequired:"请写明超装的原因",otherAllocationTitle:"同一实施单上,合同 {contract} 的这个变体还要装 {n} 件",otherAllocationBody:"装好的件数比这条需求还要装的 {r} 件多。先在这里装满,多出的记为现场待装;再从合同 {contract} 那条需求出库,把它们带过去结算。那边也装满之后还多出来的,才算超出合同。",otherAllocationFix:"多出的改为现场待装",tabReturns:"退回 / RMA",returnsHint:"从现场拿回、在维修、或按保修退给供应商的件。重新入库的件回到在库。",searchReturns:"搜索退回单号或序列号",colRmaNo:"退回单号",colFrom:"来源",colReason:"原因",noReturns:"还没有退回单",returnTitle:"退回单 {no}",returnSourceLabel:"来源类型",returnSplitFrom:"拆自",returnNote:"备注",returnCreatedAt:"新建于",returnClosedAt:"结束于",returnUnits:"单件({n})",returnHistory:"流转记录",returnSplitOff:"拆出 {no}",returnSplitOffFrom:"拆自 {no}",actReceive:"收回",actCancel:"取消退回",actRepair:"送修",actSendToSupplier:"退供应商",actRestock:"重新入库",actScrap:"报废",actionUnits:"这次处理哪几件({n} / {total})",actionUnitsRequired:"至少选一件",actionSplitHint:"只选了其中几件:这几件会拆成一张新的退回单再处理,原单留下其余的件,状态不变。",restockWarehouseHint:"不选就留在件现在所在的仓库",actionDone:"{action}完成 · {no}",consequenceReceive:"这几件回到仓库、离开项目。需求的已装数不变,请款与实施步骤都不动。",consequenceCancel:"现场的件照旧在用。这张退回单以「已取消」留在列表里,不能恢复。",consequenceRepair:"这几件转为维修中,仍在原仓。",consequenceSendToSupplier:"这几件退给供应商保修,仓库与库位清空。",consequenceRestock:"这几件回到在库、可以再出库;不回到原来的需求与项目。",consequenceScrap:"这几件报废,之后只读、不能恢复;序列号不再占用。",siteReturn:"现场退回",siteReturnTitle:"现场退回",warehouseReturnTitle:"送检退回",createReturnUnits:"退回哪几件({n} / {total})",createReturnNoUnits:"这个项目上没有能退回的件(已在未结退回单上的不列)",returnReasonPlaceholder:"例如传感器故障、项目结束收回",returnReasonRequired:"请写明退回原因",createReturnHintSite:"建单后件仍装在项目上、显示「待检查」,收回时才回到仓库。不补装,不动请款与实施步骤。",createReturnHintWarehouse:"这几件转为「已退回」等待检验,不再算在库。",createReturn:"建退回单",returnCreated:"已建退回单 {no}",unitsSelected:"已选 {n} 件",unitsReturn:"送检退回",unitsTransfer:"移动",unitsReturnDisabled:"只有在库、且不在未结退回单上的件能送检",unitsTransferDisabled:"选的件要在同一个仓库,且是在库、已退回或维修中",unitOnReturn:"在 {no} 上",transferTitle:"移动单件",transferSub:"{n} 件 · 从 {warehouse}",transferTo:"移到仓库",transferBinSame:"在同一个仓库里移动,要填一个不同的库位",transferHint:"只改位置,状态不变;预留按项目记数量,不受影响。",transferred:"已移动 {n} 件",poQuickToggle:"目录里没有这个型号?",poQuickHint:"快速建一个硬件型号——会同时建好产品目录,不用离开这一页",poQuickName:"型号名称(例如 Turnstile Gate)",poQuickSku:"型号编号(例如 TG-X2)",poQuickSupplier:"供应商",poQuickCost:"进价",poQuickAdd:"建型号并选上",poQuickFull:"完整的产品表单 →",poQuickNameRequired:"请填型号名称",poQuickSkuRequired:"请填型号编号",poQuickAdded:"已建型号 {name}。售价还空着,要在产品页补上才能报价",receiveDirectShip:"到货直发",receiveDirectShipHint:"不进仓,直接记为合同 {contract} 在项目上的现场待装件,下次出库时带上一起结算",receiveHintDirect:"收货后,{n} 件进入在库、{m} 件直发到项目现场待装,每行记一条入库流水,直发的另记一条出库流水。",receiptDirect:"直发",receiveHintAllDirect:"收货后,{m} 件直发到项目现场待装,不进在库;每行记一条入库流水与一条出库流水。",needsCheckQty:"{n} 件在退回单上待收回",printDo:"打印 DO",registerDo:"登记签好的 DO",changeDo:"改登记",signedDo:"签好的 DO",signedDoMissing:"还没登记",signedDoAt:"{time} 登记",doFileName:"文件名",doFileNamePlaceholder:"例如 {no}-signed.pdf",doFileRef:"链接",doFileNameRequired:"请填文件名",doFileRefRequired:"请填 http:// 或 https:// 开头的链接",doHint:"客户签好的 DO 就是这一批的实施验收单。文件服务还没有,先登记文件名与链接;再次登记会覆盖。",doHintOver:"这张出库单有超装记录:登记后超装请款单才能提交;超装请款单提交后就不能再改。",doHintAmendment:"这批来自加设备的变更单:登记后,按变更单单价出的请款单才能提交;那张请款单提交后就不能再改。",doRegistered:"已登记签好的 DO",installedDate:"安装日期",dateDefaultToday:"今天",dispatchNote:"备注",confirmHintInstalled:"{n} 件转为项目上的已安装,并为这一批生成一张请款单草稿。",confirmHintOnSite:"{n} 件留在现场待装——下次出库时带上一起结算。",confirmHintFaulty:"{n} 件坏件回到出库前的仓库,并自动建一张退回单。",confirmHintSurplus:"{n} 件冗余回到在库。",confirmHintNoClaim:"一件都没装好:不生成请款单。",confirmInstall:"确认结算",confirmed:"已结算——装好 {n} 件",confirmedWithClaim:"已结算——装好 {n} 件,已生成请款单 {claim}",dispatchDetailTitle:"出库单 {no}",dispatchDetailTitleBare:"出库单",installedOfQty:"已装 {installed} / {total}",dispatchDate:"出库日期",deliveredAt:"到场时间",reservationUsed:"用掉的项目预留",overInstalledLabel:"超出合同",faultyReturn:"坏件退回单",dispatchUnits:"单件",deploymentHint:"已装好在用的硬件,关联到项目与产品部署。",colAsset:"资产",colProductDeployment:"产品部署",colDeployed:"部署时间",noInstallations:"还没有装好的硬件",dispatchTitle:"出库到现场",dispatchSub:"把单件出往项目安装",dispatchAllocation:"需求(项目 / 实施步骤)",dispatchAllocationPlaceholder:"选择为哪条需求出库",dispatchAllocationRequired:"请选择需求",dispatchNoChoices:"现在没有能出库的需求——实施单的硬件安装步骤开始后,它的需求才能出库。",nRemaining:"还要装 {n} 件",dispatchFromStock:"从仓库出的件数",dispatchOnSite:"随这张单一起结算的现场待装件({n} / {total})",dispatchQtyInvalid:"填 0 或正整数",dispatchNothing:"至少从仓库出一件,或从现场带上一件",dispatchHintBox:"先用这个项目的预留,不够再从可用在库里按收货先后取,单件转为已出库并记一条负数流水。多带几件没关系,结算时多出的按冗余回到在库。",dispatched:"已创建出库单 {no}",oviAcceptanceMissingTitle:"还没有验收单",oviAcceptanceMissingBody:"出库单 {dispatch} 还没登记签好的 DO。登记之前,超装请款单不能提交。",oviOverQty:"超出合同的件数",oviUnitPrice:"合同单价",oviUnitPriceHint:"取报价那一行的单价,不扣整单折扣",oviAmount:"金额",oviAcceptance:"验收单(签好的 DO)",oviConfirmed:"确认时间",oviNote:"说明",colOviNo:"超装记录号"},companyAddress:{siteSectionTitle:"工地地址",siteSectionHint:"— 项目所在地",addSiteLink:"+ 添加工地地址",label:"称呼",labelPlaceholder:"如 Jurong East Industrial",linkedProject:"关联项目",linkedProjectPlaceholder:"—— 不关联 ——",linkedTo:"关联项目",title:"地址",subtitle:"该组织存档的注册地址、账单地址与工地地址",create:"新增地址",createTitle:"新增地址",editTitle:"编辑地址",empty:"还没有地址",addrType:"类型",addrTypeRequired:"请选择类型",line1:"地址第一行",line1Required:"请填写地址第一行",line2:"地址第二行",postal:"邮编",country:"国家/地区",countryRequired:"请选择国家/地区",countryNotNullHint:"地址一定带着国家,没有「未设置」这个状态,缺省是新加坡。",multipleSiteHint:"一个客户可以有多个工地地址(一个工地一条),所以每种类型都不限一条。",deleteTitle:"删除地址",deleteConsequenceRemoved:"把这条{type}地址从组织档案里移除",deleted:"地址已删除",archivedReadonly:"该客户已归档,地址只读。要修改请先恢复客户。",companySection:"公司地址",siteSection:"工地地址 —— 项目所在地",registered:"注册地址",billing:"账单地址",primaryTag:"主地址",add:"添加",addSite:"添加工地地址",registeredEmpty:"还没有注册地址",sameAsRegistered:"同注册地址",billingMirrors:"账单沿用注册地址。要开到别的地址,在这里另加一条。",siteEmpty:"还没有工地地址"},projectLink:{label:"关联项目",none:"— 不选 / 签约时自动新建 —",createNew:"+ 接受报价后新建项目",newOnSign:"签约后新建项目",linkExisting:"挂到已有项目:{name}({code})",newName:"新项目名称",newNamePlaceholder:"例如 TOPAZ HDB Sengkang — 二期",newNamePlaceholderShort:"新项目名称",newNameRequired:"请填写新项目名称",newType:"项目类型",newCountry:"工地国家",newAddress:"工地地址",newAddressPlaceholder:"例如:Block 5 Tampines Street 32, Singapore 528700",notCreatedNow:"现在不建项目 —— 客户签署 / 接受这份报价后自动开通。",noneAvailable:"这个客户没有能再挂合同的项目。只列出准备中与运行中的项目。",noPermission:"你没有查看项目的权限,只能选新建项目。",acceptLabel:"项目关联",acceptHint:"一个项目可以由多份合同共同覆盖(实施合同 + 维保合同)。项目在签约后创建。",consequenceNew:"合同激活时新建项目「{name}」,并为它开实施单",consequenceExisting:"合同激活时作为追加合同挂到所选项目上 —— 只给新产品走供应、不建实施单,并跟项目的主合同一起结束",existingShort:"已有项目",later:"稍后再定",laterPlan:"稍后再定 —— 激活后再挂到项目上",consequenceLater:"合同激活时不挂项目 —— 产品照常开通、不建实施单,之后在项目详情的关联合同里挂上",notVisible:"一个不在你数据范围内的项目",newOnActivation:"激活时新建:{name}"},quotation:{inStockN:"在库 {n}",selectPlaceholder:"按报价编号搜索",termMonthsLabel:"期限(月)",termMonthsPlaceholder:"例如 12",projectLinesTitle:"项目行",projectLinesHint:"这份报价覆盖的项目",plProject:"项目",plDuration:"期限",plSiteAddress:"工地地址",plMonths:"{n} 个月",plTbd:"待定",reviseWarning:"当前版本会归档为「已被取代」,客户要接受新版本才能继续。行项与引用的条款按本版原样复制。",customerOrgHint:"— 签约与开票的主体",serviceEntity:"服务对象",serviceEntityHint:"— 实际接受服务的主体(与签约主体不同时填)",serviceEntityPlaceholder:"与签约主体相同(默认)",serviceEntityNote:"常见于大客户由母公司签约、由子公司或合资方实际使用服务。",serviceEntityNoPermission:"没有查看主体的权限,只能用默认项。",quoteTitle:"报价标题",validityDaysLabel:"有效期(天)",createdAsDraft:"报价建好后是草稿状态。",acceptSubtitle:"客户已确认,这份报价将转成合同。",whatHappensNext:"接下来会:",reviseSubtitle:"将从当前版本生成新版本 {no}",loseButton:"标记丢单",reviseButton:"创建修订版",kpiFollowUp:"待跟进",kpiWinRateLabel:"成交率 {rate}",tabAll:"全部",colQuote:"报价",colValue:"金额",colValidUntil:"有效期至",sendTo:"发送给(选填)",versionPill:"第 {n} 版",awaitingResponse:"等待客户回复",sendToPlaceholder:"customer{'@'}example.com —— 只记在报价上,不会发邮件",metaSentTo:"发送给",acceptedDate:"接受日期",acceptedDatePlaceholder:"不填按今天",acceptedDateHint:"客户接受的那一天,不能早于报价发出的日期,也不能晚于今天。",confirmedBy:"客户侧确认人",confirmedByPlaceholder:"如 PM Lee",confirmedByShort:"确认人 {name}",lossReasonLabel:"丢单原因",lossReasonPlaceholder:"选择原因",lossReasonRequired:"请选择丢单原因",lossDetails:"详情(选填)",lossDetailsPlaceholder:"补充背景,留作以后复盘",revisionReasonLabel:"修订原因",revisionReasonPlaceholder:"选择原因(选填)",revisionNotes:"备注",revisionNotesPlaceholder:"内部备注,会记进审计",revisionAlert:"修订原因:{reason}",notes:"内部备注",notesPlaceholder:"给团队看的背景说明,客户看不到",customerStageHint:"这里只列带「客户」角色、处于线索、已确认、已转换、活跃或休眠阶段的主体。",kpiOpen:"进行中",kpiOpenSub:"潜在金额 {amount}",kpiSent:"已发送 · 待回复",kpiSentSub:"{n} 份回复超期",kpiAccepted:"近 30 天成交",kpiWinRate:"成交率 {rate}",kpiAvgDeal:"平均成交额",kpiAvgDealSub:"近 30 天成交的报价",signed:"已签",pageSubtitle:"跟踪报价从草稿到成交的全过程。",daysLeft:"剩 {n} 天",daysRemaining:"还剩 {n} 天",stepContract:"合同",amountSummary:"金额摘要",discountWithPct:"折扣({pct}%)",gstWithRate:"GST({rate}%)",inclGst:"{currency} · 含 GST",validUntilOn:"有效期至 {date}",contactLoadFailed:"客户的联系人没有加载出来",noPrimaryContact:"这家客户没有设主联系人",viewCompany:"查看客户 →",nextSteps:"后续步骤",nextStep1:"客户在接受链接上接受;或客户回复后,在这里标记为已接受",nextStep2:"自动生成合同草稿",nextStep3:"合同签署后激活",nextStep4:"预建项目,状态为 Setup",daysOverdue:"已过 {n} 天",createTitle:"新建报价",createSubtitle:"报价编号在保存时自动生成",createAndOpen:"创建并打开",editTitle:"编辑报价",create:"新建报价",searchPlaceholder:"编号 / 标题",submitApproval:"提交审批",submitApprovalTitle:"提交这笔折扣审批",submitApprovalConsequenceLocked:"会在等待期间锁住这份报价,行项目与金额在批复之前都改不了",submitApprovalConsequenceCleared:"会清掉这份报价上一轮的批复,之前的驳回意见将不再显示",submitApprovalConsequenceBlocked:"在有人批准之前,这份报价仍然发不出去",approvalSubmitted:"已提交审批",approveDiscount:"批准折扣",approveDiscountTitle:"批准这笔折扣",approveConsequenceSendable:"这份报价此后可以按当前折扣发给客户",approveConsequenceAudited:"会把你记为批准人,连同时间与意见一起留痕",approveNoteLabel:"为什么这笔折扣可以批?(选填)",approveNotePlaceholder:"意见(选填)——例如:已跟 CFO 确认",discountApproved:"折扣已批准",rejectDiscount:"驳回折扣",rejectDiscountTitle:"驳回这笔折扣",rejectConsequenceBlocked:"这份报价将无法按当前折扣发出",rejectConsequenceResubmit:"负责人可以改完金额再次提交——你写的原因就是他修改的依据",rejectNoteLabel:"为什么驳回?负责人要照这句话去改",rejectNotePlaceholder:"原因(必填)——例如:这一单最多给到 8%",discountRejected:"折扣已驳回",editBlockedByApproval:"折扣正在等待审批,此时不能编辑——改了金额,那次批准针对的就是另一份报价了",sendBlockedByApproval:"这笔折扣要先通过审批,这份报价才能发送",approvalNeededAlert:"这笔折扣超过了你的上限,未经审批这份报价发不出去。请先提交审批。",approvalPendingAlert:"这笔折扣正在等待审批。批复之前,这份报价不能编辑、也发不出去。",approvalRequestedAt:"提交于",approvalRejectedAlert:"折扣已被驳回——{reason}",approvalApprovedAlert:"折扣已由 {who} 于 {at} 批准",approvalApprovedAlertNoWho:"折扣已批准",approvalNote:"意见",discountVsLimit:"折扣 {pct}%,你的上限 {limit}%",discountPctOnly:"折扣 {pct}%",quotationNo:"编号",title:"标题",titlePlaceholder:"如 BOSP + Vision · 12 months",titleRequired:"请填写标题",customerRequired:"请选择客户主体",customerOrg:"客户主体",serviceOrg:"服务接收方",serviceOrgPlaceholder:"留空 = 同结算主体",sameAsBilling:"同结算主体",currency:"币种",validityDays:"有效天数",validUntil:"有效期至",metaCreated:"创建",metaValidity:"有效期",metaValidityDays:"{n} 天",metaSent:"发送",metaAccepted:"成交",discountAmount:"折扣金额",gstRate:"GST 税率",termsTemplate:"条款模板",termsTemplateLegacy:"旧的自由文本字段,为老报价保留只读显示。商务条款现在通过下面的「商务条款」面板引用。",termsTemplatePlaceholder:"如 GL0001(自由文本)",revision:"版本",sentAt:"发送时间",acceptedAt:"成交时间",lossReason:"丢单原因:{reason}",lines:"行项",lineNo:"行号",lineType:"类型",product:"产品",licence:"Licence",label:"名称",labelPlaceholder:"行项名称",lineDescriptionPlaceholder:"说明(选填)",customHardware:"自定义硬件",noSellableVariant:"没有可售的硬件变体",singleVariant:"只有一个变体",variantNotInCatalog:"已不在目录里",catalogPriceSgdOnly:"目录价按新加坡元记,请按本报价的币种填单价。",catalogPrice:"目录价 {price}",qty:"数量",qtyUnit:"单位",unitPrice:"单价",periodType:"计费",subtotal:"小计",required:"必选",addSoftware:"+ 软件行",addHardware:"+ 硬件行",addService:"+ 服务行",noLines:"还没有行项,发送报价前至少需要 1 行",noSellableProduct:"没有可售产品——请检查产品目录(已停售的产品不能用于新签)",softwareProductAlert:"软件行必须选产品,否则合同不会铺授权产品、激活后不产生供应流水线。下拉里只列还能新签的产品;licence 由后端固定为 ENTERPRISE。",amountSubtotal:"小计",amountDiscount:"折扣",amountGst:"GST",amountTotal:"合计",previewNote:"(预览值,最终以服务端计算为准)",perOccurrenceSubtotal:"按次结算",period:"期限",perMonthSuffix:"/月",perMonthHint:"按月计价",lineMonthsPlaceholder:"月数",lineMonthsDefault:"{n}(默认)",lineMonthsRequired:"填月数或上方的期限",lineMonthsMismatch:"同一产品的按期收费行月数必须相同",perOccurrenceNote:"按次的服务按实际发生的次数结算,不计入上面的合计。",perOccurrenceUnitRequired:"请填每次的单位(如 visit)",send:"发送",accept:"接受成交",reject:"标记丢单",revise:"创建修订版",sent:"已发送",sendNeedsLines:"发送前至少需要 1 个行项",sendNeedsTerm:"发送前请先填期限(月):它决定金额,合同上不能再改",acceptNeedsTerm:"这份报价没有期限(月),请先修订、填上期限再接受",sendNeedsHardwareTerm:"发送前请给每个硬件行填上期限(月)",acceptNeedsHardwareTerm:"有硬件行没有期限(月),请先修订报价、填上再接受",hardwareTermLine:"期限:{n} 个月",hardwareTermMissing:"期限:未填",hardwareTermPlaceholder:"期限(月)",hardwareTermInvalid:"1~120",hardwareTermMismatch:"同一型号的硬件行(以及所有自定义硬件行)期限要相同",sendTitle:"发送报价",sendConsequenceStatus:"把报价转为「已发送」,并记下发送时间",sendConsequenceValidUntil:"按本报价的有效期把到期日设为今天起 {n} 天后",sendConsequenceLocked:"此后行项目与条款不能再直接编辑 —— 要改只能起修订版,原版会转为「已被取代」",sendConsequenceNoEmail:"⚠ 不会给客户发任何邮件 —— 系统只记录「已发送」这件事,报价文件仍需你自己发给客户。",softwareNeedsProduct:"软件行必须选择产品,否则合同不会铺授权产品、也不会产生供应流水线",softwareNeedsProductShort:"软件行必须选择产品",lineLabelRequired:"行项的名称不能为空",lineUnitPriceNegative:"单价不能为负",discountTooLarge:"折扣金额不得大于行项小计",acceptTitle:"接受成交",acceptButton:"确认成交",acceptConsequenceContract:"按这份报价生成一份草稿合同 —— 客户要签的就是它",acceptConsequenceLocked:"锁定这份报价:价格与明细行不能再改",acceptConsequenceFinal:"让这一版成为最终版本 —— 已接受的报价不能再修订",rejectConsequenceStatus:"把这份报价标记为「已拒绝」,它不再是一个有效报价",rejectConsequenceRevise:"客户回心转意时仍可以把它修订成新版本,这条路不会被堵死",reviseConsequenceNew:"生成这份报价的新版本,明细行与引用的条款整份复制过去——条款沿用这一版上的原文,不会自动换成条款库里的新版",reviseConsequenceSuperseded:"把当前版本标记为「已被取代」:仍可查看,但不能再发送或接受",deleteConsequenceGone:"永久删除报价 {no} 及其所有修订版,明细行一起删",acceptedUndeletable:"已成交的报价不能删除。",supersededUndeletable:"这一版已被修订版取代,请从最新一版删除整张报价。",duplicate:"复制",duplicateTitle:"复制报价",duplicateSubtitle:"会新建一张草稿,带上下面勾选的内容",duplicateSource:"来源报价",duplicateTarget:"目标客户",duplicateKeepCustomer:"— 保持原客户 —",duplicateCopyLines:"复制行项",duplicateCopyTerms:"复制条款",duplicateCopyNotes:"复制内部备注",duplicateSubmit:"复制并打开",duplicated:"已复制为 {no}",deleteConsequenceAudit:"保留它的动态记录,审计日志里照样查得到",accepted:"已成交,正在生成合同…",contractReady:"合同 {no} 已生成",contractPending:"合同仍在生成中,请稍后在合同列表查看",contractNoPermission:"合同会由系统自动生成;你没有查看合同的权限,所以这里不跳转、也不显示合同链接。",acceptedAlert:"报价已成交,合同由系统自动创建。",viewContract:"查看合同",contractCreating:"合同生成中,可稍后在合同列表按客户查看。",rejectTitle:"标记丢单",rejectPrompt:"请填写丢单原因(必填)",rejectPlaceholder:"如 Price too high",rejected:"已标记丢单",reviseTitle:"创建修订版",revised:"已创建修订版 {no}",deleteTitle:"删除报价"},claimFiles:{title:"支撑文件",empty:"还没有支撑文件",full:"每张请款单最多 {n} 份支撑文件",uploadTitle:"上传支撑文件",docType:"文件类型",uploaded:"已上传",deleted:"已删除",deleteTitle:"删除这份支撑文件?",deleteConsequenceGone:"「{name}」从这张请款单上移除,不能再查看或下载",deleteConsequenceAudit:"删除会记进请款单的操作历史"},claimVo:{title:"发起变更单",sub:"请款审核时发现范围或数量变化",note:"变更单(VO)会在合同上建一张变更单(可能还会生成小报价)。生效后调整额回到这张请款单——在本页的变更单列表里点「带入」。",reason:"变更原因",reasonPlaceholder:"例如:现场追加 4 台合同范围外的摄像头",reasonRequired:"请填写变更原因",amount:"金额变化({currency})",amountPlaceholder:"例如 11,200",amountPositive:"请填大于 0 的金额,减范围请在类型里选「减范围」",direction:"类型",additive:"加范围",deductive:"减范围",submit:"建立变更单 → 合同变更",raised:"已建立变更单 {no}",listTitle:"变更单",colAmendment:"变更单",colDelta:"金额变化",colApply:"调整额",apply:"带入本请款单",applied:"已为 {no} 加入一行调整额",appliedOn:"{date} 已带入",waitActive:"变更单生效后才能带入",waitEditable:"先把请款单退回草稿再带入",noPermission:"需要编辑请款单的权限"},miniQuote:{acceptButton:"确认接受",nextStep1:"客户在接受链接上接受;或客户回复后,在这里标记为已接受",nextStep2:"回到合同,给变更单 {no} 发起签署",nextStep3:"双方签署后登记签署",acceptTitle:"接受小报价",acceptSubtitle:"客户已确认。接受后变更单 {no} 可以发起签署。",amends:"变更单 {no} ·",noProject:"无:小报价不生成合同,也不涉及项目",acceptedAlert:"小报价已接受。现在可以在合同上给变更单 {no} 发起签署。",acceptConsequence:"不会生成合同;接受后变更单 {no} 可以发起签署"},renewal:{title:"合同续约",subtitle:"按当前合同条款生成一份续约报价",sourceContract:"来源合同",term:"续约期限",termDefault:"{n} 个月(默认)",termMonths:"{n} 个月",priceUplift:"价格调整",termRequired:"请选择续约期限",priceUpliftRequired:"请选择价格调整",customPercent:"自定义调整(%)",customPercentPlaceholder:"如 7.5,下调写 -3",customPercentHint:"作用于按期收费的行项单价。5 表示上调 5%,负数表示下调。",customPercentRequired:"请填写调整比例",customPercentDecimals:"最多两位小数",carryOver:"把当前所有变更单带入续约",carryOverHint:"已生效的变更单逐条写进续约报价的内部备注,不改行项与金额。",submit:"生成续约报价",created:"已生成续约报价 {no}",menu:"续约",menuNoteExpired:"合同已结束,续约后可继续服务。",alreadyRenewed:"已由 {no} 续约。要再续,请从那份合同发起。",terminationBlocked:"续约接替期间不能终止:续约合同已激活,本合同还没到期。原合同到期后,两份合同都可以终止。",renews:"续约自",renewedBy:"已续约为",headButton:"续约报价",opportunityTitle:"续约机会",opportunityBody:"{customer} 还有 {n} 份生效中的合同。建议在合同到期前提出续约。",opportunityBodyNone:"建议在合同到期前提出续约。",opportunityCta:"生成续约报价 →",opportunityNotRenewable:"这份合同{status},只有即将到期或已到期的合同能续约。",projectFixed:"续约——沿用 {no} 的项目",projectFixedHint:"续约的项目关联由系统按原合同定,不能改。",activateTakeOver:"接替 {no} 成为项目的主合同——租户、项目与实例都沿用,不开新的实施单(那个项目已在收尾或已归档的,改为新建项目)",activatePush:"按授权产品建权益(待供应),并逐条向 Control 推一段新的授权期;原合同到期时权益转为已开通、实例改挂过来",activateHandover:"取消原合同上还没走完的交接(如果有)",activateNoTerminate:"原合同到期之前,两份合同都不能终止",acceptConsequence:"生成的合同续约 {no}:激活后接替它成为项目的主合同,租户、项目与实例都沿用"},amendment:{fromClaim:"发起自请款单",linkedArtifacts:"关联单据",miniQuotation:"小报价 {no}",generateMiniQuotation:"生成小报价",miniQuotationCreated:"已生成小报价 {no},请修改后发给客户",waitingQuoteHint:"小报价 {no} 还没被接受。先发给客户并登记接受,再发起签署。",createTitle:"新建变更单",createButton:"新建变更单",createMenu:"新建变更单",createSubList:"合同 {no}",createSubDetail:"变更需要双方重新签署",type:"变更类型",typeOption:{list:{SCOPE_ADDITION:"增加范围(更多站点 / 用户 / 摄像头)",SCOPE_REDUCTION:"缩减范围",PRICE_ADJUSTMENT:"调价",TERM_EXTENSION:"延期",VO_DRIVEN:"源自 VO(现场变更单)"},detail:{SCOPE_ADDITION:"增加范围(加产品 / 项目)",PRICE_ADJUSTMENT:"调价",TERM_EXTENSION:"延期",CONTACT_BILLING_CHANGE:"联系人 / 账单变更",OTHER:"其他"}},sourceVo:"来源 VO(仅源自 VO 时填)",sourceVoPlaceholder:"如 VO-2026-007",changeDescription:"变更说明",descriptionOfChange:"变更说明",descriptionPlaceholder:"改了什么、为什么改",costDelta:"金额变化",costDeltaPlaceholder:"如 36000 或 -5000({currency})",effectiveFrom:"生效日",effectiveDate:"生效日",typeRequired:"请选择变更类型",descriptionRequired:"请填写变更说明",effectiveDateRequired:"请选择生效日",costDeltaDecimals:"最多两位小数",costDeltaTooLarge:"金额太大",createNoteList:"将新建一张 AMD-YYYY-NNN 草稿。",createNoteDetail:"变更单是挂在 {no} 下的子文件。双方签署变更单之前,原合同照旧有效。",created:"已新建 {no}(草稿)",cardTitle:"变更单",cardSub:"增加范围、调价、延期",empty:"还没有变更单",cardFoot:"VO(现场变更单)与变更单是同一个对象——变更源于现场变更申请时,类型选「源自 VO」。",contractRef:"合同 {no}",createdBy:"创建人",voTitle:"来源 VO(现场变更单)",voBody:"源于现场的变更——这张变更单由现场提出的 VO 引起。",voBodyClaim:"审核请款时提出:审请款时发现的范围或数量变化。",voRef:"来源 VO:",sentAt:"{time} 发起签署",signedOn:"{date} 签署",sendForSignature:"发起签署",sendTitle:"发起 {no} 的签署",sendConsequenceStatus:"把变更单转为待签署,等双方签字",sendConsequenceNoMail:"不会发邮件——签字由你自己去收,收齐后用「登记已签署」记下",sendConsequenceNoChange:"合同本身不变",sent:"已发起签署",markSigned:"登记已签署",markSignedTitle:"登记变更单已签署",markSignedHint:"记下双方已签署这张变更单。它会转为已生效;不会改动合同的金额、期限或产品。",signedDate:"签署日",signedDatePlaceholder:"不填则为今天",signed:"已登记签署,变更单已生效",hwTitle:"加设备",hwSub:"在主合同 {no} 上建一份变更单",hwLines:"加哪些硬件",hwQty:"件数",hwUnitPrice:"单价({currency})",hwLinesRequired:"至少加一行硬件",hwTotal:"合计 {amount},就是这份变更单的金额变化",hwTermMonths:"期限(月)",hwTermMonthsInvalid:"1~120 个月",hwTermDate:"生效日",hwTermDateRequired:"请选择日期",hwModeRequired:"请选择",hwStepUnavailable:"硬件的流程模板没有「开始合同期限」的步骤,不能选「按实施流程标记点生效」。",hwNote:"下一步在合同详情:要客户确认价钱的,先生成小报价(金额为 0 时不能生成),客户接受后再发起签署;也可以直接发起签署。登记双方签署后稍后建需求:有小报价的按客户接受的那份里的目录硬件行,没有的按这里的硬件行。之后照常出库、结算,每批按单价出请款单,那张出库单登记了签好的 DO 才能提交。",hwTypeHint:"只有「增加范围」与「源自 VO」能加设备",hwGoContract:"去合同详情",hwCreatedGo:"已新建 {no}(草稿),到合同详情生成小报价、发起签署",addHardware:"加设备",addHardwareClosing:"项目在收尾期或已归档,不能再加设备",addHardwareNoPrimary:"项目还没有主合同",addHardwareContractInactive:"主合同 {no} 不是生效中或即将到期,不能建变更单",hwSection:"硬件行",hwSectionCount:"{lines} 行 · 共 {qty} 件",hwSectionNote:"有小报价的,生效时以客户接受的那份为准,这里不回写;小报价里另加的服务行、目录外的自定义硬件不建需求,由财务手工建请款单。",hwAllocations:"建出的需求",hwSubtotal:"小计",hwAllocationsPending:"还没有查到需求:生效后稍后才建,过一会儿重新打开再看;客户接受的小报价里没有目录硬件行时不会建。",markSignedHintHardware:"记下双方已签署这张变更单。它会转为已生效,稍后建需求(有小报价的按客户接受的那份,没有的按硬件行),项目里这个型号没有进行中的硬件实施单时会新建一份;合同的金额、期限与产品不变。"},contract:{partyHintBilling:"主体 · 签约",partyHintRecipient:"执行项目",partyHintRecipientSub:"子公司 · 执行项目",partyHintBes:"卖方 · 服务提供方",viewAll:"查看全部 →",viewCompanyProfile:"查看组织资料 →",kpiRenewalBadge:"待续约",colContract:"合同",colValue:"金额",colExpires:"到期",tabExpiring:"即将到期",linkPrimary:"主合同",allowedProjects:"授权项目",linkAddOn:"追加合同",planLinkExisting:"合同激活时挂到这个项目上",planNewProject:"新项目,合同激活时创建",planLater:"稍后再定 —— 还没挂到项目上",planLaterNote:"合同激活后,在项目详情的关联合同里挂上",pageSubtitle:"所有客户承诺的唯一依据。合同是开通供应的授权。",noCreateLead:"报价被接受后,系统自动生成草稿合同。",menuNoteDraft:"草稿合同在会签之前能做的操作有限。",menuNotePending:"等待客户签署。",menuNoteExpired:"合同已结束。",noCreateAlert:"{lead}合同不能手工新建,这样每份合同都能追溯到销售过程。要开始新的销售,请到{quotations}。",searchPlaceholder:"合同编号",selectPlaceholder:"按合同编号搜索",oneProject:"1 个项目",metaFromQuotation:"来源报价",metaSigned:"签署",metaEffective:"期限",termsCard:"期限与生效",termsCardSub:"每个产品与硬件各从自己的生效日起算期限",termsEmpty:"没有自带期限的产品或硬件,合同签约即生效。",termsEmptyActive:"没有自带期限的产品或硬件,合同已在签约时生效。",termModesEdit:"设定生效方式",termCustomHardware:"自定义硬件",termFromAmendment:"来自 {no}",termModeLine:"生效方式:{mode}",termModeDateLine:"生效方式:{mode}({date})",termSourceLine:"生效日来源:{source}",termStepGone:"匹配到的流程模板已没有「开始合同期限」的步骤,送签前请改选别的生效方式。",termStepUnavailable:"匹配到的流程模板没有「开始合同期限」的步骤",termSetDate:"设定生效日",termChangeDate:"修改生效日",termModesTitle:"生效方式",termModesHint:"给每一项选期限从什么时候开始。合同送签后锁定,不能再改。",termColItem:"项目",termColMode:"生效方式",termColDate:"日期",termModesDateRequired:"请选择「{name}」的生效日",termModesModeRequired:"请选择「{name}」的生效方式",termModesSaved:"生效方式已保存",termDateTitleSet:"设定生效日:{name}",termDateTitleChange:"修改生效日:{name}",termDateCurrent:"现在:{line}",termDateLabel:"生效日",termDateHint:"签约日({date})到今天之间。期限从这一天起算 {n} 个月。",termDateRequired:"请选择生效日",termDateReason:"原因",termDateReasonPlaceholder:"为什么设定或修改生效日,会写进审计记录",termDateReasonRequired:"请填写原因",termDateSoftwareNote:"改晚会把客户在 Control 的使用期接到新的期限结束;改早暂时缩不短已经给出的使用期,对账会提示期间不一致。",termDateSaved:"生效日已保存",metaCreated:"创建",viewProvisioning:"查看供应",counterParties:"签约方",counterPartiesSub:"谁签约、谁接受服务——涉及集团内多个主体时要分清",filterTerm:"使用条款 {code}",kpiActive:"生效中",kpiActiveSub:"合计 {amount}",kpiExpiring:"90 天内到期",kpiExpiringSub:"{amount} 待续约",kpiPending:"待签署",kpiPendingSub:"客户待签 {n}",kpiAvg:"平均期限",kpiAvgValue:"{n} 个月",kpiAvgSub:"最常见 {n} 个月",tabAll:"全部",tabPendingSig:"待签署",projectsUnder:"这份合同下的项目",viewAllProjects:"查看全部 {n} 个 →",colProject:"项目",colProducts:"产品",colPeriod:"周期",noProjects:"这份合同下还没有项目。",partyRelationOf:"{parent} 的{relation}",partyDescBilling:"法定签署方 · 发票开给这一方",partyDescRecipient:"在项目现场作业 · 接收开通与培训",partyAccountOwner:"客户负责人:{name}",terminateNotesLine:"内部备注:{notes}",signedBy:"{name} 已签署 · {date}",authScope:"授权范围",authScopeSub:"本合同授权的产品与项目",allowedProducts:"授权产品",contractValue:"合同金额",customer:"客户",notYetActive:"尚未生效",awaitingSignature:"等待签署",contractNo:"编号",termMonths:"期限",billingCycle:"账期",billingCyclePlaceholder:"如 Quarterly",nextInvoiceDate:"下次开票",editTitle:"编辑合同",termMonthsLabel:"期限(月)",amountFixed:"金额承袭报价,不可在合同上修改。",amountFixedShort:"金额承袭报价,不可修改",notSigned:"未签署",noProducts:"无授权产品 —— 报价行都没填 productId,激活后不会产生供应流水线",tenant:"租户",tenantOutOfScope:"该合同的租户不在你的数据范围内",project:"项目",sendForSignature:"发起签署",activate:"激活",terminate:"终止",termRequiredAlert:"这份草稿生成于改成月单价之前,没有期限(月)。发起签署前请先补填一次。",termLockedHint:"照报价抄,决定金额;要改请修订报价。",termFillOnceHint:"可以补填一次,填后不能再改,也不改变金额。",termRequired:"请先编辑合同补填期限(月)",sentForSignature:"已发起签署",sendTitle:"发起签署",sendConsequenceLocked:"合同转为待客户签署,之后不能再编辑",sendConsequenceTerms:"绑定的条款就此冻结 —— 只有草稿状态才能改条款",activateTitle:"激活合同",activateButton:"确认激活",activateConsequenceProvision:"为合同上每条产品权益拉起供应流水线 —— 租户与部署实例是真的会被建出来",activateConsequenceOnboarding:"为每个产品各开一份实施单(每个硬件型号各一份):进场施工、培训、交接,通常 6–10 周",activateConsequenceReserve:"会把合同里的目录硬件记为库存里的一条需求——出库时才从库存取件",activateConsequenceTermStart:"选了「签约即生效」的项从签约日开始合同期限,选了「指定日期生效」的到那天开始",activateConsequenceUndo:"要撤销只能先终止合同、再走一遍交接腾退 —— 没有「重新激活」这个按钮",activateConsequenceEntitlement:"建立权益(初始 PENDING)并开始供应 —— 要等流水线跑完才转 ACTIVE",activated:"合同已激活,正在拉起供应流水线…",runsStarted:"已产生 {n} 条供应流水线",runsPending:"供应流水线仍在拉起中,请稍后在供应监控查看",runsNone:"该合同没有授权产品,不会产生供应流水线",terminateTitle:"终止合同?",terminatePrompt:"终止原因",terminateReasonPlaceholder:"选择原因",terminateReasonRequired:"请选择终止原因",terminateNotes:"内部备注",terminatePlaceholder:"选填,给团队看的背景说明",terminateButton:"终止合同",terminateEffectiveDate:"生效日",terminateEffectiveDatePlaceholder:"不填按今天",terminateEffectiveDateHint:"今天或更早当场终止(更早用来补录已经发生的终止);晚于今天则到那天才终止,此前合同显示为「终止中」。",terminateIrreversible:"提交后不可撤销,要反悔只能签新合同。",terminateLead:"这会拉起收尾交接流程。",terminateConsequenceEntitlement:"到生效日停止供应:本合同名下的全部权益终止,客户失去这些产品的访问。在此之前交付、请款、开票照常。",terminateConsequencePdpa:"客户在生效日之后有 30 天下载自己的数据(PDPA)。",terminateConsequenceHandover:"当即建好收尾交接(5 步);已有未走完的交接,则把它的合同结束日改到生效日。",terminateConsequenceBilling:"已开出但未付清的发票不会因此一笔勾销,该收的钱照收。",terminated:"合同已终止,名下权益联动终止",terminationScheduled:"已安排终止:合同于 {date} 结束,在此之前交付照常",terminatedAlert:"已终止:{reason}(生效日 {date})",terminatingAlert:"将于 {date} 终止:{reason}。在此之前权益与交付照常;不能撤回。",earlyTermination:"提前终止",paymentPlan:"付款计划",paymentPlanBase:"额度按合同不含税金额 {base} 计",paymentPlanEdit:"编辑付款计划",paymentPlanEditTitle:"编辑付款计划",paymentPlanEditHint:"每个付款节点占合同不含税金额({base})的一个百分比,请款按节点申报、按节点控额度。合计不足 100% 也能先保存,发起签署前必须恰好 100%。",paymentPlanIncomplete:"付款计划合计 {pct}%:发起签署前必须恰好 100%。",paymentPlanMissing:"还没有付款计划:发起签署前必须设置付款节点,且合计恰好 100%。",paymentNodeSeq:"序号",paymentNodeName:"付款节点",occurrenceTitle:"按次的服务",occurrenceSub:"按次计价,不计入合同金额;每发生一批就登记一次,生成请款草稿",occurrenceService:"服务",occurrenceUnitPrice:"单价",occurrenceRegistered:"已登记",occurrenceRegisteredValue:"{n} {unit} · {claims} 张请款单",occurrenceRecord:"登记次数",occurrenceNotActive:"合同生效后才能登记",projectClosingNoNew:"项目在收尾期,不能再新建请款单与变更单",projectArchivedNoNew:"项目已归档,不能再新建请款单与变更单",occurrenceRecordTitle:"登记次数",occurrenceCount:"次数({unit})",occurrenceCountShort:"次数",occurrenceCountInvalid:"1 到 9999 的整数",occurrencePeriod:"发生日期",occurrencePeriodFrom:"开始",occurrencePeriodTo:"结束",occurrencePeriodRequired:"请选择发生的日期区间",occurrenceNote:"说明",occurrenceNotePlaceholder:"例如:电梯检测额外到场 3 次",occurrenceNoteRequired:"请写明做了什么",occurrenceHint:"会生成一张 {amount}(不含税)的请款草稿,由财务核对后提交。",occurrenceRecorded:"已登记,生成请款草稿 {no}",occurrenceClaim:"请款单",occurrenceAmount:"金额",occurrenceNoHistory:"这项服务还没有登记过",paymentNodeProduct:"产品",paymentNodeStep:"里程碑步骤",paymentNodeNoLink:"不挂",paymentNodeStepPlaceholder:"选择里程碑步骤",paymentNodeStepNoPerm:"没有查看流程模板的权限,列不出步骤。产品留空,这个节点就不挂。",paymentNodeStepGone:"{name}(当前模板里没有)",paymentNodeLinkIncomplete:"挂节点要产品和步骤都选,不挂就两个都清空",paymentNodeNamePlaceholder:"如 签约首付、上线验收",paymentNodePercentage:"百分比",paymentNodeAmount:"节点额度(不含税)",paymentNodeAmountEstimate:"节点额度(预估)",paymentNodeClaimed:"已申报",paymentNodeRemaining:"剩余可申报",paymentNodeAdd:"添加节点",paymentPlanEmptyDraft:"还没有付款节点",paymentPlanEmptyLegacy:"这份合同没有付款计划(付款计划上线前已离开草稿),请款按合同不含税金额整体控额度。",paymentPlanDraftNote:"草稿阶段可随时修改;发起签署后付款计划随合同冻结。",paymentPlanFrozenNote:"付款计划已随合同冻结。已申报与剩余随请款单实时变化,草稿请款单不计入已申报。",paymentPlanTotal:"合计 {pct}%",paymentPlanTotalEstimate:"合计 {pct}%(预估)",paymentPlanTotal_over:"合计超过 100%,不能保存。",paymentPlanTotal_under:"不足 100% 也能先保存,但发起签署前必须补足到恰好 100%。",paymentPlanTotal_exact:"合计恰好 100%。",paymentNodeNameRequired:"每个付款节点都要填名称",paymentNodePercentageRequired:"每个付款节点都要填大于 0 的百分比",paymentPlanSaved:"付款计划已保存",sendNeedsPaymentPlan:"付款计划各节点合计须恰好 100% 才能发起签署",sendConsequencePaymentPlan:"付款计划就此冻结 —— 之后请款按这些节点申报、按节点控额度",sendConsequenceTermModes:"各项的生效方式就此锁定 —— 生效后只能手工设定或修改生效日"},acceptLink:{title:"客户接受链接",copy:"复制",copied:"链接已复制",copyFailed:"复制失败,请选中上面的链接手动复制",email:"邮件",emailUnavailable:"还不能从这里发邮件,请复制链接后自己发给客户",expires:"到期",endOfDay:"{date} 当天结束",opened:"打开",openedTimes:"{n} 次",lastOpened:"最近 {time}",notOpened:"客户还没打开过",created:"生成",noUrl:{ACTIVE:"",EXPIRED:"这条链接已过期,客户打不开了。",REVOKED:"这条链接已撤销,客户打不开了。",SUPERSEDED:"这一版已被修订,它的链接打不开了。",DECIDED:"已经有了结果,链接也已到期。"},decidedAccepted:"客户已在线接受",decidedRejected:"客户已在线拒绝",reasonIs:"原因:{reason}",regenerate:"重新生成链接",regenerateTitle:"重新生成接受链接?",regenerateOldStops:"当前链接立即失效,拿着它的人再也打不开这张报价",regenerateNew:"生成一条新链接,有效到 {date} 当天结束",regenerateCount:"新链接的打开次数从 0 重新计",regenerated:"新链接已生成,请复制后发给客户",revoke:"撤销链接",revokeTitle:"撤销接受链接?",revokeStops:"链接立即失效,客户不能再打开、接受或拒绝这张报价",revokeRegenerate:"报价仍是已发送;要再给客户看,重新生成一条链接",revoked:"链接已撤销",expiresOnLabel:"接受链接到期日(选填)",expiresOnPlaceholder:"不填到有效期最后一天({date})",sendConsequenceLink:"生成客户接受链接,请在报价上复制后自己发给客户"},quotationFiles:{title:"附件",subtitle:"纸质签署的报价扫描件、客户采购单、邮件确认",full:"这张报价已有 {n} 份附件,删掉一份才能再传",autoGenerated:"系统生成",pdfTag:"报价单",tag:{SIGNED_SCAN:"已签",CUSTOMER_PO:"采购单",EMAIL_CONFIRMATION:"邮件",REFERENCE:"参考",OTHER:"其他"},uploadTitle:"上传附件",docType:"附件类型",uploaded:"附件已上传",deleteTitle:"删除这份附件?",deleteGone:"「{name}」从这张报价上移除,不能再查看或下载",deleteAudit:"删除会记进报价的动态",deleted:"附件已删除"},productFiles:{photoTitle:"产品照片",photoPlaceholder:"产品图片",replacePhoto:"替换照片",uploadPhoto:"上传照片",photoUploaded:"照片已上传",datasheetsTitle:"Datasheet 与手册",datasheetsEmpty:"还没有 Datasheet 或手册。",datasheetsFull:"这个型号已有 {n} 份文件,删掉一份才能再传",uploadDatasheet:"上传 Datasheet / 手册",uploadDatasheetTitle:"上传 Datasheet / 手册",docType:"文件类型",datasheetUploaded:"文件已上传",deleteDatasheetTitle:"删除这份文件?",deleteDatasheetGone:"「{name}」从这个硬件型号上移除,不能再查看或下载",deleteAudit:"删除会记进型号的操作历史",datasheetDeleted:"文件已删除",newPhotoFailed:"硬件型号已建好,但照片没有传上去,请到详情页再传。"},files:{dropTitle:"点击选择文件,或把文件拖到这里",dropHint:"{types},{size} MB 以内",remove:"移除",typeNotAllowed:"这里只能上传 {types} 文件",empty:"文件是空的",tooLarge:"文件超过 {size} MB",noPreview:"这种类型不能在页面里预览,请下载后打开",previewFailed:"文件没能取回,无法预览",download:"下载",view:"查看",upload:"上传",replace:"替换",delete:"删除",sizeAndDate:"{size} · 上传于 {date}",uploadedBy:"{size} · {name} 上传于 {date}"},serviceTerm:{daysLeft:"最后一天 | 还剩 {n} 天 | 还剩 {n} 天",monthsLeft:"还剩 {n} 个月 | 还剩 {n} 个月",expiredDaysAgo:"已到期 {n} 天 | 已到期 {n} 天",expiredMonthsAgo:"已到期 {n} 个月 | 已到期 {n} 个月",pending:"待生效",pendingFor:"待生效 · {n} 个月",effectiveOn:"{date} · {n} 个月",effectiveOnShort:"{date} 生效",takesEffectOn:"将于 {date} 生效 · {n} 个月",takesEffectOnShort:"将于 {date} 生效",months:"{n} 个月 | {n} 个月",endsOn:"{date} 结束"},termBinding:{titleQuotation:"条款与条件",titleContract:"引用的条款",subtitleContract:"这份合同引用的标准条款",versionN:"第 {v} 版",langBilingual:"中英双语",langEn:"英文",langZh:"中文",showSnapshot:"查看绑定时的正文",hideSnapshot:"收起正文",boundAtTip:"绑定于 {at}",title:"商务条款",subtitle:"本单据引用的条款文本 —— 绑定当时整份抄下来的快照",setTerms:"设置条款",setTermsTitle:"设置引用的商务条款",saved:"商务条款已更新",empty:"还没有引用任何商务条款",sourceState:"来源版本",boundAt:"绑定时间",staleHint:"下面有 {n} 条来自已经不是当前版本的条款。这些引用照常有效 —— 快照就是客户当时看到的那段字 —— 只是条款库里已经有新版本了。",lockedQuotation:"只有草稿或已发送的报价能改引用的条款 —— 已接受或已过期的报价换条款没有意义。",lockedContract:"只有草稿状态的合同能改引用的条款。一旦送签,客户手里的 PDF 就已经带着条款文本了,再改就意味着签的和存的不是同一份。",pickerTitle:"选择商务条款",pickerOnlyCurrent:"只有当前生效的版本能被引用,所以这里只列出这些。草稿和已换版的版本服务端会拒绝。",selectedCount:"已选 {n} 条",consequenceReplace:"把引用的条款整份换成你选的这 {n} 条 —— 这不是追加",consequenceRemoved:"解除你没选的 {n} 条({codes})",consequenceAdded:"新引用 {n} 条({codes}),按它们现在的正文抄一份存下来",consequenceRebound:"⚠ 把已引用的 {n} 条换版({codes})—— 正文会变成当前版本,而之后这个界面上看不出来发生过这件事",consequenceSnapshot:"不影响任何已签单据里抄好的条款文本 —— 只动这一份单据"},term:{createDraftNote:"条款建好后是草稿。正文定稿后再发布,只有已发布的版本才能被绑定。",pdfLangBilingual:"中英双语(当前视图)",pdfLangEn:"仅英文",pdfLangZh:"仅中文",lockTitle:"版本锁定",lockBody:"已发布的条款要改,就开一个新版本。已经绑定的合同与报价保留绑定时的那段正文。",versionPill:"第 {n} 版",footNote:"条款按版本引用,绑定时把那一版的正文存成快照。条款之后再改不会追溯到已有合同,每份合同保留绑定时的那段正文。",codeAutoHint:"保存时按分类自动生成(如 GL0001)",adjustmentMonths:"期限调整(月)",adjustmentMonthsPlaceholder:"如 3 或 -2",adjustmentMonthsHint:"正数延长、负数缩短每个授权产品的服务期,不影响金额。发布前必须填写。",adjustmentMonthsNonZero:"不能为 0",namePlaceholder:"如 付款条款——年度订阅",categoryPrefixHint:"改分类不会改编号前缀。",languageField:"语言",langBilingual:"中英双语",langEnOnly:"仅英文",langZhOnly:"仅中文",lang:{BILINGUAL:"中英双语",EN:"英文",ZH:"中文"},shortDescription:"简短描述",shortDescriptionPlaceholder:"如 按季度 · 30 天账期",jurisdiction:"司法辖区",jurisdictionPlaceholder:"如 新加坡",governingLaw:"适用法律",governingLawPlaceholder:"如 新加坡法律",contentPlaceholder:"条款正文……",createAndOpen:"创建并打开",newVersionTitle:"开新版本",newVersionSub:"{code} · 当前 {from} → 新 {to}",newVersionReason:"开新版本的原因",newVersionReasonPlaceholder:"选择原因",newVersionReasonRequired:"请选择开新版本的原因",changeSummary:"变更摘要",changeSummaryPlaceholder:"说明改了什么,会记进版本历史……",newVersionNote:"新版本从草稿开始。已在用这个条款的 {n} 份合同仍按 {from};{to} 发布后,新合同才会用它。",newVersionButton:"创建 {to}(草稿)",newDraftLong:"开新版本",duplicate:"复制",duplicateTitle:"复制条款",duplicateFrom:"来自 {code} {name}",duplicateName:"新条款名称",duplicateDefaultName:"{name}(副本)",duplicateNote:"会新建一个条款,从草稿 v1 开始,正文与属性都复制过去。原条款不受影响。",duplicated:"已创建 {code}",kpiTotal:"条款总数",kpiTotalSub:"分布在 {n} 个分类",kpiActive:"生效中",kpiActiveSub:"合同在用",kpiDraft:"草稿",kpiDraftSub:"法务审核中",kpiNeedUpdate:"需要更新",kpiNeedUpdateSub:"6 个月以上未更新",usedBy:"使用中",usedByHint:"绑定了这个条款任一版本的合同数(不含报价),包括你看不到的合同。",usedByUnit:"份合同",lastUpdated:"最后更新",approvedBy:"批准人",inUseBy:"使用中",inUseByValue:"{n} 份合同",termInfo:"条款信息",languages:"语言",contractsUsing:"使用这个条款的合同",colContract:"合同",colCustomer:"客户",colLockedVersion:"锁定版本",viewAllContracts:"查看全部 {n} 份合同 →",usageCount:"{n} 份合同引用了这个条款。",usageFirst:"{n} 份合同引用了这个条款,这里显示前 {shown} 份。",usageScoped:"{n} 份合同引用了这个条款,其中 {visible} 份在你的数据范围内。",noContractReferences:"还没有合同在用这个条款。",versionTitle:"版本 {n}",versionTitleCurrent:"版本 {n}(当前)",versionViewing:"正在查看",versionContracts:"{n} 份合同",versionContractsLocked:"{n} 份合同(已锁定)",pageSubtitle:"可复用的商务条款库:付款、支持与 SLA、质保、续约等条款。报价和合同引用条款时,会把当时的正文存成快照。",tabCurrent:"当前生效",tabAll:"全部",keywordPlaceholder:"编号或名称",code:"编号",colTerm:"条款",codeHint:"只能是字母、数字、连字符和下划线。同一条款的所有版本共用它,建后不可修改。",codeImmutableHint:"编号不可修改——已经有引用指着它了。",codeRequired:"请填写编号",codeFormat:"只允许字母、数字、连字符和下划线",name:"名称",nameRequired:"请填写名称",category:"分类",categoryRequired:"请选择分类",language:"正文语言",version:"版本",references:"引用数",referenceCountHint:"统计全部报价与合同,包含你的数据范围之外的单据。",create:"新建条款",createTitle:"新建商务条款",editTitle:"编辑草稿",content:"正文",contentDraftHint:"草稿阶段两种语言都可以空着,发布时才要求至少有一种语言写了正文。",contentEn:"英文",contentZh:"中文",noContentEn:"没有英文正文",noContentZh:"没有中文正文",noContent:"两种语言都还没有正文",tabContent:"正文",tabUsage:"引用",tabHistory:"版本历史",tabAudit:"审计",langBoth:"双语",langEn:"英文",langZh:"中文",wordCountEn:"英文约 {n} 词",charCountZh:"中文 {n} 字",showAll:"展开全部",collapse:"收起",emptyCurrent:"当前没有生效中的条款。草稿与已停用的版本在「全部版本」里。",emptyFiltered:"没有符合当前筛选条件的条款",emptyAll:"还没有建过商务条款",publishedAt:"发布时间",retiredAt:"停用时间",metaCreated:"创建",metaUpdated:"更新",notPublished:"未发布",noteDraftTitle:"草稿",noteDraft:"报价与合同还选不到它。正文定稿后再发布——发布之后就不能再编辑了。",noteCurrentTitle:"当前生效",noteCurrent:"新建的报价与合同会引用这一版。",noteSupersededTitle:"已被更新版取代",noteSuperseded:"新单据会改引用更新的那一版。已经绑定这一版的单据不受影响——它们持有的是绑定当时抄下来的快照。",noteRetiredTitle:"已停用",noteRetired:"选条款时不再出现。已经引用它的单据不受影响——它们持有各自的快照。",publish:"发布",publishTitle:"发布这一版",publishDiffAgainst:"与 {v} 相比,这一版改动了:",publishNoChange:"与 {v} 完全相同——除了版本号什么都没变。确定要发布吗?",publishNoBaseline:"没有可比较的版本——这是该编号的第一版。",publishDiffUnavailable:"没能取到版本差异。这不代表没有差异——发布前请去版本历史里比一下。",diffLines:"+{add} / -{del} 行",publishConsequenceSupersede:"会把 {v} 转为「已取代」,新单据改为引用这一版。",publishConsequenceBind:"此后新建的报价与合同会引用这一版。",publishConsequenceSnapshot:"已经签过的单据仍是绑定当时的正文,对它们没有任何影响。",publishConsequenceImmutable:"这一版从此只读,再要改正文只能发新版本。",published:"已发布",retire:"停用",retireTitle:"停用这条条款",retireConsequenceHidden:"给报价或合同选条款时不会再出现它。",retireConsequenceExisting:"已经引用它的 {n} 份单据保留各自的快照,不受影响。",retireConsequenceNewVersion:"停用不等于换版——如果只是正文改了,应该发一个新版本而不是停用。",retired:"已停用",newDraft:"开新版草稿",draftCreated:"草稿已创建",deleteTitle:"删除这份草稿",deleteConsequenceGone:"草稿及其正文会被永久删除。",deleteConsequenceOnlyDraft:"只有未被引用的草稿能删,已发布的版本永远不能。",deleteOnlyDraftHint:"只有未被引用的草稿能删除。",actionTarget:"条款:",versionHistory:"版本历史",versionHistoryHint:"这个编号的全部版本",compare:"比较",compareTitle:"版本比较",changed:"有变化",unchanged:"无变化",columnUnchanged:"这两版之间没有变化。",columnEmptyBoth:"两版都没有这个语言的正文。",contentIdentical:"两版正文完全相同。",contentIdenticalUnknown:"其中一版还是草稿,服务端无法判断两版正文是否相同——请看下面的逐行比较。",referencedBy:"被谁引用",referencesScopedHint:"显示 {shown} / {total} 条,其余在你的数据范围之外。",referencesAllScoped:"全部 {total} 条引用都在你的数据范围之外。",noReferences:"还没有被任何报价或合同引用",refType:"单据类型",refNo:"单据编号",boundAt:"绑定时间"},product:{colInventory:"库存",stockOut:"缺货",stockWithOut:"{n} · {k} 个变体缺货",stockLowSingle:"{n} 件,偏低",stockWithLow:"{n} · {k} 个变体偏低",stockIn:"在库 {n}",title:"产品目录",pageSubtitle:"BES 的产品组合。每个产品都是报价里售卖、由合同授权的基本单位。",kpiTotal:"产品总数",kpiSoftwareN:"{n} 个软件",kpiHardwareN:"{n} 个硬件",kpiServiceN:"{n} 个服务",kpiMostSold:"部署最多",kpiMostSoldSub:"{n} 个在用部署",kpiDeployments:"在用部署",kpiDeploymentsSub:"分布在 {n} 个项目",tabAll:"全部",viewGrid:"卡片视图",viewList:"列表视图",colProduct:"产品",colDescription:"描述",colPermissions:"权限点",colDeployments:"部署",colCode:"编号",manage:"管理",colModel:"型号",colSupplier:"供应商",colUnitPrice:"单价",variantsN:"没有变体 | {n} 个变体 | {n} 个变体",modelsN:"没有型号 | {n} 个型号 | {n} 个型号",hwSectionSub:"— BES 转售的第三方设备",hwTableHint:"硬件用紧凑表展示,型号多了也放得下;完整的变体与价格在各型号的页面上。",requiresHardware:"需要硬件",customerCanSelfProvide:"客户可自备",footNoteLead:"产品定义了 BES 卖什么。",footNote:"每个产品带一组权限点,由客户的公司管理员通过默认角色分配。报价与合同绑定到具体的产品版本。",createSubtitle:"产品编号在保存时自动分配",formType:"产品类型",typeSoftwareDesc:"BOSP、AIVA、SHELL——按期订阅",typeHardwareDesc:"摄像头、工作站、机器人——一次性售卖加维保",typeServiceDesc:"咨询、培训、定制开发——按项目计费",formName:"产品名称",namePlaceholder:"例如 BOSP",shortTitle:"短标题",shortTitlePlaceholder:"例如 Build Operation & Site Platform",descriptionPlaceholder:"这个产品做什么……",initialStatus:"初始状态",initialStatusRequired:"请选择初始状态",prefixPlaceholder:"例如 bosp",prefixFixedHint:"建后不可改——它是本产品 Layer 2 权限点的命名空间。",scopeLevel:"权益范围",scopeLevelRequired:"请选择权益范围",scopeLevelHint:"按项目:每个项目单独授权,开通项目时连同第一个权益周期一起建。按租户:按客户租户授权,同一租户下的项目共用这一份。建后不可改。",scopeFixedHint:"建后不可改——它决定本产品在 Control 里怎么建权益。",controlSync:"Control 登记",controlSyncHint:"软件产品新建、改名、改状态后会登记到 Control,在后台进行,失败会自动重试,这里不用操作。",controlSyncFailed:"登记到 Control 失败,系统会自动重试",hwDeps:"硬件依赖",hwDepsSoftwareOnly:"——仅软件产品",hwDepsHint:"像 AIVA 这样的软件要配硬件才能运行(摄像头、工作站)。标明必需还是推荐。客户可以选择自备硬件。",hwCandidatesEmpty:"还没有可售的硬件产品",allowCustomerHardware:"允许客户自备硬件(报价里标为「客户自备」)",createFootnote:"版本、权限点、默认角色与实施模板在建好后到产品详情页配置。",editFootnote:"版本、权限点、默认角色与实施模板在各自的页签里编辑。",createAndConfigure:"创建并配置",create:"新建产品",createTitle:"新建产品",editTitle:"编辑产品",searchPlaceholder:"产品编号 / 名称",productCode:"产品编号",name:"名称",productType:"类型",permissionPrefix:"权限前缀",permissionPrefixHint:"仅软件产品可填,自动转小写。它决定整份 Layer 2 权限 registry 的命名空间,建后不可改。",description:"描述",permissionCount:"权限点",roleTemplateCount:"角色模板",belongsTo:"所属产品",countScopeHint:"这里的计数只统计本产品,平台总数是所有产品之和。",nameRequired:"请填写名称",typeRequired:"请选择产品类型",changeStatus:"变更状态",changeStatusTitle:"变更产品状态",currentStatus:"当前:",reason:"原因",updateStatus:"更新",statusDesc:{ACTIVE:"可售,正常支持",BETA:"抢先使用,有限支持",DEPRECATED:"不再新签,存量照常支持"},changeStatusLabel:"新状态",statusChanged:"状态已变更",kpiActiveDeployments:"在用部署",kpiPermissionPoints:"权限点",kpiRoleTemplates:"角色模板",navViews:"视图",section:{setup:"产品配置",access:"权限与角色",delivery:"交付"},view:{surfaces:"产品应用",permissions:"权限点",templates:"角色模板",pipeline:"供应流水线模板",projects:"项目"},appPages:"{n} 个页面",appIncluded:"已含",appsVerbatim:"应用说明逐字同步自 {name}。",appsSyncedAtValue:"最近同步 {time}",projectsUsing:"使用 {name} 的项目",projectsShowing:"显示 {n} 个已部署 {name} 的项目中的 {shown} 个",viewAllProjects:"查看全部项目",colProject:"项目",colEdition:"版本",editionEnterprise:"Enterprise",noDeployedProjects:"还没有项目部署了 {name}。",layer2Alert:"本页的权限点与角色模板属于 Layer 2:它们下发给客户租户、由产品侧校验。BOSS 后台自身的菜单与按钮权限从不使用它们。",placeholderAlert:"当前载入的权限点是占位数据,待产品侧确认——其中多数码名是按命名规律推导的,并非文档原文。真正下发给客户前必须逐条核对。",unpublishedTemplatesAlert:"有 {n} 个角色模板从未发布。供应只下发已发布的快照,因此租户那边拿不到它们的任何权限。",neverSynced:"从未同步",appCode:"应用编码",appName:"名称",appPageCount:"页数",appSortNo:"顺序",syncApps:"同步应用清单",syncAppsTitle:"同步应用镜像",syncAppsHint:"应用名称与描述是从产品侧逐字同步的镜像,所以这里是整体替换而非逐条编辑:本次没列出的应用会被删除。被删应用下的权限点会保留,分组回落成原始应用编码。",addRow:"+ 添加一行",appsEmpty:"尚未同步任何应用",appRowIncomplete:"每行都要填应用编码与名称",appsRequired:"清单不能为空——空清单等于把镜像清光,不是「什么都不改」",synced:"已同步",resultAdded:"新增",resultUpdated:"更新",resultUnchanged:"未变",resultOrphaned:"孤立",resultPruned:"已删除",resultKeptInUse:"占用保留",resultUnknownApps:"未知应用编码",resultOrphanedHint:"本地有、本次提交里没有的条目——通常意味着产品侧已经下架了它们。",resultKeptInUseHint:"仍被角色模板引用,因此没有删除。要清理得先改模板。",resultUnknownAppsHint:"在应用镜像里找不到这些编码。权限点照常导入,分组回落成原始应用编码。",importPoints:"导入权限点",importPointsTitle:"导入 Layer 2 权限点",importPointsHint:"粘贴产品侧导出的清单。导入是幂等的——同一份清单导多少次结果一样,重复导入只更新显示文案。",importJsonLabel:"权限点(JSON)",importJsonInvalid:"不是合法的 JSON",importJsonShape:"需要一个 JSON 数组,每个元素都要有 code",importCount:"已解析 {n} 条",pruneOrphans:"删除本次清单里没有的权限点",pruneOrphansHint:"默认不删、只报告。即使勾选,被角色模板引用的权限点也一律不会被删除。",pointCode:"权限码",pointName:"名称",pointRisk:"风险",pointsEmpty:"还没有权限点——请从产品侧导入",ungrouped:"不在应用镜像中",imported:"已导入",templateCode:"模板编号",templateCodeHint:"跨所有产品全局唯一,建后不可改——已开通的租户靠它识别角色。",templateName:"名称",templatePermissions:"权限点",publishedRevision:"已发布版本",revisionNoValue:"第 {n} 版",neverPublished:"从未发布",neverPublishedHint:"从未发布——供应会整个跳过这个模板。",unpublishedChanges:"有未发布改动",unpublishedChangesAlert:"该模板有未发布的改动。在你点发布之前,租户拿到的一直是上一次发布的快照。",systemTemplate:"预置",createTemplate:"新建角色模板",createTemplateTitle:"新建角色模板",editTemplateTitle:"编辑角色模板",isSystem:"产品预置",isSystemHint:"预置模板不可删除。该标记只在新建时生效——允许后改的话,把预置摘掉再删就绕过了保护。",templateCodeRequired:"请填写模板编号",templateNameRequired:"请填写名称",deleteTemplateTitle:"删除角色模板",deleteTemplateConsequenceGone:"删掉角色模板「{name}」以及它的全部已发布版本",deleteTemplateConsequenceProvision:"已经拿到它的租户不受影响,但此后的供应不会再下发这个角色",templatesEmpty:"没有角色模板——该产品供应时会跳过 seed_roles 步骤",publish:"发布",publishTitle:"发布角色模板",publishConsequenceSnapshot:"把当前工作副本冻结成一个新的只读版本",publishConsequenceTenant:"此后的供应下发给租户的就是这一版",publishConsequenceServerCopy:"发布的是服务器上已保存的那份 —— 在这里改了但没保存的内容不算数",publishPrompt:"发布会把工作副本冻成新版本,并顺着供应铺到所有装了该产品的客户租户。备注(可选):",publishPlaceholder:"如:补 sealant 权限",published:"已发布为第 {n} 版",workingCopy:"工作副本",workingCopyHint:"可编辑。在发布之前,租户看不到这里的任何改动。",publishedSnapshot:"已发布快照",publishedSnapshotHint:"只读,冻结于第 {n} 版。这才是租户手上实际生效的那份。",pendingDiff:"待发布:相比已发布快照 +{added} / -{removed}",unsavedChanges:"有未保存的改动。发布冻结的是服务器上的工作副本、不是屏幕上这份,请先保存。",revisions:"版本历史",revisionNo:"版本",revisionNote:"备注",publishedAt:"发布时间",publishedBy:"发布人",revisionPermissions:"权限点",revisionsEmpty:"还没有已发布的版本",registryEmpty:"该产品还没有 Layer 2 权限点——请先导入再配置模板",pipelineTitle:"{name} 供应流水线",pipelineSubtitle:"为新客户开通 {name} 时自动执行的系统步骤 · {n} 步",currentlyVersion:"当前 {v}",provVsOnbTitle:"开通与实施的区别",provVsOnbBody:"这条流水线在合同激活时由系统自动执行,为这个产品搭好技术侧(租户、授权、访问)。BES 员工带着客户走的人工实施步骤(勘察、安装、培训、交接)按实施类型定义在流程模板里,不在这里。",provNotOnboardingLead:"供应 ≠ 实施。",provNotOnboarding:"这里是本产品的自动化技术流程——合同激活后由系统 worker 执行。BES 员工与客户一起走的人工实施流程定义在",addStep:"添加步骤",addStepTitle:"添加供应步骤",addStepSubtitle:"给 {name} 的供应流水线加一个自动步骤",editStepTitle:"编辑供应步骤",stepDescription:"说明",stepNamePlaceholder:"例如 Seed sample sites",handlerPlaceholder:"provisioning.seed_sites",estimatedDuration:"预计耗时",estimatedDurationPlaceholder:"例如 5s",insertPosition:"插入位置",insertLast:"第 {n} 步之后(最后)",insertFirst:"第 1 步之前",insertCustom:"自定义(建好后拖动)",stepNameRequired:"请填写步骤名",handlerRequired:"请填写处理函数",handlerDuplicate:"已有步骤用了这个处理函数",stepTypeRequired:"请选择类型",stepBehaviorRequired:"请选择执行方式",insertPositionRequired:"请选择插入位置",systemWorker:"System (worker)",handlerValue:"handler: {h}",dragToReorder:"拖动排序",draftUnsaved:"步骤有未保存的改动——保存为新版本之前都不会生效。",discardDraft:"放弃改动",deleteStepTitle:"删除这一步?",deleteStepConsequenceDraft:"会把「{name}」从本页的步骤里去掉——保存为新版本之前不会发布",deleteStepConsequenceRuns:"会让已有的客户供应运行继续按 {v} 执行",deleteStepConsequenceRequired:"会去掉一个必需步骤——新客户的供应可能因此出错,可以考虑改它而不是删它",pipelineSummary:"流水线概况",totalSteps:"步骤总数",avgExecution:"平均耗时",successRate30d:"成功率(30 天)",durationSeconds:"约 {n} 秒",durationMinutes:"约 {n} 分钟",durationHours:"约 {n} 小时",history:"历史",activeRunsUseVersion:"{n} 个在用部署用的是这一版",historicalRuns:"累计 {n} 次运行",lastUpdated:"最近更新 {date}",lastUpdatedBy:"最近更新 {date},{name}",noVersionYet:"还没有发布过版本",saveAsNewVersion:"保存为新版本",saveVersionNoChanges:"步骤还没有改动",provisioningEventsLead:"过往运行的执行日志见",provisioningEventsLink:"供应事件 →",saveVersionTitle:"保存为新的流水线版本",saveVersionSubtitle:"{from} → {to} · 已有的运行继续按 {from} 执行",saveVersionFirst:"这条流水线的第一个版本",versionLabel:"版本号",changeSummary:"变更说明",changeSummaryPlaceholder:"简要说明改了什么、为什么……",changeSummaryRequired:"请填写变更说明",saveVersionButton:"保存 {version}",historyTitle:"供应流水线历史",historySubtitle:"{name} · {n} 个版本",historyEmpty:"还没有发布过版本",versionActive:"当前",versionArchived:"已归档",stepCountN:"{n} 步",compare:"对比",compareTitle:"对比版本",compareSubtitle:"两个流水线版本之间的步骤变化",compareBase:"基准",compareTo:"对比到",compareCurrent:"{v}(当前)",comparePick:"选两个版本来对比",diff:{added:"新增",removed:"删除",changed:"改动",same:"未变"},diffField:{stepNo:"位置",stepName:"名称",stepType:"类型",behavior:"执行方式",description:"说明",estimatedDuration:"预计耗时"},diffUnchanged:"其余 {n} 步没有变化",diffIdentical:"两个版本的步骤完全相同",leaveDraftTitle:"流水线有未保存的改动,确定离开?",leaveDraftAction:"离开",leaveDraftConsequence:"会丢掉本页对步骤的改动——它们还没有发布",pipelineVersion:"版本",pipelineNoneAlert:"尚未配置供应流水线模板。含该产品的合同激活时,会直接跳过它的供应——什么都不开通,也不报错。",stepName:"步骤名",stepType:"类型",stepBehavior:"行为",handlerFn:"处理函数",handlerMissing:"无实现",handlerMissingAlert:"有 {n} 个必需步骤指向后端不存在的处理器——该产品的每一次供应都会卡在那里失败。",requiredCount:"必需",optionalCount:"可选",versionRequired:"请填写版本号",versionDuplicate:"该产品已有同名版本",requiredHandlerHint:"必需步骤的处理器必须在后端真有实现,否则发布会被拒绝。可选步骤不校验——编排器遇到没实现的可选步骤会跳过。",pipelinePublished:"供应流水线模板 {version} 已发布"},hardware:{manageInventory:"管理库存",kpiInStock:"在库",kpiDeployed:"已部署",tabInventory:"库存",tabDeployments:"部署",tabDatasheet:"Datasheet",deploymentsTitle:"这个硬件装在哪里",deploymentsSub:"各项目现场装好的件数",colProject:"项目",colCustomer:"客户",colUnits:"件数",noDeployments:"还没有装在任何项目上",dispatch:"出库",colInStock:"在库",inventorySnapshot:"这个型号的库存快照。完整操作请打开{link}。",inventoryModule:"硬件库存",reorderNewPo:"补货(新建采购单)",invInStock:"在库",invAllocated:"已预留",invOnOrder:"待到货",invInstalled:"已安装",recentMovements:"最近库存流水",openInventory:"打开库存 →",colMovement:"流水",colQty:"数量",colReference:"引用",colDate:"日期",noMovements:"还没有库存流水",initialStock:"初始库存",safetyStock:"安全库存提醒",wholeNumber:"请填不小于 0 的整数",inventoryRecordHint:"保存后会建好目录条目和库存记录,之后的库存在「硬件库存」里管理。",kpiUnitPrice:"单价",kpiMargin:"毛利",tabCatalog:"目录",tabPricing:"价格与供应商",variantsTitle:"变体",variantsTitleSku:"(SKU)",variantsSub:"每个变体是一个可售的规格,价格按变体记。",addVariant:"添加变体",addVariantTitle:"添加变体",editVariantTitle:"编辑变体",colVariant:"变体",colSku:"SKU",colPrice:"价格",default:"默认",noVariants:"还没有变体。至少加一个,这个型号才能报价。",singleSpecHint:"单一规格的产品在这里就只有一个变体。",firstVariantTitle:"硬件信息",firstVariantSub:"— 首个变体",firstVariantHint1:"一个产品可以有多个变体(规格),建好后再添加。",firstVariantHint2:"价格按变体记。单一规格的产品只保留一个变体——例如一台有 i5 / i7 / i9 三种配置的工作站,是一个产品下的三个变体。这几项可以先空着,建好后再加变体。",sharedSpecs:"共享规格",sharedSpecsSub:"— 所有变体通用",noSpecs:"还没有共享规格",noDescription:"还没有描述",bundledTitle:"配套软件",defaultCompanionOf:"是以下软件的默认配套硬件",notBundled:"还没有软件产品把这个硬件列为依赖。",pricingTitle:"价格",pricingOf:"变体 {name} · {sku}",pricingHint:"金额按新加坡元记。批量价与年维保只是目录参考,报价不会自动套用。",supplierTitle:"供应商",supplier:"供应商",supplierPlaceholder:"例如 Hikvision",warranty:"保修期",warrantyMonths:"保修期(月)",warrantyPlaceholder:"例如 36",warrantyMonthsInvalid:"1~120 个月",warrantyYears:"{n} 年 | {n} 年",sku:"变体 SKU / 型号",skuPlaceholder:"例如 AIVA-CAM-4MP",skuRequired:"请填写 SKU",variantName:"变体名称",variantNamePlaceholder:"例如 4MP Standard",specNote:"规格说明",specNotePlaceholder:"例如 2.8mm lens · day-only",sellPrice:"售价(单台)",sellPriceRequired:"请填写售价",unitPriceSell:"单价(售价)",costPrice:"进价",margin:"毛利",bulkPrice:"批量价",bulkPriceN:"批量价({n} 台起)",bulkMinQty:"批量起订(台)",bulkMinQtyPlaceholder:"至少 2",bulkUnitPrice:"批量单价",bulkPairRequired:"批量的两项要一起填,或都不填",maintenancePerYear:"年维保费",variantFootnote:"金额按新加坡元记。报价行保存时会记下当时的 SKU、名称与价格,之后改这里不影响已有报价。",specNamePlaceholder:"例如 Power",specValuePlaceholder:"例如 PoE (802.3af)",specNameRequired:"请填名称",specValueRequired:"请填内容",addSpec:"添加规格",specsMax:"最多 {n} 项规格",moveUp:"上移",moveDown:"下移",createFootnote:"建好后在型号页上继续添加变体、共享规格与价格。",editFootnote:"变体与价格在型号页上编辑。",deleteVariantTitle:"删除变体",deleteVariantConsequence:"会把 SKU {sku} 从目录里移除,新的报价行选不到它;已有报价行保留当时记下的 SKU 与价格。",deleteDefaultConsequence:"会由 {name} 成为默认变体,型号页头的 SKU、单价与毛利改显示它的。"},provisioning:{pageTitle:"供应监控",pageSubtitle:"进行中或失败的客户开通。成功的运行记录在各条权益的页面上。",kpiInProgress:"进行中",kpiInProgressBadge:"运行中",kpiInProgressHint:"正在跑,无需处理",kpiFailed:"失败 · 待 Ops 处理",kpiFailedBadge:"需处理",kpiFailedHint:"先查根因,再重试",tabAll:"全部",rolledBackAtStep:"回滚于第 {current} / {total} 步",failedAtStep:"失败于第 {current} / {total} 步",footTitle:"所有供应事件同时写入审计日志。",footBody:"每个事件都是幂等的,可以从失败的那一步安全重试。更完整的事件历史见{link}。",searchPlaceholder:"流水线编号",runNo:"编号",entitlementNo:"权益编号",progress:"进度",stepProgress:"Step {current} of {total}",pipelineVersionValue:"模板 {version}",startedAt:"开始时间",finishedAt:"结束时间",took:"耗时 {d}",entitlementStatus:"权益状态",product:"产品",contract:"合同",deploymentId:"部署 ID",traceId:"Trace ID",steps:"执行步骤",noSteps:"暂无步骤",attempt:"第 {n} 次尝试",runningAlert:"流水线执行中,本页每 2 秒自动刷新。",errorBeforeRollback:"回滚之前的错误:回滚时这一步已跳过",rolledBackAlert:"已回滚:开通还没完成,权益就被终止了。剩下的步骤已跳过,部署实例不会上线。这条运行不能重试。",projectLevelAlert:"交接腾退后的项目级收回,这条运行没有权益与产品。",termExtendedAlert:"接续授权期:在 Control 已给出的授权期末尾接一段,让客户用到服务期结束(产品还没生效时再接一个期限)。不重建别的东西。",failedAlert:"流水线在第 {step} 步失败并已停下(失败不自动重试)。排查根因后点「人工重试」,从失败步续跑,已成功/已跳过的前序步不会重跑。",retry:"人工重试",retryTitle:"重试开通?",retryConsequenceResume:"从失败的那一步继续,而不是从头再跑一遍",retryConsequenceIdempotent:"对租户重新执行那一步 —— 这些步骤本来就是按可重复执行写的",retryConsequenceAgain:"可以反复来:再失败还能再重试",retryPrompt:"根因确认——会记入审计(必填,≤500 字)",retryPlaceholder:"如 CMDB handler 未随本次发版上线,已补部署",retryReasonTooLong:"根因说明不得超过 500 字",retryButton:"确认重试",triggeredBy:"触发来源",retryFromStep:"从第 {n} 步重试",retrySuccess:"流水线已全部执行成功",retryStillFailed:"仍在第 {step} 步失败,请继续排查",retryRestarted:"已重新拉起",reconcileScope:"所有已推到 Control 的租户",reconcileSummary:"租户 {tenants} 个 · 差异 {n} 条",reconcileInSync:"租户 {tenants} 个 · 与 Control 一致",reconcileAlert:"每天与 Control 对账:回读每个租户的授权期,与 BOSS 的记录比对。只报差异,不改 BOSS,也不改 Control。下一次对账会重新判断,处理好的差异自然不再出现。",tenantCount:"读取租户",discrepancyCount:"差异",discrepancies:"差异",discrepancyKind:"差异",discrepancyLocal:"BOSS",discrepancyControl:"Control",controlEntitlementId:"Control 授权期 ID",period:"{start} → {end}",noDiscrepancies:"没有差异,BOSS 与 Control 一致",discrepanciesPending:"读完之后这里列出差异",discrepanciesFailed:"回读失败,没有结果。重试会从头再读一遍所有租户。",discrepancyHint:{NOT_PUSHED:"去重试这条权益的开通运行",MISSING_IN_CONTROL:"去 Control 查:BOSS 记着的那条授权期不见了",INACTIVE_IN_CONTROL:"去 Control 查:BOSS 记为有效,客户却没有访问权",ACTIVE_IN_CONTROL:"去重试这条权益的收回运行:客户仍有访问权",PERIOD_MISMATCH:"去 Control 核对授权期起止",UNKNOWN_IN_CONTROL:"去 Control 查:BOSS 没有这条授权期的记录"},reconcileFailedAlert:"回读失败,已停下(失败不自动重试)。查明根因后点「人工重试」,会从头再读一遍所有租户。",retryReconcileConsequenceRead:"从头再回读一遍所有租户",retryReconcileConsequenceNoChange:"不改 BOSS,也不改 Control,只报差异"},notes:{add:"添加备注",onboardingTitle:"给实施单添加备注",handoverTitle:"给交接添加备注",placeholder:"备注会显示在「备注」里,团队都能看到……",internalOnly:"只有 BOSS 内部员工看得到;加了之后不能改、不能删。",required:"请先填写备注",added:"已添加备注",title:"备注",empty:"还没有备注"},onboarding:{title:"实施跟进",fromAmendment:"加设备 · 变更单 {no}",pageSubtitle:"跟进从合同激活到全面上线的项目实施。由生效的合同自动创建。",completedLast30d:"近 30 天 {n}",viewAllCompleted:"查看全部 {n} 条已完成 →",footTitle:"实施是合同签署之后运行的操作流程。",footBody:"合同转为生效时自动创建,并按所售内容匹配对应的流程模板:",footDefault:"默认",footClaim:"步骤可以设置为触发请款(财务里程碑)和 / 或通知销售(增购机会)。",priorityBadge:"{level}优先级",metaStarted:"开始",metaTarget:"目标",implementationType:"实施类型",stepsCount:"{n} 步",slaTotal:"SLA 合计 {n} 个工作日",overallProgress:"总进度",currentlyOn:"当前在",progressTriggers:"每一步完成都可以触发请款和 / 或通知销售",usesLabel:"本实施使用:",usesHint:"—— 合同转为生效时按所售内容匹配",compareFlows:"对比流程类型",editDefinitions:"编辑模板 →",editDefinitionsLong:"编辑流程模板 →",compareTitle:"实施流程类型",gotIt:"知道了",customerContacts:"客户联系人",primaryContact:"主联系人",noContacts:"这家客户还没有联系人",searchPlaceholder:"实施编号",noCreateAlert:"实施单不能手工创建——合同激活时自动拉起,与供应流水线同一个来源。供应是系统几分钟开好租户,这边是人去工地装设备、培训、交接的 6–10 周。",boardView:"看板",listView:"列表",boardMore:"还有 {n} 条 →",onboardingNo:"实施编号",customer:"客户",contract:"合同",project:"项目",product:"产品",definition:"流程模板",currentMilestone:"当前里程碑",progress:"进度",progressValue:"{done} / {total} 步",progressHint:"维保这类持续阶段不计入分母——它们永远不会完成,算进去实施就永远到不了 100%。",targetDate:"目标日期",overdueParen:"(超期 {n} 天)",overdueDays:"超期 {n} 天",viewLog:"查看日志",stepLogTitle:"步骤日志",stepLogSub:"{step} · 全部事件",startedAt:"开始时间",completedAt:"完成时间",timelineCompleted:"完成于 {time}",timelineSkipped:"跳过于 {time}",timelineStarted:"开始于 {time}",timelineTarget:"目标日期 {date}",priority:"优先级",owner:"负责人",noOwner:"未指派",blockedReason:"阻塞原因:{reason}",blockedAlert:"该实施已阻塞,解除之前所有步骤都推不动(开始/完成/跳过都会被拒)。原因:{reason}",emptyColumn:"暂无",steps:"步骤",stepOwnerRole:"建议角色",stepOwnerRoleHint:"来自流程模板的建议,不等于已指派。",durationDays:"耗时 {n} 天",milestone:"里程碑",milestoneHint:"里程碑步骤完成后据此向客户请款——它是一次计费事件,不只是状态打勾。",continuous:"持续阶段",continuousHint:"持续阶段永远不会完成、也不计入进度。它在最后一个常规步骤结束时自动开启(交付完成 → 维保开始),因此既没有「开始」也没有「完成」按钮——只留「跳过」,供客户不续维保时使用。",skippedReason:"已跳过:{reason}",pendingRequiredHint:"还差 {n} 个必需项,先把它们做完。",autoNextHint:"只有第一步需要手工开始:一步完成或跳过后,下一步会自动进入进行中。",items:"勾选项与交付物",itemRequired:"必需",itemOptional:"可选",itemDoneBy:"{name} 于 {time} 完成",itemLockedHint:"该步骤已结束,勾选项不能再改——确实要改的话,先回退这个步骤。",checklistTitle:"勾选项",checklistCount:"{done} / {total} 已完成",deliverablesTitle:"交付物",deliverablesCount:"必填 {done} / {total} 已上传",deliverableMissing:"必填,还没上传",legacyLink:"旧链接:",itemFileUploaded:"已上传",itemFileReplaced:"已替换",itemFileDeleted:"已删除",itemFileDeleteTitle:"删除这份文件?",itemFileDeleteGone:"「{name}」从这一项上移除,不能再查看或下载",itemFileDeleteUndone:"「{label}」回到未完成",itemFileDeleteUndoneRequired:"「{label}」回到未完成:它是必填项,重新上传之前这一步完成不了",signOffHint:"上传客户签字的文件。这一项没完成之前步骤不能完成。",customHardware:"自定义硬件",allProjectProducts:"项目全部产品",colDeliveredProduct:"交付产品",deliversLabel:"交付",hardwareDispatchHint:"硬件按这一步分批出库、结算,全部装好(或记为客户不装)、也没有现场待装件后才能完成。",startsTermHint:"完成这一步,这份实施单交付的产品或硬件(选了「按实施流程标记点生效」的)从完成那天开始合同期限;跳过这一步不开始。",hardwareNotInstalledHint:"还有 {n} 件硬件没装。每张出库单都结算(现场待装的件带进下一张出库单),或登记客户不装的件数后,才能完成这一步。",hardwareNotInstalledHintSite:"还有 {n} 件硬件没装,{site} 件留在现场待装。每张出库单都结算(现场待装的件带进下一张出库单),或登记客户不装的件数后,才能完成这一步。",hardwareNotInstalledTip:"还有硬件没装、有出库单没结算,或有件留在现场待装",skipConsequenceRelease:"会把还要装的 {n} 件硬件记为客户不装——这些件不再请款",skipHardwareInTransit:"还有 {n} 张出库单没结算——先结算或取消出库,再跳过这一步",skipHardwareOnSite:"还有 {n} 件留在现场待装——先带进一张出库单结算,再跳过这一步",hwBadge:"库存出库",hwInstalledOf:"已装 {installed} / {total}",hwInTransit:"在途 {n}",hwOnSite:"现场待装 {n}",hwReserved:"预留 {n}",hwReleased:"客户不装 {n}",hwOverInstalled:"超出合同 {n}",hwShort:"缺 {n}",hwNoAllocations:"自定义硬件——不在库存里管。这一步照普通里程碑请款。",hwClaim:"请款单",hwOverClaim:"超装请款单",hwViewInventory:"在库存里查看",salesHint:"这一步提示团队通知 Sales 跟进增购机会。步骤进行中或完成后,可以点「通知销售」。",notifySales:"通知销售(增购机会)",actionsTitle:"可执行的动作:",claimCreated:"已生成请款单 · {no}",triggered:"已触发:",notified:"已通知:",notifiedOpen:"(",notifiedClose:")",notifiedNameSep:"、",notifiedGroupSep:",",claimRef:"请款单 {no}",actionsMilestoneReached:"🎯 已达成{label},可执行的动作:",notifySalesTitle:"通知销售跟进",notifySalesSubtitle:"把这一步标成增购 / 交叉销售机会,通知销售团队跟进",notifySalesTo:"通知(销售人员)",notifySalesOwnerSuffix:"客户当前负责人(默认)",notifySalesToRequired:"请选择要通知的人",opportunityType:"机会类型",opportunityTypeRequired:"请选择机会类型",notifySalesContext:"给销售的背景说明",notifySalesContextPlaceholder:"客户说了什么、做了什么,让你觉得有增购机会……",notifySalesContextRequired:"类型选「其他」时请写明是什么机会",notifySalesUrgency:"紧急程度",notifySalesUrgencyRequired:"请选择紧急程度",notifySalesFollowUpBy:"建议跟进日期",notifySalesDraftQuotation:"同时建一张草稿报价,预填客户与背景说明",notifySalesSelf:"选的是你自己:不会给自己发通知,其余照常记录。",notifySalesSubmit:"通知销售",notifySalesDone:"已通知销售",notifySalesDoneQuotation:"已通知销售,并建了草稿报价 {no}。",notifySalesDoneSelf:"已记录。选的是你自己,没有发通知。",notifySalesDoneSelfQuotation:"已记录,并建了草稿报价 {no}。选的是你自己,没有发通知。",definitionRevision:"v{n}",definitionRevisionHint:"这份实施单按模板的这个版本建的。模板再发布新版本,它也不变。",start:"开始",complete:"完成",skip:"跳过",reopen:"回退",reassign:"重新指派",block:"标记阻塞",unblock:"解除阻塞",startDone:"步骤已开始",completeTitle:"将步骤标记为完成?",completeConfirm:"标记完成",completeConsequenceStep:"把第 {seq} 步「{step}」标记为已完成",completeConsequenceLocked:"这一步的勾选项与交付物就此锁定,之后要改只能回退",completeConsequenceNext:"自动开始下一个未开始的步骤",completeConsequenceClaim:"按里程碑「{label}」自动生成一张草稿请款单",completeConsequenceTerm:"这份实施单交付的、选了「按实施流程标记点生效」且还没生效的产品或硬件,从今天开始合同期限",completeDone:"步骤已完成——下一步已自动进入进行中",completeAllDone:"步骤已完成——全部步骤都已结束",linkedRecords:"关联记录",cantCompleteHint:"清单全部勾完、必需的交付物都上传之前,这一步不能标为完成(还差 {n} 项)。",progressComplete:"已完成 {done} / {total} 步",currentStepLabel:"第 {n} 步:{name}",whenDone:"{date} 完成",whenSkipped:"{date} 跳过",whenTarget:"目标:{date}",whenStarted:"{date} 开始",whenDays:"{n} 天",skipTitle:"跳过这一步?",skipPrompt:"跳过理由——这个交付环节将不再做(必填,会记入审计)",skipPlaceholder:"如:客户自备摄像头,无需安装",skipDone:"步骤已跳过",reopenTitle:"回退步骤",reopenWarning:"回退「{step}」会同时把它之后的 {n} 个步骤重置为未开始,实施本身也退回进行中。那些步骤可能已经开出过账单——里程碑产生的请款单不会因为回退而消失。",reopenNoFollowing:"回退「{step}」会让实施退回进行中。",reopenItemsKept:"勾选项与交付物刻意保留——它们记着「谁什么时候勾的」,是审计痕迹。确实要重做的,手工取消勾选即可。",reopenPrompt:"请填写理由(必填,会进审计):",reopenPlaceholder:"如:勘查报告需要重出",reopenReasonRequired:"请填写理由",reopenDone:"步骤已回退",blockTitle:"将实施标记为阻塞",blockSubtitle:"暂停 SLA · 升级给经理",blockNotify:"通知负责人与经理",blockConsequenceSla:"暂停 SLA:剩余天数不再减少,解除时目标日期按受阻的工作日往后顺延",blockConfirm:"标记阻塞",skipConsequenceNotDone:"把「{step}」标记为已跳过而不是已完成 —— 这一步本该产出的东西并不存在",skipConsequenceProgress:"它仍然计入进度分子,所以实施还能走到 100%",skipConsequenceNext:"下一步会自动开始",blockConsequenceFrozen:"冻结全部步骤:解除阻塞之前,开始 / 完成 / 跳过都推不动",blockConsequenceBoard:"这条实施会移到看板的「阻塞」列,等着有人来处理",blockConsequenceUnblock:"可以撤销:解除阻塞后回到原来的位置",blockPrompt:"阻塞的实施会单独排在看板一列等人处理,请说明卡在哪里(必填):",blockPlaceholder:"如:客户超级管理员迟迟未指派",blockDone:"已标记阻塞",unblockDone:"已解除阻塞",blockReasonLabel:"阻塞原因",blockReasonRequired:"请选择阻塞原因",blockDetails:"详细说明",blockDetailsPlaceholder:"具体卡在哪里",blockedAlertDetails:"该实施已阻塞,解除之前所有步骤都推不动(开始/完成/跳过都会被拒)。原因:{reason} —— {details}",completeNoteLabel:"完成备注(选填)",completionNote:"完成备注:{note}",cancelRun:"取消实施",cancelTitle:"取消这份实施?",cancelSubStatus:"项目保持「{status}」",cancelSubUnknown:"项目保持原状",cancelReasonLabel:"原因",cancelReasonRequired:"请选择原因",cancelNoteLabel:"备注(选填)",cancelConsequenceFinal:"这是终态,不能撤回;之后只能加备注。",cancelConsequenceScope:"只改这份实施单:项目、租户、权益和已经生成的请款单都不动。",cancelConsequenceNoNew:"系统不会再为这个项目建实施单,BOSS 也不会给客户发邮件。",cancelConfirmWord:"输入 {word} 确认",cancelConfirmMismatch:"请准确输入 {word}",keepRun:"保留实施",cancelDone:"已取消实施",cancelledAlert:"这份实施已于 {date} 取消,原因:{reason}。步骤不能再推进,仍可添加备注。",cancelledAlertNote:"这份实施已于 {date} 取消,原因:{reason}。备注:{note}。步骤不能再推进,仍可添加备注。",reassignTitle:"重新指派",reassignStepTitle:"指派步骤负责人",reassignDone:"已重新指派",related:"关联记录",viewContract:"查看合同",viewCustomer:"查看客户",kpiInProgress:"进行中",colOnboarding:"实施单",kpiBlockedBadge:"需处理",kpiBlocked:"已阻塞",kpiCompleted30d:"近 30 天完成",kpiAvgDays:"平均完成耗时",kpiDaysValue:"{n} 天"},billing:{from:"开票方",paymentInstructions:"收款指引",bankTransferTo:"银行转账至 {bank}",accountName:"户名:{name}",paymentReference:"付款参考号:{ref}",termsNet:"账期:NET {n}",lastReminder:"最近一次催款记录于 {at}(共 {n} 次)",sendReminder:"催款",reminderTitle:"催款",reminderNoEmail:"BOSS 不发邮件,这里只记下催了谁、用的什么语气 —— 邮件请自己发。",reminderRecipient:"收件人",reminderFinanceContact:"财务联系人",reminderPrimaryContact:"主联系人",reminderCustom:"自己填邮箱…",reminderCustomEmail:"邮箱",reminderEmailRequired:"请填写收件人邮箱",reminderRecipientRequired:"请选择收件人",reminderToneRequired:"请选择催款语气",reminderEmailInvalid:"邮箱格式不对",reminderTone:"催款语气",reminderMessage:"正文(不保存)",reminderCc:"抄送(不保存)",reminderCcPlaceholder:"例如财务负责人",reminderPrevious:"上一次催款记录于 {at} · 共 {n} 次",reminderSubmit:"记录催款",reminderRecorded:"已记录这次催款",currentlyWith:"当前处理方:",holderWithName:"{role}({name})",submittedByLine:"— 由 {name} 提交",actionsCount:"{n} 个可执行动作:{list}",noActions:"你没有可执行的动作",autoCreatedTitle:"到达计费里程碑时自动生成",autoCreatedBody:"实施单 {run} 的「{step}」{date}完成后,系统自动生成了这张请款单。由财务核对、补明细后再提交给客户。",autoCreatedOn:"于 {date} ",autoCreatedBodyDispatch:"实施单 {run} 的「{step}」下,出库单 {dispatch} 结算后,系统自动生成了这张请款单。由财务核对后再提交给客户。",autoCreatedBodyAmendment:"实施单 {run} 的出库单 {dispatch} 结算后,系统按变更单 {amd} 的单价,为这一批装好的件数自动生成了这张请款单:不在付款计划里。出库单登记签好的 DO 后才能提交。",autoCreatedBodyOverInstall:"实施单 {run} 的出库单 {dispatch} 结算时确认了超装({ovi}),系统为超出合同的件数自动生成了这张请款单:按合同单价算,不在付款计划里。出库单登记签好的 DO 后才能提交。",triggeringOps:"触发操作",triggeringOpsSub:"以下实施步骤完成后触发了这张请款单",triggeredClaim:"触发请款",nextPaymentNode:"下一个付款节点:{name}({pct}%)",nextPaymentNodeSub:"剩余可申报 {amount}",claimant:"请款方",claimantOwner:"负责人:{name}",claimantOwnerDept:"负责人:{name}({dept})",counterpartiesSub:"请款开给付款方,服务交付给服务对象",partyBilling:"付款",partyService:"服务",partyBes:"BES",paysInvoice:"支付发票",paysInvoiceWithRoles:"{roles} · 支付发票",runsProject:"负责 {name}",sameAsBillingParty:"与付款方相同",customerContact:"客户联系人",customerContactNone:"付款方没有主联系人,或你没有查看这个客户的权限。",stepperApprovedInvoiced:"已批准并开票",claimsSubtitle:"由合同付款计划与实施里程碑生成的里程碑请款。",claimsSubtitleMuted:"(不是 BOSP 的工程请款。)",invoicesSubtitle:"请款单批准时生成的发票,发给客户付款。",customerColumn:"客户",submittedColumn:"提交日期",claimFlowTitle:"请款 → 发票 → 收款流程。",claimFlowBody:"完成里程碑步骤会生成请款单;批准后自动开出{link};收到款项后发票与请款单都标为已付款。",claimFlowInvoice:"发票",createSubtitle:"只用于例外情况——请款单通常是自动生成的",createHintTitle:"请款单通常应当自动生成",createSubmit:"创建草稿请款单",subBilling:"付款方:",subService:"服务对象:",subContract:"合同",subMilestone:"里程碑:{name}",claimSummary:"请款摘要",flowCardTitle:"请款 → 发票 → 收款",flowDraft:"草稿",flowDraftSub:"还没提交",flowSubmitted:"请款已提交",flowAwaitingApproval:"待批准",flowDisputed:"争议中",flowApproved:"已批准",flowApprovalSub:"批准后自动开票",flowInvoiced:"已开票",flowAwaitingReissue:"待重新开票",flowPaid:"已收款",flowDue:"{date} 到期",disputeSubmit:"提出争议",kpiUnpaidAcross:"共 {n} 张发票",statusOverdueDays:"逾期 {n} 天",statusDueIn:"{n} 天后到期",statusDueToday:"今天到期",statusOverdueDaysLong:"逾期 {n} 天",statusSent:"已发送",amountColumn:"金额",dueDateColumn:"到期日",linkedClaim:"关联请款",fromClaim:"来自请款",invoicePaper:"发票",creditNotePaper:"红字发票",dateIssued:"开票日期",lineDescription:"描述",lineRate:"单价",gstWithRate:"GST({rate}%)",paymentStatus:"收款状态",invoiceTotalLabel:"发票合计",overdueDaysLong:"已逾期 {n} 天",paymentHistory:"收款记录",sourceClaimCard:"来源请款",approvedOn:"{date} 批准",paymentAmountWithCurrency:"收款金额({currency})",paymentPaidNote:"金额等于未收额时发票标为{paid};部分收款时发票保持未结清、余额相应减少。",outstandingSub:"未收 {amount}",methodDefault:"{method}(默认)",claimsTitle:"请款单",invoicesTitle:"发票",noCreateAlert:"请款单由里程碑自动生成——实施跟进里的里程碑步骤一完成就落一张,一个里程碑只生成一张。这里要做的是补明细,不是新建;「新建请款单」只用于例外情况。",claimNo:"请款单号",invoiceNo:"发票号",contract:"合同",project:"项目",milestone:"里程碑",claimType:"类型",amount:"金额",period:"服务期间",periodFrom:"服务期间(起)",periodTo:"服务期间(止)",source:"来源",autoCreated:"自动",manualCreated:"手工",triggerStep:"由「{step}」触发",createdBy:"发起人",sourceFilter:"生成方式",searchClaimPlaceholder:"单号或里程碑名",searchInvoicePlaceholder:"发票号或请款单号",tabAll:"全部",tabDraft:"草稿",tabSubmitted:"已提交",tabUnderReview:"审查中",tabInvoiced:"已批准并开票",tabPaid:"已收款",tabDisputed:"争议中",tabIssued:"已开票",tabOverdue:"已逾期(催收)",tabAwaitingReinvoice:"待重新开票",tabCredited:"已冲销",tabCreditNotes:"红字发票",reissueInvoice:"重新开票",awaitingReinvoiceAlert:"这张单的发票已被红字冲销,现在名下没有有效发票。核对明细无误后「重新开票」;开出的新发票金额取当前明细。",invoiceHistory:"开票记录",reissueConsequenceNew:"会签发一张新发票(新的 INV 编号,签发日为今天)",reissueConsequenceAmount:"金额取这张单当前的明细:{amount}(不含税,开票时按合同税率加 GST)",reissueConsequenceDue:"到期日按 NET 30 从今天重新计算",reissueConsequenceStatus:"这张单转回「已批准并开票」,被冲销的原发票与红字发票都留在开票记录里",reissueDone:"已重新开票:{no}",reissueDoneNoNo:"已重新开票",creditNote:"红字冲销",creditNoteTitle:"红字冲销 {no}",creditNeedsReversal:"这张发票已经收过款。要先在下方收款记录里把收款冲销掉、已收归零,才能红字冲销。",creditNeedsInvoicedClaim:"来源请款单现在是「{status}」。只有「已批准并开票」的才能冲销;争议中的请先撤回争议。",creditedAlert:"这张发票已被红字冲销,不再计入应收。冲销它的红字发票:",billTo:"开票抬头",billToMissing:"这张发票签发时尚未按账单主体开票,没有记录开票抬头。",billToLine:"抬头:{name}",viewBillingAccounts:"查看客户的账单主体",paymentTermsValue:"{n} 天",noDefaultBillingAccount:"付款方「{name}」没有默认账单主体,现在批准或重新开票会被拦下:发票要取它的抬头与账期。请先到客户详情新建一个账单主体(第一个自动成为默认),或把已有的设为默认。",noDefaultBillingAccountShort:"付款方没有默认账单主体,开不出发票",goSetBillingAccount:"去设置账单主体",noDefaultBillingAccountNoPerm:"请有账单主体维护权限的同事处理。",creditNoteOfAlert:"这是一张红字发票(负数金额),不收款、不逾期。它冲销的原发票:",creditReasonIs:"冲销原因:{reason}",creditConsequenceNote:"会开出一张红字发票(新的 CN 编号),金额为 {amount},把这张发票抵消掉",creditConsequenceOriginal:"这张发票本身不动(编号、金额、明细都保留),状态转为「已冲销」,不再计入应收",creditConsequenceClaim:"请款单 {no} 退回「待重新开票」,由 Finance 核对后重新开票",creditReasonLabel:"为什么要冲销这张发票?",creditReasonPlaceholder:"如:金额开错、开错客户(会记在红字发票上)",creditNoteDone:"已开出红字发票 {no}",creditNoteDoneNoNo:"已红字冲销",paymentReversal:"冲销记录",paymentReversed:"已冲销",reversalReasonIs:"冲销原因:{reason}",reversePayment:"冲销",reversePaymentTitle:"冲销这笔收款",reverseConsequenceRecord:"会新增一条金额为 {amount} 的冲销记录(日期为今天),原记录保留",reverseConsequencePaid:"这张发票的已收金额相应减少",reverseConsequenceStatus:"发票从「已收款」按到期日退回「已开票」或「已逾期」,请款单从「已收款」退回「已批准并开票」",reversalReasonLabel:"为什么要冲销这笔收款?",reversalReasonPlaceholder:"如:登记错了金额、退款给客户",reversePaymentDone:"已冲销这笔收款",approvedTabHint:"批准与开票在同一个事务里完成,所以批准过的单子都在「已批准并开票」下;「待重新开票」是发票被红字冲销后、等着重开的单。",collectionsHint:"催收不是独立模块、也不是独立状态,就是下面「已逾期」页签里的那批发票。",kpiOutstanding:"待批准",kpiOutstandingHint:"口径是已提交 + 审查中,不是「已开票未收款」——后者在发票页统计。",kpiUnderReview:"审查中",kpiApprovedThisMonth:"本月已批准",kpiAvgApproval:"平均批准耗时",kpiDaysValue:"{n} 天",kpiUnpaid:"未收款",kpiOverdue:"已逾期",kpiDueSoon:"30 天内到期",kpiDueSoonHint:"已开票、到期日在今天到 30 天后之间(含两端)的发票,金额是未收余额;已逾期的不算在这里,在「已逾期」里。",kpiPaidThisMonth:"本月已收",kpiPaidThisMonthHint:"本月 1 日到今天收到的款项合计,按收款日期算、不按登记时间:月初补登的上月收款算在上月。",kpiScope:"全量口径,不受下面的筛选与分页影响。",kpiMixedCurrency:"金额按面值直接相加、不做汇率换算,所以单据币种不唯一时不显示币种。",zeroAmountAlert:"这张单子生成时金额为 0,是正常的、不是异常:里程碑不会自动对应付款节点,金额由 Finance 补。请点「编辑」添加明细行(合同有付款计划时先选付款节点)——金额恒等于各行之和,不能直接填。",paymentNode:"付款节点",paymentNodeLabel:"{name}({pct}%)",paymentNodeNone:"未挂节点",paymentNodeNoPermission:"选择付款节点要读合同的付款计划,需要合同查看权限(boss.contracts.view)。",paymentNodePickContract:"先选合同",paymentNodeLoadFailed:"合同付款计划加载失败。",paymentNodeNoPlan:"这份合同没有付款计划,请款按合同不含税金额整体控额度。",paymentNodeNonePlaceholder:"不挂节点(计划外费用)",paymentNodeRequiredPlaceholder:"选择付款节点",paymentNodeRemainingShort:"剩余 {amount}",paymentNodeNoneHint:"不挂节点:计划外的例外费用,不占任何节点的额度,也不校验额度。",paymentNodeRequiredHint:"这份合同有付款计划:自动生成的请款单提交前必须选择付款节点。",nodeAmount:"节点额度",nodeClaimed:"已申报累计",nodeRemaining:"剩余可申报",nodeQuotaHint:"金额均不含税(开票时才加 GST);已申报累计不含草稿。",claimLimit:"本单最多可申报",claimLimitShort:"本单最多可申报 {amount}(不含税)。",claimLimitContract:"本单最多可申报 {amount}(不含税):合同不含税金额减去该合同其他已申报的请款单。",claimLimitDisputedHint:"金额均不含税。这张单在争议中、已计入节点的已申报累计,所以本单上限比剩余可申报多出本单原金额。",claimLimitNone:"未挂付款节点,不校验额度",claimLimitPickNode:"先选付款节点,选好后按节点控额度",fillFromLimit:"按剩余额度填一行",overLimitDraft:"明细合计超出本单上限 {amount}:可以先存草稿,但提交时会被拒绝。",overLimitBlocked:"明细合计超出本单上限 {amount}:争议中的单子保存时就校验额度,请调整明细。",submitNeedsAcceptance:"这张单对应的出库单还没登记签好的 DO(客户对超装的验收)。先在超装记录或出库单上登记,再提交。",submitNeedsAcceptanceAmendment:"这张单对应的出库单还没登记签好的 DO(客户对这一批装好的验收)。先在出库单上登记,再提交。",submitNeedsNode:"先点「编辑」选择付款节点 —— 这份合同有付款计划,自动生成的请款单必须挂节点才能提交。",submitOverLimit:"金额超出本单上限 {amount}(不含税),提交会被拒绝。",nodeRequiredAlert:"这份合同有付款计划:提交前请点「编辑」选择付款节点。",zeroAmountShort:"待补明细",submitNeedsAmount:"先补至少一行明细——金额为 0 的单子不能提交。",editableStatesHint:"只有草稿与争议中可编辑:交给客户之后再改金额,客户看到的和系统里的就对不上;争议中允许改,是因为「调整金额」本就是解决争议的路径之一。",counterparties:"相关主体",billingParty:"付款方(发票开给)",serviceRecipient:"服务对象(实际交付给)",breakdown:"里程碑明细",lineLabel:"说明",lineLabelRequired:"说明不能为空",qty:"数量",unitPrice:"单价",subtotal:"小计",noLines:"还没有明细行——不补明细,金额会一直是 0。",addLine:"添加明细行",linesTotal:"请款合计",linesTotalHint:"由服务端按明细行计算,合计本身不提交。",approvalTimeline:"审批时间线",createdStep:"已生成",submittedStep:"已提交",approvedStep:"已批准并开票",paidStep:"已收款",disputedStep:"已发起争议",byWhom:"由 {name}",pending:"待进行",description:"说明",justification:"理由说明",claimReason:"请款事由",invoice:"发票",viewInvoice:"查看发票",viewClaim:"查看请款单",create:"新建请款单",createTitle:"新建请款单(例外路径)",editTitle:"编辑请款单",createHint:"流程里标为请款里程碑的实施步骤完成时,系统会自动生成对应的里程碑请款。手工新建只用于周期外的情形(额外到场、定制服务、争议更正等)。事由与理由都会进审计日志。",formSourceContract:"来源合同",formClaimReason:"请款事由",formPeriodCovered:"覆盖期间",justificationPlaceholder:"为什么要手工建、而不是等自动生成。涉及变更单、合同修订或客户邮件的,写上编号或出处。",claimReasonOption:{EXTRA_SITE_TRIP:"额外到场(变更单驱动)",ADJUSTMENT:"对此前请款的调整或更正",CUSTOM_SERVICE:"标准里程碑以外的定制服务",EXTRA_MAINTENANCE:"超出合同次数的维保到场",OTHER:"其它(在说明里写清)"},contractRequired:"请选择合同",contractProjectClosing:"项目收尾中 · 不能新建请款单",contractProjectArchived:"项目已归档 · 不能新建请款单",reasonRequired:"请款事由必填",justificationRequired:"理由说明必填",milestoneNamePlaceholder:"如:临时到场一次",submit:"提交",submitDone:"已提交",submitTitle:"提交请款单",submitConsequenceLocked:"明细与金额就此锁定 —— 只有草稿与争议中的请款单可以编辑",submitConsequenceApproval:"进入财务审批,批准时会签发发票",startReview:"开始审查",startReviewDone:"已进入审查",startReviewHint:"可选步骤——已提交的单子可以直接批准。",approve:"批准并开票",approveTitle:"批准请款并生成发票",approveTwoActions:"这一步会做两件事:",approveActionMark:"把请款单 {no} 标为{status}",approveActionApproved:"已批准",approveActionInvoice:"向 {name}(付款方)开出发票",approveConfirm:"批准并开票",invoiceDueDate:"发票到期日",invoiceNotesOptional:"发票备注(选填)",invoiceNotesPlaceholder:"发票的内部备注……",dueDate:"到期日",dueDateHint:"不填按付款方默认账单主体的账期计算。",dueDateHintTerms:"不填按付款方默认账单主体的账期:批准日 + {n} 天。",notes:"备注",sendImmediately:"同时标记为已发送给客户",sendImmediatelyHint:"不会真的发邮件——邮件基建尚未落地,勾上只是记一个时间戳。别让人以为客户已经收到了。",approveDone:"已批准,发票 {no} 已签发",approveDoneNoNo:"已批准并签发发票",dispute:"发起争议",disputeTitle:"发起争议",disputeSub:"标记对这张请款单的异议,交由多部门协同处理",disputeParty:"发起方",disputePartyHint:"三方都可以发起,不是只有客户。",disputeType:"争议类型",disputeReason:"争议内容",disputePartyCustomer:"客户({name})",disputePartyInternal:"{party}(内部)",disputeReasonPlaceholder:"说明分歧在哪里……",disputeMovesTo:"请款单会转为{status}。可以改金额、发起变更,或撤回争议来解决。",disputeReasonRequired:"争议内容必填",disputeDone:"已发起争议",disputeAlert:"{party} 提出争议 —— {type}。{reason}",withdrawDispute:"撤回争议",withdrawOccurrence:"撤回登记",withdrawOccurrenceConsequenceFinal:"会把 {no} 标为已撤回——单子留着备查,不能再编辑或提交",withdrawOccurrenceConsequenceCount:"会从合同上「{line}」的已登记次数里减去 {n} 次",withdrawOccurrenceReason:"原因(选填)",withdrawOccurrenceDone:"已撤回登记",withdrawnAlert:"这次按次登记已于 {time} 撤回,请款单留作记录。",paymentNodeOccurrence:"按次请款不挂付款节点,也不占任何节点的额度。",paymentNodeOverInstall:"超装请款不挂付款节点,也不占任何节点的额度。",paymentNodeAmendment:"加设备的请款单按变更单单价出,不挂付款节点,也不占任何节点的额度。",occurrenceLineLocked:"登记的次数——要改请撤回后重新登记",withdrawConsequenceReview:"把这单请款退回争议之前的「审查中」",withdrawConsequenceInvoiced:"把这单请款退回「已批准并开票」—— 它回不到审查态,因为发票已经签发,再批一次会被拦下",withdrawConsequenceReopen:"如果争议其实没谈拢,三方仍可以重新发起",markSentConsequenceStamp:"在这张发票上记录你发送它的时间",markSentConsequenceNoEmail:"不发送任何邮件 —— BOSS 不发邮件,发票仍要你自己送到客户手上",withdrawDone:"已撤回争议",reject:"退回",rejectTitle:"退回请款单",rejectConsequenceDraft:"请款单回到草稿,由编制的人修改后重新提交",rejectConsequenceQuota:"不再计入已申报,所占的付款节点额度随之释放",rejectConsequenceReapprove:"改完重新提交、重新批准时会自动开出新发票,不需要再点「重新开票」",rejectConsequenceReason:"退回原因会显示在请款单上,并记入审计",rejectReasonLabel:"为什么退回?编制的人要据此修改",rejectReasonPlaceholder:"如 调整金额缺依据,请补附件说明",rejectDone:"已退回草稿",rejectedAlert:"已被退回:{reason}({by},{at})。请修改后重新提交。",rejectedStep:"已退回",rejectedTag:"被退回",rejectedAtHint:"{at} 被退回,等待修改后重新提交",contractClaimed:"合同已申报累计",contractClaimedHint:"这份合同下已提交及之后状态的请款单金额之和(不含税),本单已申报时也算在内;草稿不算。",approvalNote:"审批意见",approvalNoteHint:"存到请款单上,同时写入发票备注。",customerFilter:"客户(付款方)",createdFrom:"创建日期起",createdTo:"创建日期止",customer:"客户",issuedDate:"开票日",dueFrom:"到期日起",dueTo:"到期日止",invoiceTotal:"合计",amountPaid:"已收",outstanding:"未收",sentAt:"标记发送于",notSent:"未标记发送",markSent:"标记为已发送",markSentDone:"已标记为已发送",noEmailHint:"发送目前靠人工:「标记为已发送」与批准时的「同时标记为已发送」都只写一个时间戳,系统不发邮件。",recordPayment:"登记收款",remittanceOptional:"汇款凭证(选填)",remittance:"汇款凭证",uploadRemittance:"附上汇款凭证",replaceRemittance:"替换",replaceRemittanceTitle:"替换汇款凭证?",replaceRemittanceGone:"替换「{name}」,这笔收款上不再显示旧文件",replaceRemittanceAudit:"替换会记进发票的操作历史",remittanceUploaded:"汇款凭证已附上",remittanceNotAttached:"收款已登记,但汇款凭证没有附上,请到收款记录里这笔收款上补传。",recordPaymentTitle:"登记收款",paymentAmountPlaceholder:"输入本次收到的金额",fillOutstanding:"填入未收额",paidDate:"收款日期",method:"收款方式",reference:"流水号",referencePlaceholder:"如 TXN-001",paymentHint:"允许分次收款。超收会被直接拒绝——不属于这张发票的钱记进来,对账时会变成一笔说不清来源的差额。",outstandingIs:"本张发票未收:{amount}",overpayError:"超过未收余额 {amount}。",amountRequired:"收款金额必须大于 0",paymentDone:"已登记收款",paymentSettled:"已登记收款——本张发票收满,请款单同时标记为已收款",noPayments:"还没有收款记录。",recordPaymentButton:"登记收款",recordedBy:"登记人 {name}"},workflow:{subtitle:"按实施类型定义实施步骤顺序的模板。合同变为 Active 时,自动按匹配的流程生成实施单。",create:"新建流程",createTitle:"新建流程模板",createSubtitle:"自定义一套实施步骤",editTitle:"编辑模板信息",editSubtitle:"名称、描述、匹配条件不进版本,保存即生效。",editInfo:"编辑信息",nameEn:"流程名称(英文)",nameZh:"流程名称(中文)",namePlaceholder:"如:Express SW Onboarding",zhPlaceholder:"中文(选填)",descriptionEn:"描述(英文)",descriptionZh:"描述(中文)",nameRequired:"请填写英文名称",matchCondition:"自动匹配条件",matchRequired:"请选择自动匹配条件",matchHint:"每个产品的实施单按它交付的是软件还是硬件匹配,「硬件 + 软件」不再自动匹配。只有发布过的模板参与匹配;从未发布的模板还不占用条件。",manualHint:"不会被自动选中,目前也没有手工选用的入口。",baseOn:"基于已有模板",startFromScratch:"从空白开始",copyOf:"复制:{name}({n} 步)",createInfo:"建好后可以增删、排序步骤,并逐步设置请款与 Sales 提示。",createInfoMatch:"发布一次后,符合条件的合同才会选中它。",createSubmit:"创建并编辑步骤",createdHint:"模板已建好。添加或调整步骤后发布一次,符合条件的合同才会选中它。",createdHintManual:"模板已建好,可以接着添加或调整步骤。",stepsCount:"{n} 步",revisionValue:"v{n}",neverPublished:"从未发布",statusActive:"已启用 · 已发布",default:"默认模板",defaultHint:"合同一个模板都匹配不上时用它。默认模板只有一个,这里改不了。",unpublished:"有未发布的改动",pillUnpublished:"未发布",autoMatch:"自动匹配:",neverPublishedAlert:"这个模板还没发布过:不参与自动匹配,合同激活不会用到它。步骤改好后发布一次。",workingCopy:"工作副本",workingCopyHint:"你在改的是工作副本:发布之前不影响任何实施单。",noSteps:"还没有步骤。",addStep:"+ 添加步骤",moveUp:"上移",moveDown:"下移",duplicate:"复制",copySuffix:"(副本)",stepMenu:"步骤操作",slaValue:"SLA {n} 个工作日",checklistCount:"{n} 项勾选",deliverableCount:"{n} 项交付物",stepTitleAdd:"添加步骤",stepTitleEdit:"编辑步骤",stepTypeContinuous:"持续阶段",stepTypeContinuousDesc:"在维保合同期内一直进行:永不完成、不计入进度,总是排在所有普通步骤之后;不能请款,也不能要求签字。",stepNameEn:"步骤名(英文)",stepNameZh:"步骤名(中文)",stepNamePlaceholder:"如:Pre-Survey",descPlaceholder:"这一步做什么……",stepNameRequired:"请填写英文步骤名",stepNameDuplicate:"这个模板里已经有同名的步骤",responsibility:"负责与时限",ownerRole:"负责角色",ownerRoleSuffix:"(仅提示)",sla:"SLA(工作日)",slaHint:"计划日期按周一到周五计算,不扣公众假期。",slaRange:"1 到 365 之间",completion:"完成条件",completionSuffix:"——满足什么才算完成",deliverables:"必需交付物",deliverablesSuffix:"(须上传)",checklist:"勾选项",checklistSuffix:"(必需项要勾完)",newDeliverable:"新交付物…",newChecklistItem:"新勾选项…",itemLabelZh:"(中文)",addDeliverable:"+ 添加交付物",addChecklistItem:"+ 添加勾选项",itemLabelRequired:"请填写英文名称",itemRequired:"必需",removeItem:"移除",autoActions:"完成时的自动动作",milestone:"生成请款单",milestoneHint:"标记完成时自动生成请款单草稿。合同付款计划里有节点挂在这一步时金额自动带上,否则由财务补。",milestoneLabelEn:"里程碑名(英文)",milestoneLabelZh:"里程碑名(中文)",milestoneLabelRequired:"请填写英文里程碑名",salesPrompt:"提示通知 Sales",salesPromptHint:"标记增购机会:实施单上这一步会出现「通知销售」,给选定的销售发站内通知。",signOff:"需要客户签字",signOffHint:"没有上传客户签字的文件,这一步不能完成。",hardwareDispatch:"触发硬件出库",hardwareDispatchHint:"从库存出库硬件去安装——硬件实施单按这一步出库并结算。",hardwareDispatchTaken:"已有别的步骤触发硬件出库,一个模板只能有一步。",startsTerm:"开始合同期限",startsTermHint:"合同里选了「按实施流程标记点生效」的项,期限从这一步完成那天起算。",startsTermTaken:"已有别的步骤开始合同期限,一个模板只能有一步。",continuousDisabled:"持续阶段不能设置。",saveStep:"保存步骤",deleteStepTitle:"删除步骤",deleteStepConsequence:"会从工作副本里删掉「{name}」及其勾选项和交付物。",deleteStepRecover:"已发布的版本不受影响;可以用「放弃改动」把工作副本恢复成当前版本。",deleteStepRecoverNever:"这个模板从未发布过,删掉之后没有版本可以恢复。",stepConflict:"这个模板刚被别人改过,后面的步骤列表已刷新。你填的内容还在,对照最新的步骤核对后再保存。",stepConflictEdit:"保存会覆盖最新列表里的第 {n} 步「{name}」。",stepConflictAppend:"你在改的那一步已经不在了,保存会把你填的加到末尾。",versions:"版本与发布",versionsLead:"{count}按 v{v} 运行。发布新版本{not}改变它们。",versionsLeadCount:"{n} 份在用的实施单",versionsLeadNot:"不会",versionsNone:"还没有发布过的版本。",publishedOn:"发布于 {date}",revisionActive:"{n} 份在用",revisionTooltip:"{name} 发布于 {time}",revisionTooltipNone:"无发布人(迁移生成)· {time}",compare:"比较",publish:"发布新版本",publishFirst:"发布",publishNoChanges:"没有未发布的改动。",publishNoSteps:"先添加至少一个普通步骤。",publishTitle:"发布 v{n}",publishConsequenceNew:"之后新建的实施单都会照这一版复制步骤。",publishConsequenceKeep:"已建的实施单不变,仍按各自创建时的版本。",publishConsequenceNext:"发布之后激活的合同会用 v{n}。",publishConsequenceStay:"在用的实施单仍按 v{n},不会迁移。",publishConsequenceFirst:"这个模板开始参与自动匹配({condition})。",publishConsequenceManual:"它的匹配条件是「仅手动」,不会被合同自动选中。",publishNoteLabel:"这一版改了什么?(选填)",publishNotePlaceholder:"如:新增 AI 额度步骤",publishChangesLead:"与 v{n} 相比:",publishStepsLead:"第一版的步骤:",published:"已发布 v{n}",takeOverTitle:"接管匹配条件",takeOverConsequenceHolder:"「{other}」目前占用「{condition}」,会在同一步里改成「{manual}」。",takeOverConsequenceNext:"之后激活、符合这个条件的合同改用「{name}」。",takeOverUnknown:"另一个已发布的模板",takeOverAction:"接管",discard:"放弃改动",discardTitle:"放弃未发布的改动",discardConsequence:"工作副本会恢复成 v{n},未发布的步骤改动全部丢掉。",discarded:"工作副本已恢复成 v{n}",legend:"步骤配置图例",badgeClaim:"$ 请款",badgeSales:"Sales",badgePhase:"持续阶段",badgeSign:"签字",badgeInventory:"库存",badgeTerm:"期限",legendClaim:"该步骤完成时自动生成请款单草稿。",legendSales:"该步骤提示团队通知 Sales 跟进追加销售。",legendSign:"没有客户签字,该步骤不能完成。",legendInventory:"这一步从库存出库硬件。",legendTerm:"完成这一步,实施单交付的产品或硬件开始合同期限。",legendPhase:"持续阶段——在维保合同期内一直进行。",usage:"使用情况",usageActive:"在用的实施单",usageCompleted:"已完成(累计)",usageAvg:"平均耗时",usageAvgValue:"{n} 周",usageScopeHint:"按你的数据范围统计,与实施列表一致。",matchingTitle:"怎么匹配:",matchingText:"合同里每个产品各开一份实施单,按它交付的是什么选模板。软件 → {sw};硬件(目录型号或自定义硬件)→ {hw};没有模板占用这个条件 → {fallback}。「硬件 + 软件」不再自动匹配。",vsProvisioningTitle:"实施流程与供应的区别。",vsProvisioningText:"这里定义的是 BES 员工和客户一起走的{manual},按实施类型划分。每个产品的{auto}(建租户、推送权益到 Control、配置 SSO)另外定义在它的供应流水线模板里,在产品页上。",vsManual:"人工实施步骤",vsAuto:"自动化技术开通",compareTitle:"比较版本",compareFrom:"从",compareTo:"到",compareHeader:"{from} → {to}",workingCopyOption:"工作副本(未发布)",compareSame:"没有差异。",comparePick:"两边各选一个版本再比较。",compareReordered:"步骤顺序有调整。",changeLine:"{kind}:{name}",changeAdded:"新增",changeRemoved:"删除",changeChanged:"修改",addedAfter:"排在「{name}」之后",addedAtTop:"排在最前",renamedFrom:"原名「{name}」",titleWith:"{name}({extra})",valueChange:"{field}:{from} → {to}",listChange:"{field}:+{plus} / −{minus}",valueOn:"开",valueOnWith:"开({name})",valueOff:"关",valueNone:"无",field:{stepName:"名称",description:"描述",stepType:"类型",ownerRole:"负责角色",slaWorkingDays:"SLA(工作日)",milestone:"请款",salesPrompt:"Sales 提示",signOffRequired:"客户签字",hardwareDispatch:"硬件出库",startsTerm:"开始合同期限",checklist:"勾选项",deliverables:"交付物"},noTemplates:"还没有流程模板。"},handover:{scopeNote:"合同结束时的项目收尾:把数据交还客户、把租户交给客户,最后腾退。",noCreateAlert:"交接单自动生成——合同到期前 90 天,或提前终止的那一刻。一个合同同时只有一条未取消的交接;合同没有关联项目就不会有(纯硬件单没有要交接的系统)。这里没有「新建交接」。",pdpaNote:"PDPA:客户数据在合同结束(到期或提前终止)后保留 30 天,随后不可逆删除。这个模块存在的意义就是确保客户在这个窗口关闭前拿到自己的数据。",handoverNo:"交接编号",customer:"客户",project:"项目",contract:"合同",trigger:"触发来源",owner:"负责人",noOwner:"未指派",reassign:"重新指派",reassignTitle:"重新指派交接负责人",reassignHint:"负责人会在「我的待办」里收到这条交接的待办;清空表示不指派任何人。",reassigned:"负责人已更新",unassigned:"已取消指派",searchPlaceholder:"交接编号",product:"产品",kpiInProgress:"进行中",kpiPendingExport:"待导出数据",kpiCompleted90d:"近 90 天完成",kpiAvgClosure:"平均结清耗时",kpiDaysValue:"{n} 天",kpiOverdue:"已逾期",kpiOverdueHint:"合同已经结束、交接还没走完——与发票页的「已逾期」不是一回事",pageSubtitle:"项目收尾交接。合同到期前 90 天自动创建,提前终止的合同在终止时立即创建。",metaStarted:"交接发起",daysShort:"{n} 天",skipStep:"跳过这一步",markStepComplete:"完成这一步",stepShort:{1:"已通知",2:"数据已准备",3:"客户下载",4:"验收",5:"腾退"},stepTitle:"第 {n} 步 · {name}",stepLocked:"未解锁",retentionWindow:"保留窗口",retentionDays:"{n} 天",importantLabel:"重要:",importantBody:"客户必须在 {date} 之前下载全部数据。过了这一天,客户的全部数据将按 PDPA 不可恢复地删除。",cancelSubtitle:"用于合同续签、不再终止的情况",cancelTypeToConfirm:"输入 {word} 确认",keepHandover:"保留交接",reminderSend:"发送",kpiInProgressSub:"合同 90 天内到期或已到期",kpiPendingExportSub:"还没登记数据导出",kpiActionBadge:"待处理",kpiCompletedSub:"五步全部结束",kpiAvgClosureSub:"近 90 天",menuReadOnly:"已完成、已取消的交接只读。",footTitle:"交接在合同到期前 90 天自动发起,合同提前终止时也会发起。",footBody:"5 个标准步骤:通知 → 数据导出 → 客户下载 → 验收 → 腾退。",tabActive:"进行中",tabAll:"全部",progress:"进度",progressValue:"{done} / {total} 步",colHandover:"交接单",startedOn:"{date} 发起",completedOn:"{date} 完成",linkedRecords:"关联记录",linkedProject:"项目",linkedContract:"合同",linkedCustomer:"客户",closed:"已结束",contractEnds:"合同结束日",daysLeft:"还有 {n} 天",overdueDays:"已逾期 {n} 天",autoDeletion:"数据删除日",deletionCountdown:"还有 {n} 天",deletionPassed:"删除窗口已过",stepDesc:{1:"交接发起时向客户发出收尾通知",2:"导出客户数据并登记存放位置",3:"客户须在 PDPA 保留期内下载自己的数据",4:"客户签署交接验收单 · 自下载之日起 14 天内",5:"停用租户 · 数据进入保留期,到期自动删除"},completedLine:"{time} 完成",skippedLine:"{time} 跳过",downloadStatus:"客户下载状态",downloadedOn:"客户已于 {time} 下载数据",notDownloadedYet:"客户还没有下载",notDownloadedBody:"合同到期后,数据按 PDPA 只保留 {n} 天,之后自动删除。",stepCurrentHint:"这一步做完后,用页头的「跳过」或「标记完成」推进。",steps:"收尾步骤",stepLockedHint:"请先完成上一步——步骤必须按顺序做。",deprovisionNotYet:"腾退会停掉客户的实例、收回访问,合同结束({date})之后才能完成或跳过这一步。",stepCurrent:"下一步做这个",stepName:{1:"关闭通知",2:"数据已准备",3:"客户下载数据",4:"验收签署",5:"腾退"},stepNote:"说明",stepSkipReason:"已跳过:{reason}",doneBy:"{name} · {time}",notStarted:"未开始",complete:"完成",skip:"跳过",markDataExported:"登记导出",sendReminder:"催办",cancel:"取消交接",completeTitle:"标记这一步完成?",markComplete:"标记完成",completeNote:"说明",completeNotePlaceholder:"一句话说明发生了什么",step2ExportHint:"「登记导出」会一并完成这一步,同时留下数据究竟去了哪;直接完成则这一步什么记录都没有。如果 BES 根本不出包,该用「跳过」并写明理由。",exportOnSkippedHint:"「数据已准备」这一步已被跳过,所以这里登记只保存元数据、步骤仍保持「已跳过」。这是有意为之:当时决定不出包、后来还是补了一份,这份记录同样该留下。",step3NoteHint:"系统里没有客户下载的记录,所以完成这一步等于人工声明「数据已经通过别的渠道交到客户手里」。请说明是怎么交付的——审计日志里留下的就是这句话。",step3NoteRequired:"请说明数据是怎么交付的",effectStep3:"完成后记为「客户已取到数据」,并给客户 14 天时间完成验收签署。",effectStep4:"完成后记录验收签署,并让项目进入收尾期。",effectStep5:"完成后执行腾退:租户封存、名下实例停机,并收回这个项目及其权益下未结束的临时访问授权。这一步不删数据——数据在保留窗口结束后才由保留策略清理。",completeDone:"已完成该步骤",completeAllDone:"已完成该步骤——整条交接结束",skipTitle:"跳过这一步?",skipSubtitle:"需要书面理由 · 按高风险记入审计",skipWarning:"跳过意味着这一步不做了。步骤会标记为「已跳过」而不是「已完成」,这一步的副作用也不会执行,流程只是继续往下走。",skipNoSideEffect4:"跳过它,项目不会进入收尾期。",skipNoSideEffect5:"跳过它,不会封存租户、也不会停机实例。",skipReason:"为什么跳过",skipReasonPlaceholder:"如:客户自行从 BOSP 导出,无需 BES 出包",skipReasonRequired:"跳过理由必填",skipDone:"已跳过该步骤",exportTitle:"登记数据导出完成",markExported:"标记已导出",exportFormatDefault:"SQL dump + CSV(默认)",exportFormatCustomer:"客户指定格式",exportLocation:"存放位置",exportLocationPlaceholder:"s3://… · SFTP 路径 · 交接目录",exportLocationRequired:"存放位置必填",exportFormat:"格式",exportFormatPlaceholder:"选一项,或直接填写格式",exportSha256:"SHA-256",exportSha256Placeholder:"供客户核对文件包完整性",notifyCustomer:"同时标记为已通知客户",exportDone:"已登记导出",exportMeta:"导出信息",noExport:"还没有登记",exportedAt:"登记于",reminderTitle:"催办",reminderTypeLabel:"语气",recipient:"接收人",recipientPlaceholder:"pm{'@'}customer.com",message:"内容",reminderHint:"这不会真的发出去——邮件基建尚未落地。它只记录「催过一次、催的是谁」。",reminderDone:"已记录催办",reminders:"催办",reminderCount:"已催 {n} 次",lastReminder:"最近一次",neverReminded:"还没催过",reject:"退回",rejectTitle:"退回交接、打回重做",rejectDone:"已退回重做",rejectReasonLabel:"哪里不合格?",rejectReasonPlaceholder:"例如:导出包缺少 2026 年 6 月之后的巡检记录,请补齐后重新提供",rejectConsequenceStatus:"把交接退回「数据导出中」—— 这不是取消,交接仍在跑、只是打回重做",rejectConsequenceStep:"把第 3 步(客户下载数据)重置为待处理,需要重新做一次",rejectConsequenceDeadline:"清空 14 天签署期 —— 重新完成第 3 步时才重新起算",rejectConsequenceDownloaded:"保留「客户确实下载过数据」这条记录 —— 退回不会撤销已经发生的事",cancelTitle:"取消这条交接",cancelWarning:"通常是因为合同续签了、没有要交接的东西。取消后这条交接转为只读。已经导出的数据不会被删——那些包还在存储里,要走数据保留流程单独清理。",cancelReuseHint:"取消不占位:这份合同将来再次接近到期时,会重新生成一条新的交接。",cancelReasonLabel:"取消原因",cancelDone:"已取消交接",customerDownloaded:"客户已取到数据",notDownloaded:"未登记",acceptanceDeadline:"验收截止",signedOffAt:"验收签署于",related:"关联记录",timeline:"PDPA 保留时间线",noEmailHint:"这里没有任何东西会发邮件——关闭通知、「数据已备好」、催办,全都只记一个时间戳。别读成「客户已经收到了」。",noExportPackages:"没有导出包列表(BOSP 项目数据 / 照片库 / 报表,带记录量与大小)——那依赖文件服务,尚未落地。当前能登记的就是上面这组元数据。",accessRevocation:"临时权限处理结果",revokedGrantCount:"已收回 {n} 条授权",revokedGrantDone:"腾退时收回:这个项目及其权益下待审批与审批通过的授权都已关闭。",revokedGrantNone:"腾退已执行,但当时没有需要收回的授权。",revokedGrantSnapshot:"这是腾退那一刻的快照,不是实时值。腾退之后新申请的临时访问不计在内。",revokedGrantPending:"尚未腾退",revokedGrantPendingHint:"临时权限在第 5 步「腾退」完成时收回。在那之前没有结果可显示——这与「一条都没收回」不是同一件事。"},task:{pageSubtitle:"派给你的报价、合同、实施与交接事项,按紧急程度排列。",snoozeView:"暂时隐藏",hideTasksFor:"隐藏待办",snooze1h:"1 小时",snooze4h:"4 小时",snoozeTomorrow:"到明天上午 9 点",snoozeCustom:"自定义…",snoozeFoot:"到时间后,隐藏的待办会重新出现。",snoozedUntil:"已隐藏至 {time}。在此之前已有的待办暂不显示,新出现的照常显示。",showNow:"立即显示",snoozed:"待办已隐藏至 {time},期间新出现的待办照常显示。",unsnoozed:"全部待办已重新显示",snoozeCustomTitle:"暂时隐藏",snoozeUntil:"隐藏到",snoozeUntilPlaceholder:"选择日期和时间",snoozeCustomHint:"最长 30 天。期间新出现的待办照常显示。",snoozeApply:"隐藏",kpiOverdue:"已逾期",kpiUrgent:"紧急",kpiOverdueHint:"需要立即处理",kpiDueToday:"今天到期",kpiToday:"今天",kpiDueTodayHint:"下班前",kpiThisWeek:"本周",kpiThisWeekHint:"本周日前",kpiCompleted:"已完成(7 天)",kpiCompletedHint:"最近 7 天",kpiTrend:"{arrow} 较上周 {pct}%",tabAll:"全部",tab:{QUOTATION:"报价",CONTRACT:"合同",ONBOARDING:"实施",HANDOVER:"交接"},sortedBy:"排序",sortedByDue:"到期日 ↑",titleDiscount:"审批 {no} 的折扣(减 {pct}%)",titleOnboarding:"{project}:{step}",titleHandover:{2:"为 {customer} 准备数据导出",3:"腾退前确认 {customer} 已下载数据",4:"取得 {customer} 的验收签字",5:"保留期满后为 {customer} 腾退"},stepOf:"第 {seq}/{count} 步",descDiscount:"{name} 申请了 {pct}% 的折扣,需要审批。",descDiscountLimit:"{name} 申请了 {pct}% 的折扣(超过 {limit}% 的上限),需要审批。",descOnboardingStep:"实施的第 {seq} 步,共 {count} 步。",descHandoverStep:"收尾交接的第 {seq} 步,共 {count} 步:{step}。",overdueDays:"逾期 {n} 天 | 逾期 {n} 天",dueToday:"今天到期",noDueDate:"没有到期日",dueOn:"{date} 到期",requestedBy:"申请人 {name}",pctOff:"减 {pct}%",approveTitle:"批准折扣",approveSubtitleLimit:"{off}(超过 {limit}% 的上限)",requestedByLabel:"申请人",original:"原价",afterDiscount:"减 {pct}% 后",approveReason:"意见",optional:"(选填)",approvePlaceholder:"写给审计日志的备注…",approveFoot:"批准会记入审计日志,包括你的账号、时间和意见。",confirmApprove:"确认批准",denyTitle:"驳回折扣申请",denySubtitle:"{no} · 申请人 {name}",denyReason:"驳回原因",denyPlaceholder:"{name} 会看到这段原因,并记入审计…",denyReasonRequired:"请写驳回原因",denyFoot:"驳回必须写原因。{name} 可以调整后重新提交。",confirmDeny:"确认驳回",theRequester:"申请人",approve:"批准",deny:"驳回",openOnboarding:"打开实施",alreadyHandled:"这条申请已经有人处理过了,列表已刷新。",emptyAll:"目前没有派给你的待办。报价、实施和交接产生的待办会自动出现在这里。",emptyTab:"这一类下没有待办。",emptySnoozed:"待办暂时隐藏了,点上方的「立即显示」可以重新看到。",footLead:"待办由业务事件自动生成",footBody:"折扣审批申请、实施步骤、交接节点。待办不能手工创建,会按流程状态自动出现。"},notificationTpl:{pageSubtitle:"按事件类型配置通知:通知谁、走哪些渠道、写什么。",create:"新建模板",infoLead:"匹配的事件发生时,模板自动触发。",infoBody:"每个模板绑定一个 boss.* 事件,并定义:启用的渠道、收件人规则(负责人 / 角色 / 指定员工 / Slack 频道)、各渠道带 {'{'}变量{'}'} 的正文。系统事件(审计、开通)的模板不能停用,只能改渠道和收件人。",kpiActive:"启用中的模板",kpiActiveHint:"覆盖 {n} 个分类 | 覆盖 {n} 个分类",kpiDisabled:"已停用",kpiDisabledHint:"暂不触发",tabAll:"全部",searchPlaceholder:"搜索模板名称或事件码",cannotDisable:"不能停用",active:"启用",disabled:"停用",emptyTab:"这个分类下没有模板。",emptySearch:"没有符合条件的模板。",selectHint:"选择一个模板查看配置。",enabledSwitch:"启用",triggerCondition:"触发条件",noConditions:"(这类事件每次发生都触发)",recipients:"收件人",roleLabel:"角色:{role}",roleMembers:"{role} 角色的全部员工({n} 人) | {role} 角色的全部员工({n} 人)",staffMember:"指定员工",slackChannel:"Slack 频道",noRecipients:"还没有收件人。",channelTemplate:"{channel} 模板",preview:"预览",noContent:"还没有写文案。",subject:"主题:",to:"收件人:",availableVariables:"可用变量",updatedBy:"最后由 {name} 修改 · {time}",created:"模板已创建。配好文案和收件人后再启用。",saved:"模板已保存",enabledMsg:"模板已启用",disabledMsg:"模板已停用",disableTitle:"停用这个模板",disable:"停用",disableConsequence:"会让这个模板不再用于 {event} 的通知",disableReversible:"随时可以重新启用,文案和收件人都会保留",prereq:{NO_CHANNEL:"至少选一个渠道。",CHANNEL_CONTENT_MISSING:"请写 {channel} 的文案。",NO_RECIPIENT:"至少加一条收件人。",NO_SLACK_CHANNEL:"选了 Slack,还要加一个 Slack 频道收件人。"},createTitle:"新建通知模板",name:"模板名称",namePlaceholder:"例如:合同已激活",nameRequired:"请填写模板名称",category:"分类",categoryPlaceholder:"默认取事件的分类",categoryRequired:"请选择分类",eventCode:"事件码",eventPlaceholder:"选择事件",eventRequired:"请选择事件",description:"描述",channels:"渠道",createHint:"新建的模板是停用的,配好文案和收件人后再启用。",createAndConfigure:"创建并配置",editTitle:"编辑模板",conditionHint:"全部条件都满足才触发;不加条件表示这类事件每次发生都触发。",conditionField:"字段",conditionOperator:"比较",conditionValue:"值",conditionValues:"值(每输入一项按回车)",addCondition:"添加条件",ownerPlaceholder:"选择负责人",rolePlaceholder:"选择角色",addRecipient:"添加收件人",messages:"文案",tokenHintPre:"用",tokenHintPost:"写变量,鼠标停在变量上可看样本值。",noChannelHint:"先在上面选渠道,再写对应的文案。",emailSubject:"邮件主题",inAppTitle:"站内通知标题",bodyOf:"{channel} 正文",unknownVariables:"这个事件没有这些变量:{vars}",fixBeforeSave:"保存前请先改好",problemCondition:"每条触发条件都要选字段、比较方式并填值。",problemRecipient:"每条收件人都要填完整;Slack 频道形如 #sales-wins。",problemUnknown:"{channel} 的文案用了这个事件没有的变量:{vars}",previewTitle:"模板预览",previewSubtitle:"用样本数据渲染",previewEmpty:"没有可预览的渠道。",optionalVar:"投递时可能为空"},inbox:{pageSubtitle:"系统通知与告警。需要处理的事项在",quickSelect:"快速选择",customRange:"自选区间",from:"起始日",to:"结束日",toWord:"至",apply:"应用",range:{TODAY:"今天",LAST_7:"近 7 天",LAST_30:"近 30 天",LAST_90:"近 90 天",THIS_YEAR:"今年"},markAllRead:"全部标为已读",preferences:"通知偏好",kpiUnread:"未读",kpiUnreadHint:"所选区间内",kpiCritical:"严重告警",kpiUnreadBadge:"未读",kpiCriticalNone:"没有未读的严重告警",kpiToday:"今天",kpiTodayHint:"已读 {read} · 未读 {unread}",kpiAvg:"日均 {n} 条",tabAll:"全部",tabUnread:"未读",showing:"显示",group:{TODAY:"今天",YESTERDAY:"昨天",THIS_WEEK:"本周早些时候",EARLIER:"更早"},minAgo:"{n} 分钟前",hAgo:"{n} 小时前",emptyAll:"这个区间内没有通知。",emptyUnread:"这个区间内没有未读通知。",emptyTab:"这个区间内没有这类通知。",footLead:"通知只做告知,需要处理的事项在我的待办。",footBody:"收到哪些通知按事件类型配置,见",footAnd:"里的全局默认,以及",footSettings:"个人设置 → 通知",footTail:"里你自己的渠道(Email / Slack / 站内)。"},notifPrefs:{channelsTitle:"按分类选择渠道",channelsSubtitle:"选择哪些业务通知发给你、走哪些渠道。",category:"分类",outboundPendingShort:"对外发信上线后生效",alwaysOn:"这些通知不管怎么设都会进收件箱:{events}。",listSep:"、",deliveryTitle:"投递方式",deliverySubtitle:"Email、Slack、短信怎么发给你。",outboundPending:"Email、Slack、短信还没有开始发送。这些设置现在先存下,对外发信上线后生效。",preferredChannel:"首选渠道",preferredHint:"一条通知能走多个渠道时,用这一个。",urgentOverride:"紧急告警不受免打扰限制",urgentHint:"适用于:{events}。",quietHours:"免打扰时段",from:"开始",to:"至",timeZone:"时区",quietHint:"免打扰期间,Email、Slack、短信推迟到时段结束再发;站内通知不受影响。",needPreferred:"请选择首选渠道。",needQuiet:"请填完免打扰时段和时区。",sameTimes:"免打扰的开始和结束不能是同一时间。",save:"保存偏好",saved:"通知偏好已保存",conflict:"这些偏好在别处改过了(可能是另一个标签页),已载入最新的,请核对后再保存。"},project:{filterOwner:"客户负责人:{name}",linkExisting:"挂上已有合同",linkTitle:"挂上已有合同",linkSubtitle:"一个项目可以由多份合同共同覆盖(实施合同 + 维保合同 + 追加合同)",linkRule:"这里列出这个客户已激活、还没挂到任何项目上的合同。挂上后作为追加合同,跟项目的主合同一起结束。",linkSigned:"签约 {date}",linkEmpty:"这个客户没有等着挂项目的已激活合同。接受报价或合同草稿时选了「稍后再定」的合同才会出现在这里。",linkNoContractPermission:"你没有查看合同的权限,列不出候选合同。",linkSubmit:"挂上所选",linkSubmitN:"挂上所选({n})",linked:"已把 {n} 份合同挂到这个项目上",linkDisabled:"只有准备中或运行中的项目能再挂合同",selectPlaceholder:"搜索项目",pageSubtitle:"工地项目在合同激活时自动预建;激活时没挂项目的合同,可以从合同导入建项目。",footLead:"合同生效时自动建出项目,初始为准备中(Setup)。",footBody:"指派了客户的 Company Admin、所有产品都供应完成后,项目自动转为运行中(Active)。",outOfScope:"该项目不在你的数据范围内",projectCode:"项目编号",name:"项目名称",colProject:"项目",editInfo:"编辑项目信息",nameRequired:"项目名称必填",customer:"客户",projectType:"项目类型",tenant:"租户",primaryContract:"主合同",site:"工地",siteCountry:"国家",siteAddress:"工地地址",period:"项目周期",internalNotes:"内部备注",internalNotesPlaceholder:"只有 BES 员工看得到,不会给客户",searchPlaceholder:"项目编号或名称",viaContract:"来自 {no}",periodColumn:"周期",contractNotSigned:"合同未签",productsColumn:"产品",filterContract:"合同 {no}",tabOverview:"概览",tabEntitlements:"产品权益",tabLifecycle:"生命周期",tabAudit:"审计",info:"项目信息",sourceChain:"来源链",sourceChainHint:"本项目由以下链路生成(主来源)",chainQuotation:"报价",chainContract:"合同",chainProject:"项目",chainSigned:"{date} 签署",chainAccepted:"已接受 · {date}",chainYouAreHere:"(当前)",openInstance:"打开权益 →",lifecycleTitle:"项目生命周期",lifecycleHint:"本项目走到了生命周期的哪一步。每次状态变更都记在「审计」页签里。",lifecycleBlocked:"本项目在筹备期受阻,解除之前不会往下走。",trackOnboardings:"未完成的实施见{link}。",superAdmin:"客户超级管理员",superAdminPending:"待指派",superAdminPlaceholder:"ops.lead{'@'}customer.com",superAdminRequired:"请填写超级管理员标识",superAdminRefHint:"这里登记的是客户那侧的标识(邮箱或产品侧用户名),BOSS 不会为它建用户——所以这是一个普通输入框,而不是员工下拉。",kpiActive:"进行中合计",kpiActiveSub:"涉及 {n} 份合同",kpiSetup:"筹备中",kpiSetupBadge:"实施中",kpiSetupSub:"等待客户超管激活",kpiLive:"运行中",kpiLiveSub:"日常运行",kpiEndingSoon:"即将结束",kpiEndingSoonSub:"未来 90 天",overdueClosingAlert:"有 {n} 个项目过了归档日仍停在收尾中。这个数正常恒为 0——它是后台归档扫描器停摆的唯一信号,请报运维。",tabAll:"全部",tabSetup:"筹备中",tabLive:"运行中",tabBlocked:"受阻",tabPendingContract:"待合同",tabEnding:"即将结束",tabArchived:"已归档",importButton:"从合同导入",importTitle:"从合同导入",importSubtitle:"选一份已生效的合同,按它的产品与权益建项目。",importContract:"合同",importContractPlaceholder:"按合同编号搜索",importContractRequired:"请选择合同",importContractHint:"只列已生效、还没挂项目的合同",importNoCandidate:"没有可导入的合同:只有已生效、还没挂项目的合同能导入。",importName:"项目名称",importNamePlaceholder:"不填则用来源报价的标题",importFixedHint:"项目建好后类型与国家不能再改,请在这里定。",importSubmit:"导入",importDone:"已建项目 {code}",importRetryHint:"这份合同有 {n} 条开通失败,请到开通监控人工重试。",closingAlert:"收尾期至 {date}",closingRemaining:"收尾期 —— {total} 天里还剩 {n} 天({date} 自动归档)",extendClosing:"延长收尾期",archiveNow:"立即归档(跳过剩余天数)",archiveProject:"归档项目",extendClosingTitle:"延长收尾期",extendClosingRemaining:"目前收尾期 {total} 天,还剩 {n} 天",extendBy:"延长",extendByDays:"+{n} 天",extendByRequired:"请选择延长多少天",extendReason:"原因",extendReasonPlaceholder:"为什么需要延长收尾期",extendClosingNote:"延长后项目可编辑的时间更长(仍不能新建请款单与变更单)。这次延长会记入审计。",extendSubmit:"延长",extended:"收尾期已延长,将于 {date} 自动归档",archiveTitle:"归档项目?",archiveTarget:"项目:",archiveSubmit:"归档",archiveBlocked:"合同 {no} 还没结束,现在归档会失败:先终止它,或等它到期。",archiveConsequenceReadOnly:"会把项目转为已归档:项目信息不能再编辑,挂着的合同不能再新建请款单与变更单",archiveConsequenceSkipClosing:"会立即结束收尾期,不再等到 {date} 自动归档",archiveConsequenceExisting:"已经发起的请款单与变更单仍可照常走完",archiveConsequenceNoDeprovision:"不会腾退客户租户,也不会停实例:那是交接里的事",archiveConsequenceHandover:"还没走完的交接照常走完,签署时不会把项目拉回收尾期",archivedDone:"项目已归档",editTitle:"编辑项目信息",editImmutableHint:"合同、项目期间、产品与超级管理员指派只能经各自的流程修改。",assignSuperAdmin:"指派超级管理员",reassignSuperAdmin:"更换超级管理员",assignSuperAdminTitle:"指派客户超级管理员",reassignSuperAdminTitle:"更换客户超级管理员",assignHint:"这是走出「筹备中」的唯一出口:超级管理员登记好、权益也都供应完成,项目即转为运行中。",reassignWarning:"这会把登记的客户侧超级管理员从 {ref} 换成新填的人,变更会记入审计。",assignNotAllowed:"只有筹备中 / 受阻 / 运行中的项目可以指派超级管理员。",assignNote:"备注",assignNotePlaceholder:"例如:上一任离职",assignNoteHint:"换人时建议写一句——审计里看到的就是它。",assignActivationHint:"重复指派同一个人不改变任何东西,也不会留痕——只有真正换人才写审计。",assignNoInviteHint:"不会给客户发任何通知:这里只登记谁是他们的超级管理员。向产品侧发邀请要等 integration adapter,那条还没通。",assigned:"已指派超级管理员",assignedAndActive:"已指派超级管理员——项目转为运行中",contracts:"关联合同",contractNo:"合同编号",linkType:"挂接方式",primaryTag:"主合同",expiresDate:"到期日",contractsHint:"一个项目可以被多份合同覆盖:实施主合同,加上后来签的维保或增购。",relatedContractsTitle:"关联合同",relatedContractsSubtitle:"覆盖这个项目的全部合同:实施、维保与追加",activeContracts:"{n} 份生效",contractTerm:"{n} 个月",contractSigned:"签署 {date}",signedOn:"签约日",entitlementTerm:"期限",termInfo:"期限",timelineRemaining:"剩余时间",contractRecipient:"服务接收方:{name}",inclAmendments:"含 {n} 份变更单",perMonth:"{amount}/月",contractRestricted:"这份合同不在你的数据范围内",entitlements:"产品权益",entitlementNo:"权益编号",product:"产品",instance:"运行实例",noInstance:"无可监控实例",entitlementsHint:"每张卡把权益和它的运行实例并在一起,回答「这个产品在这个工地跑起来没有」。不是每条权益都有实例。",linkedRecords:"关联记录",linkedRecordsHint:"与这个项目相关的全部记录",linkedCompany:"客户",linkedContract:"合同",linkedQuotation:"报价",linkedEntitlements:"产品权益",linkedOnboarding:"实施",linkedHandover:"交接",linkedInvoices:"发票",linkedClaims:"请款单",linkedRuns:"供应记录",linkedLoadFailed:"加载失败,点击重试",infoSiteCountry:"站点国家",headPeriod:"期间",activeBannerTitle:"项目运行中,一切正常",activeBannerBody:"交付、请款、供应都照常进行。项目一直保持运行,直到实施交接签署完成,之后进入收尾期。",closingBannerBody:"交接已签署,项目在收尾:不能再新建请款单与变更单,也不能再挂合同、更换 Company Admin;已有记录仍可编辑。收尾期满后自动归档,变成完全只读。",archivedBannerTitle:"已归档,只读",archivedBannerTitleDate:"已归档,只读——自 {date} 起",archivedBannerBody:"这个项目已结束,什么都不能再改;所有记录都保留着,仍可浏览。",readOnlyStripLead:"只读模式。",readOnlyStripBody:"项目归档期间,本页所有编辑按钮与操作菜单都已置灰。",timelineTitle:"时间线——合同与项目",timelineHint:"合同的法律期(卖了什么)与项目实际执行的日期(现场在做什么)",timelineContract:"合同 {no}(法律期)",timelineContractActive:"合同有效",timelineExecution:"项目执行(现场)",timelineImplementation:"实施",timelineMaintenance:"维保({no})",timelineSigned:"合同签署",timelineImplStart:"实施开始",timelineHandoverTarget:"交接目标",timelineNotStarted:"实施尚未开始",timelineImplSuffix:"(实施)",timelineThenMaint:"· 之后进入维保",tabUsers:"用户",accessTitle:"客户访问申请",accessHint:"应客户要求、为短期操作开的 BES 临时访问",accessHow:"运作方式",accessBandLead:"只由客户发起。",accessBandBody:"BES 员工不会自行开访问:客户提出申请 → BES 审核批准 → 到期自动失效。",accessSubmitted:"提交于 {time}",accessEmpty:"这个项目上没有访问申请",accessHowTitle:"客户访问申请怎么运作",accessHowSub:"为什么 BES 不主动进入客户系统",accessStep1Title:"客户提出",accessStep1Body:"客户的 Company Admin 提出协助申请,写明原因与所需范围;申请会记下是谁提的。",accessStep2Title:"BES 审核批准",accessStep2Body:"持有审批权限的员工核对原因后批准或驳回,并指定由哪位 BES 员工去操作。",accessStep3Title:"访问有时限",accessStep3Body:"每条授权都有固定的到期时刻,到期自动失效,也可以提前撤销。BOSS 只记录授权,不建账号、不发口令。",accessStep4Title:"全程审计",accessStep4Body:"申请、批准、撤销、到期都写进审计记录,并记下相关人员。",accessHowWhy:"这样设计的原因:BES 不会不经请求就进入客户系统。这能防止滥用、满足审计要求,也尊重客户的数据主权。"},entitlement:{pageSubtitle:"查看每家客户按合同能用什么、哪个租户是数据边界,以及技术部署是否健康。",viewActivationQueue:"查看开通队列",colCustomerTenant:"客户 · 租户",colEntitlementId:"权益 ID",colAiQuota:"AI / 额度",linkedRecords:"关联记录",quotation:"报价",tenantId:"租户 ID",companyAdmin:"Company Admin",creditLine:"本月 {used} / {grant} 点",scopeNote:"组织 → 租户 → 产品权益 → 项目。",scopeBody:"合同激活时创建权益,并启动一次幂等的部署。租户是安全边界,项目都在租户里面。只有真的有部署可监控时才显示技术实例。",customerFilter:"客户:{name}",provisioningBtn:"供应记录",moreActions:"更多操作",copySystemId:"复制系统 ID",viewAuditTrail:"查看审计记录",openMonitor:"打开供应监控",systemIdCopied:"已复制系统 ID",copyFailed:"复制失败,请手动选中文字复制",runTitle:"供应运行",runSub:"最近一次",runCount:"共 {n} 次",runTriggeredBy:"触发合同",runViewLog:"查看完整技术日志 →",noRun:"这条权益还没有供应记录",entitlementNo:"权益编号",customer:"客户",tenant:"租户",product:"产品",contract:"合同",project:"项目",term:"期限",kpiActive:"在用",kpiLive:"运行中",kpiPending:"待供应",kpiPendingHint:"等供应跑完的,数字变大说明那条流水线卡住了",kpiRenewingSoon:"90 天内续期",kpiStaleRoleGrant:"角色权限非最新版",kpiStaleHint:"0 不代表没问题:供应还没跑到角色下发那一步的权益不计入",tabActive:"在用",tabStaleRole:"角色版本落后",tabAll:"全部",instance:"部署实例",systemId:"系统标识",deploymentState:"实例状态",provisioningStatus:"供应结果",accessStatus:"接管状态",accessStatusHint:"机器活没活(实例状态)与客户侧有没有人接管(接管状态)是两件事——「运行中 + 待指派超级管理员」正是「系统开好了、没人来管」。「已登记,待客户确认」只表示记下了客户侧超级管理员的标识,客户是否真的在管,BOSS 现在无从得知。",noInstance:"无实例",noInstanceHint:"这条权益没有可监控的运行实例——不是每条权益都有。",roleGrant:"已下发的角色权限",versionLabel:"版本",current:"最新版",notCurrent:"非最新版",granted:"权限点",grantedUnknown:"无法确定",notCurrentHint:"下发之后模板又发布过新版,而版本标签里的哈希不可逆,当时到底下发了多少个权限点已经查不回来了。拿今天的快照顶上去,会让「当时给了客户什么」——审计恰恰要问的那句——得到一个错答案。",noOutboundHint:"目前只在 BOSS 侧完成快照选定与版本回填,还没有真正的出站下发(要等 integration adapter)。等真下发时会另存一份下发记录,那时这里才能精确回溯。",noRoleGrant:"尚无角色版本记录",noRoleGrantHint:"这条权益的供应还没跑到角色下发那一步,所以没有版本可记。",wfTemplate:"实施流程模板",credit:"AI Credit",creditGrant:"授予",creditTopup:"充值",creditUsed:"已用",creditBalance:"余额",creditNotSyncedTitle:"尚未回流——这不是真实余额",creditNotSyncedHint:"Credit 数字是产品侧回流过来的镜像,而入站通道还没落地,所以一直是 0。这里的 0 表示「还没有数据回来」,不是「客户已经用光了」。"},accessPlanes:{pageSubtitle:"三个刻意分开的授权平面:内部工作、客户产品角色、临时跨租户支持。每一项授权都有明确的边界和审计记录。",staffKicker:"BOSS 内部",staffBadge:"生效中的策略",staffTitle:"内部员工权限",staffDesc:"角色决定能用 BOSS 的哪些模块;数据范围(全部 / 我经手的)限制能看到哪些客户和项目。",staffFoot:"角色 × 数据范围",productKicker:"客户产品",productBadge:"租户内",productTitle:"产品角色模板",productDesc:"Company Admin、项目经理等角色都在各产品租户里,它们不会授予 BOSS 的访问权。",productFoot:"打开产品角色 →",customerKicker:"跨租户支持",customerBadge:"{n} 条待审批",customerTitle:"临时客户访问",customerDesc:"临时访问须写明原因、客户与租户范围、审批人、到期时间,并留下不可改的审计事件。",customerFoot:"查看申请 →",boundaryTitle:"授权边界在平面之间从不继承。",boundaryBody:"BES 角色进不了客户租户,客户产品角色也打不开 BOSS。临时访问是另外一项会到期的授权,挂在指定的客户和租户上。"},accessGrant:{introLead:"访问边界彼此独立。",introBody:"这个页签只管 BES 支持人员临时进入客户租户、以及 break-glass 紧急访问。BES 员工在 BOSS 里的角色在另一个页签;客户自己的产品角色(Company Admin、项目角色)在各自的{tenant}里管理。",introTenant:"租户",cardTitle:"临时访问与 break-glass 访问",cardSub:"BES 员工为支持客户而进入其在用租户的申请。每一条授权都限定范围与时长,并写进审计日志。",colExpiry:"到期",colAction:"操作",footAudit:"每一次批准、延期与撤销都记录在{link}里。",review:"审批",revokeEarly:"提前撤销",viewAudit:"审计记录",intro:"BES 支持人员临时进入客户系统的授权记录:谁申请、谁批准、管哪个项目、为什么、到什么时候。BOSS 只记录授权——它不签发任何口令、令牌或连接串,一条审批通过的授权也不会让任何人在 BOSS 里多出一个权限。",tabOpen:"未结束",tabAll:"全部记录",keywordPlaceholder:"申请编号、操作类型或范围",requestNo:"申请编号",grantType:"类型",grantTypeRequired:"请选择类型",carHint:"由客户的系统管理员发起,有效期最长 7 天。",breakGlassHint:"紧急介入。不设时长上限——时长由审批人判断,但同样要走审批。",scope:"授权范围",scopeType:"范围类型",scopeProject:"某个项目",scopeEntitlement:"某条产品权益",scopeRequired:"请指定这次授权管什么",scopeDesc:"范围说明",project:"项目",entitlement:"产品权益",entitlementPlaceholder:"按权益编号搜索",operationType:"操作类型",operationTypePlaceholder:"例如:数据库只读",tenant:"目标租户",tenantUnknown:"从项目上读取——数据范围之外的项目读不到。",who:"相关人员",besOperator:"指派给",besOperatorHint:"指定谁去做这件事。这不等于把凭据交给了他。",besOperatorRequired:"请指定由谁执行",requestedByRef:"客户侧发起人",requestedByRefPlaceholder:"超级管理员邮箱或工单号",requestedByRefHint:"客户那边是谁要求的。BES 不能主动为客户建账号。",reason:"原因",reasonHint:"将来有人问「为什么进过客户的系统」时,审计里显示的就是这段话。",reasonRequired:"原因必填",reasonPlaceholder:"说明发生了什么、为什么需要这次访问",approvedBy:"审批人",notApprovedYet:"尚未审批",expiresAt:"到期时刻",expiresAtPlaceholder:"选择日期与时间",expiresAtRequired:"请设置到期时刻",expiryCarHint:"CAR 最长 7 天,最终以服务端校验为准。",expiryFreeHint:"BREAK_GLASS 不设上限——够用就好,别开长。",expiredTag:"已过期",expiresInHours:"{n} 小时后到期",expiresInDays:"{n} 天后到期",expiresWithinHour:"1 小时内到期",expiredOn:"已于 {date} 到期",durationHours:"{n} 小时",durationDays:"{n} 天",create:"新建申请",createTitle:"申请临时访问",createNote:"提交后是「待审批」状态。申请了不等于能进——还得有人批准。",submitRequest:"提交申请",requested:"申请已提交",emptyOpen:"当前没有待审批或审批通过的授权",emptyAll:"还没有任何访问授权记录",expiredAlertTitle:"已过到期时刻",expiredAlert:"到期扫描器每小时跑一轮,所以过了时间之后状态可能还显示为审批通过。这条授权应当视为已失效。",pendingAlertTitle:"等待审批",pendingAlert:"待审批的申请不代表任何访问权,没有人能凭它进入客户系统。",noCredentialNote:"这条记录不是钥匙。BOSS 记的是「谁被授权、管什么、到什么时候」——口令、令牌和连接串不在这里发放。",approve:"批准",approveTitle:"批准这次访问",approveConsequenceActive:"{who} 就此获准进入客户系统,有效到 {until}。",approveConsequenceScope:"授权范围仅限 {scope},不覆盖其它。",approveConsequenceAudit:"这次批准会以 HIGH 风险记入审计,事后一直查得到是你批的。",approveConsequenceRevocable:"之后可以随时撤销,但撤销之前已经发生的访问收不回来。",approved:"已批准",reject:"驳回",rejectTitle:"驳回这条申请",rejectConsequence:"申请人不会获得任何访问权,这次申请就此结束。",rejectConsequenceFinal:"驳回之后不能再批准这一条,需要重新提申请。",rejectReasonLabel:"为什么驳回?",revokeReasonLabel:"为什么撤销?",rejected:"已驳回",revoke:"撤销",revokeTitle:"撤销这次访问",revokeConsequenceActive:"这条授权立即撤销,不再有效。",revokeConsequencePending:"这条还没批的申请会被作废,不再需要有人处理。",revokeConsequenceFinal:"撤销之后无法恢复,需要重新提申请。",revokeConsequenceAudit:"撤销原因会进审计——它要回答的正是「为什么把这次访问停了」。",revoked:"已撤销"},compliance:{dailyVerification:"每日校验",automated:"自动",siemExport:"SIEM 导出",enabledValue:"已启用",chainTitle:"审计链完整性",verifyNow:"立即校验",verified:"已重新校验",status:"状态",verifiedAt:"最近校验",entries:"审计行数",breaks:"断点数",lastHash:"链尾哈希",lastHashHint:"定期把它送到系统之外留档(SIEM 或打印)—— 哈希链只保证「改动不能悄无声息」,能改数据的人同样能把整条链重算一遍。",neverVerifiedHint:"这条链从未校验过 —— 这不等于完好。",brokenHint:"链已断。下面每一个断点都需要排查。",breakList:"断点明细(最多 20 条)",breakId:"审计行",tamper:"篡改手法",contentAltered:"内容被改",contentAlteredHint:"这一行自身的内容被改过",predecessorMissing:"前驱缺失",predecessorMissingHint:"行本身没动,是它前面那行被删了、或中间被插入了行",prevHash:"记录的前驱",expectedPrevHash:"应有的前驱",off:"未开启"},authPolicy:{control:{title:"登录与安全由 BES 管理",sub:"员工经 BES 登录 BOSS",body:"口令规则、两步验证、会话时长与单点登录都在 BES 统一设置,不在 BOSS 里。每个人自己的口令与两步验证在 BES 账户页修改。",open:"打开你的 BES 账户页"},readOnly:"这些规则写在系统里,这里只做说明,不能在本页修改。",mfa:{title:"两步验证",sub:"所有账号都要启用",require:{label:"所有员工必须启用两步验证",desc:"第一次登录时绑定验证器应用(TOTP)。验证码连错 3 次锁定账号 15 分钟。",value:"已启用"},backup:{label:"备份码",desc:"绑定验证器时生成 10 个一次性备份码",value:"允许"},sms:{label:"短信作为备用",desc:"不提供短信验证码",value:"不支持"},webauthn:{label:"WebAuthn / 通行密钥",desc:"不提供硬件密钥与平台通行密钥",value:"不支持"}},password:{title:"口令策略",sub:"适用于新建账号、管理员重置与本人修改口令",length:{label:"最短长度",desc:"12–64 位,须同时包含大写字母、小写字母、数字与符号",value:"12 位"},expiration:{label:"过期",desc:"口令不会过期",value:"不强制"},history:{label:"历史口令",desc:"可以重复使用以前的口令",value:"不强制"},failures:{label:"最多失败次数",desc:"口令连续错 5 次锁定账号(15 分钟后解除)",value:"5 次"}},sso:{title:"SSO 身份提供方",sub:"SAML 2.0 / OIDC · 未配置",emptyTitle:"没有配置 SSO 身份提供方",emptyBody:"目前都用用户名、口令加验证器验证码登录。接入公司统一 SSO 后改为跳转登录。"},session:{title:"会话策略",sub:"一次登录能保持多久",timeout:{label:"闲置会话超时",desc:"闲置超过这段时间自动登出;一次会话最长 24 小时",value:"30 分钟"},autoSuspend:{label:"自动停用不活跃账号",desc:"90 天没有登录就自动停用,管理员可以重新启用",value:"90 天"}}},orgSettings:{keepEditing:"继续编辑",invoicingTitle:"开票",invoicingNote:"印在发票上:开票方的 GST 注册号与收款指引。发票签发时复制到发票上,之后在这里改不影响已开出的发票。",gstRegistrationNo:"GST 注册号",bankName:"收款银行",bankNamePlaceholder:"例如 DBS",bankAccountName:"账户户名",bankAccountNo:"收款账号",subtitle:"BES 全公司的配置。只有 Owner / Admin 角色可以修改。你自己的资料与偏好见",personalSettings:"个人设置",adminOnly:"仅管理员",infoTitle:"组织信息",infoSub:"合同与发票上使用的法定主体资料",legalName:"法定名称",uen:"UEN",displayName:"显示名",country:"国家/地区",registeredAddress:"注册地址",legalNameRequired:"法定名称必填——报价、合同、条款 PDF 的抬头都用它",countryRequired:"请选择国家/地区",incompleteHint:"UEN 或注册地址还没填。在填上之前,发给客户的 PDF 抬头只有法定名称和国家。",save:"保存修改",saveTitle:"保存设置?",saveConfirm:"保存",saveConsequenceImmediate:"修改立即生效",saveConsequenceDocs:"此后下载的报价、合同、条款 PDF 抬头都会用新的资料",saveConsequenceAudit:"会记一条审计日志",discardTitle:"放弃修改?",discard:"放弃",discardConsequence:"未保存的修改会丢失"},document:{downloadPdf:"下载 PDF",exportPdf:"导出 PDF",quotationTitle:"下载报价 PDF",contractTitle:"下载合同 PDF",termTitle:"导出条款 PDF",includeCoverLetter:"包含封面信",includeTerms:"包含条款",includeSignaturePage:"包含签字页",contractIncludeTerms:"包含条款",version:"版本",versionOriginal:"原件(客户签署前)",versionOriginalHint:"BOSS 里还没有存双方签回的文件,只能下载系统生成的原件。",englishOnly:"单据一律以英文生成,与界面语言无关。",language:"语言",langBilingual:"中英双语",langEn:"仅英文",langZh:"仅中文",termNoContent:"这一版还没有正文,无可导出。",thisVersion:"当前页",includeVersionHistory:"附版本历史脚注",draftWatermark:"封面加「DRAFT」水印",download:"下载",export:"导出"},provisioningLog:{title:"开通日志",live:"实时",viewLive:"查看实时日志",viewFull:"查看完整日志",autoRefresh:"每 2 秒自动刷新",empty:"还没有日志",pollFailed:"最新的日志没取到,每 2 秒重试一次"},companyExport:{title:"导出公司数据",section:{company:"公司信息、联系人与地址",quotations_contracts:"报价与合同",projects_subscriptions:"项目与产品权益",activity_audit:"动态与审计记录"},noPermission:"你没有导出这一部分的权限",format:"格式",formatRequired:"请选择格式",formatOption:{zip:"ZIP(CSV 文件)",xlsx:"Excel(.xlsx)",pdf:"PDF 报告"},generate:"生成导出"},dataExport:{button:"导出",asCsv:"导出为 CSV",asXlsx:"导出为 Excel",asPdf:"导出为 PDF",asJson:"导出为 JSON",currentFilter:"按当前筛选导出({n} 行)",tooManyRows:"当前筛选共 {n} 行,一次最多导出 {max} 行。请缩小筛选后再导出。",nothingToExport:"当前筛选没有数据,无需导出。",dialogTitle:"导出数据",format:"格式",scope:"范围",scopeCurrent:"当前筛选结果({n} 行)",scopeAll:"全部记录",includeHeaders:"包含表头",includeHeadersPdfHint:"PDF 总是带表头",download:"下载"},enum:{companyRole:{CUSTOMER:"客户",SERVICE_RECIPIENT:"服务接收方",MAIN_CON:"主承包商",SUB_CON:"分包商",DEVELOPER:"开发商",CONSULTANT:"顾问",SUPPLIER:"供应商",EQUIPMENT:"设备供应商"},lifecycleStage:{LEAD:"线索",QUALIFIED:"已确认",CUSTOMER:"已转换",ACTIVE:"活跃",DORMANT:"休眠",CHURNED:"流失"},companyStatus:{ACTIVE:"正常",ARCHIVED:"已归档"},billingAccountStatus:{ACTIVE:"启用中",ARCHIVED:"已停用"},relationshipType:{NONE:"无",SUBSIDIARY:"子公司",JV_PARTNER:"合资伙伴",BRANCH:"分公司",DIVISION:"事业部"},discountApprovalStatus:{NOT_REQUIRED:"未提交审批",PENDING:"待审批",APPROVED:"已批准",REJECTED:"已驳回"},acceptLinkStatus:{ACTIVE:"有效",EXPIRED:"已过期",REVOKED:"已撤销",SUPERSEDED:"已被修订",DECIDED:"已有结果"},quotationStatus:{DRAFT:"草稿",SENT:"已发送",ACCEPTED:"已接受",REJECTED:"已拒绝",EXPIRED:"已过期",SUPERSEDED:"已被取代"},lineType:{SOFTWARE:"软件",HARDWARE:"硬件",SERVICE:"服务"},deliveryType:{SOFTWARE:"软件",HARDWARE:"硬件",MIXED:"整个项目(早期实施单)"},productType:{SOFTWARE:"软件",HARDWARE:"硬件",SERVICE:"服务"},stockStatus:{HEALTHY:"充足",LOW:"偏低",OUT:"缺货"},hardwareUnitStatus:{IN_STOCK:"在库",DISPATCHED:"已出库",ON_SITE:"现场待装",INSTALLED:"已安装",RETURNED:"已退回",UNDER_REPAIR:"维修中",AT_SUPPLIER:"在供应商",SCRAPPED:"已报废"},purchaseOrderStatus:{ORDERED:"已下单",IN_TRANSIT:"在途",PARTIALLY_RECEIVED:"部分收货",RECEIVED:"已收货",CANCELLED:"已取消"},stockMovementType:{INITIAL:"初始库存",RECEIVE:"收货",ALLOCATE:"预留",RELEASE:"释放",DISPATCH:"出库",RECALL:"回仓",INSTALL:"安装",HOLD_ON_SITE:"留在现场",RETURN:"退回",REPAIR:"送修",TO_SUPPLIER:"退供应商",RESTOCK:"重新入库",SCRAP:"报废",TRANSFER:"移动"},allocationStatus:{PENDING_ONBOARDING:"待实施",RESERVED:"可出库",FULFILLED:"已完成"},dispatchStatus:{IN_TRANSIT:"在途",DELIVERED:"已到场",CONFIRMED:"已结算",CANCELLED:"已取消"},dispatchOutcome:{INSTALLED:"装好",ON_SITE:"现场待装",FAULTY:"坏件",SURPLUS:"冗余"},installationStatus:{NEEDS_CHECK:"待检查",INSTALLING:"安装中",OPERATIONAL:"运行中"},returnStatus:{REPORTED:"待收回",RETURNED:"待检验",UNDER_REPAIR:"维修中",AT_SUPPLIER:"已退供应商",RESTOCKED:"已重新入库",SCRAPPED:"已报废",CANCELLED:"已取消"},returnSource:{SITE:"现场",WAREHOUSE:"仓库",INSTALLATION:"安装时坏件"},returnHistoryAction:{CREATE:"新建",RECEIVE:"收回",REPAIR:"送修",SEND_TO_SUPPLIER:"退供应商",RESTOCK:"重新入库",SCRAP:"报废",CANCEL:"取消",SPLIT:"拆单"},productStatus:{ACTIVE:"在售",BETA:"公测",DEPRECATED:"已停售"},productScopeLevel:{PROJECT:"按项目",TENANT:"按租户"},controlSyncStatus:{NOT_APPLICABLE:"不登记",PENDING:"等待登记",SYNCED:"已登记",FAILED:"失败"},hardwareRequirement:{REQUIRED:"必需",RECOMMENDED:"推荐"},revisionStatus:{CURRENT:"当前版本",SUPERSEDED:"已被取代"},stepType:{REQUIRED:"必需",OPTIONAL:"可选"},periodType:{RECURRING:"周期性",ONE_TIME:"一次性",PER_OCCURRENCE:"按次"},amendmentType:{SCOPE_ADDITION:"增加范围",SCOPE_REDUCTION:"缩减范围",PRICE_ADJUSTMENT:"调价",TERM_EXTENSION:"延期",VO_DRIVEN:"源自 VO",CONTACT_BILLING_CHANGE:"联系人 / 账单变更",OTHER:"其他"},amendmentStatus:{DRAFT:"草稿",PENDING_SIGNATURE:"待签署",ACTIVE:"已生效"},contractStatus:{DRAFT:"草稿",PENDING_CUSTOMER_SIGNATURE:"待客户签署",ACTIVE:"生效中",EXPIRING:"即将到期",EXPIRED:"已到期",TERMINATING:"终止中",TERMINATED:"已终止"},termStatus:{DRAFT:"草稿",CURRENT:"当前生效",SUPERSEDED:"已取代",RETIRED:"已停用"},termCategory:{GENERAL:"通用",PAYMENT:"付款",DPA:"数据处理(DPA)",SLA:"SLA",INDUSTRY_SPECIFIC:"行业专用",TERM_ADJUSTMENT:"期限调整"},termSourceState:{CURRENT:"最新版本",SUPERSEDED:"已有新版本",RETIRED:"来源已停用",GONE:"来源已删除"},termLanguage:{EN:"英文",ZH:"中文"},termRefType:{QUOTATION:"报价",CONTRACT:"合同"},partyRole:{BILLING:"结算方",SERVICE_RECIPIENT:"服务接收方",BES:"BES"},effectiveMode:{IMMEDIATE:"签约即生效",STEP:"按实施流程标记点生效",DATE:"指定日期生效"},effectiveSource:{IMMEDIATE:"签约即生效",DATE:"指定日期",STEP:"实施流程标记点",MANUAL:"手工设定",RENEWAL:"续约接续"},effectiveState:{PENDING:"待生效",PARTIAL:"部分生效",EFFECTIVE:"已生效"},entitlementStatus:{PENDING:"待供应",ACTIVE:"已开通",SUSPENDED:"已暂停",EXPIRED:"已到期",TERMINATED:"已终止"},runStatus:{RUNNING:"执行中",SUCCESS:"成功",FAILED:"失败",ROLLED_BACK:"已回滚"},runType:{PROVISION:"开通",DEPROVISION:"收回",RECONCILE:"对账"},runTrigger:{CONTRACT_ACTIVATED:"合同激活",CONTRACT_RENEWED:"合同续约",TERM_EXTENDED:"接续授权期",ENTITLEMENT_TERMINATED:"合同结束",HANDOVER_VACATED:"交接腾退",SCHEDULED:"定时"},discrepancyKind:{NOT_PUSHED:"未推送",MISSING_IN_CONTROL:"Control 缺少",INACTIVE_IN_CONTROL:"Control 未生效",ACTIVE_IN_CONTROL:"Control 仍有效",PERIOD_MISMATCH:"起止不一致",UNKNOWN_IN_CONTROL:"Control 多出"},controlEntitlementStatus:{PENDING:"待激活",ACTIVE:"有效",REVOKED:"已撤销",EXPIRED:"已到期"},stepStatus:{PENDING:"待执行",RUNNING:"执行中",SUCCESS:"成功",SKIPPED:"已跳过",FAILED:"失败"},stepBehavior:{IDEMPOTENT:"幂等",RETRYABLE:"可重试",CONDITIONAL:"条件执行"},userRemovalBlocker:{OWNS_COMPANIES:"名下有客户",HAS_ACTIVE_PROJECTS:"名下有进行中的项目",HAS_OPEN_TASKS:"有未处理的待办",SELF:"自己的账号",LAST_ADMIN:"最后一个管理员",ALREADY_REMOVED:"已经移除"},loginStatus:{INVITED:"已邀请",INVITE_EXPIRED:"邀请已过期",ACTIVE:"已设口令"},userStatus:{Active:"在职","MFA Pending":"待验证 MFA",Suspended:"已停用",Removed:"已移除"},dataScope:{ALL:"全部数据",OWNED:"仅本人负责"},permissionRisk:{STANDARD:"常规",SENSITIVE:"敏感",HIGH_RISK:"高危"},actorType:{USER:"用户",SYSTEM:"系统",EXTERNAL:"外部"},auditCategory:{AUTHENTICATION:"认证",SALES:"销售(客户、报价、合同)",DELIVERY:"交付(项目、实施)",ACCESS:"访问(员工、角色、权限)",SYSTEM_BILLING:"系统与账务"},auditSeverity:{INFO:"信息",WARNING:"警告",CRITICAL:"严重"},auditRisk:{NORMAL:"普通",HIGH:"高危"},action:{export:"导出",view:"查看",create:"新建",update:"编辑",delete:"删除",archive:"归档",restore:"恢复",qualify:"标记 Qualified",accept:"接受",send:"发送",revise:"创建修订版",submit_approval:"提交折扣审批",approve_discount:"批准折扣",reject_discount:"驳回折扣",update_payment_plan:"编辑付款计划",send_for_signature:"发起签署",create_amendment:"新建变更单",quote_amendment:"变更单生成小报价",raise_variation_order:"从请款单发起变更单",apply_variation_order:"变更单调整额带入请款单",duplicate:"复制",send_amendment_for_signature:"变更单发起签署",activate_amendment:"变更单已签署",renew:"已生成续约报价",activate:"激活",terminate:"终止",retry:"重试",roll_back:"回滚",manage:"管理",suspend:"停用",auto_suspend:"自动停用",change_roles:"变更角色",change_permissions:"变更权限",reset_password:"重置密码",start:"开始",complete:"完成",go_live:"上线",reject:"拒绝",expire:"过期",supersede:"被取代",mark_expiring:"标记即将到期",mark_expired:"标记已过期",start_term:"期限开始",set_effective_date:"设定生效日",mark_active:"转回生效中",extend_authorization:"接续授权期",advance_contract_end:"合同结束日提前",fail:"失败",change_password:"修改密码",lock:"锁定",unlock:"解锁",ship:"标记在途",receive:"收货",record_movement:"记录库存流水",reserve:"预留",deliver:"标记到场",confirm_installation:"结算",register_delivery_receipt:"登记签好的 DO",change:"修改",repair:"送修",send_to_supplier:"退供应商",restock:"重新入库",scrap:"报废",split:"拆单",withdraw:"撤回",record_occurrences:"登记次数",change_stage:"推进阶段",change_status:"变更状态",sync:"同步",start_step:"开始步骤",complete_step:"完成步骤",skip_step:"跳过步骤",reopen_step:"回退步骤",block:"阻塞 / 封禁",unblock:"解除阻塞",reassign:"重新指派",assign_staff:"指派客户团队",remove_staff:"移出客户团队",notify_sales:"通知销售",publish:"发布",publish_pipeline:"发布流水线",discard:"放弃改动",release_match_condition:"让出匹配条件",sync_apps:"同步应用清单",import_permissions:"导入权限点",submit:"提交",start_review:"开始审查",approve:"批准",dispute:"发起争议",withdraw_dispute:"撤回争议",settle:"结清",issue_invoice:"签发发票",record_payment:"登记收款",mark_sent:"标记已发送",mark_overdue:"标记逾期",credit:"红字冲销",issue_credit_note:"开出红字发票",reverse_payment:"冲销收款",revert_to_approved:"退回待重新开票",reissue_invoice:"重新开票",revert_to_invoiced:"退回已批准并开票",mark_data_exported:"登记数据导出",send_reminder:"催办",sign_off:"验收签署",deprovision:"腾退",cancel:"取消",start_closing:"进入收尾期",stop:"停机",assign_super_admin:"指派超级管理员",extend_closing:"延长收尾期",link_contract:"挂上合同",add_note:"添加备注",enable_mfa:"启用两步验证",reset_mfa:"重置两步验证",send_invite:"发首次登录链接",send_password_reset:"发重置口令链接",remove:"移除员工",skip:"跳过",reopen:"回退重开",payment:"登记收款",release:"解封",set_default:"设为默认",set_primary:"设为主联系人",update_item:"更新勾选项/交付物",upload_item_file:"上传交付物文件",replace_item_file:"替换交付物文件",delete_item_file:"删除交付物文件",upload_attachment:"上传附件",delete_attachment:"删除附件",create_accept_link:"生成接受链接",revoke_accept_link:"撤销接受链接",open_accept_link:"客户打开接受链接",upload_photo:"上传照片",replace_photo:"替换照片",upload_datasheet:"上传 Datasheet / 手册",delete_datasheet:"删除 Datasheet / 手册",upload_remittance:"上传汇款凭证",replace_remittance:"替换汇款凭证",upload_avatar:"上传头像",replace_avatar:"替换头像",remove_avatar:"删除头像",update_profile:"修改本人资料",download:"下载",reject_infected:"拒收(发现恶意内容)",request:"申请",revoke:"撤销",new_version:"创建新版本",retire:"停用"},addrType:{REGISTERED:"注册地址",BILLING:"账单地址",SITE:"工地地址"},onboardingStatus:{NOT_STARTED:"未开始",IN_PROGRESS:"进行中",BLOCKED:"已阻塞",COMPLETED:"已完成",CANCELLED:"已取消"},blockedReason:{CUSTOMER_UNRESPONSIVE:"客户无回应",AWAITING_SIGNATURE:"等客户签字",AWAITING_INFRASTRUCTURE:"等客户现场条件",CUSTOMER_PAUSE:"客户要求暂停",INTERNAL_PROVISIONING:"内部原因 —— 供应问题",OTHER:"其他"},onboardingCancelReason:{CONTRACT_TERMINATED:"合同在激活前终止",CUSTOMER_WITHDREW:"客户撤回",RESTART_NEEDED:"范围大改,需要重来",OTHER:"其他"},onboardingStepStatus:{PENDING:"未开始",IN_PROGRESS:"进行中",COMPLETED:"已完成",SKIPPED:"已跳过"},onboardingStepType:{NORMAL:"常规",CONTINUOUS:"持续阶段"},projectSetupStage:{ONBOARDING:"筹备中 · 实施中",BLOCKED:"筹备中 · 受阻"},priority:{NORMAL:"普通",HIGH:"高",URGENT:"紧急"},opportunityType:{CROSS_SELL:"交叉销售",UPSELL_SCALE:"增购:增加站点或摄像头",UPSELL_TERM:"增购:延长维保期",RENEWAL_PREVIEW:"新增:模块续约预告",OTHER:"其他(在下方说明)"},employeeType:{FULL_TIME:"全职",CONTRACTOR:"外包",PART_TIME:"兼职"},staffRelationship:{PRIMARY_OWNER:"主负责人",CSM:"客户成功经理",SECONDARY_CONTACT:"次要联系人"},notifiedAudience:{FINANCE:"财务",SALES:"销售"},opportunityUrgency:{NORMAL:"普通",HIGH:"高(本周跟进)",LOW:"低"},itemType:{CHECKLIST:"勾选项",DELIVERABLE:"交付物",SIGN_OFF:"客户签字"},matchCondition:{HW_SOFTWARE:"合同含硬件 + 软件",SOFTWARE_ONLY:"合同只含软件",HARDWARE_ONLY:"合同只含硬件",MANUAL:"仅手动"},workflowOwnerRole:{PM:"项目经理(PM)",FE:"现场工程师(FE)",OPS:"运营协调",CS:"客户成功"},claimStatus:{DRAFT:"草稿",SUBMITTED:"已提交",UNDER_REVIEW:"审查中",APPROVED:"待重新开票",INVOICED:"已批准并开票",PAID:"已收款",DISPUTED:"争议中",WITHDRAWN:"已撤回"},claimReason:{EXTRA_SITE_TRIP:"额外到场",ADJUSTMENT:"金额调整",CUSTOM_SERVICE:"定制服务",EXTRA_MAINTENANCE:"额外维保",OTHER:"其它",PER_OCCURRENCE:"按次服务",OVER_INSTALLATION:"超装",AMENDMENT_HARDWARE:"变更单加设备"},claimHolder:{CREATOR:"新建人",FINANCE:"财务",CUSTOMER:"客户",OPERATIONS:"运营"},claimAction:{edit:"编辑",submit:"提交",start_review:"开始审查",approve:"批准",reject:"退回",issue_invoice:"重新开票",dispute:"争议",withdraw_dispute:"撤回争议",withdraw:"撤回登记"},disputeParty:{CUSTOMER:"客户",FINANCE:"财务",OPERATIONS:"运营"},disputeType:{AMOUNT_DISCREPANCY:"金额不符",SCOPE_NOT_AS_AGREED:"范围与约定不符",MISSING_EVIDENCE:"缺少凭证",PRICING_DISAGREEMENT:"定价有异议"},invoiceStatus:{DRAFT:"草稿",ISSUED:"已开票",DUE:"待付",OVERDUE:"已逾期",PAID:"已收款",CREDITED:"已冲销"},invoiceDocType:{INVOICE:"发票",CREDIT_NOTE:"红字发票"},claimAttachmentDocType:{SITE_REPORT:"现场报告",PROVISIONING_EVIDENCE:"开通证明",TRAINING_SIGNOFF:"培训签收",DELIVERY_ORDER:"出库单",OTHER:"其他"},productDatasheetDocType:{DATASHEET:"技术规格",MANUAL:"安装手册"},quotationAttachmentDocType:{SIGNED_SCAN:"签字报价扫描件",CUSTOMER_PO:"客户采购单",EMAIL_CONFIRMATION:"邮件确认",REFERENCE:"参考文件",OTHER:"其他"},paymentMethod:{BANK_TRANSFER:"银行转账",PAYNOW:"PayNow / FAST",CHEQUE:"支票",CARD:"信用卡 / Stripe",OTHER:"其它"},notificationCategory:{SALES:"销售",DELIVERY:"交付",ACCESS:"访问",SECURITY:"安全",SYSTEM:"系统"},notificationChannel:{EMAIL:"Email",SLACK:"Slack",SMS:"短信",IN_APP:"站内"},notificationVariableType:{STRING:"文本",NUMBER:"数字",DATE:"日期",DATETIME:"日期时间",URL:"链接"},notificationOperator:{EQ:"等于",NE:"不等于",GT:"大于",GTE:"不小于",LT:"小于",LTE:"不大于",IN:"属于",NOT_IN:"不属于"},notificationRecipientType:{OWNER:"负责人",ROLE:"角色",USER:"指定员工",SLACK_CHANNEL:"Slack 频道"},inboxCategory:{ALERTS:"告警",CUSTOMER:"客户动态",SYSTEM:"系统"},inboxBadge:{CRITICAL:"严重",WIN:"赢单",SECURITY:"安全"},inboxLinkKind:{QUOTATION:"查看报价",CONTRACT:"打开合同",PROVISIONING_RUN:"查看开通记录",HANDOVER:"打开交接",ONBOARDING:"打开实施单",CLAIM:"查看请款单",ROLE:"查看角色",MY_TASKS:"去待办处理",AUDIT_LOG:"查看审计日志",OVER_INSTALLATION:"查看超装记录"},taskType:{DISCOUNT_APPROVAL:"折扣审批",ONBOARDING_STEP:"实施步骤",HANDOVER_STEP:"交接步骤"},taskCategory:{QUOTATION:"报价",CONTRACT:"合同",ONBOARDING:"实施",HANDOVER:"交接"},taskPriority:{P0:"P0",P1:"P1",P2:"P2",P3:"P3"},taskDueBucket:{OVERDUE:"已逾期",TODAY:"今天到期",THIS_WEEK:"本周",LATER:"以后"},handoverStatus:{NOTICE_SENT:"已发通知",DATA_EXPORTING:"数据导出中",AWAITING_CONFIRMATION:"待验收签署",COMPLETED:"已完成",CANCELLED:"已取消"},handoverStepStatus:{PENDING:"未开始",DONE:"已完成",SKIPPED:"已跳过"},tenantStatus:{ACTIVE:"服务中",SUSPENDED:"已停用",ARCHIVED:"已归档"},licenceCode:{ENTERPRISE:"企业版"},projectStatus:{PENDING_CONTRACT:"待签合同",SETUP:"筹备中",BLOCKED:"受阻",ACTIVE:"运行中",CLOSING:"收尾中",ARCHIVED:"已归档"},reminderTone:{FRIENDLY:"友好提醒(第一次)",FIRM:"正式提醒(逾期 7~30 天)",ESCALATION:"升级通知(逾期 30 天以上)",FINAL:"最后通知(法律行动之前)"},linkType:{IMPLEMENTATION:"实施",MAINTENANCE:"维保",ADD_ON:"增购",RENEWAL:"续约"},priceUplift:{NONE:"不变(沿用当前价格)",CPI_5:"+5% CPI 调整",MARKET_10:"+10% 市场调整",CUSTOM:"自定义"},deploymentState:{PROVISIONING:"开通中",LIVE:"运行中",RISK:"有风险",STOPPED:"已停机"},provisioningStatus:{NOT_STARTED:"未开始",RUNNING:"进行中",FAILED:"失败",LIVE:"已上线",ROLLED_BACK:"已回滚"},accessStatus:{CUSTOMER_MANAGED:"已登记,待客户确认",BES_TEMP:"BES 临时接管",PENDING_SUPER_ADMIN:"待指派超级管理员",PENDING:"待处理",NOT_PROVISIONED:"未开通"},triggerType:{TERMINATION:"合同结束",IMPLEMENTATION:"实施交付"},cancelReason:{CONTRACT_RENEWED:"合同已续签",CUSTOMER_REQUESTED_PAUSE:"客户要求暂缓",CREATED_IN_ERROR:"误建",OTHER:"其它"},reminderType:{POLITE_FOLLOW_UP:"常规提醒",APPROACHING_DEADLINE:"临近截止",FINAL_NOTICE:"最后通知"},aggregateType:{OrganizationProfile:"组织信息",NotificationTemplate:"通知模板",PurchaseOrder:"采购单",StockMovement:"库存流水",HardwareUnit:"硬件单元",Warehouse:"仓库",Allocation:"硬件需求",Dispatch:"硬件出库",Reservation:"硬件预留",OverInstallation:"超装记录",HardwareReturn:"退回单",File:"文件",MeetingNote:"会议记录",NotificationPreference:"通知偏好",DataExport:"数据导出",Organization:"组织",Quotation:"报价",Contract:"合同",Tenant:"租户",ProductEntitlement:"产品权益",Project:"项目",Deployment:"部署实例",ProvisioningRun:"供应流水线",User:"员工账号",Role:"角色",Product:"产品",ProductRoleTemplate:"角色模板",ProvisioningPipeline:"供应流水线模板",WorkflowDefinition:"流程模板",OnboardingRun:"实施",BillingClaim:"请款单",Invoice:"发票",Handover:"项目交接",IpBlock:"IP 封禁",BillingAccount:"账单主体",CommercialTerm:"商务条款",StaffAccessGrant:"员工访问授权",Contact:"联系人",Address:"地址"},grantType:{CAR:"临时支持",BREAK_GLASS:"紧急介入"},accessGrantStatus:{PENDING:"待审批",ACTIVE:"生效中",AUTO_DELETED:"已到期",REJECTED:"已驳回",REVOKED:"已撤销",DORMANT:"休眠"},chainStatus:{INTACT:"完好",BROKEN:"已断",NEVER_VERIFIED:"从未校验"},accessAction:{API:"接口调用",LOGIN:"登录",LOGIN_FAIL:"登录失败",LOGOUT:"登出",KICKOUT:"被踢下线"}}},Mi="bes-lang",Jn="en",Hi=["en","zh-CN"];function hc(){try{const e=localStorage.getItem(Mi);return Hi.includes(e)?e:Jn}catch{return Jn}}const xt=Re(hc()),rn=tc({legacy:!1,locale:xt.value,fallbackLocale:Jn,messages:{en:pc,"zh-CN":mc}}),fc=z(()=>xt.value==="zh-CN"?uc:Br);function Mm(e){if(Hi.includes(e)){xt.value=e,rn.global.locale.value=e,document.documentElement.setAttribute("lang",e);try{localStorage.setItem(Mi,e)}catch{}}}function vc(){document.documentElement.setAttribute("lang",xt.value)}function gc(){return xt.value}const ea=rn.global.t;function yc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"m20.25 7.5-.625 10.632a2.25 2.25 0 0 1-2.247 2.118H6.622a2.25 2.25 0 0 1-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125Z"})])}function Ui(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9"})])}function co(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"})])}function Sc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M2.25 18.75a60.07 60.07 0 0 1 15.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 0 1 3 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 0 0-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 0 1-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 0 0 3 15h-.75M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm3 0h.008v.008H18V10.5Zm-12 0h.008v.008H6V10.5Z"})])}function Tc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25H12"})])}function Bi(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"})])}function bc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0"})])}function Ec(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"})])}function wc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M20.25 14.15v4.25c0 1.094-.787 2.036-1.872 2.18-2.087.277-4.216.42-6.378.42s-4.291-.143-6.378-.42c-1.085-.144-1.872-1.086-1.872-2.18v-4.25m16.5 0a2.18 2.18 0 0 0 .75-1.661V8.706c0-1.081-.768-2.015-1.837-2.175a48.114 48.114 0 0 0-3.413-.387m4.5 8.006c-.194.165-.42.295-.673.38A23.978 23.978 0 0 1 12 15.75c-2.648 0-5.195-.429-7.577-1.22a2.016 2.016 0 0 1-.673-.38m0 0A2.18 2.18 0 0 1 3 12.489V8.706c0-1.081.768-2.015 1.837-2.175a48.111 48.111 0 0 1 3.413-.387m7.5 0V5.25A2.25 2.25 0 0 0 13.5 3h-3a2.25 2.25 0 0 0-2.25 2.25v.894m7.5 0a48.667 48.667 0 0 0-7.5 0M12 12.75h.008v.008H12v-.008Z"})])}function Cc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M2.25 21h19.5m-18-18v18m10.5-18v18m6-13.5V21M6.75 6.75h.75m-.75 3h.75m-.75 3h.75m3-6h.75m-.75 3h.75m-.75 3h.75M6.75 21v-3.375c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21M3 3h12m-.75 4.5H21m-3.75 3.75h.008v.008h-.008v-.008Zm0 3h.008v.008h-.008v-.008Zm0 3h.008v.008h-.008v-.008Z"})])}function Ac(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M9 12.75 11.25 15 15 9.75M21 12c0 1.268-.63 2.39-1.593 3.068a3.745 3.745 0 0 1-1.043 3.296 3.745 3.745 0 0 1-3.296 1.043A3.745 3.745 0 0 1 12 21c-1.268 0-2.39-.63-3.068-1.593a3.746 3.746 0 0 1-3.296-1.043 3.745 3.745 0 0 1-1.043-3.296A3.745 3.745 0 0 1 3 12c0-1.268.63-2.39 1.593-3.068a3.745 3.745 0 0 1 1.043-3.296 3.746 3.746 0 0 1 3.296-1.043A3.746 3.746 0 0 1 12 3c1.268 0 2.39.63 3.068 1.593a3.746 3.746 0 0 1 3.296 1.043 3.746 3.746 0 0 1 1.043 3.296A3.745 3.745 0 0 1 21 12Z"})])}function Rc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"m4.5 15.75 7.5-7.5 7.5 7.5"})])}function Nc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M11.35 3.836c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75 2.25 2.25 0 0 0-.1-.664m-5.8 0A2.251 2.251 0 0 1 13.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m8.9-4.414c.376.023.75.05 1.124.08 1.131.094 1.976 1.057 1.976 2.192V16.5A2.25 2.25 0 0 1 18 18.75h-2.25m-7.5-10.5H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V18.75m-7.5-10.5h6.375c.621 0 1.125.504 1.125 1.125v9.375m-8.25-3 1.5 1.5 3-3.75"})])}function kc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M9 12h3.75M9 15h3.75M9 18h3.75m3 .75H18a2.25 2.25 0 0 0 2.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 0 0-1.123-.08m-5.801 0c-.065.21-.1.433-.1.664 0 .414.336.75.75.75h4.5a.75.75 0 0 0 .75-.75 2.25 2.25 0 0 0-.1-.664m-5.8 0A2.251 2.251 0 0 1 13.5 2.25H15c1.012 0 1.867.668 2.15 1.586m-5.8 0c-.376.023-.75.05-1.124.08C9.095 4.01 8.25 4.973 8.25 6.108V8.25m0 0H4.875c-.621 0-1.125.504-1.125 1.125v11.25c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V9.375c0-.621-.504-1.125-1.125-1.125H8.25ZM6.75 12h.008v.008H6.75V12Zm0 3h.008v.008H6.75V15Zm0 3h.008v.008H6.75V18Z"})])}function Pc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M15.666 3.888A2.25 2.25 0 0 0 13.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 0 1-.75.75H9a.75.75 0 0 1-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 0 1-2.25 2.25H6.75A2.25 2.25 0 0 1 4.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 0 1 1.927-.184"})])}function xi(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z"}),I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"})])}function Dc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9"})])}function _c(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m5.231 13.481L15 17.25m-4.5-15H5.625c-.621 0-1.125.504-1.125 1.125v16.5c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Zm3.75 11.625a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"})])}function Ic(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"})])}function Oc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"})])}function Fi(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M16.5 10.5V6.75a4.5 4.5 0 1 0-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 0 0 2.25-2.25v-6.75a2.25 2.25 0 0 0-2.25-2.25H6.75a2.25 2.25 0 0 0-2.25 2.25v6.75a2.25 2.25 0 0 0 2.25 2.25Z"})])}function uo(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"})])}function Lc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"m9 14.25 6-6m4.5-3.493V21.75l-3.75-1.5-3.75 1.5-3.75-1.5-3.75 1.5V4.757c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0 1 11.186 0c1.1.128 1.907 1.077 1.907 2.185ZM9.75 9h.008v.008H9.75V9Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm4.125 4.5h.008v.008h-.008V13.5Zm.375 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z"})])}function Ta(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M9 12.75 11.25 15 15 9.75m-3-7.036A11.959 11.959 0 0 1 3.598 6 11.99 11.99 0 0 0 3 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285Z"})])}function qc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M3.75 6A2.25 2.25 0 0 1 6 3.75h2.25A2.25 2.25 0 0 1 10.5 6v2.25a2.25 2.25 0 0 1-2.25 2.25H6a2.25 2.25 0 0 1-2.25-2.25V6ZM3.75 15.75A2.25 2.25 0 0 1 6 13.5h2.25a2.25 2.25 0 0 1 2.25 2.25V18a2.25 2.25 0 0 1-2.25 2.25H6A2.25 2.25 0 0 1 3.75 18v-2.25ZM13.5 6a2.25 2.25 0 0 1 2.25-2.25H18A2.25 2.25 0 0 1 20.25 6v2.25A2.25 2.25 0 0 1 18 10.5h-2.25a2.25 2.25 0 0 1-2.25-2.25V6ZM13.5 15.75a2.25 2.25 0 0 1 2.25-2.25H18a2.25 2.25 0 0 1 2.25 2.25V18A2.25 2.25 0 0 1 18 20.25h-2.25A2.25 2.25 0 0 1 13.5 18v-2.25Z"})])}function Mc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M13.5 16.875h3.375m0 0h3.375m-3.375 0V13.5m0 3.375v3.375M6 10.5h2.25a2.25 2.25 0 0 0 2.25-2.25V6a2.25 2.25 0 0 0-2.25-2.25H6A2.25 2.25 0 0 0 3.75 6v2.25A2.25 2.25 0 0 0 6 10.5Zm0 9.75h2.25A2.25 2.25 0 0 0 10.5 18v-2.25a2.25 2.25 0 0 0-2.25-2.25H6a2.25 2.25 0 0 0-2.25 2.25V18A2.25 2.25 0 0 0 6 20.25Zm9.75-9.75H18a2.25 2.25 0 0 0 2.25-2.25V6A2.25 2.25 0 0 0 18 3.75h-2.25A2.25 2.25 0 0 0 13.5 6v2.25a2.25 2.25 0 0 0 2.25 2.25Z"})])}function Hc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z"})])}function Uc(e,t){return _(),M("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor","aria-hidden":"true","data-slot":"icon"},[I("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"})])}const pe=ct({mode:null,challenge:null,notice:null,busy:!1});let vn=null;function Bc(e,t){return pe.mode="confirm",pe.challenge=e,pe.notice=t,pe.busy=!1,new Promise(n=>{vn=n})}function cn(e){const t=vn;t&&(vn=null,pe.busy=e!=="cancel",t(e))}function pn(){pe.mode=null,pe.challenge=null,pe.notice=null,pe.busy=!1,vn=null}function xc(){pe.mode!=="confirm"&&(pe.mode="mfa")}let po=Promise.resolve();function Fc(e){const t=po.then(e,e);return po=t.catch(()=>{}),t}function Vc(e){window.open(e,"bes-step-up","popup,width=560,height=760,noopener")}function mo(e){return e instanceof Error&&e.name==="StepUpCancelledError"}function jc(e){window.addEventListener("unhandledrejection",t=>{mo(t.reason)&&t.preventDefault()}),e.config.errorHandler=(t,n,a)=>{mo(t)||console.error(t,a)}}const ba="bes-token";function Vi(){return localStorage.getItem(ba)||""}function ho(e){localStorage.setItem(ba,e)}function ji(){localStorage.removeItem(ba)}const xe={OK:0,PARAM_INVALID:10001,NOT_FOUND:10404,CONFLICT:10409,UNAUTHORIZED:20001,FORBIDDEN:20002,CSRF_INVALID:20003,STEP_UP_REQUIRED:20004,STEP_UP_PENDING:20005,INVALID_STATE:30001,PROVISION_STEP_FAILED:40001,INTERNAL_ERROR:5e4,SERVICE_UNAVAILABLE:50301},Gc={NO_DEFAULT_BILLING_ACCOUNT:"NO_DEFAULT_BILLING_ACCOUNT",MATCH_CONDITION_TAKEN:"MATCH_CONDITION_TAKEN",NO_CHANGES:"NO_CHANGES",NO_STEPS:"NO_STEPS",NOTHING_PUBLISHED:"NOTHING_PUBLISHED",MFA_ENROLLMENT_REQUIRED:"MFA_ENROLLMENT_REQUIRED"};class Wc extends Error{constructor(){super("step-up cancelled"),this.name="StepUpCancelledError"}}class Gi extends Error{constructor(n){super("step-up outcome");Vt(this,"envelope");this.envelope=n}}const fo="X-Step-Up-Challenge",Hm={ACCOUNT_LOCKED:"ACCOUNT_LOCKED",ACCOUNT_NOT_ACTIVE:"ACCOUNT_NOT_ACTIVE"};class Wt extends Error{constructor(n,a,o,i){super(a);Vt(this,"code");Vt(this,"reason");Vt(this,"traceId");this.name="BizError",this.code=n,this.reason=o,this.traceId=i}}const y=xr.create({baseURL:"/api/v1",timeout:15e3});y.interceptors.request.use(e=>{if(Nt()){const t=(e.method??"get").toLowerCase();if(t!=="get"&&t!=="head"){const n=Wi();n&&(e.headers["X-CSRF-Token"]=n)}}else{const t=Vi();t&&(e.headers.Authorization=t)}return e.headers["Accept-Language"]=gc(),e});function $c(e){return String(e.headers["content-disposition"]??"").toLowerCase().startsWith("attachment")}y.interceptors.response.use(e=>e.config.responseType==="blob"?$c(e)?e:e.data.text().then(t=>{let n;try{n=JSON.parse(t)}catch{n={code:-1,msg:"",data:null}}return vo({...e,data:n})}):vo(e),e=>(Qo.error({message:e.message||ea("common.networkError"),duration:5e3,showClose:!0}),Promise.reject(e)));function vo(e){const t=e.data;if(t.code===xe.OK)return t.data;if(Nt()){if(t.code===xe.STEP_UP_REQUIRED||t.code===xe.STEP_UP_PENDING){if(e.config.stepUpRetry)return Promise.reject(new Gi(t));if(t.code===xe.STEP_UP_REQUIRED){const a=e.config;return Fc(()=>Yc(a,t.data))}}if(t.code===xe.FORBIDDEN&&t.reason===Gc.MFA_ENROLLMENT_REQUIRED)return xc(),Promise.reject(new Wt(t.code,t.msg,t.reason,t.traceId))}if(Nt()&&(t.code===xe.UNAUTHORIZED||t.code===xe.CSRF_INVALID&&!Wi()))return window.location.pathname!=="/login"&&Xc(),Promise.reject(new Wt(t.code,t.msg,t.reason,t.traceId));t.code===xe.UNAUTHORIZED&&(ji(),window.location.pathname!=="/login"&&(window.location.href="/login"));const n=t.msg||ea("common.requestFailed");return e.config.silentError&&t.code!==xe.UNAUTHORIZED?Promise.reject(new Wt(t.code,n,t.reason,t.traceId)):(Qo.error({message:t.traceId?Ye("div",null,[Ye("div",null,n),Ye("div",{class:"bes-msg-trace"},`${ea("common.traceId")}: ${t.traceId}`)]):n,duration:5e3,showClose:!0}),Promise.reject(new Wt(t.code,n,t.reason,t.traceId)))}async function Yc(e,t){let n=t,a=null;try{for(;;){const o=await Bc(n,a);if(o==="cancel")throw new Wc;const i=Fr.from(e.headers);o==="continue"?i.set(fo,n.challengeId):i.delete(fo);try{return await y.request({...e,headers:i,stepUpRetry:!0})}catch(r){if(!(r instanceof Gi))throw r;r.envelope.code===xe.STEP_UP_REQUIRED?(n=r.envelope.data,a=o==="continue"?"renewed":null):a="pending"}}}finally{pn()}}function Qc(){return y.get("/auth/config",{silentError:!0})}const vt=la(null);let qn=null;function Kc(){return vt.value?Promise.resolve(vt.value):(qn??(qn=Qc().then(e=>(vt.value=e,e)).finally(()=>{qn=null})),qn)}function Nt(){var e;return((e=vt.value)==null?void 0:e.mode)==="CONTROL"}const zc="/api/v1";function Zc(e="/"){const t=e==="/login"||e.startsWith("/login?"),n=e.startsWith("/")&&!e.startsWith("//")&&!t?e:"/";return`${zc}/auth/login?redirect=${encodeURIComponent(n)}`}let go=!1;function Xc(){go||(go=!0,window.location.href=Zc(window.location.pathname+window.location.search))}function Wi(){const e=document.cookie.split("; ").find(t=>t.startsWith("BOSS_CSRF="));return e?decodeURIComponent(e.slice(10)):""}function $i(){var t;const e=(t=vt.value)==null?void 0:t.accountSettingsUrl;e&&window.open(e,"_blank","noopener")}const Je="Asia/Singapore",Yi=8*3600*1e3,Jc=/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2}))?/;function En(e){const t=Jc.exec(e);return t?Date.UTC(+t[1],+t[2]-1,+t[3],+t[4],+t[5],+(t[6]??0)):null}function gt(e){return String(e).padStart(2,"0")}function lt(e,t){const n=new Intl.DateTimeFormat("en-GB",{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(new Date(e)),a=o=>{var i;return((i=n.find(r=>r.type===o))==null?void 0:i.value)??"00"};return`${a("year")}-${a("month")}-${a("day")}T${a("hour")}:${a("minute")}:${a("second")}`}function ta(e,t){return(En(lt(e,t))??e)-e}function ed(e,t){if(t===Je)return e;const n=En(e);return n===null?e:lt(n-Yi,t)}function Qi(e,t){if(t===Je)return e;const n=En(e);if(n===null)return e;let a=n-ta(n,t);return a=n-ta(a,t),lt(a,Je)}function td(e,t=Date.now()){return Math.round(ta(t,e)/6e4)}function Um(e,t=Date.now()){const n=td(e,t),a=n<0?"-":"+",o=Math.abs(n),i=Math.floor(o/60);return o%60?`UTC${a}${i}:${gt(o%60)}`:`UTC${a}${i}`}function Bm(){var n;const e=Intl,t=((n=e.supportedValuesOf)==null?void 0:n.call(e,"timeZone"))??[];return t.includes(Je)?t:[Je,...t]}function xm(e,t){var n;try{const a=(n=new Intl.DateTimeFormat(t,{timeZone:e,timeZoneName:"longGeneric"}).formatToParts(new Date).find(o=>o.type==="timeZoneName"))==null?void 0:n.value;return a&&!/^(GMT|UTC)([+-]|$)/.test(a)?a:null}catch{return null}}function nd(e){try{return new Intl.DateTimeFormat("en-GB",{timeZone:e}),!0}catch{return!1}}function Ki(){return lt(Date.now(),Je).slice(0,10)}function Fm(e){const[t,n,a]=Ki().split("-").map(Number),o=new Date(Date.UTC(t,n-1,a)-e*864e5);return`${o.getUTCFullYear()}-${gt(o.getUTCMonth()+1)}-${gt(o.getUTCDate())}`}function zi(e,t){const n=En(e);if(n===null)return null;const a=r=>Date.UTC(+r.slice(0,4),+r.slice(5,7)-1,+r.slice(8,10)),o=a(lt(n-Yi,t)),i=a(lt(Date.now(),t));return Math.round((i-o)/864e5)}function Vm(e,t){const n=zi(e,t);return n===null?null:Math.max(0,n)}function jm(e){return lt(Date.now()+e,Je)}function Gm(e,t){const n=lt(Date.now(),t),a=new Date(Date.UTC(+n.slice(0,4),+n.slice(5,7)-1,+n.slice(8,10))+864e5),o=`${a.getUTCFullYear()}-${gt(a.getUTCMonth()+1)}-${gt(a.getUTCDate())}T${gt(e)}:00:00`;return Qi(o,t)}function ad(e){return lt(Date.now(),e).slice(0,10)}function Wm(e,t){const n=new Date(Date.UTC(+e.slice(0,4),+e.slice(5,7)-1,+e.slice(8,10))+t*864e5);return`${n.getUTCFullYear()}-${gt(n.getUTCMonth()+1)}-${gt(n.getUTCDate())}`}function $m(e,t){return Qi(`${e}T00:00:00`,t)}function Ym(e){const t=ad(e);return(new Date(Date.UTC(+t.slice(0,4),+t.slice(5,7)-1,+t.slice(8,10))).getUTCDay()+6)%7}function Qm(e){var t;if(e===Je)return"SGT";try{return((t=new Intl.DateTimeFormat("en-US",{timeZone:e,timeZoneName:"short"}).formatToParts(new Date).find(n=>n.type==="timeZoneName"))==null?void 0:t.value)??""}catch{return""}}const od=["iso","dmy","mdy","long"],id=["24h","12h"],rd=["compact","comfortable","spacious"],sd={timeZone:Je,dateFormat:"iso",timeFormat:"24h",sidebarDensity:"comfortable"},Zi="bes-prefs";function ld(){try{const e=JSON.parse(localStorage.getItem(Zi)||"{}");return{timeZone:typeof e.timeZone=="string"&&nd(e.timeZone)?e.timeZone:Je,dateFormat:od.includes(e.dateFormat)?e.dateFormat:"iso",timeFormat:id.includes(e.timeFormat)?e.timeFormat:"24h",sidebarDensity:rd.includes(e.sidebarDensity)?e.sidebarDensity:"comfortable"}}catch{return{...sd}}}const yt=ct(ld());function Km(e){Object.assign(yt,e);try{localStorage.setItem(Zi,JSON.stringify(yt))}catch{}}const cd=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function Ea(){return yt.dateFormat}function na(e){const t=e.slice(0,4),n=e.slice(5,7),a=e.slice(8,10);switch(Ea()){case"dmy":return`${a}/${n}/${t}`;case"mdy":return`${n}/${a}/${t}`;case"long":{const o=cd[Number(n)-1];return o?`${a} ${o} ${t}`:e.slice(0,10)}default:return e.slice(0,10)}}function dd(e){const t=e.slice(11,13),n=e.slice(13,19);if(yt.timeFormat!=="12h")return`${t}${n}`;const a=Number(t);return`${a%12||12}${n} ${a<12?"AM":"PM"}`}function Xi(e){return e.length>10?ed(e,yt.timeZone):e}function ud(e){if(!e)return"—";const t=Xi(e);return t.length<16?na(t):`${na(t)} ${dd(t)}`}function Ji(e){return e?na(Xi(e)):"—"}const er={iso:"YYYY-MM-DD",dmy:"DD/MM/YYYY",mdy:"MM/DD/YYYY",long:"DD MMM YYYY"},zm=z(()=>`${er[Ea()]} ${yt.timeFormat==="12h"?"h:mm:ss A":"HH:mm:ss"}`),Zm=z(()=>er[Ea()]);function Xm(e){return e==null?"—":Number(e).toLocaleString("en-SG",{maximumFractionDigits:2})}function Jm(e){return e==null?"—":e<1024?`${e} B`:e<1024*1024?`${Math.round(e/1024)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function gn(e){const t=/^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})/.exec(e);return t?Date.UTC(+t[1],+t[2]-1,+t[3],+t[4],+t[5],+t[6])/1e3:null}function pd(e,t){if(e==null)return"—";const n=Math.abs(e),a=n<60,o=a?n:Math.floor(n/30);return e>=0?t(a?"serviceTerm.daysLeft":"serviceTerm.monthsLeft",o):t(a?"serviceTerm.expiredDaysAgo":"serviceTerm.expiredMonthsAgo",o)}function md(e,t){const n=e.durationMonths;if(!e.effectiveDate)return n==null?t("serviceTerm.pending"):t("serviceTerm.pendingFor",{n});const a=Ji(e.effectiveDate),o=e.effectiveDate.slice(0,10)>Ki()?"serviceTerm.takesEffectOn":"serviceTerm.effectiveOn";return n==null?t(`${o}Short`,{date:a}):t(o,{date:a,n})}function eh(e,t){if(!e||!t)return null;const n=gn(e),a=gn(t);return n===null||a===null?null:(a-n)/3600}function th(e,t){if(!e||!t)return null;const n=gn(e),a=gn(t);if(n===null||a===null||a0?`${i}h ${String(r).padStart(2,"0")}m`:r>0?`${r}m ${s}s`:`${l}s`}function nh(e,t){if(!e)return"—";const n=zi(e,yt.timeZone);if(n===null)return e;const a=Math.abs(n),o=n>0?-1:1,i=new Intl.RelativeTimeFormat(t,{numeric:a<2?"auto":"always"});let r;return a<7?r=i.format(o*a,"day"):a<30?r=i.format(o*Math.floor(a/7),"week"):a<730?r=i.format(o*Math.floor(a/30),"month"):r=i.format(o*Math.floor(a/365),"year"),r.charAt(0).toLocaleUpperCase(t)+r.slice(1)}const hd={class:"head"},fd={class:"head-icon"},vd=["id"],gd={class:"bes-dialog-subtitle"},yd={class:"steps"},Sd={key:1,class:"expires"},Td={class:"restart-hint"},bd={class:"mfa-body"},Ed=Ue({__name:"StepUpDialog",setup(e){const{t}=et(),n=z(()=>{var r;return!!((r=vt.value)!=null&&r.accountSettingsUrl)});function a(){pe.challenge&&Vc(pe.challenge.completionUrl)}function o(r){r||cn("cancel")}function i(){$i(),pn()}return(r,l)=>{const s=le("el-icon"),c=le("el-alert"),m=le("el-button"),d=le("el-dialog");return _(),M(we,null,[Q(d,{"model-value":C(pe).mode==="confirm",width:"480px","close-on-click-modal":!1,"close-on-press-escape":!C(pe).busy,"show-close":!C(pe).busy,"append-to-body":"","onUpdate:modelValue":o},{header:Y(({titleId:u,titleClass:f})=>[I("div",hd,[I("span",fd,[Q(s,null,{default:Y(()=>[Q(C(Ta))]),_:1})]),I("div",null,[I("span",{id:u,class:Lt(f)},j(C(t)("stepUp.title")),11,vd),I("p",gd,j(C(t)("stepUp.subtitle")),1)])])]),footer:Y(()=>[Q(m,{disabled:C(pe).busy,onClick:l[0]||(l[0]=u=>C(cn)("cancel"))},{default:Y(()=>[fe(j(C(t)("common.cancel")),1)]),_:1},8,["disabled"]),Q(m,{disabled:C(pe).busy,onClick:l[1]||(l[1]=u=>C(cn)("restart"))},{default:Y(()=>[fe(j(C(t)("stepUp.restart")),1)]),_:1},8,["disabled"]),Q(m,{disabled:C(pe).busy||!C(pe).challenge,icon:C(co),onClick:a},{default:Y(()=>[fe(j(C(t)("stepUp.open")),1)]),_:1},8,["disabled","icon"]),Q(m,{type:"primary",loading:C(pe).busy,onClick:l[2]||(l[2]=u=>C(cn)("continue"))},{default:Y(()=>[fe(j(C(t)("stepUp.continue")),1)]),_:1},8,["loading"])]),default:Y(()=>[C(pe).notice?(_(),Ie(c,{key:0,type:C(pe).notice==="pending"?"warning":"info","show-icon":"",closable:!1,class:"notice"},{default:Y(()=>[fe(j(C(pe).notice==="pending"?C(t)("stepUp.pending"):C(t)("stepUp.renewed")),1)]),_:1},8,["type"])):he("",!0),I("ol",yd,[I("li",null,j(C(t)("stepUp.step1")),1),I("li",null,j(C(t)("stepUp.step2")),1)]),C(pe).challenge?(_(),M("p",Sd,j(C(t)("stepUp.expires",{time:C(ud)(C(pe).challenge.expiresAt)})),1)):he("",!0),I("p",Td,j(C(t)("stepUp.restartHint")),1)]),_:1},8,["model-value","close-on-press-escape","show-close"]),Q(d,{"model-value":C(pe).mode==="mfa",width:"440px","append-to-body":"",title:C(t)("stepUp.mfaTitle"),"onUpdate:modelValue":C(pn)},{footer:Y(()=>[Q(m,{onClick:C(pn)},{default:Y(()=>[fe(j(C(t)("common.close")),1)]),_:1},8,["onClick"]),n.value?(_(),Ie(m,{key:0,type:"primary",icon:C(co),onClick:i},{default:Y(()=>[fe(j(C(t)("stepUp.mfaOpen")),1)]),_:1},8,["icon"])):he("",!0)]),default:Y(()=>[I("p",bd,j(C(t)("stepUp.mfaBody")),1)]),_:1},8,["model-value","title","onUpdate:modelValue"])],64)}}}),wd=kt(Ed,[["__scopeId","data-v-06abc474"]]),Cd=Ue({__name:"App",setup(e){return(t,n)=>{const a=le("router-view"),o=le("el-config-provider");return _(),Ie(o,{locale:C(fc)},{default:Y(()=>[Q(a),Q(wd)]),_:1},8,["locale"])}}});/*! * vue-router v4.5.1 * (c) 2025 Eduardo San Martin Morote * @license MIT */const _t=typeof document<"u";function tr(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function Ad(e){return e.__esModule||e[Symbol.toStringTag]==="Module"||e.default&&tr(e.default)}const ie=Object.assign;function Mn(e,t){const n={};for(const a in t){const o=t[a];n[a]=Qe(o)?o.map(e):e(o)}return n}const Yt=()=>{},Qe=Array.isArray,nr=/#/g,Rd=/&/g,Nd=/\//g,kd=/=/g,Pd=/\?/g,ar=/\+/g,Dd=/%5B/g,_d=/%5D/g,or=/%5E/g,Id=/%60/g,ir=/%7B/g,Od=/%7C/g,rr=/%7D/g,Ld=/%20/g;function wa(e){return encodeURI(""+e).replace(Od,"|").replace(Dd,"[").replace(_d,"]")}function qd(e){return wa(e).replace(ir,"{").replace(rr,"}").replace(or,"^")}function aa(e){return wa(e).replace(ar,"%2B").replace(Ld,"+").replace(nr,"%23").replace(Rd,"%26").replace(Id,"`").replace(ir,"{").replace(rr,"}").replace(or,"^")}function Md(e){return aa(e).replace(kd,"%3D")}function Hd(e){return wa(e).replace(nr,"%23").replace(Pd,"%3F")}function Ud(e){return e==null?"":Hd(e).replace(Nd,"%2F")}function tn(e){try{return decodeURIComponent(""+e)}catch{}return""+e}const Bd=/\/$/,xd=e=>e.replace(Bd,"");function Hn(e,t,n="/"){let a,o={},i="",r="";const l=t.indexOf("#");let s=t.indexOf("?");return l=0&&(s=-1),s>-1&&(a=t.slice(0,s),i=t.slice(s+1,l>-1?l:t.length),o=e(i)),l>-1&&(a=a||t.slice(0,l),r=t.slice(l,t.length)),a=Gd(a??t,n),{fullPath:a+(i&&"?")+i+r,path:a,query:o,hash:tn(r)}}function Fd(e,t){const n=t.query?e(t.query):"";return t.path+(n&&"?")+n+(t.hash||"")}function yo(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Vd(e,t,n){const a=t.matched.length-1,o=n.matched.length-1;return a>-1&&a===o&&Ht(t.matched[a],n.matched[o])&&sr(t.params,n.params)&&e(t.query)===e(n.query)&&t.hash===n.hash}function Ht(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function sr(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const n in e)if(!jd(e[n],t[n]))return!1;return!0}function jd(e,t){return Qe(e)?So(e,t):Qe(t)?So(t,e):e===t}function So(e,t){return Qe(t)?e.length===t.length&&e.every((n,a)=>n===t[a]):e.length===1&&e[0]===t}function Gd(e,t){if(e.startsWith("/"))return e;if(!e)return t;const n=t.split("/"),a=e.split("/"),o=a[a.length-1];(o===".."||o===".")&&a.push("");let i=n.length-1,r,l;for(r=0;r1&&i--;else break;return n.slice(0,i).join("/")+"/"+a.slice(r).join("/")}const ot={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0};var nn;(function(e){e.pop="pop",e.push="push"})(nn||(nn={}));var Qt;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Qt||(Qt={}));function Wd(e){if(!e)if(_t){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),xd(e)}const $d=/^[^#]+#/;function Yd(e,t){return e.replace($d,"#")+t}function Qd(e,t){const n=document.documentElement.getBoundingClientRect(),a=e.getBoundingClientRect();return{behavior:t.behavior,left:a.left-n.left-(t.left||0),top:a.top-n.top-(t.top||0)}}const wn=()=>({left:window.scrollX,top:window.scrollY});function Kd(e){let t;if("el"in e){const n=e.el,a=typeof n=="string"&&n.startsWith("#"),o=typeof n=="string"?a?document.getElementById(n.slice(1)):document.querySelector(n):n;if(!o)return;t=Qd(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.scrollX,t.top!=null?t.top:window.scrollY)}function To(e,t){return(history.state?history.state.position-t:-1)+e}const oa=new Map;function zd(e,t){oa.set(e,t)}function Zd(e){const t=oa.get(e);return oa.delete(e),t}let Xd=()=>location.protocol+"//"+location.host;function lr(e,t){const{pathname:n,search:a,hash:o}=t,i=e.indexOf("#");if(i>-1){let l=o.includes(e.slice(i))?e.slice(i).length:1,s=o.slice(l);return s[0]!=="/"&&(s="/"+s),yo(s,"")}return yo(n,e)+a+o}function Jd(e,t,n,a){let o=[],i=[],r=null;const l=({state:u})=>{const f=lr(e,location),A=n.value,P=t.value;let N=0;if(u){if(n.value=f,t.value=u,r&&r===A){r=null;return}N=P?u.position-P.position:0}else a(f);o.forEach(v=>{v(n.value,A,{delta:N,type:nn.pop,direction:N?N>0?Qt.forward:Qt.back:Qt.unknown})})};function s(){r=n.value}function c(u){o.push(u);const f=()=>{const A=o.indexOf(u);A>-1&&o.splice(A,1)};return i.push(f),f}function m(){const{history:u}=window;u.state&&u.replaceState(ie({},u.state,{scroll:wn()}),"")}function d(){for(const u of i)u();i=[],window.removeEventListener("popstate",l),window.removeEventListener("beforeunload",m)}return window.addEventListener("popstate",l),window.addEventListener("beforeunload",m,{passive:!0}),{pauseListeners:s,listen:c,destroy:d}}function bo(e,t,n,a=!1,o=!1){return{back:e,current:t,forward:n,replaced:a,position:window.history.length,scroll:o?wn():null}}function eu(e){const{history:t,location:n}=window,a={value:lr(e,n)},o={value:t.state};o.value||i(a.value,{back:null,current:a.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function i(s,c,m){const d=e.indexOf("#"),u=d>-1?(n.host&&document.querySelector("base")?e:e.slice(d))+s:Xd()+e+s;try{t[m?"replaceState":"pushState"](c,"",u),o.value=c}catch(f){console.error(f),n[m?"replace":"assign"](u)}}function r(s,c){const m=ie({},t.state,bo(o.value.back,s,o.value.forward,!0),c,{position:o.value.position});i(s,m,!0),a.value=s}function l(s,c){const m=ie({},o.value,t.state,{forward:s,scroll:wn()});i(m.current,m,!0);const d=ie({},bo(a.value,s,null),{position:m.position+1},c);i(s,d,!1),a.value=s}return{location:a,state:o,push:l,replace:r}}function tu(e){e=Wd(e);const t=eu(e),n=Jd(e,t.state,t.location,t.replace);function a(i,r=!0){r||n.pauseListeners(),history.go(i)}const o=ie({location:"",base:e,go:a,createHref:Yd.bind(null,e)},t,n);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}function nu(e){return typeof e=="string"||e&&typeof e=="object"}function cr(e){return typeof e=="string"||typeof e=="symbol"}const dr=Symbol("");var Eo;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(Eo||(Eo={}));function Ut(e,t){return ie(new Error,{type:e,[dr]:!0},t)}function at(e,t){return e instanceof Error&&dr in e&&(t==null||!!(e.type&t))}const wo="[^/]+?",au={sensitive:!1,strict:!1,start:!0,end:!0},ou=/[.+*?^${}()[\]/\\]/g;function iu(e,t){const n=ie({},au,t),a=[];let o=n.start?"^":"";const i=[];for(const c of e){const m=c.length?[]:[90];n.strict&&!c.length&&(o+="/");for(let d=0;dt.length?t.length===1&&t[0]===80?1:-1:0}function ur(e,t){let n=0;const a=e.score,o=t.score;for(;n0&&t[t.length-1]<0}const su={type:0,value:""},lu=/[a-zA-Z0-9_]/;function cu(e){if(!e)return[[]];if(e==="/")return[[su]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(f){throw new Error(`ERR (${n})/"${c}": ${f}`)}let n=0,a=n;const o=[];let i;function r(){i&&o.push(i),i=[]}let l=0,s,c="",m="";function d(){c&&(n===0?i.push({type:0,value:c}):n===1||n===2||n===3?(i.length>1&&(s==="*"||s==="+")&&t(`A repeatable param (${c}) must be alone in its segment. eg: '/:ids+.`),i.push({type:1,value:c,regexp:m,repeatable:s==="*"||s==="+",optional:s==="*"||s==="?"})):t("Invalid state to consume buffer"),c="")}function u(){c+=s}for(;l{r(b)}:Yt}function r(d){if(cr(d)){const u=a.get(d);u&&(a.delete(d),n.splice(n.indexOf(u),1),u.children.forEach(r),u.alias.forEach(r))}else{const u=n.indexOf(d);u>-1&&(n.splice(u,1),d.record.name&&a.delete(d.record.name),d.children.forEach(r),d.alias.forEach(r))}}function l(){return n}function s(d){const u=hu(d,n);n.splice(u,0,d),d.record.name&&!No(d)&&a.set(d.record.name,d)}function c(d,u){let f,A={},P,N;if("name"in d&&d.name){if(f=a.get(d.name),!f)throw Ut(1,{location:d});N=f.record.name,A=ie(Ao(u.params,f.keys.filter(b=>!b.optional).concat(f.parent?f.parent.keys.filter(b=>b.optional):[]).map(b=>b.name)),d.params&&Ao(d.params,f.keys.map(b=>b.name))),P=f.stringify(A)}else if(d.path!=null)P=d.path,f=n.find(b=>b.re.test(P)),f&&(A=f.parse(P),N=f.record.name);else{if(f=u.name?a.get(u.name):n.find(b=>b.re.test(u.path)),!f)throw Ut(1,{location:d,currentLocation:u});N=f.record.name,A=ie({},u.params,d.params),P=f.stringify(A)}const v=[];let S=f;for(;S;)v.unshift(S.record),S=S.parent;return{name:N,path:P,params:A,matched:v,meta:mu(v)}}e.forEach(d=>i(d));function m(){n.length=0,a.clear()}return{addRoute:i,resolve:c,removeRoute:r,clearRoutes:m,getRoutes:l,getRecordMatcher:o}}function Ao(e,t){const n={};for(const a of t)a in e&&(n[a]=e[a]);return n}function Ro(e){const t={path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:e.aliasOf,beforeEnter:e.beforeEnter,props:pu(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}};return Object.defineProperty(t,"mods",{value:{}}),t}function pu(e){const t={},n=e.props||!1;if("component"in e)t.default=n;else for(const a in e.components)t[a]=typeof n=="object"?n[a]:n;return t}function No(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function mu(e){return e.reduce((t,n)=>ie(t,n.meta),{})}function ko(e,t){const n={};for(const a in e)n[a]=a in t?t[a]:e[a];return n}function hu(e,t){let n=0,a=t.length;for(;n!==a;){const i=n+a>>1;ur(e,t[i])<0?a=i:n=i+1}const o=fu(e);return o&&(a=t.lastIndexOf(o,a-1)),a}function fu(e){let t=e;for(;t=t.parent;)if(pr(t)&&ur(e,t)===0)return t}function pr({record:e}){return!!(e.name||e.components&&Object.keys(e.components).length||e.redirect)}function vu(e){const t={};if(e===""||e==="?")return t;const a=(e[0]==="?"?e.slice(1):e).split("&");for(let o=0;oi&&aa(i)):[a&&aa(a)]).forEach(i=>{i!==void 0&&(t+=(t.length?"&":"")+n,i!=null&&(t+="="+i))})}return t}function gu(e){const t={};for(const n in e){const a=e[n];a!==void 0&&(t[n]=Qe(a)?a.map(o=>o==null?null:""+o):a==null?a:""+a)}return t}const mr=Symbol(""),Do=Symbol(""),Cn=Symbol(""),Ca=Symbol(""),ia=Symbol("");function Gt(){let e=[];function t(a){return e.push(a),()=>{const o=e.indexOf(a);o>-1&&e.splice(o,1)}}function n(){e=[]}return{add:t,list:()=>e.slice(),reset:n}}function yu(e,t,n){const a=()=>{e[t].delete(n)};Yo(a),jr(a),Gr(()=>{e[t].add(n)}),e[t].add(n)}function ah(e){const t=Xe(mr,{}).value;t&&yu(t,"leaveGuards",e)}function mt(e,t,n,a,o,i=r=>r()){const r=a&&(a.enterCallbacks[o]=a.enterCallbacks[o]||[]);return()=>new Promise((l,s)=>{const c=u=>{u===!1?s(Ut(4,{from:n,to:t})):u instanceof Error?s(u):nu(u)?s(Ut(2,{from:t,to:u})):(r&&a.enterCallbacks[o]===r&&typeof u=="function"&&r.push(u),l())},m=i(()=>e.call(a&&a.instances[o],t,n,c));let d=Promise.resolve(m);e.length<3&&(d=d.then(c)),d.catch(u=>s(u))})}function Un(e,t,n,a,o=i=>i()){const i=[];for(const r of e)for(const l in r.components){let s=r.components[l];if(!(t!=="beforeRouteEnter"&&!r.instances[l]))if(tr(s)){const m=(s.__vccOpts||s)[t];m&&i.push(mt(m,n,a,r,l,o))}else{let c=s();i.push(()=>c.then(m=>{if(!m)throw new Error(`Couldn't resolve component "${l}" at "${r.path}"`);const d=Ad(m)?m.default:m;r.mods[l]=m,r.components[l]=d;const f=(d.__vccOpts||d)[t];return f&&mt(f,n,a,r,l,o)()}))}}return i}function _o(e){const t=Xe(Cn),n=Xe(Ca),a=z(()=>{const s=C(e.to);return t.resolve(s)}),o=z(()=>{const{matched:s}=a.value,{length:c}=s,m=s[c-1],d=n.matched;if(!m||!d.length)return-1;const u=d.findIndex(Ht.bind(null,m));if(u>-1)return u;const f=Io(s[c-2]);return c>1&&Io(m)===f&&d[d.length-1].path!==f?d.findIndex(Ht.bind(null,s[c-2])):u}),i=z(()=>o.value>-1&&wu(n.params,a.value.params)),r=z(()=>o.value>-1&&o.value===n.matched.length-1&&sr(n.params,a.value.params));function l(s={}){if(Eu(s)){const c=t[C(e.replace)?"replace":"push"](C(e.to)).catch(Yt);return e.viewTransition&&typeof document<"u"&&"startViewTransition"in document&&document.startViewTransition(()=>c),c}return Promise.resolve()}return{route:a,href:z(()=>a.value.href),isActive:i,isExactActive:r,navigate:l}}function Su(e){return e.length===1?e[0]:e}const Tu=Ue({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"},viewTransition:Boolean},useLink:_o,setup(e,{slots:t}){const n=ct(_o(e)),{options:a}=Xe(Cn),o=z(()=>({[Oo(e.activeClass,a.linkActiveClass,"router-link-active")]:n.isActive,[Oo(e.exactActiveClass,a.linkExactActiveClass,"router-link-exact-active")]:n.isExactActive}));return()=>{const i=t.default&&Su(t.default(n));return e.custom?i:Ye("a",{"aria-current":n.isExactActive?e.ariaCurrentValue:null,href:n.href,onClick:n.navigate,class:o.value},i)}}}),bu=Tu;function Eu(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function wu(e,t){for(const n in t){const a=t[n],o=e[n];if(typeof a=="string"){if(a!==o)return!1}else if(!Qe(o)||o.length!==a.length||a.some((i,r)=>i!==o[r]))return!1}return!0}function Io(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const Oo=(e,t,n)=>e??t??n,Cu=Ue({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:n}){const a=Xe(ia),o=z(()=>e.route||a.value),i=Xe(Do,0),r=z(()=>{let c=C(i);const{matched:m}=o.value;let d;for(;(d=m[c])&&!d.components;)c++;return c}),l=z(()=>o.value.matched[r.value]);kn(Do,z(()=>r.value+1)),kn(mr,l),kn(ia,o);const s=Re();return je(()=>[s.value,l.value,e.name],([c,m,d],[u,f,A])=>{m&&(m.instances[d]=c,f&&f!==m&&c&&c===u&&(m.leaveGuards.size||(m.leaveGuards=f.leaveGuards),m.updateGuards.size||(m.updateGuards=f.updateGuards))),c&&m&&(!f||!Ht(m,f)||!u)&&(m.enterCallbacks[d]||[]).forEach(P=>P(c))},{flush:"post"}),()=>{const c=o.value,m=e.name,d=l.value,u=d&&d.components[m];if(!u)return Lo(n.default,{Component:u,route:c});const f=d.props[m],A=f?f===!0?c.params:typeof f=="function"?f(c):f:null,N=Ye(u,ie({},A,t,{onVnodeUnmounted:v=>{v.component.isUnmounted&&(d.instances[m]=null)},ref:s}));return Lo(n.default,{Component:N,route:c})||N}}});function Lo(e,t){if(!e)return null;const n=e(t);return n.length===1?n[0]:n}const Au=Cu;function Ru(e){const t=uu(e.routes,e),n=e.parseQuery||vu,a=e.stringifyQuery||Po,o=e.history,i=Gt(),r=Gt(),l=Gt(),s=la(ot);let c=ot;_t&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const m=Mn.bind(null,T=>""+T),d=Mn.bind(null,Ud),u=Mn.bind(null,tn);function f(T,L){let q,$;return cr(T)?(q=t.getRecordMatcher(T),$=L):$=T,t.addRoute($,q)}function A(T){const L=t.getRecordMatcher(T);L&&t.removeRoute(L)}function P(){return t.getRoutes().map(T=>T.record)}function N(T){return!!t.getRecordMatcher(T)}function v(T,L){if(L=ie({},L||s.value),typeof T=="string"){const Z=Hn(n,T,L.path),me=t.resolve({path:Z.path},L),We=o.createHref(Z.fullPath);return ie(Z,me,{params:u(me.params),hash:tn(Z.hash),redirectedFrom:void 0,href:We})}let q;if(T.path!=null)q=ie({},T,{path:Hn(n,T.path,L.path).path});else{const Z=ie({},T.params);for(const me in Z)Z[me]==null&&delete Z[me];q=ie({},T,{params:d(Z)}),L.params=d(L.params)}const $=t.resolve(q,L),oe=T.hash||"";$.params=m(u($.params));const ye=Fd(a,ie({},T,{hash:qd(oe),path:$.path})),J=o.createHref(ye);return ie({fullPath:ye,hash:oe,query:a===Po?gu(T.query):T.query||{}},$,{redirectedFrom:void 0,href:J})}function S(T){return typeof T=="string"?Hn(n,T,s.value.path):ie({},T)}function b(T,L){if(c!==T)return Ut(8,{from:L,to:T})}function g(T){return w(T)}function k(T){return g(ie(S(T),{replace:!0}))}function O(T){const L=T.matched[T.matched.length-1];if(L&&L.redirect){const{redirect:q}=L;let $=typeof q=="function"?q(T):q;return typeof $=="string"&&($=$.includes("?")||$.includes("#")?$=S($):{path:$},$.params={}),ie({query:T.query,hash:T.hash,params:$.path!=null?{}:T.params},$)}}function w(T,L){const q=c=v(T),$=s.value,oe=T.state,ye=T.force,J=T.replace===!0,Z=O(q);if(Z)return w(ie(S(Z),{state:typeof Z=="object"?ie({},oe,Z.state):oe,force:ye,replace:J}),L||q);const me=q;me.redirectedFrom=L;let We;return!ye&&Vd(a,$,q)&&(We=Ut(16,{to:me,from:$}),V($,$,!0,!1)),(We?Promise.resolve(We):G(me,$)).catch(Ne=>at(Ne)?at(Ne,2)?Ne:B(Ne):tt(Ne,me,$)).then(Ne=>{if(Ne){if(at(Ne,2))return w(ie({replace:J},S(Ne.to),{state:typeof Ne.to=="object"?ie({},oe,Ne.to.state):oe,force:ye}),L||me)}else Ne=te(me,$,!0,J,oe);return se(me,$,Ne),Ne})}function W(T,L){const q=b(T,L);return q?Promise.reject(q):Promise.resolve()}function U(T){const L=Pe.values().next().value;return L&&typeof L.runWithContext=="function"?L.runWithContext(T):T()}function G(T,L){let q;const[$,oe,ye]=Nu(T,L);q=Un($.reverse(),"beforeRouteLeave",T,L);for(const Z of $)Z.leaveGuards.forEach(me=>{q.push(mt(me,T,L))});const J=W.bind(null,T,L);return q.push(J),X(q).then(()=>{q=[];for(const Z of i.list())q.push(mt(Z,T,L));return q.push(J),X(q)}).then(()=>{q=Un(oe,"beforeRouteUpdate",T,L);for(const Z of oe)Z.updateGuards.forEach(me=>{q.push(mt(me,T,L))});return q.push(J),X(q)}).then(()=>{q=[];for(const Z of ye)if(Z.beforeEnter)if(Qe(Z.beforeEnter))for(const me of Z.beforeEnter)q.push(mt(me,T,L));else q.push(mt(Z.beforeEnter,T,L));return q.push(J),X(q)}).then(()=>(T.matched.forEach(Z=>Z.enterCallbacks={}),q=Un(ye,"beforeRouteEnter",T,L,U),q.push(J),X(q))).then(()=>{q=[];for(const Z of r.list())q.push(mt(Z,T,L));return q.push(J),X(q)}).catch(Z=>at(Z,8)?Z:Promise.reject(Z))}function se(T,L,q){l.list().forEach($=>U(()=>$(T,L,q)))}function te(T,L,q,$,oe){const ye=b(T,L);if(ye)return ye;const J=L===ot,Z=_t?history.state:{};q&&($||J?o.replace(T.fullPath,ie({scroll:J&&Z&&Z.scroll},oe)):o.push(T.fullPath,oe)),s.value=T,V(T,L,q,J),B()}let be;function Ge(){be||(be=o.listen((T,L,q)=>{if(!wt.listening)return;const $=v(T),oe=O($);if(oe){w(ie(oe,{replace:!0,force:!0}),$).catch(Yt);return}c=$;const ye=s.value;_t&&zd(To(ye.fullPath,q.delta),wn()),G($,ye).catch(J=>at(J,12)?J:at(J,2)?(w(ie(S(J.to),{force:!0}),$).then(Z=>{at(Z,20)&&!q.delta&&q.type===nn.pop&&o.go(-1,!1)}).catch(Yt),Promise.reject()):(q.delta&&o.go(-q.delta,!1),tt(J,$,ye))).then(J=>{J=J||te($,ye,!1),J&&(q.delta&&!at(J,8)?o.go(-q.delta,!1):q.type===nn.pop&&at(J,20)&&o.go(-1,!1)),se($,ye,J)}).catch(Yt)}))}let He=Gt(),Le=Gt(),ge;function tt(T,L,q){B(T);const $=Le.list();return $.length?$.forEach(oe=>oe(T,L,q)):console.error(T),Promise.reject(T)}function qe(){return ge&&s.value!==ot?Promise.resolve():new Promise((T,L)=>{He.add([T,L])})}function B(T){return ge||(ge=!T,Ge(),He.list().forEach(([L,q])=>T?q(T):L()),He.reset()),T}function V(T,L,q,$){const{scrollBehavior:oe}=e;if(!_t||!oe)return Promise.resolve();const ye=!q&&Zd(To(T.fullPath,0))||($||!q)&&history.state&&history.state.scroll||null;return $o().then(()=>oe(T,L,ye)).then(J=>J&&Kd(J)).catch(J=>tt(J,T,L))}const H=T=>o.go(T);let ke;const Pe=new Set,wt={currentRoute:s,listening:!0,addRoute:f,removeRoute:A,clearRoutes:t.clearRoutes,hasRoute:N,getRoutes:P,resolve:v,options:e,push:g,replace:k,go:H,back:()=>H(-1),forward:()=>H(1),beforeEach:i.add,beforeResolve:r.add,afterEach:l.add,onError:Le.add,isReady:qe,install(T){const L=this;T.component("RouterLink",bu),T.component("RouterView",Au),T.config.globalProperties.$router=L,Object.defineProperty(T.config.globalProperties,"$route",{enumerable:!0,get:()=>C(s)}),_t&&!ke&&s.value===ot&&(ke=!0,g(o.location).catch(oe=>{}));const q={};for(const oe in ot)Object.defineProperty(q,oe,{get:()=>s.value[oe],enumerable:!0});T.provide(Cn,L),T.provide(Ca,Vr(q)),T.provide(ia,s);const $=T.unmount;Pe.add(T),T.unmount=function(){Pe.delete(T),Pe.size<1&&(c=ot,be&&be(),be=null,s.value=ot,ke=!1,ge=!1),$()}}};function X(T){return T.reduce((L,q)=>L.then(()=>U(q)),Promise.resolve())}return wt}function Nu(e,t){const n=[],a=[],o=[],i=Math.max(t.matched.length,e.matched.length);for(let r=0;rHt(c,l))?a.push(l):n.push(l));const s=e.matched[r];s&&(t.matched.find(c=>Ht(c,s))||o.push(s))}return[n,a,o]}function Aa(){return Xe(Cn)}function An(e){return Xe(Ca)}const ku="modulepreload",Pu=function(e){return"/"+e},qo={},K=function(t,n,a){let o=Promise.resolve();if(n&&n.length>0){document.getElementsByTagName("link");const r=document.querySelector("meta[property=csp-nonce]"),l=(r==null?void 0:r.nonce)||(r==null?void 0:r.getAttribute("nonce"));o=Promise.allSettled(n.map(s=>{if(s=Pu(s),s in qo)return;qo[s]=!0;const c=s.endsWith(".css"),m=c?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${s}"]${m}`))return;const d=document.createElement("link");if(d.rel=c?"stylesheet":ku,c||(d.as="script"),d.crossOrigin="",d.href=s,l&&d.setAttribute("nonce",l),document.head.appendChild(d),c)return new Promise((u,f)=>{d.addEventListener("load",u),d.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${s}`)))})}))}function i(r){const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=r,window.dispatchEvent(l),!l.defaultPrevented)throw r}return o.then(r=>{for(const l of r||[])l.status==="rejected"&&i(l.reason);return t().catch(i)})},oh="PER_OCCURRENCE",ih="RECURRING",rh=["PER_OCCURRENCE","OVER_INSTALLATION","AMENDMENT_HARDWARE"],Ra={companyRole:[{value:"CUSTOMER"},{value:"SERVICE_RECIPIENT"},{value:"MAIN_CON"},{value:"SUB_CON"},{value:"DEVELOPER"},{value:"CONSULTANT"},{value:"SUPPLIER"},{value:"EQUIPMENT"}],lifecycleStage:[{value:"LEAD",type:"info"},{value:"QUALIFIED",type:"warning"},{value:"CUSTOMER",type:"success"},{value:"ACTIVE",type:"info"},{value:"DORMANT",type:"danger"},{value:"CHURNED",type:"danger"}],companyStatus:[{value:"ACTIVE",type:"success"},{value:"ARCHIVED",type:"info"}],billingAccountStatus:[{value:"ACTIVE",type:"success"},{value:"ARCHIVED",type:"info"}],addrType:[{value:"REGISTERED"},{value:"BILLING"},{value:"SITE"}],relationshipType:[{value:"NONE"},{value:"SUBSIDIARY"},{value:"JV_PARTNER"},{value:"BRANCH"},{value:"DIVISION"}],quotationStatus:[{value:"DRAFT",type:"info"},{value:"SENT",type:"warning"},{value:"ACCEPTED",type:"success"},{value:"REJECTED",type:"danger"},{value:"EXPIRED",type:"info"},{value:"SUPERSEDED",type:"info"}],acceptLinkStatus:[{value:"ACTIVE",type:"success"},{value:"EXPIRED",type:"info"},{value:"REVOKED",type:"danger"},{value:"SUPERSEDED",type:"info"},{value:"DECIDED",type:"primary"}],discountApprovalStatus:[{value:"NOT_REQUIRED",type:"info"},{value:"PENDING",type:"warning"},{value:"APPROVED",type:"success"},{value:"REJECTED",type:"danger"}],lineType:[{value:"SOFTWARE"},{value:"HARDWARE"},{value:"SERVICE"}],productType:[{value:"SOFTWARE"},{value:"HARDWARE"},{value:"SERVICE"}],productStatus:[{value:"ACTIVE",type:"success"},{value:"BETA",type:"primary"},{value:"DEPRECATED",type:"info"}],stockStatus:[{value:"HEALTHY",type:"success"},{value:"LOW",type:"warning"},{value:"OUT",type:"danger"}],hardwareUnitStatus:[{value:"IN_STOCK",type:"success"},{value:"DISPATCHED",type:"primary"},{value:"ON_SITE",type:"warning"},{value:"INSTALLED",type:"info"},{value:"RETURNED",type:"warning"},{value:"UNDER_REPAIR",type:"warning"},{value:"AT_SUPPLIER",type:"info"},{value:"SCRAPPED",type:"danger"}],purchaseOrderStatus:[{value:"ORDERED",type:"info"},{value:"IN_TRANSIT",type:"primary"},{value:"PARTIALLY_RECEIVED",type:"warning"},{value:"RECEIVED",type:"success"},{value:"CANCELLED",type:"info"}],stockMovementType:[{value:"INITIAL",type:"success"},{value:"RECEIVE",type:"success"},{value:"ALLOCATE",type:"warning"},{value:"RELEASE",type:"info"},{value:"DISPATCH",type:"primary"},{value:"RECALL",type:"info"},{value:"INSTALL",type:"info"},{value:"HOLD_ON_SITE",type:"warning"},{value:"RETURN",type:"warning"},{value:"REPAIR",type:"warning"},{value:"TO_SUPPLIER",type:"info"},{value:"RESTOCK",type:"success"},{value:"SCRAP",type:"danger"},{value:"TRANSFER",type:"info"}],allocationStatus:[{value:"PENDING_ONBOARDING",type:"info"},{value:"RESERVED",type:"warning"},{value:"FULFILLED",type:"success"}],dispatchStatus:[{value:"IN_TRANSIT",type:"primary"},{value:"DELIVERED",type:"success"},{value:"CONFIRMED",type:"info"},{value:"CANCELLED",type:"info"}],dispatchOutcome:[{value:"INSTALLED",type:"success"},{value:"ON_SITE",type:"warning"},{value:"FAULTY",type:"danger"},{value:"SURPLUS",type:"info"}],installationStatus:[{value:"NEEDS_CHECK",type:"warning"},{value:"INSTALLING",type:"warning"},{value:"OPERATIONAL",type:"success"}],returnStatus:[{value:"REPORTED",type:"info"},{value:"RETURNED",type:"warning"},{value:"UNDER_REPAIR",type:"warning"},{value:"AT_SUPPLIER",type:"primary"},{value:"RESTOCKED",type:"success"},{value:"SCRAPPED",type:"danger"},{value:"CANCELLED",type:"info"}],returnSource:[{value:"SITE"},{value:"WAREHOUSE"},{value:"INSTALLATION"}],returnHistoryAction:[{value:"CREATE"},{value:"RECEIVE"},{value:"REPAIR"},{value:"SEND_TO_SUPPLIER"},{value:"RESTOCK"},{value:"SCRAP"},{value:"CANCEL"},{value:"SPLIT"}],productScopeLevel:[{value:"PROJECT"},{value:"TENANT"}],controlSyncStatus:[{value:"NOT_APPLICABLE",type:"info"},{value:"PENDING",type:"warning"},{value:"SYNCED",type:"success"},{value:"FAILED",type:"danger"}],hardwareRequirement:[{value:"REQUIRED"},{value:"RECOMMENDED"}],revisionStatus:[{value:"CURRENT",type:"success"},{value:"SUPERSEDED",type:"info"}],stepType:[{value:"REQUIRED",type:"primary"},{value:"OPTIONAL",type:"info"}],periodType:[{value:"RECURRING"},{value:"ONE_TIME"},{value:"PER_OCCURRENCE"}],amendmentType:[{value:"SCOPE_ADDITION"},{value:"SCOPE_REDUCTION"},{value:"PRICE_ADJUSTMENT"},{value:"TERM_EXTENSION"},{value:"VO_DRIVEN"},{value:"CONTACT_BILLING_CHANGE"},{value:"OTHER"}],amendmentStatus:[{value:"DRAFT",type:"info"},{value:"PENDING_SIGNATURE",type:"warning"},{value:"ACTIVE",type:"success"}],contractStatus:[{value:"DRAFT",type:"info"},{value:"PENDING_CUSTOMER_SIGNATURE",type:"warning"},{value:"ACTIVE",type:"success"},{value:"EXPIRING",type:"warning"},{value:"EXPIRED",type:"info"},{value:"TERMINATING",type:"warning"},{value:"TERMINATED",type:"danger"}],partyRole:[{value:"BILLING"},{value:"SERVICE_RECIPIENT"},{value:"BES"}],effectiveMode:[{value:"IMMEDIATE"},{value:"STEP"},{value:"DATE"}],effectiveSource:[{value:"IMMEDIATE"},{value:"DATE"},{value:"STEP"},{value:"MANUAL",type:"warning"},{value:"RENEWAL"}],effectiveState:[{value:"PENDING",type:"warning"},{value:"PARTIAL",type:"warning"},{value:"EFFECTIVE",type:"success"}],termStatus:[{value:"DRAFT",type:"info"},{value:"CURRENT",type:"success"},{value:"SUPERSEDED",type:"warning"},{value:"RETIRED",type:"danger"}],termCategory:[{value:"GENERAL"},{value:"PAYMENT"},{value:"DPA"},{value:"SLA"},{value:"INDUSTRY_SPECIFIC"},{value:"TERM_ADJUSTMENT"}],termSourceState:[{value:"CURRENT",type:"success"},{value:"SUPERSEDED",type:"info"},{value:"RETIRED",type:"info"},{value:"GONE",type:"info"}],termLanguage:[{value:"EN"},{value:"ZH"}],termRefType:[{value:"QUOTATION"},{value:"CONTRACT"}],grantType:[{value:"CAR",type:"info"},{value:"BREAK_GLASS",type:"danger"}],accessGrantStatus:[{value:"PENDING",type:"warning"},{value:"ACTIVE",type:"danger"},{value:"AUTO_DELETED",type:"info"},{value:"REJECTED",type:"info"},{value:"REVOKED",type:"info"},{value:"DORMANT",type:"info"}],entitlementStatus:[{value:"PENDING",type:"warning"},{value:"ACTIVE",type:"success"},{value:"SUSPENDED",type:"warning"},{value:"EXPIRED",type:"info"},{value:"TERMINATED",type:"danger"}],runStatus:[{value:"RUNNING",type:"primary"},{value:"SUCCESS",type:"success"},{value:"FAILED",type:"danger"},{value:"ROLLED_BACK",type:"info"}],runType:[{value:"PROVISION"},{value:"DEPROVISION",type:"warning"},{value:"RECONCILE",type:"primary"}],runTrigger:[{value:"CONTRACT_ACTIVATED"},{value:"CONTRACT_RENEWED"},{value:"TERM_EXTENDED"},{value:"ENTITLEMENT_TERMINATED"},{value:"HANDOVER_VACATED"},{value:"SCHEDULED"}],discrepancyKind:[{value:"NOT_PUSHED",type:"warning"},{value:"MISSING_IN_CONTROL",type:"danger"},{value:"INACTIVE_IN_CONTROL",type:"danger"},{value:"ACTIVE_IN_CONTROL",type:"danger"},{value:"PERIOD_MISMATCH",type:"warning"},{value:"UNKNOWN_IN_CONTROL",type:"warning"}],controlEntitlementStatus:[{value:"PENDING",type:"warning"},{value:"ACTIVE",type:"success"},{value:"REVOKED",type:"info"},{value:"EXPIRED",type:"info"}],stepStatus:[{value:"PENDING",type:"info"},{value:"RUNNING",type:"primary"},{value:"SUCCESS",type:"success"},{value:"SKIPPED",type:"info"},{value:"FAILED",type:"danger"}],stepBehavior:[{value:"IDEMPOTENT"},{value:"RETRYABLE"},{value:"CONDITIONAL"}],deliveryType:[{value:"SOFTWARE"},{value:"HARDWARE"},{value:"MIXED"}],onboardingStatus:[{value:"NOT_STARTED",type:"info"},{value:"IN_PROGRESS",type:"primary"},{value:"BLOCKED",type:"danger"},{value:"COMPLETED",type:"success"},{value:"CANCELLED",type:"info"}],blockedReason:[{value:"CUSTOMER_UNRESPONSIVE"},{value:"AWAITING_SIGNATURE"},{value:"AWAITING_INFRASTRUCTURE"},{value:"CUSTOMER_PAUSE"},{value:"INTERNAL_PROVISIONING"},{value:"OTHER"}],onboardingCancelReason:[{value:"CONTRACT_TERMINATED"},{value:"CUSTOMER_WITHDREW"},{value:"RESTART_NEEDED"},{value:"OTHER"}],onboardingStepStatus:[{value:"PENDING",type:"info"},{value:"IN_PROGRESS",type:"primary"},{value:"COMPLETED",type:"success"},{value:"SKIPPED",type:"warning"}],onboardingStepType:[{value:"NORMAL",type:"info"},{value:"CONTINUOUS",type:"warning"}],priority:[{value:"NORMAL",type:"info"},{value:"HIGH",type:"warning"},{value:"URGENT",type:"danger"}],projectSetupStage:[{value:"ONBOARDING",type:"warning"},{value:"BLOCKED",type:"danger"}],opportunityType:[{value:"CROSS_SELL"},{value:"UPSELL_SCALE"},{value:"UPSELL_TERM"},{value:"RENEWAL_PREVIEW"},{value:"OTHER"}],employeeType:[{value:"FULL_TIME"},{value:"CONTRACTOR"},{value:"PART_TIME"}],staffRelationship:[{value:"PRIMARY_OWNER",type:"primary"},{value:"CSM",type:"success"},{value:"SECONDARY_CONTACT",type:"info"}],notifiedAudience:[{value:"FINANCE"},{value:"SALES"}],opportunityUrgency:[{value:"NORMAL"},{value:"HIGH"},{value:"LOW"}],itemType:[{value:"CHECKLIST"},{value:"DELIVERABLE"},{value:"SIGN_OFF"}],matchCondition:[{value:"HW_SOFTWARE"},{value:"SOFTWARE_ONLY"},{value:"HARDWARE_ONLY"},{value:"MANUAL",type:"info"}],workflowOwnerRole:[{value:"PM"},{value:"FE"},{value:"OPS"},{value:"CS"}],claimStatus:[{value:"DRAFT",type:"info"},{value:"SUBMITTED",type:"primary"},{value:"UNDER_REVIEW",type:"warning"},{value:"APPROVED",type:"warning"},{value:"INVOICED",type:"success"},{value:"PAID",type:"info"},{value:"DISPUTED",type:"danger"},{value:"WITHDRAWN",type:"info"}],claimReason:[{value:"EXTRA_SITE_TRIP"},{value:"ADJUSTMENT"},{value:"CUSTOM_SERVICE"},{value:"EXTRA_MAINTENANCE"},{value:"OTHER"},{value:"PER_OCCURRENCE"},{value:"OVER_INSTALLATION"},{value:"AMENDMENT_HARDWARE"}],claimHolder:[{value:"CREATOR"},{value:"FINANCE"},{value:"CUSTOMER"},{value:"OPERATIONS"}],claimAction:[{value:"edit"},{value:"submit"},{value:"start_review"},{value:"approve"},{value:"reject"},{value:"issue_invoice"},{value:"dispute"},{value:"withdraw_dispute"},{value:"withdraw"}],disputeParty:[{value:"CUSTOMER",type:"danger"},{value:"FINANCE",type:"warning"},{value:"OPERATIONS",type:"warning"}],disputeType:[{value:"AMOUNT_DISCREPANCY"},{value:"SCOPE_NOT_AS_AGREED"},{value:"MISSING_EVIDENCE"},{value:"PRICING_DISAGREEMENT"}],invoiceStatus:[{value:"DRAFT",type:"info"},{value:"ISSUED",type:"primary"},{value:"DUE",type:"warning"},{value:"OVERDUE",type:"danger"},{value:"PAID",type:"success"},{value:"CREDITED",type:"info"}],invoiceDocType:[{value:"INVOICE"},{value:"CREDIT_NOTE",type:"danger"}],claimAttachmentDocType:[{value:"SITE_REPORT"},{value:"PROVISIONING_EVIDENCE"},{value:"TRAINING_SIGNOFF"},{value:"DELIVERY_ORDER"},{value:"OTHER"}],productDatasheetDocType:[{value:"DATASHEET"},{value:"MANUAL"}],quotationAttachmentDocType:[{value:"SIGNED_SCAN"},{value:"CUSTOMER_PO"},{value:"EMAIL_CONFIRMATION"},{value:"REFERENCE"},{value:"OTHER"}],paymentMethod:[{value:"BANK_TRANSFER"},{value:"PAYNOW"},{value:"CHEQUE"},{value:"CARD"},{value:"OTHER"}],handoverStatus:[{value:"NOTICE_SENT",type:"primary"},{value:"DATA_EXPORTING",type:"warning"},{value:"AWAITING_CONFIRMATION",type:"success"},{value:"COMPLETED",type:"success"},{value:"CANCELLED",type:"info"}],handoverStepStatus:[{value:"PENDING",type:"info"},{value:"DONE",type:"success"},{value:"SKIPPED",type:"warning"}],notificationCategory:[{value:"SALES"},{value:"DELIVERY"},{value:"ACCESS"},{value:"SECURITY"},{value:"SYSTEM"}],notificationChannel:[{value:"EMAIL"},{value:"SLACK"},{value:"SMS"},{value:"IN_APP"}],notificationVariableType:[{value:"STRING"},{value:"NUMBER"},{value:"DATE"},{value:"DATETIME"},{value:"URL"}],notificationOperator:[{value:"EQ"},{value:"NE"},{value:"GT"},{value:"GTE"},{value:"LT"},{value:"LTE"},{value:"IN"},{value:"NOT_IN"}],notificationRecipientType:[{value:"OWNER"},{value:"ROLE"},{value:"USER"},{value:"SLACK_CHANNEL"}],inboxCategory:[{value:"ALERTS",type:"danger"},{value:"CUSTOMER",type:"success"},{value:"SYSTEM",type:"info"}],inboxBadge:[{value:"CRITICAL",type:"danger"},{value:"WIN",type:"success"},{value:"SECURITY",type:"danger"}],inboxLinkKind:[{value:"QUOTATION"},{value:"CONTRACT"},{value:"PROVISIONING_RUN"},{value:"HANDOVER"},{value:"ONBOARDING"},{value:"CLAIM"},{value:"OVER_INSTALLATION"},{value:"ROLE"},{value:"MY_TASKS"},{value:"AUDIT_LOG"}],taskType:[{value:"DISCOUNT_APPROVAL"},{value:"ONBOARDING_STEP"},{value:"HANDOVER_STEP"}],taskCategory:[{value:"QUOTATION",type:"info"},{value:"CONTRACT",type:"primary"},{value:"ONBOARDING",type:"warning"},{value:"HANDOVER",type:"info"}],taskPriority:[{value:"P0",type:"danger"},{value:"P1",type:"warning"},{value:"P2",type:"info"},{value:"P3",type:"info"}],taskDueBucket:[{value:"OVERDUE",type:"danger"},{value:"TODAY",type:"warning"},{value:"THIS_WEEK",type:"primary"},{value:"LATER",type:"info"}],triggerType:[{value:"TERMINATION",type:"warning"},{value:"IMPLEMENTATION",type:"info"}],cancelReason:[{value:"CONTRACT_RENEWED",type:"success"},{value:"CUSTOMER_REQUESTED_PAUSE"},{value:"CREATED_IN_ERROR"},{value:"OTHER"}],reminderType:[{value:"POLITE_FOLLOW_UP",type:"info"},{value:"APPROACHING_DEADLINE",type:"warning"},{value:"FINAL_NOTICE",type:"danger"}],projectStatus:[{value:"PENDING_CONTRACT",type:"info"},{value:"SETUP",type:"warning"},{value:"BLOCKED",type:"danger"},{value:"ACTIVE",type:"success"},{value:"CLOSING",type:"warning"},{value:"ARCHIVED",type:"info"}],reminderTone:[{value:"FRIENDLY",type:"info"},{value:"FIRM",type:"warning"},{value:"ESCALATION",type:"warning"},{value:"FINAL",type:"danger"}],linkType:[{value:"IMPLEMENTATION",type:"primary"},{value:"MAINTENANCE",type:"info"},{value:"ADD_ON",type:"warning"},{value:"RENEWAL",type:"primary"}],priceUplift:[{value:"NONE"},{value:"CPI_5"},{value:"MARKET_10"},{value:"CUSTOM"}],deploymentState:[{value:"PROVISIONING",type:"primary"},{value:"LIVE",type:"success"},{value:"RISK",type:"warning"},{value:"STOPPED",type:"info"}],provisioningStatus:[{value:"NOT_STARTED",type:"info"},{value:"RUNNING",type:"primary"},{value:"FAILED",type:"danger"},{value:"LIVE",type:"success"},{value:"ROLLED_BACK",type:"info"}],accessStatus:[{value:"CUSTOMER_MANAGED",type:"primary"},{value:"BES_TEMP",type:"warning"},{value:"PENDING_SUPER_ADMIN",type:"warning"},{value:"PENDING",type:"info"},{value:"NOT_PROVISIONED",type:"info"}],tenantStatus:[{value:"ACTIVE",type:"success"},{value:"SUSPENDED",type:"warning"},{value:"ARCHIVED",type:"info"}],licenceCode:[{value:"ENTERPRISE",type:"primary"}],userStatus:[{value:"Active",type:"success"},{value:"MFA Pending",type:"warning"},{value:"Suspended",type:"info"},{value:"Removed",type:"danger"}],userRemovalBlocker:[{value:"OWNS_COMPANIES"},{value:"HAS_ACTIVE_PROJECTS"},{value:"HAS_OPEN_TASKS"},{value:"SELF"},{value:"LAST_ADMIN"},{value:"ALREADY_REMOVED"}],loginStatus:[{value:"INVITED",type:"warning"},{value:"INVITE_EXPIRED",type:"danger"},{value:"ACTIVE",type:"success"}],dataScope:[{value:"ALL",type:"primary"},{value:"OWNED",type:"warning"}],permissionRisk:[{value:"STANDARD",type:"info"},{value:"SENSITIVE",type:"warning"},{value:"HIGH_RISK",type:"danger"}],actorType:[{value:"USER",type:"primary"},{value:"SYSTEM",type:"info"},{value:"EXTERNAL",type:"warning"}],auditRisk:[{value:"NORMAL",type:"info"},{value:"HIGH",type:"danger"}],auditCategory:[{value:"AUTHENTICATION"},{value:"SALES"},{value:"DELIVERY"},{value:"ACCESS"},{value:"SYSTEM_BILLING"}],auditSeverity:[{value:"INFO",type:"info"},{value:"WARNING",type:"warning"},{value:"CRITICAL",type:"danger"}],action:[{value:"view"},{value:"create"},{value:"update"},{value:"delete"},{value:"manage"},{value:"archive"},{value:"restore"},{value:"qualify"},{value:"send"},{value:"accept"},{value:"reject"},{value:"revise"},{value:"expire"},{value:"supersede"},{value:"submit_approval"},{value:"approve_discount"},{value:"reject_discount"},{value:"update_payment_plan"},{value:"send_for_signature"},{value:"create_amendment"},{value:"send_amendment_for_signature"},{value:"activate_amendment"},{value:"renew"},{value:"activate"},{value:"terminate"},{value:"mark_expiring"},{value:"mark_expired"},{value:"start_term"},{value:"set_effective_date"},{value:"mark_active"},{value:"extend_authorization"},{value:"advance_contract_end"},{value:"go_live"},{value:"start"},{value:"complete"},{value:"fail"},{value:"retry"},{value:"roll_back"},{value:"suspend"},{value:"auto_suspend"},{value:"lock"},{value:"unlock"},{value:"change_roles"},{value:"change_password"},{value:"reset_password"},{value:"change_permissions"},{value:"change_status"},{value:"sync"},{value:"sync_apps"},{value:"import_permissions"},{value:"publish"},{value:"publish_pipeline"},{value:"discard"},{value:"release_match_condition"},{value:"start_step"},{value:"complete_step"},{value:"skip_step"},{value:"reopen_step"},{value:"block"},{value:"unblock"},{value:"reassign"},{value:"assign_staff"},{value:"remove_staff"},{value:"notify_sales"},{value:"submit"},{value:"start_review"},{value:"approve"},{value:"dispute"},{value:"withdraw_dispute"},{value:"settle"},{value:"issue_invoice"},{value:"record_payment"},{value:"mark_sent"},{value:"mark_overdue"},{value:"credit"},{value:"issue_credit_note"},{value:"reverse_payment"},{value:"revert_to_approved"},{value:"reissue_invoice"},{value:"revert_to_invoiced"},{value:"mark_data_exported"},{value:"send_reminder"},{value:"sign_off"},{value:"deprovision"},{value:"cancel"},{value:"start_closing"},{value:"stop"},{value:"assign_super_admin"},{value:"link_contract"},{value:"add_note"},{value:"enable_mfa"},{value:"reset_mfa"},{value:"send_invite"},{value:"send_password_reset"},{value:"remove"},{value:"release"},{value:"set_default"},{value:"set_primary"},{value:"request"},{value:"revoke"},{value:"new_version"},{value:"retire"},{value:"update_item"},{value:"skip"},{value:"reopen"},{value:"payment"},{value:"export"},{value:"change_stage"},{value:"ship"},{value:"receive"},{value:"record_movement"},{value:"reserve"},{value:"deliver"},{value:"confirm_installation"},{value:"register_delivery_receipt"},{value:"change"},{value:"repair"},{value:"send_to_supplier"},{value:"restock"},{value:"scrap"},{value:"split"},{value:"withdraw"},{value:"record_occurrences"}],aggregateType:[{value:"Organization"},{value:"Quotation"},{value:"Contract"},{value:"Tenant"},{value:"ProductEntitlement"},{value:"Project"},{value:"Deployment"},{value:"ProvisioningRun"},{value:"User"},{value:"Role"},{value:"Product"},{value:"ProductRoleTemplate"},{value:"ProvisioningPipeline"},{value:"WorkflowDefinition"},{value:"OnboardingRun"},{value:"BillingClaim"},{value:"Invoice"},{value:"Handover"},{value:"IpBlock"},{value:"BillingAccount"},{value:"CommercialTerm"},{value:"StaffAccessGrant"},{value:"Contact"},{value:"Address"},{value:"DataExport"},{value:"OrganizationProfile"},{value:"NotificationTemplate"},{value:"NotificationPreference"},{value:"MeetingNote"},{value:"PurchaseOrder"},{value:"StockMovement"},{value:"HardwareUnit"},{value:"Warehouse"},{value:"Allocation"},{value:"Dispatch"},{value:"Reservation"},{value:"OverInstallation"},{value:"HardwareReturn"},{value:"File"}],chainStatus:[{value:"INTACT",type:"success"},{value:"BROKEN",type:"danger"},{value:"NEVER_VERIFIED",type:"warning"}],accessAction:[{value:"API",type:"info"},{value:"LOGIN",type:"success"},{value:"LOGIN_FAIL",type:"danger"},{value:"LOGOUT",type:"info"},{value:"KICKOUT",type:"warning"}]},sh=Ra.lifecycleStage.filter(e=>["LEAD","QUALIFIED"].includes(e.value));function Du(e,t){const n=Ra[e].find(a=>a.value===t);return(n==null?void 0:n.type)??"info"}function hr(){const{t:e,te:t}=et(),n=e,a=t;function o(r,l){if(!l)return"—";const s=`enum.${r}.${l}`;return a(s)?n(s):l}function i(r,l){return z(()=>Ra[r].filter(s=>l?l(s):!0).map(s=>({...s,label:o(r,s.value)})))}return{label:o,options:i,tagType:Du}}const _u=Ue({__name:"StatusTag",props:{dict:{},value:{},wrap:{type:Boolean},bordered:{type:Boolean},plain:{type:Boolean},text:{},tone:{}},setup(e){const{label:t,tagType:n}=hr();return(a,o)=>{const i=le("el-tag");return _(),Ie(i,{type:e.tone||C(n)(e.dict,e.value),"disable-transitions":"",class:Lt(["status-tag",{"status-tag--wrap":e.wrap,"status-tag--bordered":e.bordered,"status-tag--plain":e.plain}])},{default:Y(()=>[o[0]||(o[0]=I("span",{class:"status-dot","aria-hidden":"true"},null,-1)),fe(j(e.text??C(t)(e.dict,e.value)),1),Ko(a.$slots,"default",{},void 0,!0)]),_:3},8,["type","class"])}}}),Iu=kt(_u,[["__scopeId","data-v-2cbded84"]]);function lh(e){return e.tokenValue?"done":e.mfaSetupRequired?"setup":"mfa"}function Ou(e){return y.post("/auth/login",e)}function ch(e){return y.post("/auth/mfa/verify",e)}function dh(e){return y.post("/auth/mfa/setup",{setupToken:e})}function uh(e){return y.post("/auth/mfa/setup/confirm",e)}function Lu(){return y.post("/auth/logout")}function qu(){return y.get("/auth/userinfo")}const Ft=ni("user",()=>{const e=Re(null),t=Re([]);async function n(l,s){const c=await Ou({username:l,password:s});return c.tokenValue&&ho(c.tokenValue),c}function a(l){ho(l)}async function o(){const l=await qu();return e.value=l,t.value=l.permissions||[],l}async function i(){var s;const l=Nt();try{await Lu()}finally{r(),l&&(window.location.href=((s=vt.value)==null?void 0:s.logoutRedirectUrl)||"/")}}function r(){ji(),e.value=null,t.value=[]}return{userInfo:e,permissions:t,login:n,acceptToken:a,fetchUserInfo:o,logout:i,reset:r}}),fr={company:e=>`/crm/companies/${e}`,quotation:e=>`/crm/quotations/${e}`,contract:e=>`/crm/contracts/${e}`,project:e=>`/projects/list/${e}`,instance:e=>`/product-instances/list/${e}`,claim:e=>`/billing/claims/${e}`},Mu={company:"boss.companies.view",quotation:"boss.quotations.view",contract:"boss.contracts.view",project:"boss.projects.view",instance:"boss.entitlements.view",claim:"boss.claims.view"},Hu="boss-web:recent-objects:",Uu=10,Bu=Object.keys(fr);function xu(){const e=Ft(),t=()=>{var o;return Hu+(((o=e.userInfo)==null?void 0:o.id)??"")};function n(){try{const o=JSON.parse(localStorage.getItem(t())||"[]");return Array.isArray(o)?o.filter(i=>!!i&&typeof i.id=="string"&&typeof i.title=="string"&&Bu.includes(i.type)):[]}catch{return[]}}function a(o){try{const i=[o,...n().filter(r=>!(r.type===o.type&&r.id===o.id))].slice(0,Uu);localStorage.setItem(t(),JSON.stringify(i))}catch{}}return{list:n,record:a}}function Mo(e){return y.get("/companies",{params:e})}function ph(e){return y.get(`/companies/${e}`)}function mh(e){return y.post("/companies",e)}function hh(e,t){return y.put(`/companies/${e}`,t)}function fh(e){return y.post(`/companies/${e}/archive`)}function vh(e){return y.post(`/companies/${e}/restore`)}function gh(e){return y.delete(`/companies/${e}`)}function yh(e){return y.get("/companies/staff-relations",{params:e})}function Sh(e,t){return y.post(`/companies/${e}/staff-relations`,t)}function Th(e,t){return y.delete(`/companies/${e}/staff-relations/${t}`)}const bh=["shortName","uen","industry","website","accountOwnerId","parentOrgId","relationshipType","tags","notes"];function Eh(){return y.get("/companies/stats")}function wh(e,t){return y.get(`/companies/${e}/contacts`,{silentError:t==null?void 0:t.silentError})}function Ch(e,t){return y.post(`/companies/${e}/contacts`,t)}function Ah(e,t,n){return y.put(`/companies/${e}/contacts/${t}`,n)}function Rh(e,t){return y.delete(`/companies/${e}/contacts/${t}`)}function Nh(e,t){return y.post(`/companies/${e}/contacts/${t}/set-primary`)}function kh(e,t,n){return y.get(`/companies/${e}/meeting-notes/${t}`,n)}function Ph(e,t){return y.post(`/companies/${e}/meeting-notes`,t)}function Dh(e,t,n){return y.put(`/companies/${e}/meeting-notes/${t}`,n)}function _h(e,t){return y.delete(`/companies/${e}/meeting-notes/${t}`)}function Ih(e){return y.get(`/companies/${e}/addresses`)}function Oh(e,t){return y.post(`/companies/${e}/addresses`,t)}function Lh(e,t,n){return y.put(`/companies/${e}/addresses/${t}`,n)}function qh(e,t){return y.delete(`/companies/${e}/addresses/${t}`)}function vr(e,t,n,a){const o={};for(const i of n){const r=e[i],l=t[i];r==null||String(r).trim()===""?l!=null&&String(l)!==""&&(o[i]=""):o[i]=r}for(const i of a){const r=e[i];r!=null&&String(r).trim()!==""&&(o[i]=r)}return o}function Mh(e,t){return{...vr(e,t,["title","phone"],["firstName","lastName","email","contactType"]),version:t.version}}function Hh(e,t){return{...vr(e,t,["line2","postal","label","projectId"],["addrType","line1","country"]),version:t.version}}const Uh=["siteAddress","internalNotes"],Bh=["ARCHIVED"],xh=["SETUP","BLOCKED","ACTIVE"],Fh=["SETUP","ACTIVE","CLOSING"],Vh=[30,60,90];function Fu(e){return y.get("/projects",{params:e})}function jh(e){return y.get(`/projects/${e}`)}function Gh(){return y.get("/projects/stats")}function Wh(e,t){return y.put(`/projects/${e}`,t)}function $h(e,t){return y.post(`/projects/${e}/assign-super-admin`,t)}function Yh(e){return y.post("/projects/import",e)}function Qh(e,t){return y.post(`/projects/${e}/contracts`,{contractIds:t})}function Kh(e,t){return y.post(`/projects/${e}/extend-closing`,t)}function zh(e){return y.post(`/projects/${e}/archive`)}function Vu(e){return e.status==="TERMINATING"||e.status==="TERMINATED"?e.terminatedEffectiveDate:null}function Zh(e){return e.projectStatus==="CLOSING"||e.projectStatus==="ARCHIVED"}function Xh(){return y.get("/contracts/stats")}function ju(e){return y.get("/contracts",{params:e})}function Jh(e){return y.get(`/contracts/${e}`)}function ef(e,t){return y.put(`/contracts/${e}`,t)}function tf(e,t){return y.post(`/contracts/${e}/occurrences`,t)}function nf(e,t){return y.put(`/contracts/${e}/payment-plan`,t)}function af(e){return y.post(`/contracts/${e}/send-for-signature`)}function of(e,t,n){return y.put(`/contracts/${e}/terms/${t}/effective-date`,n)}function rf(e){return y.post(`/contracts/${e}/activate`)}function sf(e,t){return y.post(`/contracts/${e}/terminate`,t)}function lf(e,t){return y.post(`/contracts/${e}/renew`,t)}const cf=["billingCycle","ownerId"];function df(e){return y.get(`/contracts/${e}/amendments`)}function uf(e,t){return y.post(`/contracts/${e}/amendments`,t)}function pf(e,t){return y.post(`/contracts/${e}/amendments/${t}/mini-quotation`)}function mf(e,t){return y.post(`/contracts/${e}/amendments/${t}/send-for-signature`)}function hf(e,t,n){return y.post(`/contracts/${e}/amendments/${t}/activate`,n)}function Gu(){const{t:e}=et(),{label:t}=hr(),n=e;function a(s){return pd(s,n)}function o(s){return md(s,n)}function i(s){const c=Vu(s);return c?e("serviceTerm.endsOn",{date:Ji(c)}):s.status==="DRAFT"||s.status==="PENDING_CUSTOMER_SIGNATURE"?e("common.none"):s.effectiveState&&s.effectiveState!=="EFFECTIVE"?t("effectiveState",s.effectiveState):a(s.daysToExpiry)}function r(s){return s.effectiveState&&s.effectiveState!=="EFFECTIVE"?t("effectiveState",s.effectiveState):a(s.daysToEnd)}function l(s,c){if(s==null)return e("common.none");const m=e("serviceTerm.months",s);return c?`${m} · ${c>0?"+":"−"}${Math.abs(c)}`:m}return{remaining:a,termLine:o,contractRemaining:i,projectRemaining:r,termLabel:l}}const ff=["SUSPENDED","EXPIRED"];function Wu(e){return y.get("/entitlements",{params:e})}function vf(e){return y.get(`/entitlements/${e}`)}function gf(){return y.get("/entitlements/stats")}const yf=["EXPIRED","TERMINATED"],Sf=90,gr=12e4;function Rn(e,t,n={}){const a=new FormData;a.append("file",t);for(const[o,i]of Object.entries(n))a.append(o,i);return y.post(e,a,{timeout:gr})}async function $u(e,t={}){return(await y.get(e,{responseType:"blob",timeout:gr,silentError:t.silentError})).data}const pt=1024*1024,Tf={onboardingItem:{extensions:["pdf","png","jpg","jpeg","docx","xlsx"],maxBytes:25*pt},claimAttachment:{extensions:["pdf","xlsx","jpg","jpeg"],maxBytes:25*pt},productPhoto:{extensions:["png","jpg","jpeg"],maxBytes:5*pt},productDatasheet:{extensions:["pdf"],maxBytes:25*pt},remittance:{extensions:["pdf","png","jpg","jpeg"],maxBytes:10*pt},quotationAttachment:{extensions:["pdf","png","jpg","jpeg"],maxBytes:10*pt},avatar:{extensions:["png","jpg","jpeg","gif"],maxBytes:2*pt}};function Yu(e){const t=e.lastIndexOf(".");return t<0?"":e.slice(t+1).toLowerCase()}function Qu(e){return e.extensions.filter(t=>t!=="jpeg").map(t=>t.toUpperCase())}function bf(e){return e.extensions.map(t=>`.${t}`).join(",")}function Ef(e,t){return t.extensions.includes(Yu(e.name))?e.size===0?{key:"files.empty",params:{}}:e.size>t.maxBytes?{key:"files.tooLarge",params:{size:Math.round(t.maxBytes/pt)}}:null:{key:"files.typeNotAllowed",params:{types:Qu(t).join(", ")}}}function wf(e){const t=e.contentType.toLowerCase();return t==="application/pdf"?"pdf":t.startsWith("image/")?"image":null}function Ku(e){return y.get("/quotations",{params:e})}function Cf(e){return y.get(`/quotations/${e}`)}function Af(e,t,n){return Rn(`/quotations/${e}/attachments`,t,{docType:n})}function Rf(e,t){return y.delete(`/quotations/${e}/attachments/${t}`)}function Nf(e,t){return`/quotations/${e}/attachments/${t}/content`}function kf(e){return y.post("/quotations",e)}function Pf(e,t){return y.put(`/quotations/${e}`,t)}function Df(e,t){return y.post(`/quotations/${e}/send`,t??{})}function _f(e,t){return y.post(`/quotations/${e}/accept-link/regenerate`,{})}function If(e){return y.post(`/quotations/${e}/accept-link/revoke`)}function Of(e,t){return y.post(`/quotations/${e}/accept`,t??{})}function Lf(e){return y.post(`/quotations/${e}/submit-approval`)}function qf(e,t,n=!1){return y.post(`/quotations/${e}/approve-discount`,{note:t},{silentError:n})}function Mf(e,t,n=!1){return y.post(`/quotations/${e}/reject-discount`,{note:t},{silentError:n})}function Hf(e,t){return y.post(`/quotations/${e}/reject`,t)}function Uf(e,t){return y.post(`/quotations/${e}/revise`,t??{})}function Bf(e,t){return y.post(`/quotations/${e}/duplicate`,t)}function xf(){return y.get("/quotations/stats")}function Ff(e){return y.delete(`/quotations/${e}`)}const Vf=["serviceOrgId","relatedProjectId","newProjectName","newProjectType","newProjectSiteCountry","newProjectSiteAddress","termMonths","ownerId","termsTemplateCode","validityDays","discountAmount","notes"],jf=["paymentNodeId"];function zu(e){return y.get("/claims",{params:e})}function Gf(e,t=!1){return y.get(`/claims/${e}`,{silentError:t})}function Wf(e){return y.post("/claims",e)}function $f(e,t){return y.put(`/claims/${e}`,t)}function Yf(e){return y.post(`/claims/${e}/submit`)}function Qf(e,t){return y.post(`/claims/${e}/reject`,{reason:t})}function Kf(e,t){return y.post(`/claims/${e}/variation-orders`,t)}function zf(e,t){return y.post(`/claims/${e}/variation-orders/${t}/apply`)}function Zf(e,t,n){return Rn(`/claims/${e}/attachments`,t,{docType:n})}function Xf(e,t){return y.delete(`/claims/${e}/attachments/${t}`)}function Jf(e,t){return`/claims/${e}/attachments/${t}/content`}function ev(e){return y.post(`/claims/${e}/start-review`)}function tv(e,t){return y.post(`/claims/${e}/approve`,t)}function nv(e,t){return y.post(`/claims/${e}/dispute`,t)}function av(e){return y.post(`/claims/${e}/withdraw-dispute`)}function ov(e,t){return y.post(`/claims/${e}/withdraw`,t?{reason:t}:{})}function iv(e){return y.post(`/claims/${e}/issue-invoice`)}function rv(e){return y.get("/invoices",{params:e})}function sv(e){return y.get(`/invoices/${e}`)}function lv(e,t){return y.post(`/invoices/${e}/payments`,t)}function cv(e,t,n){return Rn(`/invoices/${e}/payments/${t}/remittance`,n)}function dv(e,t){return`/invoices/${e}/payments/${t}/remittance/content`}function uv(e){return y.post(`/invoices/${e}/mark-sent`)}function pv(e,t){return y.post(`/invoices/${e}/send-reminder`,t)}function mv(e,t){return y.post(`/invoices/${e}/credit-note`,{reason:t})}function hv(e,t,n){return y.post(`/invoices/${e}/payments/${t}/reverse`,{reason:n})}function fv(){return y.get("/claims/stats")}function vv(){return y.get("/invoices/stats")}function Zu(e){return y.get("/access-grants",{params:e})}function Xu(){return Zu({status:"PENDING",current:1,size:1}).then(e=>e.total)}function gv(e){return y.get(`/access-grants/${e}`)}function yv(e){return y.post(`/access-grants/${e}/approve`)}function Sv(e,t){return y.post(`/access-grants/${e}/reject`,{reason:t})}function Tv(e,t){return y.post(`/access-grants/${e}/revoke`,{reason:t})}function Ju(e,t){var a,o;if((a=e.meta)!=null&&a.localOnly&&Nt())return!1;const n=(o=e.meta)==null?void 0:o.perms;return!n||n.length===0?!0:n.some(i=>t.includes(i))}function yr(e,t){const n=[];for(const a of e)if(Ju(a,t)){const o={...a};o.children&&(o.children=yr(o.children,t)),n.push(o)}return n}const Na=ni("permission",()=>{const e=Re([]);function t(n){return e.value=yr(ym,n),e.value}return{accessRoutes:e,generateRoutes:t}});function bv(e){return y.get("/tasks/mine",{params:void 0})}function ep(e=!1){return y.get("/tasks/mine/stats",{silentError:e})}function Ev(e){return y.post("/tasks/mine/snooze",{until:e})}function wv(){return y.delete("/tasks/mine/snooze")}function Cv(e){return y.get("/notifications/mine",{params:e})}function tp(e,t=!1){return y.get("/notifications/mine/stats",{params:e,silentError:t})}function Av(e){return y.post(`/notifications/mine/${e}/read`)}function Rv(){return y.post("/notifications/mine/read-all")}const Sr=Re(null),Tr=Re(null),np=6e4;let Ho=0;function ap(e){Sr.value=e.open}function op(e){Tr.value=e.unreadTotal}async function Uo(e=!1){if(!e&&Date.now()-HoYe("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"1.6","aria-hidden":"true"},[Ye("path",{d:"M19 21V5A2 2 0 0017 3H7A2 2 0 005 5V21L8 19L11 21L14 19L17 21Z"})]),Er={title:"shell.orgSettings",icon:xi,routes:["OrgGeneral","AuthPolicy","Compliance"],tabs:["shell.tab.general","shell.tab.auth","shell.tab.compliance"],sideTabIcons:[ip,Fi,Wr]},rp=[...br.flatMap(e=>e.items),Er];function wr(e){return rp.find(t=>t.routes.includes(e))}function sp(e,t){if(t.startsWith("/"))return t;const n=e.endsWith("/")?e:e+"/";return t?n+t:e}function lp(){const e=Na();return z(()=>{const t=new Map,n=(a,o)=>{for(const i of a){const r=sp(o,i.path);typeof i.name=="string"&&t.set(i.name,r),i.children&&n(i.children,r)}};return n(e.accessRoutes,""),t})}function Nn(){const e=lp();function t(o){const i=o.routes.map((r,l)=>{var s;return{name:r,title:((s=o.tabs)==null?void 0:s[l])??o.title,path:e.value.get(r)}}).filter(r=>!!r.path);return i.length?{...o,path:i[0].path,visibleTabs:i}:null}const n=z(()=>br.map(o=>({title:o.title,items:o.items.map(t).filter(i=>!!i)})).filter(o=>o.items.length)),a=z(()=>t(Er));return{groups:n,orgSettings:a,visible:t,accessible:e}}const cp=["aria-label"],dp={class:"trigger-text"},up={class:"search-row"},pp={class:"body"},mp={class:"section-title"},hp=["onClick","onMouseenter"],fp={class:"jump-icon"},vp={class:"section-title"},gp={key:0,class:"empty"},yp=["onClick","onMouseenter"],Sp={class:"type"},Tp={class:"title"},bp={key:0,class:"meta"},Ep={key:0,class:"empty"},wp={key:0,class:"group"},Cp={class:"section-title"},Ap={key:0,class:"count"},Rp={key:0,class:"error"},Np={key:1,class:"empty"},kp=["onClick","onMouseenter"],Pp={class:"title"},Dp={key:0,class:"code"},_p={key:1,class:"empty"},Ip={class:"keys"},dt=5,Op=Ue({__name:"GlobalSearch",setup(e){const t=["company","quotation","contract","project","instance","claim"],{t:n}=et(),{contractRemaining:a}=Gu(),o=Aa(),i=Ft(),{list:r}=xu(),l=Re(!1),s=Re(""),c=Re(),m=Re(0),d=Re([]),u=ct([]),f=Re(!1),A=z(()=>s.value.trim()),{groups:P}=Nn(),N=z(()=>{const B=P.value.flatMap(H=>H.items),V=A.value.toLowerCase();return V?B.filter(H=>[n(H.title),rn.global.t(H.title,{},{locale:"en"}),...H.aliases??[]].some(ke=>ke.toLowerCase().includes(V))):B}),v=B=>i.permissions.includes(Mu[B]),S=z(()=>t.filter(v)),g=/Mac|iPhone|iPad/.test(navigator.platform||navigator.userAgent)?"⌘K":"Ctrl K",k={async company(B){const[V,H]=await Promise.all([Mo({keyword:B,current:1,size:dt}),Mo({keyword:B,status:"ARCHIVED",current:1,size:dt})]),ke=[...V.records??[],...H.records??[]].slice(0,dt);return{total:(V.total??0)+(H.total??0),items:ke.map(Pe=>({type:"company",id:Pe.id,title:Pe.legalName,code:Pe.orgNo,meta:[Pe.countryName].filter(Boolean),statusDict:"companyStatus",status:Pe.status}))}},async quotation(B){const V=await Ku({keyword:B,current:1,size:dt});return{total:V.total??0,items:(V.records??[]).map(H=>({type:"quotation",id:H.id,title:H.title||H.quotationNo,code:H.quotationNo,meta:[H.customerOrgName].filter(Boolean),statusDict:"quotationStatus",status:H.status}))}},async project(B){const V=await Fu({keyword:B,current:1,size:dt});return{total:V.total??0,items:(V.records??[]).map(H=>({type:"project",id:H.id,title:H.name||H.projectCode,code:H.projectCode,meta:[H.customerName].filter(Boolean),statusDict:"projectStatus",status:H.status}))}},async contract(B){const V=await ju({keyword:B,current:1,size:dt});return{total:V.total??0,items:(V.records??[]).map(H=>({type:"contract",id:H.id,title:H.contractNo,code:null,meta:[H.customerOrgName,H.status==="DRAFT"||H.status==="PENDING_CUSTOMER_SIGNATURE"?null:a(H)].filter(Boolean),statusDict:"contractStatus",status:H.status}))}},async instance(B){const V=await Wu({keyword:B,current:1,size:dt});return{total:V.total??0,items:(V.records??[]).map(H=>({type:"instance",id:H.id,title:H.entitlementNo,code:null,meta:[H.customerName,H.productName].filter(Boolean),statusDict:"entitlementStatus",status:H.status}))}},async claim(B){const V=await zu({keyword:B,current:1,size:dt});return{total:V.total??0,items:(V.records??[]).map(H=>({type:"claim",id:H.id,title:H.claimNo,code:null,meta:[H.milestoneName,H.billingOrgName].filter(Boolean),statusDict:"claimStatus",status:H.status}))}}},O=z(()=>[...N.value.map(B=>({kind:"nav",path:B.path})),...(A.value?u.flatMap(B=>B.items):d.value).map(B=>({kind:"obj",type:B.type,id:B.id}))]),w=z(()=>u.reduce((B,V)=>B+V.items.length,0)),W=z(()=>u.filter(B=>B.error).length);function U(B){return O.value.findIndex(V=>V.kind==="obj"&&V.type===B.type&&V.id===B.id)}let G=0,se;async function te(B){const V=++G;f.value=!1,u.splice(0,u.length,...S.value.map(H=>({type:H,items:[],total:0,loading:!0,error:!1}))),await Promise.all(u.map(async H=>{try{const ke=await k[H.type](B);if(V!==G)return;H.items=ke.items,H.total=ke.total}catch{if(V!==G)return;H.error=!0}finally{V===G&&(H.loading=!1)}})),V===G&&(f.value=!0,m.value=0)}je(A,B=>{if(clearTimeout(se),m.value=0,!B){G++,u.splice(0,u.length);return}se=setTimeout(()=>te(B),300)});function be(){ge(),d.value=r().filter(B=>v(B.type)),l.value=!0}function Ge(B,V){He(fr[B](V))}function He(B){l.value=!1,o.push(B)}function Le(B){if(!(B instanceof KeyboardEvent)||B.isComposing)return;const V=O.value.length;if(B.key==="ArrowDown"&&V)B.preventDefault(),m.value=(m.value+1)%V;else if(B.key==="ArrowUp"&&V)B.preventDefault(),m.value=(m.value-1+V)%V;else if(B.key==="Enter"&&V){B.preventDefault();const H=O.value[m.value];(H==null?void 0:H.kind)==="nav"?He(H.path):H&&Ge(H.type,H.id)}}function ge(){clearTimeout(se),G++,s.value="",u.splice(0,u.length),m.value=0}function tt(){ge()}function qe(B){(B.metaKey||B.ctrlKey)&&!B.altKey&&!B.shiftKey&&B.key.toLowerCase()==="k"&&(B.preventDefault(),l.value||be())}return ca(()=>window.addEventListener("keydown",qe)),da(()=>window.removeEventListener("keydown",qe)),(B,V)=>{const H=le("el-icon"),ke=le("el-input"),Pe=le("el-scrollbar"),wt=le("el-dialog");return _(),M(we,null,[I("button",{type:"button",class:"trigger","aria-label":C(n)("globalSearch.shortcutHint",{key:C(g)}),onClick:be},[Q(H,{class:"trigger-icon"},{default:Y(()=>[Q(C(uo))]),_:1}),I("span",dp,j(C(n)("globalSearch.trigger")),1),I("kbd",null,j(C(g)),1)],8,cp),Q(wt,{modelValue:l.value,"onUpdate:modelValue":V[1]||(V[1]=X=>l.value=X),"show-close":!1,width:"600px",top:"96px","append-to-body":"",class:"global-search",onOpened:V[2]||(V[2]=X=>{var T;return(T=c.value)==null?void 0:T.focus()}),onClosed:tt},{default:Y(()=>[I("div",up,[Q(H,{class:"search-icon"},{default:Y(()=>[Q(C(uo))]),_:1}),Q(ke,{ref_key:"inputRef",ref:c,modelValue:s.value,"onUpdate:modelValue":V[0]||(V[0]=X=>s.value=X),clearable:"",class:"search-input",placeholder:C(n)("globalSearch.placeholder"),onKeydown:Le},null,8,["modelValue","placeholder"]),V[3]||(V[3]=I("kbd",null,"ESC",-1))]),Q(Pe,{"max-height":"420px"},{default:Y(()=>[I("div",pp,[N.value.length?(_(),M(we,{key:0},[I("div",mp,j(C(n)("globalSearch.jumpTo")),1),(_(!0),M(we,null,it(N.value,(X,T)=>(_(),M("div",{key:X.path,class:Lt(["jump",{active:T===m.value}]),onClick:L=>He(X.path),onMouseenter:L=>m.value=T},[I("span",fp,[Q(H,null,{default:Y(()=>[(_(),Ie(zo(X.icon)))]),_:2},1024)]),I("span",null,j(C(n)(X.title)),1)],42,hp))),128))],64)):he("",!0),A.value?(_(),M(we,{key:2},[S.value.length?he("",!0):(_(),M("div",Ep,j(C(n)("globalSearch.noSearchable")),1)),(_(!0),M(we,null,it(u,X=>(_(),M(we,{key:X.type},[X.loading||X.error||X.items.length?(_(),M("div",wp,[I("div",Cp,[fe(j(C(n)(`globalSearch.type.${X.type}`))+" ",1),X.total>X.items.length?(_(),M("span",Ap,j(C(n)("globalSearch.showingTop",{n:X.items.length,total:X.total})),1)):he("",!0)]),X.error?(_(),M("div",Rp,j(C(n)("globalSearch.groupFailed")),1)):X.loading&&!X.items.length?(_(),M("div",Np,j(C(n)("globalSearch.searching")),1)):he("",!0),(_(!0),M(we,null,it(X.items,T=>(_(),M("div",{key:T.id,class:Lt(["item",{active:U(T)===m.value}]),onClick:L=>Ge(T.type,T.id),onMouseenter:L=>m.value=U(T)},[I("span",Pp,j(T.title),1),T.code?(_(),M("span",Dp,j(T.code),1)):he("",!0),(_(!0),M(we,null,it(T.meta,(L,q)=>(_(),M("span",{key:q,class:"meta"},j(L),1))),128)),Q(Iu,{class:"status",dict:T.statusDict,value:T.status},null,8,["dict","value"])],42,kp))),128))])):he("",!0)],64))),128)),S.value.length&&f.value&&!w.value&&!W.value&&!N.value.length?(_(),M("div",_p,j(C(n)("globalSearch.noResult")),1)):he("",!0)],64)):(_(),M(we,{key:1},[I("div",vp,j(C(n)("globalSearch.recent")),1),d.value.length?he("",!0):(_(),M("div",gp,j(C(n)("globalSearch.recentEmpty")),1)),(_(!0),M(we,null,it(d.value,(X,T)=>(_(),M("div",{key:X.type+X.id,class:Lt(["item",{active:N.value.length+T===m.value}]),onClick:L=>Ge(X.type,X.id),onMouseenter:L=>m.value=N.value.length+T},[I("span",Sp,j(C(n)(`globalSearch.type.${X.type}`)),1),I("span",Tp,j(X.title),1),X.subtitle?(_(),M("span",bp,j(X.subtitle),1)):he("",!0)],42,yp))),128))],64))])]),_:1}),I("div",Ip,[I("span",null,[V[4]||(V[4]=I("kbd",null,"↑↓",-1)),fe(" "+j(C(n)("globalSearch.keyMove")),1)]),I("span",null,[V[5]||(V[5]=I("kbd",null,"enter",-1)),fe(" "+j(C(n)("globalSearch.keyOpen")),1)]),I("span",null,[V[6]||(V[6]=I("kbd",null,"esc",-1)),fe(" "+j(C(n)("globalSearch.keyClose")),1)])])]),_:1},8,["modelValue"])],64)}}}),Lp=kt(Op,[["__scopeId","data-v-c46b6aef"]]);let yn=!1,ra=!1;const Cr="boss-web:scroll:";window.addEventListener("popstate",()=>{yn=!0},{capture:!0});function Ar(){return document.querySelector(".main-scroll > .el-scrollbar__wrap")}function qp(e){e.beforeEach((t,n)=>{var a;if(n===ot){const o=(a=performance.getEntriesByType)==null?void 0:a.call(performance,"navigation")[0];ra=(o==null?void 0:o.type)==="reload"||(o==null?void 0:o.type)==="back_forward"}else{ra=yn;const o=Ar();if(o)try{sessionStorage.setItem(Cr+n.fullPath,String(o.scrollTop))}catch{}}}),e.afterEach(()=>{yn=!1})}function Bo(){yn=!0}function Nv(){return ra}function kv(e){let t=0;try{t=Number(sessionStorage.getItem(Cr+e)??0)}catch{return}if(!t)return;const n=performance.now()+2e3,a=()=>{const o=Ar();if(o){if(o.scrollHeight-o.clientHeight>=t||performance.now()>n){o.scrollTop=t;return}requestAnimationFrame(a)}};requestAnimationFrame(a)}const Ot=Re(!1);function xo(){Ot.value=!Ot.value}const $e=ct({path:"",name:null,trail:[]});function Pv(e,t){const a=An().fullPath;Zo(()=>{$e.path=a,$e.name=e()||null,$e.trail=(t==null?void 0:t())??[]}),da(()=>{$e.path===a&&($e.path="",$e.name=null,$e.trail=[])})}const ht=ct({path:"",text:null});function Dv(e){const n=An().fullPath;Zo(()=>{ht.path=n,ht.text=e()||null}),da(()=>{ht.path===n&&(ht.path="",ht.text=null)})}const Fo="BES BOSS";function Rr(e){document.title=e?`${e} — ${Fo}`:Fo}const Mp={key:0,class:"page-head"},Hp=["aria-label"],Up=["aria-label"],Bp={class:"crumb-current"},xp=["aria-label"],Fp={class:"crumb-current"},Vp={class:"title-row"},jp={class:"title-block"},Gp={class:"title"},Wp={key:0,class:"head-badge"},$p={key:0,class:"subtitle"},Yp={key:0,class:"subtitle-muted"},Qp={key:0,class:"tab-badge"},Kp=Ue({__name:"PageHead",setup(e){const{t}=et(),n=An(),a=Aa(),{visible:o,accessible:i}=Nn(),r=b=>b?t(b):"",l=z(()=>typeof n.name=="string"?n.name:""),s=z(()=>!!n.meta.parent),c=z(()=>{const b=wr(n.meta.parent??l.value);return b?o(b):null}),m=z(()=>$e.path===n.fullPath?$e.name:null),d=z(()=>$e.path===n.fullPath?$e.trail:[]),u=z(()=>s.value?m.value||r(n.meta.title):n.meta.heading?r(n.meta.heading):c.value?r(c.value.title):r(n.meta.title)),f=z(()=>ht.path===n.fullPath&&ht.text?ht.text:r(n.meta.subtitle)),A=z(()=>!!l.value&&!!u.value),P=z(()=>{const b=n.meta.parent??"";if(c.value)return r(c.value.title);const g=a.hasRoute(b)?a.resolve({name:b}):null;return r(g==null?void 0:g.meta.title)}),N=z(()=>{const b=n.meta.parent??"";return i.value.get(b)??{name:b}}),v=ct({});je(()=>{var b;return(b=c.value)==null?void 0:b.title},()=>{const b=c.value;if(b!=null&&b.tabBadges)for(const g of b.visibleTabs){const k=b.tabBadges[g.name];k&&k().then(O=>v[g.name]=O).catch(()=>delete v[g.name])}},{immediate:!0});function S(b){var k;const g=(k=c.value)==null?void 0:k.visibleTabs.find(O=>O.name===b);g&&g.name!==l.value&&a.push(g.path)}return je([u,()=>n.fullPath],([b])=>Rr(b),{immediate:!0}),(b,g)=>{var U;const k=le("router-link"),O=le("el-icon"),w=le("el-tab-pane"),W=le("el-tabs");return A.value?(_(),M("div",Mp,[I("button",{type:"button",class:"menu-toggle","aria-label":C(t)("shell.openNav"),onClick:g[0]||(g[0]=(...G)=>C(xo)&&C(xo)(...G))},[Q(C(Bi))],8,Hp),s.value?(_(),M("nav",{key:0,class:"crumbs","aria-label":C(t)("shell.breadcrumb")},[C(n).meta.crumbGroup?(_(),M(we,{key:0},[Q(k,{class:"crumb-link",to:{name:"Dashboard"}},{default:Y(()=>[fe(j(r(C(n).meta.crumbGroup)),1)]),_:1}),Q(O,{class:"sep"},{default:Y(()=>[Q(C(Pn))]),_:1})],64)):he("",!0),Q(k,{class:"crumb-link",to:N.value,onClick:C(Bo)},{default:Y(()=>[fe(j(P.value),1)]),_:1},8,["to","onClick"]),(_(!0),M(we,null,it(d.value,G=>(_(),M(we,{key:G.label},[Q(O,{class:"sep"},{default:Y(()=>[Q(C(Pn))]),_:1}),Q(k,{class:"crumb-link",to:G.to,onClick:C(Bo)},{default:Y(()=>[fe(j(G.label),1)]),_:2},1032,["to","onClick"])],64))),128)),Q(O,{class:"sep"},{default:Y(()=>[Q(C(Pn))]),_:1}),I("span",Bp,j(u.value),1)],8,Up)):(_(),M(we,{key:1},[C(n).meta.listCrumb?(_(),M("nav",{key:0,class:"list-crumbs","aria-label":C(t)("shell.breadcrumb")},[I("span",null,j(r(C(n).meta.listCrumb)),1),g[1]||(g[1]=I("span",null,"/",-1)),I("span",Fp,j(u.value),1)],8,xp)):he("",!0),I("div",Vp,[I("div",jp,[I("h1",Gp,[fe(j(u.value)+" ",1),C(n).meta.headBadge?(_(),M("span",Wp,[Q(C(Fi),{class:"lock"}),fe(j(r(C(n).meta.headBadge)),1)])):he("",!0),g[2]||(g[2]=I("span",{id:"page-head-title-extra",class:"title-extra"},null,-1))]),f.value?(_(),M("p",$p,[fe(j(f.value)+" ",1),C(n).meta.subtitleMuted?(_(),M("span",Yp,j(r(C(n).meta.subtitleMuted)),1)):he("",!0),C(n).meta.subtitleLink?(_(),Ie(k,{key:1,class:"subtitle-link",to:{name:C(n).meta.subtitleLink.to}},{default:Y(()=>[fe(j(r(C(n).meta.subtitleLink.text)),1)]),_:1},8,["to"])):he("",!0)])):he("",!0)]),g[3]||(g[3]=I("div",{id:"page-head-actions",class:"actions"},null,-1))]),g[4]||(g[4]=I("div",{id:"page-head-before-tabs"},null,-1)),(U=c.value)!=null&&U.tabs&&!c.value.sideTabIcons?(_(),Ie(W,{key:1,"model-value":l.value,class:"tabs",onTabChange:S},{default:Y(()=>[(_(!0),M(we,null,it(c.value.visibleTabs,G=>(_(),Ie(w,{key:G.name,name:G.name},{label:Y(()=>[fe(j(C(t)(G.title)),1),v[G.name]?(_(),M("span",Qp,j(v[G.name]),1)):he("",!0)]),_:2},1032,["name"]))),128))]),_:1},8,["model-value"])):he("",!0)],64))])):he("",!0)}}}),zp=kt(Kp,[["__scopeId","data-v-ea4d4adb"]]);function _v(e){return y.get("/users",{params:{keyword:e}})}function Iv(e){return y.get("/users/page",{params:e})}function Ov(e){return y.get(`/users/${e}`)}function Lv(e){return y.get(`/users/${e}/stats`)}function qv(e){return y.post("/users",e)}function Mv(e,t){return y.put(`/users/${e}`,t)}function Hv(e){return y.post(`/users/${e}/suspend`)}function Uv(e){return y.post(`/users/${e}/activate`)}function Bv(e,t){return y.post(`/users/${e}/reset-password`,{newPassword:t})}function xv(e){return y.post("/users/me/password",e)}function Fv(e){return y.post(`/users/${e}/mfa/reset`)}function Vv(e){return y.post(`/users/${e}/resend-invite`)}function jv(e){return y.post(`/users/${e}/send-password-reset`)}function Gv(e){return y.get(`/users/${e}/removal-check`)}function Wv(e){return y.post(`/users/${e}/remove`)}function $v(){return y.get("/users/me")}const Yv=["fullName","jobTitle"];function Qv(e){return y.put("/users/me",e)}function Kv(e){return Rn("/users/me/avatar",e)}function zv(){return y.delete("/users/me/avatar")}function Zp(e){return`/users/${e}/avatar/content`}const Zv=["email","department","seniority","reportsToId","firstName","lastName","fullName","jobTitle","employeeType","joinedOn"],Bn=new Map;function Xp(e,t){const n=`${e}#${t}`;let a=Bn.get(n);return a||(a=$u(`${e}?v=${encodeURIComponent(t)}`,{silentError:!0}).then(o=>URL.createObjectURL(o)).catch(()=>(Bn.delete(n),null)),Bn.set(n,a)),a}const Jp=["src","alt"],em=Ue({__name:"FileImage",props:{path:{},fileId:{},alt:{}},setup(e){const t=e,n=Re(null),a=Re(!1);return je(()=>[t.path,t.fileId],async([o,i])=>{if(a.value=!1,n.value=null,!i)return;if(Nt()){n.value=`/api/v1${o}?v=${encodeURIComponent(i)}`;return}const r=await Xp(o,i);t.fileId===i&&(r?n.value=r:a.value=!0)},{immediate:!0}),(o,i)=>n.value&&!a.value?(_(),M("img",{key:0,src:n.value,alt:e.alt,class:"file-image",onError:i[0]||(i[0]=r=>a.value=!0)},null,40,Jp)):Ko(o.$slots,"default",{},void 0,!0,1)}}),tm=kt(em,[["__scopeId","data-v-8cb83f7e"]]),nm={type:"button",class:"user-card"},am={class:"avatar"},om={class:"who"},im={class:"name"},rm={key:0,class:"sub"},sm=Ue({__name:"UserCard",setup(e){const{t}=et(),n=Aa(),a=Ft(),{orgSettings:o}=Nn(),i=z(()=>{var d;return!!((d=vt.value)!=null&&d.accountSettingsUrl)}),r=z(()=>{var d;return((d=a.userInfo)==null?void 0:d.displayName)||t("user.fallbackName")}),l=z(()=>{var d;return Zp(((d=a.userInfo)==null?void 0:d.id)??"")}),s=z(()=>{const d=r.value.trim().split(/\s+/).filter(Boolean);return d.length?/^[一-鿿]/.test(d[0])?d[0].charAt(0):d.slice(0,2).map(u=>u.charAt(0)).join("").toUpperCase():"?"}),c=z(()=>{var u;const d=a.userInfo;return[(u=d==null?void 0:d.roles)==null?void 0:u.join(", "),d==null?void 0:d.department].filter(Boolean).join(" · ")});async function m(d){if(d==="profile"){n.push("/profile");return}if(d==="guide"){n.push({name:"SystemGuide"});return}if(d==="org"){o.value&&n.push(o.value.path);return}if(d==="account"){$i();return}if(d==="logout"){if(await a.logout(),Nt())return;Tm(),n.push("/login")}}return(d,u)=>{const f=le("el-icon"),A=le("el-dropdown-item"),P=le("el-dropdown-menu"),N=le("el-dropdown");return _(),Ie(N,{class:"user-card-wrap",trigger:"click",placement:"top-start","show-arrow":!1,offset:4,"popper-class":"user-card-menu",onCommand:m},{dropdown:Y(()=>[Q(P,null,{default:Y(()=>[Q(A,{command:"profile",icon:C(Hc)},{default:Y(()=>[fe(j(C(t)("menu.profile")),1)]),_:1},8,["icon"]),i.value?(_(),Ie(A,{key:0,command:"account",icon:C(Ta)},{default:Y(()=>[fe(j(C(t)("shell.accountSettings")),1)]),_:1},8,["icon"])):he("",!0),C(o)?(_(),Ie(A,{key:1,command:"org",icon:C(xi)},{default:Y(()=>[fe(j(C(t)("shell.orgSettings")),1)]),_:1},8,["icon"])):he("",!0),Q(A,{command:"guide",divided:"",icon:C(Ec)},{default:Y(()=>[fe(j(C(t)("menu.systemGuide")),1)]),_:1},8,["icon"]),Q(A,{command:"logout",divided:"",icon:C(Ui),class:"logout"},{default:Y(()=>[fe(j(C(t)("user.logout")),1)]),_:1},8,["icon"])]),_:1})]),default:Y(()=>{var v;return[I("button",nm,[I("span",am,[Q(tm,{path:l.value,"file-id":(v=C(a).userInfo)==null?void 0:v.avatarFileId,alt:r.value},{default:Y(()=>[fe(j(s.value),1)]),_:1},8,["path","file-id","alt"])]),I("span",om,[I("span",im,j(r.value),1),c.value?(_(),M("span",rm,j(c.value),1)):he("",!0)]),Q(f,{class:"chevron"},{default:Y(()=>[Q(C(Rc))]),_:1})])]}),_:1})}}}),lm=kt(sm,[["__scopeId","data-v-b9e06373"]]),cm={class:"brand-text"},dm={class:"brand-name"},um={class:"brand-sub"},pm={class:"search"},mm={key:0,class:"nav-badge"},hm=["aria-label"],fm={class:"account"},vm=Ue({__name:"index",setup(e){const t=An(),{t:n}=et(),{groups:a,visible:o}=Nn();je(()=>t.fullPath,()=>{Ot.value=!1,Uo()}),ca(()=>Uo(!0));const i=z(()=>{var s;const r=t.meta.parent??(typeof t.name=="string"?t.name:""),l=wr(r);return l&&((s=o(l))==null?void 0:s.path)||t.path});return(r,l)=>{const s=le("router-link"),c=le("el-icon"),m=le("el-menu-item"),d=le("el-menu-item-group"),u=le("el-menu"),f=le("el-scrollbar"),A=le("el-aside"),P=le("router-view"),N=le("el-main"),v=le("el-container");return _(),Ie(v,{class:"app-wrapper"},{default:Y(()=>[C(Ot)?(_(),M("div",{key:0,class:"sidebar-mask",onClick:l[0]||(l[0]=S=>Ot.value=!1)})):he("",!0),Q(A,{width:"248px",class:Lt(["sidebar",[`density-${C(yt).sidebarDensity}`,{open:C(Ot)}]])},{default:Y(()=>[Q(s,{to:"/dashboard",class:"brand"},{default:Y(()=>[l[1]||(l[1]=I("span",{class:"brand-icon"},[I("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2.5","aria-hidden":"true"},[I("path",{d:"M4 4H20V20H4z M4 12H20 M12 4V20"})])],-1)),I("span",cm,[I("span",dm,j(C(n)("shell.brand")),1),I("span",um,j(C(n)("shell.brandSub")),1)])]),_:1}),I("div",pm,[Q(Lp)]),Q(f,{class:"nav"},{default:Y(()=>[Q(u,{"default-active":i.value,router:"",class:"menu"},{default:Y(()=>[(_(!0),M(we,null,it(C(a),S=>(_(),Ie(d,{key:S.title,title:C(n)(S.title)},{default:Y(()=>[(_(!0),M(we,null,it(S.items,b=>(_(),Ie(m,{key:b.title,index:b.path},{default:Y(()=>{var g,k;return[Q(c,null,{default:Y(()=>[(_(),Ie(zo(b.icon)))]),_:2},1024),I("span",null,j(C(n)(b.title)),1),(g=b.badge)!=null&&g.value?(_(),M("span",mm,j(b.badge.value),1)):(k=b.dot)!=null&&k.value?(_(),M("span",{key:1,class:"nav-dot","aria-label":C(n)("shell.unread")},null,8,hm)):he("",!0)]}),_:2},1032,["index"]))),128))]),_:2},1032,["title"]))),128))]),_:1},8,["default-active"])]),_:1}),I("div",fm,[Q(lm)])]),_:1},8,["class"]),Q(N,{class:"main"},{default:Y(()=>[Q(f,{class:"main-scroll","view-class":"main-view"},{default:Y(()=>[Q(zp),(_(),Ie(P,{key:`${C(t).fullPath}|${C(xt)}`}))]),_:1})]),_:1})]),_:1})}}}),De=kt(vm,[["__scopeId","data-v-a9366c94"]]),gm=[{path:"/login",name:"Login",component:()=>K(()=>import("./index-DXQKqyV-.js"),__vite__mapDeps([0,1,2,3])),meta:{title:"menu.login",hidden:!0}},{path:"/:pathMatch(.*)*",name:"NotFound",component:De,meta:{hidden:!0},children:[{path:"",component:()=>K(()=>import("./404-b8XRalOG.js"),__vite__mapDeps([4,1,2])),meta:{title:"error.notFound",hidden:!0}}]}],ym=[{path:"/",component:De,redirect:"/dashboard",children:[{path:"dashboard",name:"Dashboard",component:()=>K(()=>import("./index-D-kw78Ie.js"),__vite__mapDeps([5,1,2,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29])),meta:{title:"menu.dashboard",heading:"dashboard.pageTitle",subtitle:"dashboard.pageSubtitle",icon:"HomeFilled"}},{path:"my-tasks",name:"MyTasks",component:()=>K(()=>import("./index-DDIreSTD.js"),__vite__mapDeps([30,1,2,21,31,32,17,18,33,15,23,24,22,34,8,35,36,12,16,37,38])),meta:{title:"menu.myTasks",subtitle:"task.pageSubtitle"}},{path:"inbox",name:"Inbox",component:()=>K(()=>import("./index-C3GCEMRK.js"),__vite__mapDeps([39,1,2,21,31,32,23,24,40,41,22,42,8,35,16,12,15,43,44,25,45])),meta:{title:"menu.inbox",subtitle:"inbox.pageSubtitle",subtitleLink:{text:"menu.myTasks",to:"MyTasks"}}}]},{path:"/overview",component:De,meta:{title:"menu.analytics"},children:[{path:"",name:"Overview",component:()=>K(()=>import("./index-SWfQHGjZ.js"),__vite__mapDeps([46,10,11,1,2,12,13,14,15,16,17,18,19,22,20,21,23,24,47,48])),meta:{title:"menu.analytics",heading:"analytics.pageTitle",subtitle:"analytics.desc.sales",perms:["boss.quotations.view","boss.onboarding.view","boss.invoices.view","boss.entitlements.view","boss.access_grants.view"]}}]},{path:"/crm",component:De,redirect:"/crm/companies",meta:{title:"menu.crm",icon:"OfficeBuilding"},children:[{path:"companies",name:"Companies",component:()=>K(()=>import("./index-BmWqmj3Y.js"),__vite__mapDeps([49,1,2,50,20,40,41,51,52,11,47,12,53,54,35,8,55,56,23,24,21,57,58,59,60,61,62,18,63,64,65,66,67,68,17,69,70,71,72,31,32,22,73,7,74,75,36,76,77])),meta:{title:"menu.companies",subtitle:"company.pageSubtitle",perms:["boss.companies.view"]}},{path:"companies/:id",name:"CompanyDetail",component:()=>K(()=>import("./detail-CJLCvgV6.js"),__vite__mapDeps([78,1,2,31,32,35,8,22,56,23,24,79,80,81,82,7,83,84,57,58,59,60,61,62,18,63,64,65,66,67,68,17,69,70,52,11,71,72,36,85,74,86,87,16,88,33,89,90,43,47,91])),meta:{title:"menu.companyDetail",hidden:!0,parent:"Companies",perms:["boss.companies.view"]}},{path:"quotations",name:"Quotations",component:()=>K(()=>import("./index-3SIznyo9.js"),__vite__mapDeps([92,1,2,31,32,35,8,50,20,40,41,51,52,11,47,12,53,54,60,55,56,23,24,21,61,64,65,66,59,62,67,68,58,18,17,69,70,22,73,71,72,93,94,95,74,75,96,85,97])),meta:{title:"menu.quotations",subtitle:"quotation.pageSubtitle",perms:["boss.quotations.view"]}},{path:"quotations/:id",name:"QuotationDetail",component:()=>K(()=>import("./detail-C5tkQz5D.js"),__vite__mapDeps([98,8,35,60,1,2,22,56,23,24,79,80,81,82,7,83,84,99,40,41,100,37,101,64,61,65,66,59,62,67,68,58,18,17,69,70,102,93,94,11,95,103,104,53,105,106,107,86,108,89,16,43,109,28,96,47,90,110])),meta:{title:"menu.quotationDetail",hidden:!0,parent:"Quotations",perms:["boss.quotations.view"]}},{path:"contracts",name:"Contracts",component:()=>K(()=>import("./index-C9sa7cy7.js"),__vite__mapDeps([111,1,2,50,20,40,41,21,51,52,11,47,12,53,54,60,23,24,61,22,73,71,72,31,32,112,67,68,58,18,113,114,115,35,8,94,17,55,116,76,28,117,118])),meta:{title:"menu.contracts",subtitle:"contract.pageSubtitle",perms:["boss.contracts.view"]}},{path:"contracts/:id",name:"ContractDetail",component:()=>K(()=>import("./detail-Ce_wiY24.js"),__vite__mapDeps([119,8,112,1,2,67,68,58,18,113,23,24,120,121,99,56,22,40,41,100,37,101,17,122,60,73,79,80,81,82,7,83,84,62,123,94,11,59,65,66,35,6,28,16,43,26,116,76,124])),meta:{title:"menu.contractDetail",hidden:!0,parent:"Contracts",perms:["boss.contracts.view"]}}]},{path:"/products",component:De,redirect:"/products/catalog",meta:{title:"menu.products",icon:"Goods"},children:[{path:"catalog",name:"Products",component:()=>K(()=>import("./index-BdXJriId.js"),__vite__mapDeps([125,1,2,40,41,8,35,23,24,21,31,32,126,62,67,68,103,104,53,105,22,58,69,127,17,18,20,74,128])),meta:{title:"menu.products",subtitle:"product.pageSubtitle",perms:["boss.products.view"]}},{path:"workflow-templates",name:"WorkflowTemplates",component:()=>K(()=>import("./index-BIonH9wD.js"),__vite__mapDeps([129,1,2,23,24,123,56,130,20,131,132,21,67,68,133,62,58,33,74,88,36,96,85,44,134])),meta:{title:"menu.workflowTemplates",subtitle:"workflow.subtitle",perms:["boss.onboarding.view"]}},{path:"notification-templates",name:"NotificationTemplates",component:()=>K(()=>import("./index--7TL5ZIF.js"),__vite__mapDeps([135,1,2,21,31,32,23,24,22,56,62,59,60,136,133,74,33,36,137])),meta:{title:"menu.notificationTemplates",subtitle:"notificationTpl.pageSubtitle",perms:["boss.notification_templates.view"]}},{path:"catalog/:id",name:"ProductDetail",component:()=>K(()=>import("./detail-0dV3CsYl.js"),__vite__mapDeps([138,1,2,22,56,81,82,7,83,23,24,84,79,80,71,72,31,32,126,62,67,68,103,104,53,105,58,69,127,139,140,36,85,8,35,28,141])),meta:{title:"menu.productDetail",hidden:!0,parent:"Products",perms:["boss.products.view"]}},{path:"hardware/:id",name:"HardwareDetail",component:()=>K(()=>import("./hardware-detail-CgazElxP.js"),__vite__mapDeps([142,35,1,2,22,56,17,18,81,82,7,83,23,24,84,71,72,79,80,40,41,126,62,67,68,103,104,53,105,58,69,127,139,140,106,11,107,122,143])),meta:{title:"menu.hardwareDetail",hidden:!0,parent:"Products",perms:["boss.products.view"]}},{path:"role-templates/:id",name:"ProductRoleTemplateDetail",component:()=>K(()=>import("./role-template-B8q9WUj5.js"),__vite__mapDeps([144,22,1,2,56,23,24,81,82,7,83,84,62,69,145])),meta:{title:"menu.roleTemplateDetail",hidden:!0,parent:"Products",perms:["boss.products.view"]}}]},{path:"/terms",component:De,redirect:"/terms/list",meta:{title:"menu.terms",icon:"Tickets"},children:[{path:"list",name:"CommercialTerms",component:()=>K(()=>import("./index-DMseGPDc.js"),__vite__mapDeps([146,1,2,8,50,20,40,41,51,52,11,47,12,53,54,73,23,24,21,147,62,67,68,58,100,18,56,148,71,72,31,32,22,74,75,36,96,85,43,13,149])),meta:{title:"menu.terms",subtitle:"term.pageSubtitle",perms:["boss.terms.view"]}},{path:"list/:id",name:"CommercialTermDetail",component:()=>K(()=>import("./detail-Db_z_nzQ.js"),__vite__mapDeps([150,1,2,8,35,60,23,24,81,82,7,83,22,84,31,32,71,72,147,62,67,68,58,100,18,56,148,94,11,55,16,116,85,151])),meta:{title:"menu.termDetail",hidden:!0,parent:"CommercialTerms",perms:["boss.terms.view"]}}]},{path:"/system",component:De,redirect:"/system/users",meta:{title:"menu.system",icon:"Setting"},children:[{path:"users",name:"Users",component:()=>K(()=>import("./index-O3g_z3yr.js"),__vite__mapDeps([152,1,2,50,20,40,41,51,52,11,47,12,53,54,23,24,21,71,72,73,35,8,153,62,58,136,22,44,56,154,74,36,89,25,85,155])),meta:{title:"menu.users",subtitle:"user.pageSubtitle",perms:["boss.users.manage"]}},{path:"users/:id",name:"UserDetail",component:()=>K(()=>import("./detail-CWhVyn3c.js"),__vite__mapDeps([156,1,2,23,24,71,72,40,41,153,62,58,136,22,44,56,154,59,60,61,73,7,35,8,36,89,25,85,157])),meta:{title:"menu.userDetail",hidden:!0,parent:"Users",perms:["boss.users.manage"]}},{path:"roles",name:"Roles",component:()=>K(()=>import("./index-C6XsvfXj.js"),__vite__mapDeps([158,1,2,56,21,51,52,11,47,12,53,54,23,24,22,62,136,159,160,161])),meta:{title:"menu.roles",subtitle:"accessPlanes.pageSubtitle",perms:["boss.roles.view"]}},{path:"access-grants",name:"AccessGrants",component:()=>K(()=>import("./index-DJnY4xgr.js"),__vite__mapDeps([162,50,20,1,2,40,41,21,51,52,11,47,12,53,54,23,24,79,80,159,160,22,87,56,163])),meta:{title:"menu.accessGrants",subtitle:"accessPlanes.pageSubtitle",perms:["boss.access_grants.view"]}},{path:"access-grants/:id",name:"AccessGrantDetail",component:()=>K(()=>import("./detail-DbhrQTHW.js"),__vite__mapDeps([164,1,2,23,24,79,80,81,82,7,83,22,84,56,87,165])),meta:{title:"menu.accessGrantDetail",hidden:!0,parent:"AccessGrants",perms:["boss.access_grants.view"]}},{path:"organization",name:"OrgGeneral",component:()=>K(()=>import("./org-general-D_IR0U81.js"),__vite__mapDeps([166,1,2,23,24,62,56,22,18,167,168,58,169])),meta:{title:"menu.orgGeneral",subtitle:"orgSettings.subtitle",subtitleLink:{text:"orgSettings.personalSettings",to:"Profile"},headBadge:"orgSettings.adminOnly",perms:["boss.settings.view"]}},{path:"auth",name:"AuthPolicy",component:()=>K(()=>import("./auth-policy-Cyygvchr.js"),__vite__mapDeps([170,167,1,2,168,171])),meta:{title:"menu.authPolicy",subtitle:"orgSettings.subtitle",subtitleLink:{text:"orgSettings.personalSettings",to:"Profile"},headBadge:"orgSettings.adminOnly",perms:["boss.settings.view"]}},{path:"compliance",name:"Compliance",component:()=>K(()=>import("./compliance-DH4XosMl.js"),__vite__mapDeps([172,22,1,2,23,24,167,168,7,173])),meta:{title:"menu.compliance",subtitle:"orgSettings.subtitle",subtitleLink:{text:"orgSettings.personalSettings",to:"Profile"},headBadge:"orgSettings.adminOnly",perms:["boss.audit.view"]}}]},{path:"/audit",component:De,redirect:"/audit/events",meta:{title:"menu.audit",icon:"Document"},children:[{path:"events",name:"AuditEvents",component:()=>K(()=>import("./events-CC-xH08S.js"),__vite__mapDeps([174,1,2,50,20,40,41,21,8,35,9,55,60,23,24,61,59,175,69,82,7,83,22,51,52,11,47,12,53,54,176,177,130,178])),meta:{title:"menu.auditEvents",subtitle:"audit.pageSubtitle",perms:["boss.audit.view"]}},{path:"access-logs",name:"AccessLogs",component:()=>K(()=>import("./access-logs-cbfhFl4M.js"),__vite__mapDeps([179,1,2,50,20,40,41,23,24,82,7,83,67,68,176,177,22,130,180])),meta:{title:"menu.accessLogs",perms:["boss.audit.view"]}}]},{path:"/guide",name:"SystemGuide",component:()=>K(()=>import("./index-BzPM8_d-.js"),__vite__mapDeps([181,1,2,182])),meta:{title:"menu.systemGuide",hidden:!0}},{path:"/profile",component:De,meta:{hidden:!0},children:[{path:"",name:"Profile",component:()=>K(()=>import("./index-BOsSPP6V.js"),__vite__mapDeps([183,1,2,56,22,58,35,23,24,33,42,184])),meta:{title:"menu.profile",subtitle:"profile.pageSubtitle",hidden:!0}}]},{path:"/projects",component:De,redirect:"/projects/list",meta:{title:"menu.projects",icon:"Coordinate"},children:[{path:"list",name:"Projects",component:()=>K(()=>import("./index-BW6RWg8i.js"),__vite__mapDeps([185,1,2,50,20,40,41,21,51,52,11,47,12,53,54,60,73,55,23,24,61,69,22,130,18,31,32,71,72,6,35,8,186,62,58,187,36,188])),meta:{title:"menu.projects",subtitle:"project.pageSubtitle",perms:["boss.projects.view"]}},{path:"list/:id",name:"ProjectDetail",component:()=>K(()=>import("./detail-BLoq3d1u.js"),__vite__mapDeps([189,22,1,2,23,24,81,82,7,83,84,31,32,71,72,35,8,87,56,75,27,33,186,62,58,187,60,67,68,17,18,69,74,133,190,191,6,86,16,88,43,37,102,14,28,53,26,192])),meta:{title:"menu.projectDetail",hidden:!0,parent:"Projects",perms:["boss.projects.view"]}}]},{path:"/product-instances",component:De,redirect:"/product-instances/list",meta:{title:"menu.productInstances",icon:"Monitor"},children:[{path:"list",name:"ProductInstances",component:()=>K(()=>import("./index-DnpIosmR.js"),__vite__mapDeps([193,1,2,50,20,40,41,23,24,21,194,195,35,8,73,55,22,130,26,196])),meta:{title:"menu.productInstances",subtitle:"entitlement.pageSubtitle",listCrumb:"shell.group.delivery",perms:["boss.entitlements.view"]}},{path:"list/:id",name:"ProductInstanceDetail",component:()=>K(()=>import("./detail-CkAN-bfn.js"),__vite__mapDeps([197,22,1,2,60,23,24,79,80,81,82,7,83,84,71,72,35,8,6,108,26,198])),meta:{title:"menu.productInstanceDetail",hidden:!0,parent:"ProductInstances",crumbGroup:"shell.group.delivery",perms:["boss.entitlements.view"]}}]},{path:"/provisioning",component:De,redirect:"/provisioning/runs",meta:{title:"menu.delivery",icon:"SetUp"},children:[{path:"runs",name:"ProvisioningRuns",component:()=>K(()=>import("./index-BtI9L6Ss.js"),__vite__mapDeps([199,1,2,50,20,40,41,21,51,52,11,47,12,53,54,73,60,23,24,31,32,200,194,195,22,130,201,6,56,202,55,203])),meta:{title:"menu.provisioning",heading:"provisioning.pageTitle",subtitle:"provisioning.pageSubtitle",perms:["boss.provisioning.view"]}},{path:"runs/:id",name:"ProvisioningRunDetail",component:()=>K(()=>import("./detail-D2sjd-u1.js"),__vite__mapDeps([204,22,1,2,60,23,24,31,32,79,80,81,82,7,83,84,6,201,56,202,205])),meta:{title:"menu.provisioningDetail",hidden:!0,parent:"ProvisioningRuns",perms:["boss.provisioning.view"]}}]},{path:"/onboarding",component:De,redirect:"/onboarding/runs",meta:{title:"menu.onboarding",icon:"Checked"},children:[{path:"runs",name:"Onboardings",component:()=>K(()=>import("./index-DXWJjgUc.js"),__vite__mapDeps([206,1,2,40,41,60,21,51,52,11,47,12,53,54,23,24,59,175,207,61,79,80,35,8,22,130,73,123,190,20,55,69,208])),meta:{title:"menu.onboarding",subtitle:"onboarding.pageSubtitle",perms:["boss.onboarding.view"]}},{path:"runs/:id",name:"OnboardingDetail",component:()=>K(()=>import("./detail-T5D8td-M.js"),__vite__mapDeps([209,60,1,2,22,56,23,24,79,80,81,82,7,83,84,59,106,11,107,210,211,131,132,122,212,213,214,67,68,215,216,217,207,35,8,71,72,123,190,16,43,117,102,104,109,218])),meta:{title:"menu.onboardingDetail",hidden:!0,parent:"Onboardings",perms:["boss.onboarding.view"]}}]},{path:"/billing",component:De,redirect:"/billing/claims",meta:{title:"menu.billing",icon:"Money"},children:[{path:"claims",name:"Claims",component:()=>K(()=>import("./claims-B4Qeuoln.js"),__vite__mapDeps([219,1,2,50,20,40,41,51,52,11,47,12,53,54,60,55,23,24,21,220,17,18,58,62,67,68,221,61,200,175,176,177,31,32,8,35,22,130,73,74,222])),meta:{title:"menu.claims",subtitle:"billing.claimsSubtitle",subtitleMuted:"billing.claimsSubtitleMuted",perms:["boss.claims.view"]}},{path:"claims/:id",name:"ClaimDetail",component:()=>K(()=>import("./claim-detail-kS6E_l8L.js"),__vite__mapDeps([223,22,1,2,60,56,23,24,79,80,216,217,81,82,7,83,84,71,72,220,17,18,58,62,67,68,221,103,104,53,105,106,11,107,94,44,74,47,102,224])),meta:{title:"menu.claimDetail",hidden:!0,parent:"Claims",perms:["boss.claims.view"]}},{path:"invoices",name:"Invoices",component:()=>K(()=>import("./invoices-CE0Tsp1Z.js"),__vite__mapDeps([225,1,2,50,20,40,41,51,52,11,47,12,53,54,60,23,24,61,194,195,55,31,32,22,130,17,18,73,8,35,226])),meta:{title:"menu.invoices",subtitle:"billing.invoicesSubtitle",perms:["boss.invoices.view"]}},{path:"invoices/:id",name:"InvoiceDetail",component:()=>K(()=>import("./invoice-detail-DIE8SZKx.js"),__vite__mapDeps([227,22,1,2,60,18,56,23,24,79,80,71,72,81,82,7,83,84,17,67,68,103,104,53,105,106,11,107,94,228])),meta:{title:"menu.invoiceDetail",hidden:!0,parent:"Invoices",perms:["boss.invoices.view"]}}]},{path:"/inventory",component:De,redirect:"/inventory/hardware",meta:{title:"menu.inventory",icon:"Box"},children:[{path:"hardware",name:"Inventory",component:()=>K(()=>import("./index-BMcK0B3y.js"),__vite__mapDeps([229,1,2,21,31,32,71,72,23,24,40,41,56,22,50,20,35,122,67,68,200,60,62,58,74,133,17,18,120,121,79,80,175,216,217,212,213,230,231,117,94,11,214,215,86,61,36,232])),meta:{title:"menu.inventory",subtitle:"inventory.pageSubtitle",perms:["boss.inventory.view"]}},{path:"over-installations/:id",name:"OverInstallationDetail",component:()=>K(()=>import("./over-installation-detail-CKtD2-zU.js"),__vite__mapDeps([233,23,1,2,24,79,80,60,17,18,22,122,212,213,230,231,234])),meta:{title:"menu.overInstallationDetail",hidden:!0,parent:"Inventory",perms:["boss.inventory.view"]}}]},{path:"/handover",component:De,redirect:"/handover/list",meta:{title:"menu.handover",icon:"Box"},children:[{path:"list",name:"Handovers",component:()=>K(()=>import("./index-B_IUGBfF.js"),__vite__mapDeps([235,1,2,50,20,40,41,21,51,52,11,47,12,53,54,60,55,23,24,175,59,61,69,22,130,73,71,72,31,32,8,236,237,191,75,117,238])),meta:{title:"menu.handovers",subtitle:"handover.pageSubtitle",perms:["boss.handovers.view"]}},{path:"list/:id",name:"HandoverDetail",component:()=>K(()=>import("./detail-B60UVMEg.js"),__vite__mapDeps([239,22,1,2,60,56,23,24,79,80,81,82,7,83,84,71,72,114,67,68,58,115,8,35,34,44,236,237,59,210,211,191,16,43,117,102,26,240])),meta:{title:"menu.handoverDetail",hidden:!0,parent:"Handovers",perms:["boss.handovers.view"]}}]}],Bt=Ru({history:tu(),routes:gm});qp(Bt);let an=!1;Bt.beforeEach(async e=>{let t;try{t=(await Kc()).mode}catch{return e.path==="/login"?!0:"/login"}if(t==="CONTROL")return Sm(e);if(!Vi())return e.path==="/login"?!0:"/login";if(e.path==="/login")return"/";if(!an){const a=Ft(),o=Na();try{const i=await a.fetchUserInfo();return o.generateRoutes(i.permissions).forEach(l=>Bt.addRoute(l)),an=!0,{...e,replace:!0}}catch{return a.reset(),"/login"}}return!0});async function Sm(e){if(e.path==="/login"||an)return!0;const t=Ft(),n=Na();try{const a=await t.fetchUserInfo();return n.generateRoutes(a.permissions).forEach(i=>Bt.addRoute(i)),an=!0,{...e,replace:!0}}catch(a){t.reset();const o=a instanceof Wt?a.code:null;return o===xe.UNAUTHORIZED?!1:{path:"/login",query:{error:o===xe.FORBIDDEN?"NO_ACCESS":"UNAVAILABLE"}}}}Bt.afterEach((e,t,n)=>{if(n)return;const a=e.meta.title;Rr(a?rn.global.t(a):null)});function Tm(){an=!1}const bm={mounted(e,t){var r;const n=t.value,a=Ft().permissions;(Array.isArray(n)?n:[n]).some(l=>a.includes(l))||(r=e.parentNode)==null||r.removeChild(e)}};function Em(e){e.directive("auth",bm)}const wm=160,Cm=400;let dn=null;function xn(e,t){const n=e.querySelector("input");if(!n||!n.placeholder||!e.offsetParent||(dn??(dn=document.createElement("canvas").getContext("2d")),!dn))return;const a=getComputedStyle(n);dn.font=`${a.fontStyle} ${a.fontWeight} ${a.fontSize} ${a.fontFamily}`;const o=Math.ceil(dn.measureText(n.placeholder).width),i=n.clientWidth-parseFloat(a.paddingLeft)-parseFloat(a.paddingRight),r=e.getBoundingClientRect().width-i,l=(t==null?void 0:t.min)??wm,s=(t==null?void 0:t.max)??Cm,c=Math.min(s,Math.max(l,Math.ceil(o+r+2)));e.style.setProperty("--fit-width",`${c}px`)}const Am={mounted(e,t){var n;e.classList.add("fit-placeholder"),xn(e,t.value),(n=document.fonts)==null||n.ready.then(()=>xn(e,t.value))},updated(e,t){xn(e,t.value)}};function Rm(e){e.directive("fit-placeholder",Am)}const Nr="bes-theme",Nm="#0891b2",km="light",Pm=["light","dark","auto"],kr=window.matchMedia("(prefers-color-scheme: dark)"),Pr=Re(kr.matches);kr.addEventListener("change",e=>Pr.value=e.matches);function Dm(){const e={mode:km};try{const t=JSON.parse(localStorage.getItem(Nr)||"{}");return{mode:Pm.includes(t.mode)?t.mode:e.mode}}catch{return e}}const Rt=ct(Dm()),on=z(()=>Rt.mode==="dark"||Rt.mode==="auto"&&Pr.value);function Dr(){const e=document.documentElement;e.classList.toggle("dark",on.value);const t=$r(Nm,on.value);for(const[n,a]of Object.entries(t))e.style.setProperty(n,a)}function _m(){try{localStorage.setItem(Nr,JSON.stringify(Rt))}catch{}}je(on,Dr);je(Rt,_m,{deep:!0});function Im(){Dr()}function Xv(){function e(n){Rt.mode=n}function t(){Rt.mode=on.value?"light":"dark"}return{config:Rt,isDark:on,setMode:e,toggleDark:t}}Im();vc();const Et=Yr(Cd);Et.use(Kr());Et.use(Bt);Et.use(rn);Et.use(Qr);Em(Et);Rm(Et);jc(Et);Et.mount("#app");export{Qm as $,Xh as A,Wt as B,gf as C,ud as D,nh as E,Ra as F,Cc as G,zm as H,yt as I,Je as J,bv as K,Hm as L,ep as M,qf as N,Mf as O,xe as P,jm as Q,Gm as R,Hi as S,Qi as T,wv as U,ap as V,Ev as W,Zm as X,xi as Y,Cv as Z,ed as _,dh as a,If as a$,yc as a0,Ui as a1,Ac as a2,Nc as a3,bc as a4,Av as a5,Rv as a6,op as a7,ad as a8,$m as a9,Dh as aA,Ph as aB,kh as aC,_h as aD,xu as aE,Pv as aF,Gu as aG,Hc as aH,gh as aI,Tv as aJ,hh as aK,ju as aL,Wu as aM,Zu as aN,Ku as aO,Fi as aP,sh as aQ,bh as aR,mh as aS,Bf as aT,Ff as aU,Jm as aV,Tf as aW,Nf as aX,Af as aY,Rf as aZ,_f as a_,Wm as aa,tp as ab,zi as ac,Ym as ad,y as ae,Ki as af,uo as ag,Iu as ah,Eh as ai,Vm as aj,ph as ak,fh as al,vh as am,Mo as an,Ah as ao,Mh as ap,Ch as aq,wh as ar,Nh as as,Rh as at,Fu as au,Lh as av,Hh as aw,Oh as ax,Ih as ay,qh as az,uh as b,$i as b$,jh as b0,Xm as b1,oh as b2,ih as b3,Cf as b4,Df as b5,Lf as b6,Hf as b7,Uf as b8,Of as b9,tm as bA,bf as bB,Ef as bC,_v as bD,Nt as bE,Zp as bF,Iv as bG,Mv as bH,Zv as bI,Ov as bJ,Sh as bK,Lv as bL,yh as bM,Th as bN,qv as bO,Gv as bP,Wv as bQ,jv as bR,Vv as bS,Fv as bT,Bv as bU,Uv as bV,Hv as bW,Xu as bX,gv as bY,yv as bZ,Sv as b_,Pf as ba,Vf as bb,kf as bc,Zh as bd,sf as be,Vu as bf,df as bg,pf as bh,mf as bi,hf as bj,nf as bk,Jh as bl,ef as bm,of as bn,tf as bo,zu as bp,bu as bq,cf as br,af as bs,rf as bt,uf as bu,kv as bv,ea as bw,Gc as bx,rn as by,ah as bz,Ft as c,ev as c$,co as c0,Nn as c1,Er as c2,Fm as c3,Nv as c4,ni as c5,Rn as c6,eh as c7,Qu as c8,Ec as c9,Qh as cA,qc as cB,Bh as cC,xh as cD,Fh as cE,Kh as cF,zh as cG,rv as cH,$h as cI,ff as cJ,th as cK,yf as cL,Sf as cM,vf as cN,Bi as cO,fv as cP,rh as cQ,$f as cR,jf as cS,Wf as cT,Gf as cU,Jf as cV,Zf as cW,Xf as cX,Kf as cY,zf as cZ,Yf as c_,Yu as ca,$u as cb,wf as cc,lf as cd,Km as ce,Jn as cf,sd as cg,od as ch,id as ci,Pm as cj,rd as ck,Bm as cl,xm as cm,Um as cn,td as co,$v as cp,Qv as cq,Kv as cr,zv as cs,Yv as ct,xv as cu,Gh as cv,Yh as cw,Wh as cx,Uh as cy,Vh as cz,An as d,tv as d0,nv as d1,iv as d2,Qf as d3,ov as d4,av as d5,vv as d6,pv as d7,dv as d8,sv as d9,lv as da,cv as db,mv as dc,hv as dd,uv as de,Uo as df,vt as e,Ji as f,Zc as g,Xv as h,xt as i,Aa as j,lp as k,lh as l,ch as m,kc as n,Uc as o,Ta as p,Dc as q,Tm as r,Mm as s,Lc as t,et as u,Sc as v,Ic as w,Dv as x,hr as y,xf as z};