@fleox-agent-crm/agentcrm 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +16 -16
  2. package/changelog.json +11 -0
  3. package/dist/admin/admin-files.json +7 -7
  4. package/dist/admin/assets/{chartsImpl-B45AAqnr.js → chartsImpl-qlHW3VOv.js} +1 -1
  5. package/dist/admin/assets/firebase-U38f5kc9.js +2 -0
  6. package/dist/admin/assets/{gitJson-CAUSxl8d.js → gitJson-wy2Tytfd.js} +1 -1
  7. package/dist/admin/assets/{index-ChFauO8y.js → index-BpaxrJx9.js} +5 -5
  8. package/dist/admin/assets/{lucide-react.min--rznIkmQ.js → lucide-react.min-Djrg16BH.js} +1 -1
  9. package/dist/admin/assets/{sdk-DgzLACmL.js → sdk-mu08RFtk.js} +1 -1
  10. package/dist/admin/index.html +1 -1
  11. package/dist/agent/agentcrm.mjs +70 -12
  12. package/dist/agent/chunks/api-Dwb4xz1k.mjs +27 -0
  13. package/dist/agent/chunks/{firebase-DxGVQV9E.mjs → firebase-BciZWdc6.mjs} +41 -17
  14. package/dist/agent/chunks/{hosting-Bme7LxPc.mjs → hosting-Dnn1k3cV.mjs} +1 -1
  15. package/dist/agent/chunks/{index-DUSdTBkz.mjs → index-CNXq2Yk_.mjs} +1 -24
  16. package/dist/agent/chunks/index-Dio0aBWA.mjs +6920 -0
  17. package/dist/agent/chunks/{index-CRkw3_iF.mjs → index-rut-KC39.mjs} +1 -1
  18. package/dist/agent/chunks/{install-CbpD_7gd.mjs → install-BBTA4nMm.mjs} +13 -4
  19. package/dist/agent/chunks/{sdk-whvfg786.mjs → sdk-CYgNyuoK.mjs} +132 -7005
  20. package/dist/version.json +1 -1
  21. package/package.json +1 -1
  22. package/plugin/.claude-plugin/plugin.json +1 -1
  23. package/plugin/skills/agentcrm-admin/SKILL.md +67 -67
  24. package/plugin/skills/agentcrm-admin/references/records.md +5 -5
  25. package/plugin/skills/agentcrm-admin/references/schema.md +19 -19
  26. package/plugin/skills/agentcrm-extensions/SKILL.md +8 -8
  27. package/plugin/skills/agentcrm-extensions/references/module-recipes.md +2 -2
  28. package/plugin/skills/agentcrm-extensions/references/testing.md +14 -14
  29. package/plugin/skills/agentcrm-extensions/references/theme-recipes.md +3 -3
  30. package/plugin/skills/agentcrm-install/SKILL.md +13 -13
  31. package/plugin/skills/agentcrm-install/references/firebase.md +1 -1
  32. package/plugin/skills/agentcrm-install/references/github.md +1 -1
  33. package/plugin/skills/agentcrm-install/references/mcp.md +2 -2
  34. package/plugin/skills/agentcrm-install/references/plans.md +1 -1
  35. package/plugin/skills/agentcrm-install/references/s3.md +1 -1
  36. package/plugin/skills/agentcrm-manage/SKILL.md +15 -15
  37. package/plugin/skills/agentcrm-sales/SKILL.md +18 -18
  38. package/dist/admin/assets/firebase-C1x_l9P9.js +0 -2
@@ -1127,7 +1127,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
1127
1127
  [Write the message${typeof t.purpose=="string"?` (${t.purpose})`:""} here.]
1128
1128
 
1129
1129
  Best,
1130
- ${(d==null?void 0:d.name)??""}`;return{draft:{to:s.slice(0,10),subject:p,body:m},sent:!1,note:"Draft only — nothing was sent. The user can send it from the record's Emails tab (Gmail / Outlook integration).",context:{record:{id:n.id,object:n.object,label:ct(r,n)},recentActivities:o.map(y=>({type:y.type,title:y.title,at:new Date(y.createdAt).toISOString()})),...l?{lastEmail:{title:l.title,body:(x=l.body)==null?void 0:x.slice(0,800),at:new Date(l.createdAt).toISOString()}}:{}}}}}];function lx(e){const{logo:t,favicon:n,customCss:r,...s}=e;return{...s,hasLogo:!!t,hasFavicon:!!n,customCssBytes:r?r.length:0}}const E9={accent:{type:"string",description:"Accent color, hex #rrggbb (a full 50–950 scale is generated from it)."},neutral:{type:"string",enum:F1,description:"Gray scale used for surfaces, borders and text."},radius:{type:"string",enum:z1},density:{type:"string",enum:bT,description:"compact = shorter table rows and paddings."},font:{type:"string",enum:Uc.map(e=>e.id),description:'"system" needs no network; the others load from Google Fonts.'},sidebar:{type:"string",enum:xT},defaultMode:{type:"string",enum:vT,description:"Default light/dark mode for users who never toggled it."},contrast:{type:"string",enum:wT},buttons:{type:"string",enum:kT,description:"Primary buttons: neutral (near-black) or accent colored."},customCss:{type:["string","null"],description:"Extra CSS for the whole workspace (≤ 50 KB). null removes it."},themeId:{type:["string","null"],description:"Installed theme extension to use (see list_extensions); null clears it."}},T9=[{name:"list_modules",description:"List the workspace modules (built-in features such as dashboard, deals, reports, tasks, automations, forms, integrations, assistant, plus installed extension modules) with enabled / required state and dependencies.",inputSchema:{type:"object",properties:{}},mutating:!1,handler:e=>Qh(e).map(t=>({id:t.id,name:t.name,category:t.category,source:t.source,enabled:t.enabled,...t.required?{required:!0}:{},...t.dependsOn.length?{dependsOn:t.dependsOn}:{},...t.dependents.length?{dependents:t.dependents}:{},...t.objects.length?{objects:t.objects}:{},...t.version?{version:t.version}:{}}))},{name:"set_module_enabled",description:"Enable or disable a module for the whole workspace (admin only). Disabling hides its pages, navigation and widgets (and objects, e.g. deals) without deleting data. Fails when other modules depend on it unless cascade is true.",inputSchema:{type:"object",properties:{id:{type:"string",description:"Module id (see list_modules)."},enabled:{type:"boolean"},cascade:{type:"boolean",default:!1,description:"Also disable dependents / enable dependencies."}},required:["id","enabled"]},mutating:!0,handler:(e,t)=>vf(e,String(t.id),t.enabled===!0,{cascade:t.cascade===!0})},{name:"get_appearance",description:"Get the workspace appearance (accent color, neutral scale, radius, density, font, sidebar style, default mode, selected theme) and the available presets / themes.",inputSchema:{type:"object",properties:{}},mutating:!1,handler:e=>({appearance:lx(w0(e)),presets:VT(e).map(t=>({id:t.id,name:t.name,source:t.source,description:t.description}))})},{name:"set_appearance",description:"Change the workspace appearance for every user (admin only). Pass only the keys to change; null resets a key to its default. Applied live in every open admin.",inputSchema:{type:"object",properties:E9,additionalProperties:!1},mutating:!0,handler:async(e,t)=>lx(await sp(e,t))},{name:"apply_appearance_preset",description:"Apply an appearance preset (default, ocean, forest, sunset, graphite, rose, high-contrast) or an installed theme extension id (admin only). Logo, favicon and custom CSS are kept.",inputSchema:{type:"object",properties:{id:{type:"string",description:"Preset or theme id (see get_appearance)."}},required:["id"]},mutating:!0,handler:async(e,t)=>lx(await W1(e,String(t.id)))},{name:"list_extensions",description:"List the installed extensions (external modules and themes) with version, author, enabled state and API compatibility.",inputSchema:{type:"object",properties:{kind:{type:"string",enum:["module","theme"]}}},mutating:!1,handler:(e,t)=>pT(e,t.kind==="module"||t.kind==="theme"?{kind:t.kind}:{})},{name:"set_extension_enabled",description:"Enable or disable an installed extension without uninstalling it (admin only). Installing new code is not possible through tools — use Settings → Modules or the CLI.",inputSchema:{type:"object",properties:{id:{type:"string"},enabled:{type:"boolean"},cascade:{type:"boolean",default:!1}},required:["id","enabled"]},mutating:!0,handler:(e,t)=>{if(typeof t.id!="string"||!t.id)throw new he("validation",'Missing "id".');return L1(e,t.id,t.enabled===!0,{cascade:t.cascade===!0})}}],XN=["image","pdf","document","spreadsheet","presentation","archive","text","audio","video","other"];function eA(e,t){var n;return{id:t.id,name:t.name,kind:As(t.mime,t.name),mime:t.mime,size:t.size,sizeLabel:Is(t.size),...t.width&&t.height?{dimensions:`${t.width}×${t.height}`}:{},createdAt:new Date(t.createdAt).toISOString(),...t.createdBy?{uploadedBy:((n=wn(e.store,t.createdBy))==null?void 0:n.name)??t.createdBy}:{},attachedTo:t.targets.map(r=>{var s;return r.kind==="record"?{kind:"record",id:r.id,label:Sw(e,r.id)}:{kind:"activity",id:r.id,title:(s=e.store.get("activities",r.id))==null?void 0:s.title}}),...t.via?{via:t.via.kind}:{},...t.deletedAt?{deleted:!0}:{}}}const I9=[{name:"list_files",description:"Files (images, PDFs, documents) of a record — attached to it, its image fields, its activities' attachments; includeRelated adds linked records' files — or of one activity. Metadata only (name, type, size, attached to); without recordId / activityId: storage usage + the most recent files.",inputSchema:{type:"object",properties:{recordId:{type:"string",description:"Record id."},activityId:{type:"string",description:"Activity id (note, task…)."},includeRelated:{type:"boolean",description:"Also files of related records (e.g. a company's people and deals)."},kind:{type:"string",enum:XN},search:{type:"string",description:"Part of the file name."},limit:{type:"number",default:30,maximum:200}}},mutating:!1,handler:(e,t)=>{const n=typeof t.recordId=="string"&&t.recordId?t.recordId:typeof t.activityId=="string"&&t.activityId?t.activityId:null,r=Math.min(200,typeof t.limit=="number"?t.limit:30),s=p0(e,n,{includeRelated:t.includeRelated===!0,kind:XN.includes(t.kind)?t.kind:void 0,search:typeof t.search=="string"?t.search:void 0});return{...n?{}:{usage:f1(e)},total:s.length,files:s.slice(0,r).map(a=>eA(e,a))}}},{name:"describe_attachments",description:"What is attached to an activity, or to every activity of a record: file metadata (name, type, size, dimensions) and the images referenced inline in the Markdown body. Use it before summarising a note / task that mentions attachments. Never returns file contents.",inputSchema:{type:"object",properties:{activityId:{type:"string"},recordId:{type:"string",description:"All activities of this record that have attachments."}}},mutating:!1,handler:(e,t)=>{const n=typeof t.activityId=="string"?t.activityId:"",r=typeof t.recordId=="string"?t.recordId:"";if(!n&&!r)throw new he("validation","Give activityId or recordId.");if(r&&!$n(e.store,r))throw new he("notFound",`Record "${r}" not found.`);const s=rr(e.store).filter(o=>n?o.id===n:o.targets.some(l=>l.id===r));if(n&&!s.length)throw new he("notFound",`Activity "${n}" not found.`);return{activities:s.map(o=>{const d=[...new Set([...o.attachments??[],...Zx(o.body)])].map(f=>cl(e.store,f)).filter(f=>!!f&&!f.deletedAt);return{activity:{id:o.id,type:o.type,title:o.title},inline:Zx(o.body),files:d.map(f=>eA(e,f))}}).filter(o=>o.files.length)}}}],mu={type:"string",description:'Object id, e.g. "companies", "people", "deals" (see describe_schema).'},tA={type:"object",description:"Field values keyed by field id (see describe_schema). Select fields take the option id or label; relation fields take record ids; dates YYYY-MM-DD; datetimes ISO 8601; multi values as arrays.",additionalProperties:!0},R9={type:"object",properties:{field:{type:"string",description:"Field id, or id / ownerId / createdAt / updatedAt."},op:{type:"string",enum:Wg},value:{description:"Operand. in/notIn: array. withinDays: number (negative = past). Dates: YYYY-MM-DD, 'today', '+30d'."}},required:["field","op"]},$9={type:"string",description:"Record id the activity is attached to."};function Zo(e,t,n={}){var o,l;const r=Zt(e.store,t.object),s=r?_i(e,r):void 0,a={};for(const[d,f]of Object.entries(t.fields)){const p=r?Nr(r,d):void 0;if(!p||!s){a[d]=f;continue}if(p.type==="relation"){const m=Array.isArray(f)?f:[f];a[d]=m.map(h=>({id:h,label:s.recordLabel("",String(h))??String(h)})),((o=p.relation)==null?void 0:o.cardinality)==="one"&&(a[d]=a[d][0])}else if(p.type==="image"||p.type==="files"){const h=(Array.isArray(f)?f:[f]).map(String).map(b=>{var x;return{id:b,name:((x=e.store.get("files",b))==null?void 0:x.name)??b}});a[d]=p.type==="image"?h[0]:h}else p.type==="select"||p.type==="multiSelect"||p.type==="user"?a[d]={value:f,label:_s(p,f,s)}:a[d]=f}return{id:t.id,object:t.object,label:ct(r,t),fields:a,...t.ownerId?{owner:{id:t.ownerId,name:(l=wn(e.store,t.ownerId))==null?void 0:l.name}}:{},...n.full?{createdAt:new Date(t.createdAt).toISOString(),updatedAt:new Date(t.updatedAt).toISOString()}:{},...t.deletedAt?{deleted:!0}:{}}}function Wo(e){var t;return{id:e.id,type:e.type,title:e.title,...e.body?{body:e.body.length>600?`${e.body.slice(0,600)}…`:e.body}:{},targets:e.targets,...e.dueAt?{dueAt:new Date(e.dueAt).toISOString()}:{},...e.doneAt?{doneAt:new Date(e.doneAt).toISOString()}:{},...e.assigneeId?{assigneeId:e.assigneeId}:{},...(t=e.attachments)!=null&&t.length?{attachments:e.attachments.length}:{},createdAt:new Date(e.createdAt).toISOString()}}function xn(e,t,n=!0){const r=e[t];if(typeof r=="string"&&r.trim())return r.trim();if(n)throw new he("validation",`Missing "${t}".`);return""}function hu(e,t,n){const r=e[t];return typeof r=="number"&&Number.isFinite(r)?r:n}const bg=[{name:"describe_schema",description:"Describe the CRM data model: objects, their fields (ids, types, select options, relations) and pipelines with stages. Call this first to learn field ids.",inputSchema:{type:"object",properties:{object:{...mu,description:"Only this object (optional)."}}},mutating:!1,handler:(e,t)=>Lw(e,typeof t.object=="string"?t.object:void 0)},{name:"search_records",description:"Full-text search across records (names, emails, domains, phones) and activity titles. Returns the best matches with ids.",inputSchema:{type:"object",properties:{query:{type:"string",description:"Search text."},objects:{type:"array",items:{type:"string"},description:"Restrict to these object ids."},limit:{type:"number",default:10,maximum:50}},required:["query"]},mutating:!1,handler:(e,t)=>v5(e,xn(t,"query"),{objects:t.objects,limit:Math.min(50,hu(t,"limit",10))})},{name:"list_records",description:"List records of an object with optional filters, sorts and pagination (max 100 per call).",inputSchema:{type:"object",properties:{object:mu,filters:{type:"array",items:R9},sorts:{type:"array",items:{type:"object",properties:{field:{type:"string"},dir:{type:"string",enum:["asc","desc"]}},required:["field","dir"]}},search:{type:"string"},viewId:{type:"string",description:"Apply a saved view's filters and sorts."},offset:{type:"number",default:0},limit:{type:"number",default:25,maximum:100}},required:["object"]},mutating:!1,handler:(e,t)=>{const n=_w(e,xn(t,"object"),{filters:t.filters,sorts:t.sorts,search:typeof t.search=="string"?t.search:void 0,viewId:typeof t.viewId=="string"?t.viewId:void 0,offset:hu(t,"offset",0),limit:Math.min(100,hu(t,"limit",25))});return{total:n.total,offset:n.offset,hasMore:n.hasMore,records:n.items.map(r=>Zo(e,r))}}},{name:"get_record",description:"Get one record with every field, its relations (both directions) and its latest activities.",inputSchema:{type:"object",properties:{id:{type:"string"}},required:["id"]},mutating:!1,handler:(e,t)=>{const n=x5(e,xn(t,"id")),r=ul(e,{target:n.record.id,limit:10}).items.map(Wo);return{...Zo(e,n.record,{full:!0}),relations:n.relations,related:n.inverse.filter(s=>s.records.length).map(s=>({object:s.object,via:s.field,records:s.records.slice(0,25),count:s.records.length})),activities:r}}},{name:"create_record",description:"Create a record of an object. Returns the created record.",inputSchema:{type:"object",properties:{object:mu,fields:tA,ownerId:{type:"string",description:"User id owning the record (default: you)."}},required:["object","fields"]},mutating:!0,handler:async(e,t)=>Zo(e,await dl(e,xn(t,"object"),t.fields??{},{...typeof t.ownerId=="string"?{ownerId:t.ownerId}:{}}))},{name:"update_record",description:"Update some fields of a record (only the given fields change; null clears a field).",inputSchema:{type:"object",properties:{id:{type:"string"},fields:tA,ownerId:{type:["string","null"]}},required:["id","fields"]},mutating:!0,handler:async(e,t)=>Zo(e,await Ar(e,xn(t,"id"),t.fields??{},t.ownerId!==void 0?{ownerId:t.ownerId}:{}))},{name:"delete_record",description:"Delete a record (soft delete: restorable until the data is compacted).",inputSchema:{type:"object",properties:{id:{type:"string"}},required:["id"]},mutating:!0,handler:(e,t)=>sf(e,xn(t,"id"))},{name:"merge_records",description:"Merge duplicate records into a primary one: empty fields are filled from the duplicates, relations and activities move to the primary, duplicates are removed.",inputSchema:{type:"object",properties:{primaryId:{type:"string"},duplicateIds:{type:"array",items:{type:"string"}}},required:["primaryId","duplicateIds"]},mutating:!0,handler:async(e,t)=>{const n=await Qw(e,xn(t,"primaryId"),t.duplicateIds??[]);return{record:Zo(e,n.record),merged:n.merged,movedActivities:n.movedActivities}}},{name:"add_note",description:"Add a note (markdown) to a record's timeline.",inputSchema:{type:"object",properties:{recordId:$9,body:{type:"string"},title:{type:"string"}},required:["recordId","body"]},mutating:!0,handler:async(e,t)=>Wo(await Rw(e,xn(t,"recordId"),xn(t,"body"),typeof t.title=="string"?t.title:void 0))},{name:"log_activity",description:"Log a call, email or meeting on one or more records.",inputSchema:{type:"object",properties:{type:{type:"string",enum:Xs.filter(e=>e!=="task")},title:{type:"string"},body:{type:"string"},recordIds:{type:"array",items:{type:"string"}},meta:{type:"object",additionalProperties:!0,description:"e.g. { durationMin } for calls, { startAt, endAt } (epoch ms) for meetings."}},required:["type","title","recordIds"]},mutating:!0,handler:async(e,t)=>{const n=(t.recordIds??[]).map(r=>({object:"",id:r}));return Wo(await ga(e,{type:xn(t,"type"),title:xn(t,"title"),body:typeof t.body=="string"?t.body:void 0,targets:n,meta:t.meta}))}},{name:"create_task",description:"Create a task, optionally attached to records, with a due date and an assignee.",inputSchema:{type:"object",properties:{title:{type:"string"},body:{type:"string"},dueAt:{type:"string",description:"ISO date or datetime."},assigneeId:{type:"string"},recordIds:{type:"array",items:{type:"string"}}},required:["title"]},mutating:!0,handler:async(e,t)=>Wo(await $w(e,{title:xn(t,"title"),body:typeof t.body=="string"?t.body:void 0,dueAt:typeof t.dueAt=="string"?t.dueAt:void 0,assigneeId:typeof t.assigneeId=="string"?t.assigneeId:void 0,targets:(t.recordIds??[]).map(n=>({object:"",id:n}))}))},{name:"complete_task",description:"Mark a task as done (or reopen it with done: false).",inputSchema:{type:"object",properties:{id:{type:"string"},done:{type:"boolean",default:!0}},required:["id"]},mutating:!0,handler:async(e,t)=>Wo(await Oc(e,xn(t,"id"),t.done!==!1))},{name:"list_tasks",description:"List tasks: open by default, optionally for one assignee / record, overdue only, or due within N days. Sorted by due date.",inputSchema:{type:"object",properties:{assigneeId:{type:"string"},recordId:{type:"string"},status:{type:"string",enum:["open","done","all"],default:"open"},overdue:{type:"boolean"},dueWithinDays:{type:"number"},limit:{type:"number",default:25,maximum:100}}},mutating:!1,handler:(e,t)=>{const n=Mw(e,{assigneeId:typeof t.assigneeId=="string"?t.assigneeId:void 0,target:typeof t.recordId=="string"?t.recordId:void 0,status:t.status??"open",overdue:t.overdue===!0,dueWithinDays:typeof t.dueWithinDays=="number"?t.dueWithinDays:void 0,limit:Math.min(100,hu(t,"limit",25))});return{total:n.total,tasks:n.items.map(Wo)}}},{name:"list_activities",description:"A record's timeline (notes, calls, emails, meetings, tasks), most recent first. includeRelated adds activities of linked records (e.g. a company's people and deals).",inputSchema:{type:"object",properties:{recordId:{type:"string"},types:{type:"array",items:{type:"string",enum:Xs}},includeRelated:{type:"boolean"},limit:{type:"number",default:20,maximum:100}}},mutating:!1,handler:(e,t)=>{const n=ul(e,{target:typeof t.recordId=="string"?t.recordId:void 0,types:t.types,includeRelated:t.includeRelated===!0,limit:Math.min(100,hu(t,"limit",20))});return{total:n.total,activities:n.items.map(Wo)}}},{name:"move_deal_stage",description:"Move a deal (or any pipeline record) to a stage, by stage id or label. Updates probability; lostReason for lost stages.",inputSchema:{type:"object",properties:{id:{type:"string"},stage:{type:"string"},lostReason:{type:"string"}},required:["id","stage"]},mutating:!0,handler:async(e,t)=>Zo(e,await Du(e,xn(t,"id"),xn(t,"stage"),{lostReason:typeof t.lostReason=="string"?t.lostReason:void 0}))},{name:"pipeline_summary",description:"Pipeline overview: per stage deal count, amount and weighted amount, plus open / weighted / won totals and open deals by close month.",inputSchema:{type:"object",properties:{pipelineId:{type:"string"},ownerId:{type:"string"}}},mutating:!1,handler:(e,t)=>({pipelines:_5(e).map(n=>({id:n.id,name:n.name})),...Cl(e,{pipelineId:typeof t.pipelineId=="string"?t.pipelineId:void 0,ownerId:typeof t.ownerId=="string"?t.ownerId:void 0})})},{name:"run_report",description:`Run a named report. Reports: ${Object.entries(mf).map(([e,t])=>`${e} (${t.description})`).join("; ")}`,inputSchema:{type:"object",properties:{name:{type:"string",enum:Object.keys(mf)},params:{type:"object",additionalProperties:!0,description:"Report parameters, e.g. { months: 6 } or { days: 30 }."}},required:["name"]},mutating:!1,handler:(e,t)=>aE(e,xn(t,"name"),t.params??{})},{name:"create_field",description:"Add a custom field to an object (admin only).",inputSchema:{type:"object",properties:{object:mu,label:{type:"string"},type:{type:"string",enum:af},options:{type:"array",items:{type:"string"},description:"Option labels for select / multiSelect."},relationObject:{type:"string",description:"Target object for relation fields."},cardinality:{type:"string",enum:["one","many"]},description:{type:"string"}},required:["object","label","type"]},mutating:!0,handler:(e,t)=>Fw(e,xn(t,"object"),{label:xn(t,"label"),type:xn(t,"type"),options:t.options,description:typeof t.description=="string"?t.description:void 0,...t.relationObject?{relation:{object:String(t.relationObject),cardinality:t.cardinality==="many"?"many":"one"}}:{}})},{name:"import_csv",description:"Import CSV text into an object. Columns are mapped to fields automatically (or via mapping {header: fieldId}); duplicates (people by email, companies by domain) are updated. Runs as a DRY RUN unless confirm is true — show the report to the user before confirming.",inputSchema:{type:"object",properties:{object:mu,csv:{type:"string"},mapping:{type:"object",additionalProperties:{type:"string"}},onDuplicate:{type:"string",enum:["update","skip","create"],default:"update"},confirm:{type:"boolean",default:!1}},required:["object","csv"]},mutating:!0,handler:async(e,t)=>{const n=await Zw(e,{object:xn(t,"object"),csv:String(t.csv??""),mapping:t.mapping,onDuplicate:t.onDuplicate??"update",dryRun:t.confirm!==!0});return{...n,rows:n.rows.slice(0,50),rowsTruncated:n.rows.length>50}}},..._9,...T9,...I9],Ac=new Map,nA=new Set,D9=/^[a-z][a-z0-9_]{1,63}$/;function Tv(e){if(!e||typeof e.name!="string"||!D9.test(e.name))throw new Error(`Invalid AI tool name "${String(e==null?void 0:e.name)}" (snake_case, ≤ 64 chars).`);if(typeof e.handler!="function")throw new Error(`AI tool "${e.name}" needs a handler.`);if(!e.inputSchema||e.inputSchema.type!=="object")throw new Error(`AI tool "${e.name}" needs an object inputSchema.`);if(bg.some(t=>t.name===e.name)||Ac.has(e.name))throw new Error(`AI tool "${e.name}" already exists.`);Ac.set(e.name,{...e,mutating:e.mutating!==!1});for(const t of[...nA])t();return()=>{if(Ac.delete(e.name))for(const t of[...nA])t()}}function Ok(){return Ac.size?[...bg,...Ac.values()]:bg}function Pk(e){return bg.find(t=>t.name===e)??Ac.get(e)}function Bu(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function Iv(e,t,n){const r=e.type===void 0?[]:Array.isArray(e.type)?e.type:[e.type];let s=t;if(r.length&&s!==null&&s!==void 0){const a=Bu(s),o=l=>l===a||l==="integer"&&a==="number"&&Number.isInteger(s);if(!r.some(o))if((r.includes("number")||r.includes("integer"))&&typeof s=="string"&&s.trim()!==""&&Number.isFinite(Number(s)))s=Number(s);else if(r.includes("boolean")&&(s==="true"||s==="false"))s=s==="true";else throw new he("validation",`${n} must be ${r.map(l=>l==="array"||l==="object"||l==="integer"?`an ${l}`:`a ${l}`).join(" or ")}, got ${a==="array"||a==="object"?`an ${a}`:`${a} ${JSON.stringify(s)}`.slice(0,80)}.`)}if(s==null)return s;if(e.enum&&!e.enum.includes(s))throw new he("validation",`${n} must be one of ${e.enum.map(a=>JSON.stringify(a)).join(", ")}, got ${JSON.stringify(s).slice(0,80)}.`);if(Array.isArray(s)&&e.items){const a=e.items;return s.map((o,l)=>Iv(a,o,`${n}[${l}]`))}if(Bu(s)==="object"&&(e.properties||e.required)){const a={...s};for(const o of e.required??[])if(a[o]===void 0||a[o]===null)throw new he("validation",`${n}: missing required "${o}".`);for(const[o,l]of Object.entries(e.properties??{}))a[o]!==void 0&&(a[o]=Iv(l,a[o],`${n}.${o}`));return a}return s}async function M9(e,t,n){const r=Pk(t);if(!r)throw new he("notFound",`Unknown tool "${t}". Tools: ${Ok().map(o=>o.name).join(", ")}.`);if(n!=null&&Bu(n)!=="object")throw new he("validation",`${t}: the input must be a JSON object, got ${Bu(n)==="array"?"an array":`a ${Bu(n)}`}.`);const s=n??{};for(const o of r.inputSchema.required??[])if(s[o]===void 0||s[o]===null)throw new he("validation",`${t}: missing required "${o}".`);const a=Iv({...r.inputSchema,required:[]},s,t);return r.handler(e,a)}function O9(e){return e}function P9(e){return e}function L9(e,t){l1(e,t)}function F9(){return S.useSyncExternalStore(zT,ng,ng)}function z9(e,t,n){return ki.addAction(e,t,n)}function U9(e,t){ki.removeAction(e,t)}function B9(e,t,n){return ki.addFilter(e,t,n)}function H9(e,t){ki.removeFilter(e,t)}function q9(e,...t){return ki.doAction(e,...t)}function V9(e,t,...n){return ki.applyFilters(e,t,...n)}function W9(e){return Tv(e)}const K9={apiVersion:b0,minApiVersion:O1,defineModule:O9,defineTheme:P9,ops:Cz,useCrm:ps,useOps:Xe,useCan:Ge,useCurrentUser:Ei,useCollection:mt,useObjects:un,useObject:gd,useRecords:Os,useRecord:Z1,useActivities:Ti,usePipelines:ms,useViews:tI,useUsers:sr,useSettings:di,useModuleConfig:Pz,useModuleEnabled:Cf,useAppearance:F9,useNavigate:dn,useParams:lo,useSearchParams:id,useLocation:ci,Link:Rn,NavLink:q_,paths:pt,recordHref:ip,addAction:z9,removeAction:U9,addFilter:B9,removeFilter:H9,doAction:q9,applyFilters:V9,registerAiTool:W9,registerAutomationAction:Jh,Button:ue,IconButton:dt,Input:Oe,Textarea:Cr,Select:Ve,Label:SI,FormField:Te,Checkbox:Ot,Switch:si,Modal:on,Drawer:cU,Card:Ke,Badge:tt,Avatar:$s,Tabs:bo,Tooltip:pU,Spinner:Ds,EmptyState:ut,PageHeader:Kr,Kbd:qr,Dropdown:Tr,Table:xo,THead:vo,TBody:wo,Tr:Vr,Th:_t,Td:bt,FieldValue:hp,FieldInput:hr,ObjectIcon:Mn,Markdown:vp,confirmDialog:qt,toast:ge,cn:ce,newId:Es,i18n:xt,addBundles:L9,activeLocale:f0,intlLocale:_r,formatFieldValue:_s,formatCurrency:Bf,formatNumber:$c,formatDate:Pw,formatDateTime:ti,formatRelative:eo,recordLabel:ct,coerceFieldValue:Uf,isEmptyFieldValue:vn};let sh=null;function G9(){const e=globalThis;if(sh&&e[cv]===sh)return sh;const t={apiVersion:b0,api:K9,modules:{react:h_,"react/jsx-runtime":GD,"react-dom":tM,"react-dom/client":sM,"react-i18next":FM},async prepare(n){if(n.includes("lucide-react")&&!t.modules["lucide-react"]){const r=await Sr(()=>import("./lucide-react.min--rznIkmQ.js").then(s=>s.l),[],import.meta.url);t.modules["lucide-react"]=r.default&&typeof r.default=="object"&&"createLucideIcon"in r.default?r.default:r}}};return e[cv]=t,sh=t,t}G9();function Ns(e){let t="";for(let r=0;r<e.length;r+=32768)t+=String.fromCharCode(...e.subarray(r,r+32768));return btoa(t)}function so(e){const t=atob(e.replace(/\s+/g,"")),n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=t.charCodeAt(r);return n}function J9(e){return Ns(new TextEncoder().encode(e))}function eR(e){return new TextDecoder().decode(so(e))}function Y9(e){return e.encoding==="base64"?so(e.content):new TextEncoder().encode(e.content)}function Lk(e,t="kv"){const n=new Map;let r=null;function s(){return r||(r=new Promise(o=>{try{if(typeof indexedDB>"u")return o(null);const l=indexedDB.open(e,1);l.onupgradeneeded=()=>l.result.createObjectStore(t),l.onsuccess=()=>o(l.result),l.onerror=()=>o(null),l.onblocked=()=>o(null)}catch{o(null)}})),r}function a(o,l){return s().then(d=>new Promise((f,p)=>{if(!d)return f(void 0);const m=d.transaction(t,o),h=l(m.objectStore(t));m.oncomplete=()=>f(h?h.result:void 0),m.onerror=()=>p(m.error),m.onabort=()=>p(m.error)}))}return{async get(o){return await s()?a("readonly",l=>l.get(o)):n.get(o)},async set(o,l){if(!await s())return void n.set(o,l);await a("readwrite",d=>void d.put(l,o))},async delete(o){if(!await s())return void n.delete(o);await a("readwrite",l=>void l.delete(o))},async keys(){return await s()?(await a("readonly",o=>o.getAllKeys())??[]).map(String):[...n.keys()]},async entries(){if(!await s())return[...n.entries()];const o=[];return await a("readonly",l=>{const d=l.openCursor();d.onsuccess=()=>{const f=d.result;f&&(o.push([String(f.key),f.value]),f.continue())}}),o},async clear(){if(!await s())return void n.clear();await a("readwrite",o=>void o.clear())}}}const za=Lk("agentcrm-site-mirror","files");function Z9(e){const t=(e.siteUrl??"").replace(/\/+$/,""),n=r=>r.replace(/^\/+/,"");return{id:"browser-mirror",model:"files",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0},async put(r){await za.set(n(r.path),{content:r.content,encoding:r.encoding==="base64"?"base64":"utf-8",updatedAt:Date.now()})},async get(r){const s=await za.get(n(r));if(!s)throw new Si(`File not found: ${r}`,404);return s.encoding==="base64"?eR(s.content):s.content},async getBytes(r){const s=await za.get(n(r));return s?s.encoding==="base64"?so(s.content):new TextEncoder().encode(s.content):null},delete:r=>za.delete(n(r)),async deletePrefix(r){const s=n(r).replace(/\/+$/,"")+"/";for(const a of await za.keys())a.startsWith(s)&&await za.delete(a)},async list(r,s){const a=(await za.keys()).sort().map(o=>({path:o,type:"file",url:t?`${t}/${o}`:`/${o}`}));return{items:a.slice((r-1)*s,r*s),page:r,per_page:s,total:a.length}},async listPrefix(r){const s=n(r);return(await za.keys()).filter(a=>a.startsWith(s)).sort()},async publicUrl(r){return t?`${t}/${n(r)}`:`/${n(r)}`}}}const Q9={id:"browser-mirror",create:Z9},X9="agentcrm-git-blobs",Tf="texts",Rv=new Map;let ih=null;function tR(){return ih||(ih=new Promise(e=>{try{if(typeof indexedDB>"u")return e(null);const t=indexedDB.open(X9,1);t.onupgradeneeded=()=>t.result.createObjectStore(Tf),t.onsuccess=()=>e(t.result),t.onerror=()=>e(null),t.onblocked=()=>e(null)}catch{e(null)}}),ih)}async function nR(e){const t=new Map,n=[];for(const s of e){const a=Rv.get(s);a!==void 0?t.set(s,a):n.push(s)}if(n.length===0)return t;const r=await tR();return r&&await new Promise(s=>{try{const a=r.transaction(Tf,"readonly"),o=a.objectStore(Tf);for(const l of n){const d=o.get(l);d.onsuccess=()=>{typeof d.result=="string"&&(t.set(l,d.result),Rv.set(l,d.result))}}a.oncomplete=()=>s(),a.onerror=()=>s(),a.onabort=()=>s()}catch{s()}}),t}async function rR(e){for(const[n,r]of e)Rv.set(n,r);const t=await tR();!t||e.size===0||await new Promise(n=>{try{const r=t.transaction(Tf,"readwrite"),s=r.objectStore(Tf);for(const[a,o]of e)s.put(o,a);r.oncomplete=()=>n(),r.onerror=()=>n(),r.onabort=()=>n()}catch{n()}})}class nl extends Error{constructor(t,n){super(t),this.currentHeadSha=n,this.name="GitConflictError"}}const rA=300,sA=50,eB=3;function tB(e){const t=(e.apiBaseUrl||"https://api.github.com").replace(/\/+$/,""),n=t.endsWith("/api/v3")?t.replace(/\/api\/v3$/,"/api/graphql"):`${t}/graphql`,r=`${t}/repos/${encodeURIComponent(e.owner)}/${encodeURIComponent(e.repo)}`,s=`heads/${e.branch.split("/").map(encodeURIComponent).join("/")}`,a={Authorization:`Bearer ${e.token}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28"},o={...a,"Content-Type":"application/json"};async function l(_,D="get"){return await(await Ys(D,_,{headers:a,cache:"no-store"})).json()}async function d(_,D,I="POST"){return await(await Ys("commit",_,{method:I,headers:o,body:JSON.stringify(D)})).json()}async function f(){var I;const _=await Ys("get",`${r}/git/ref/${s}`,{headers:a,cache:"no-store"},[404,409]);if(!_.ok)return"";const D=await _.json();return Array.isArray(D)?"":((I=D.object)==null?void 0:I.sha)??""}async function p(_){return(await l(`${r}/git/commits/${_}`)).tree.sha}async function m(_,D,I){const T=await l(`${r}/git/trees/${_}`,"list");for(const E of T.tree){const P=D+E.path;E.type==="blob"?I.push({path:P,sha:E.sha,size:E.size}):E.type==="tree"&&await m(E.sha,P+"/",I)}}async function h(_){if(!_)return{headSha:"",entries:[]};const D=await p(_),I=await l(`${r}/git/trees/${D}?recursive=1`,"list");if(!I.truncated)return{headSha:_,entries:I.tree.filter(E=>E.type==="blob").map(E=>({path:E.path,sha:E.sha,size:E.size}))};const T=[];return await m(D,"",T),{headSha:_,entries:T}}async function b(_){return(await l(`${r}/git/blobs/${_}`)).content}async function x(_){var I;const D=new Map;for(let T=0;T<_.length;T+=sA){const E=_.slice(T,T+sA),U=`query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { ${E.map((O,z)=>`b${z}: object(oid: "${O}") { ... on Blob { text isBinary isTruncated } }`).join(`
1130
+ ${(d==null?void 0:d.name)??""}`;return{draft:{to:s.slice(0,10),subject:p,body:m},sent:!1,note:"Draft only — nothing was sent. The user can send it from the record's Emails tab (Gmail / Outlook integration).",context:{record:{id:n.id,object:n.object,label:ct(r,n)},recentActivities:o.map(y=>({type:y.type,title:y.title,at:new Date(y.createdAt).toISOString()})),...l?{lastEmail:{title:l.title,body:(x=l.body)==null?void 0:x.slice(0,800),at:new Date(l.createdAt).toISOString()}}:{}}}}}];function lx(e){const{logo:t,favicon:n,customCss:r,...s}=e;return{...s,hasLogo:!!t,hasFavicon:!!n,customCssBytes:r?r.length:0}}const E9={accent:{type:"string",description:"Accent color, hex #rrggbb (a full 50–950 scale is generated from it)."},neutral:{type:"string",enum:F1,description:"Gray scale used for surfaces, borders and text."},radius:{type:"string",enum:z1},density:{type:"string",enum:bT,description:"compact = shorter table rows and paddings."},font:{type:"string",enum:Uc.map(e=>e.id),description:'"system" needs no network; the others load from Google Fonts.'},sidebar:{type:"string",enum:xT},defaultMode:{type:"string",enum:vT,description:"Default light/dark mode for users who never toggled it."},contrast:{type:"string",enum:wT},buttons:{type:"string",enum:kT,description:"Primary buttons: neutral (near-black) or accent colored."},customCss:{type:["string","null"],description:"Extra CSS for the whole workspace (≤ 50 KB). null removes it."},themeId:{type:["string","null"],description:"Installed theme extension to use (see list_extensions); null clears it."}},T9=[{name:"list_modules",description:"List the workspace modules (built-in features such as dashboard, deals, reports, tasks, automations, forms, integrations, assistant, plus installed extension modules) with enabled / required state and dependencies.",inputSchema:{type:"object",properties:{}},mutating:!1,handler:e=>Qh(e).map(t=>({id:t.id,name:t.name,category:t.category,source:t.source,enabled:t.enabled,...t.required?{required:!0}:{},...t.dependsOn.length?{dependsOn:t.dependsOn}:{},...t.dependents.length?{dependents:t.dependents}:{},...t.objects.length?{objects:t.objects}:{},...t.version?{version:t.version}:{}}))},{name:"set_module_enabled",description:"Enable or disable a module for the whole workspace (admin only). Disabling hides its pages, navigation and widgets (and objects, e.g. deals) without deleting data. Fails when other modules depend on it unless cascade is true.",inputSchema:{type:"object",properties:{id:{type:"string",description:"Module id (see list_modules)."},enabled:{type:"boolean"},cascade:{type:"boolean",default:!1,description:"Also disable dependents / enable dependencies."}},required:["id","enabled"]},mutating:!0,handler:(e,t)=>vf(e,String(t.id),t.enabled===!0,{cascade:t.cascade===!0})},{name:"get_appearance",description:"Get the workspace appearance (accent color, neutral scale, radius, density, font, sidebar style, default mode, selected theme) and the available presets / themes.",inputSchema:{type:"object",properties:{}},mutating:!1,handler:e=>({appearance:lx(w0(e)),presets:VT(e).map(t=>({id:t.id,name:t.name,source:t.source,description:t.description}))})},{name:"set_appearance",description:"Change the workspace appearance for every user (admin only). Pass only the keys to change; null resets a key to its default. Applied live in every open admin.",inputSchema:{type:"object",properties:E9,additionalProperties:!1},mutating:!0,handler:async(e,t)=>lx(await sp(e,t))},{name:"apply_appearance_preset",description:"Apply an appearance preset (default, ocean, forest, sunset, graphite, rose, high-contrast) or an installed theme extension id (admin only). Logo, favicon and custom CSS are kept.",inputSchema:{type:"object",properties:{id:{type:"string",description:"Preset or theme id (see get_appearance)."}},required:["id"]},mutating:!0,handler:async(e,t)=>lx(await W1(e,String(t.id)))},{name:"list_extensions",description:"List the installed extensions (external modules and themes) with version, author, enabled state and API compatibility.",inputSchema:{type:"object",properties:{kind:{type:"string",enum:["module","theme"]}}},mutating:!1,handler:(e,t)=>pT(e,t.kind==="module"||t.kind==="theme"?{kind:t.kind}:{})},{name:"set_extension_enabled",description:"Enable or disable an installed extension without uninstalling it (admin only). Installing new code is not possible through tools — use Settings → Modules or the CLI.",inputSchema:{type:"object",properties:{id:{type:"string"},enabled:{type:"boolean"},cascade:{type:"boolean",default:!1}},required:["id","enabled"]},mutating:!0,handler:(e,t)=>{if(typeof t.id!="string"||!t.id)throw new he("validation",'Missing "id".');return L1(e,t.id,t.enabled===!0,{cascade:t.cascade===!0})}}],XN=["image","pdf","document","spreadsheet","presentation","archive","text","audio","video","other"];function eA(e,t){var n;return{id:t.id,name:t.name,kind:As(t.mime,t.name),mime:t.mime,size:t.size,sizeLabel:Is(t.size),...t.width&&t.height?{dimensions:`${t.width}×${t.height}`}:{},createdAt:new Date(t.createdAt).toISOString(),...t.createdBy?{uploadedBy:((n=wn(e.store,t.createdBy))==null?void 0:n.name)??t.createdBy}:{},attachedTo:t.targets.map(r=>{var s;return r.kind==="record"?{kind:"record",id:r.id,label:Sw(e,r.id)}:{kind:"activity",id:r.id,title:(s=e.store.get("activities",r.id))==null?void 0:s.title}}),...t.via?{via:t.via.kind}:{},...t.deletedAt?{deleted:!0}:{}}}const I9=[{name:"list_files",description:"Files (images, PDFs, documents) of a record — attached to it, its image fields, its activities' attachments; includeRelated adds linked records' files — or of one activity. Metadata only (name, type, size, attached to); without recordId / activityId: storage usage + the most recent files.",inputSchema:{type:"object",properties:{recordId:{type:"string",description:"Record id."},activityId:{type:"string",description:"Activity id (note, task…)."},includeRelated:{type:"boolean",description:"Also files of related records (e.g. a company's people and deals)."},kind:{type:"string",enum:XN},search:{type:"string",description:"Part of the file name."},limit:{type:"number",default:30,maximum:200}}},mutating:!1,handler:(e,t)=>{const n=typeof t.recordId=="string"&&t.recordId?t.recordId:typeof t.activityId=="string"&&t.activityId?t.activityId:null,r=Math.min(200,typeof t.limit=="number"?t.limit:30),s=p0(e,n,{includeRelated:t.includeRelated===!0,kind:XN.includes(t.kind)?t.kind:void 0,search:typeof t.search=="string"?t.search:void 0});return{...n?{}:{usage:f1(e)},total:s.length,files:s.slice(0,r).map(a=>eA(e,a))}}},{name:"describe_attachments",description:"What is attached to an activity, or to every activity of a record: file metadata (name, type, size, dimensions) and the images referenced inline in the Markdown body. Use it before summarising a note / task that mentions attachments. Never returns file contents.",inputSchema:{type:"object",properties:{activityId:{type:"string"},recordId:{type:"string",description:"All activities of this record that have attachments."}}},mutating:!1,handler:(e,t)=>{const n=typeof t.activityId=="string"?t.activityId:"",r=typeof t.recordId=="string"?t.recordId:"";if(!n&&!r)throw new he("validation","Give activityId or recordId.");if(r&&!$n(e.store,r))throw new he("notFound",`Record "${r}" not found.`);const s=rr(e.store).filter(o=>n?o.id===n:o.targets.some(l=>l.id===r));if(n&&!s.length)throw new he("notFound",`Activity "${n}" not found.`);return{activities:s.map(o=>{const d=[...new Set([...o.attachments??[],...Zx(o.body)])].map(f=>cl(e.store,f)).filter(f=>!!f&&!f.deletedAt);return{activity:{id:o.id,type:o.type,title:o.title},inline:Zx(o.body),files:d.map(f=>eA(e,f))}}).filter(o=>o.files.length)}}}],mu={type:"string",description:'Object id, e.g. "companies", "people", "deals" (see describe_schema).'},tA={type:"object",description:"Field values keyed by field id (see describe_schema). Select fields take the option id or label; relation fields take record ids; dates YYYY-MM-DD; datetimes ISO 8601; multi values as arrays.",additionalProperties:!0},R9={type:"object",properties:{field:{type:"string",description:"Field id, or id / ownerId / createdAt / updatedAt."},op:{type:"string",enum:Wg},value:{description:"Operand. in/notIn: array. withinDays: number (negative = past). Dates: YYYY-MM-DD, 'today', '+30d'."}},required:["field","op"]},$9={type:"string",description:"Record id the activity is attached to."};function Zo(e,t,n={}){var o,l;const r=Zt(e.store,t.object),s=r?_i(e,r):void 0,a={};for(const[d,f]of Object.entries(t.fields)){const p=r?Nr(r,d):void 0;if(!p||!s){a[d]=f;continue}if(p.type==="relation"){const m=Array.isArray(f)?f:[f];a[d]=m.map(h=>({id:h,label:s.recordLabel("",String(h))??String(h)})),((o=p.relation)==null?void 0:o.cardinality)==="one"&&(a[d]=a[d][0])}else if(p.type==="image"||p.type==="files"){const h=(Array.isArray(f)?f:[f]).map(String).map(b=>{var x;return{id:b,name:((x=e.store.get("files",b))==null?void 0:x.name)??b}});a[d]=p.type==="image"?h[0]:h}else p.type==="select"||p.type==="multiSelect"||p.type==="user"?a[d]={value:f,label:_s(p,f,s)}:a[d]=f}return{id:t.id,object:t.object,label:ct(r,t),fields:a,...t.ownerId?{owner:{id:t.ownerId,name:(l=wn(e.store,t.ownerId))==null?void 0:l.name}}:{},...n.full?{createdAt:new Date(t.createdAt).toISOString(),updatedAt:new Date(t.updatedAt).toISOString()}:{},...t.deletedAt?{deleted:!0}:{}}}function Wo(e){var t;return{id:e.id,type:e.type,title:e.title,...e.body?{body:e.body.length>600?`${e.body.slice(0,600)}…`:e.body}:{},targets:e.targets,...e.dueAt?{dueAt:new Date(e.dueAt).toISOString()}:{},...e.doneAt?{doneAt:new Date(e.doneAt).toISOString()}:{},...e.assigneeId?{assigneeId:e.assigneeId}:{},...(t=e.attachments)!=null&&t.length?{attachments:e.attachments.length}:{},createdAt:new Date(e.createdAt).toISOString()}}function xn(e,t,n=!0){const r=e[t];if(typeof r=="string"&&r.trim())return r.trim();if(n)throw new he("validation",`Missing "${t}".`);return""}function hu(e,t,n){const r=e[t];return typeof r=="number"&&Number.isFinite(r)?r:n}const bg=[{name:"describe_schema",description:"Describe the CRM data model: objects, their fields (ids, types, select options, relations) and pipelines with stages. Call this first to learn field ids.",inputSchema:{type:"object",properties:{object:{...mu,description:"Only this object (optional)."}}},mutating:!1,handler:(e,t)=>Lw(e,typeof t.object=="string"?t.object:void 0)},{name:"search_records",description:"Full-text search across records (names, emails, domains, phones) and activity titles. Returns the best matches with ids.",inputSchema:{type:"object",properties:{query:{type:"string",description:"Search text."},objects:{type:"array",items:{type:"string"},description:"Restrict to these object ids."},limit:{type:"number",default:10,maximum:50}},required:["query"]},mutating:!1,handler:(e,t)=>v5(e,xn(t,"query"),{objects:t.objects,limit:Math.min(50,hu(t,"limit",10))})},{name:"list_records",description:"List records of an object with optional filters, sorts and pagination (max 100 per call).",inputSchema:{type:"object",properties:{object:mu,filters:{type:"array",items:R9},sorts:{type:"array",items:{type:"object",properties:{field:{type:"string"},dir:{type:"string",enum:["asc","desc"]}},required:["field","dir"]}},search:{type:"string"},viewId:{type:"string",description:"Apply a saved view's filters and sorts."},offset:{type:"number",default:0},limit:{type:"number",default:25,maximum:100}},required:["object"]},mutating:!1,handler:(e,t)=>{const n=_w(e,xn(t,"object"),{filters:t.filters,sorts:t.sorts,search:typeof t.search=="string"?t.search:void 0,viewId:typeof t.viewId=="string"?t.viewId:void 0,offset:hu(t,"offset",0),limit:Math.min(100,hu(t,"limit",25))});return{total:n.total,offset:n.offset,hasMore:n.hasMore,records:n.items.map(r=>Zo(e,r))}}},{name:"get_record",description:"Get one record with every field, its relations (both directions) and its latest activities.",inputSchema:{type:"object",properties:{id:{type:"string"}},required:["id"]},mutating:!1,handler:(e,t)=>{const n=x5(e,xn(t,"id")),r=ul(e,{target:n.record.id,limit:10}).items.map(Wo);return{...Zo(e,n.record,{full:!0}),relations:n.relations,related:n.inverse.filter(s=>s.records.length).map(s=>({object:s.object,via:s.field,records:s.records.slice(0,25),count:s.records.length})),activities:r}}},{name:"create_record",description:"Create a record of an object. Returns the created record.",inputSchema:{type:"object",properties:{object:mu,fields:tA,ownerId:{type:"string",description:"User id owning the record (default: you)."}},required:["object","fields"]},mutating:!0,handler:async(e,t)=>Zo(e,await dl(e,xn(t,"object"),t.fields??{},{...typeof t.ownerId=="string"?{ownerId:t.ownerId}:{}}))},{name:"update_record",description:"Update some fields of a record (only the given fields change; null clears a field).",inputSchema:{type:"object",properties:{id:{type:"string"},fields:tA,ownerId:{type:["string","null"]}},required:["id","fields"]},mutating:!0,handler:async(e,t)=>Zo(e,await Ar(e,xn(t,"id"),t.fields??{},t.ownerId!==void 0?{ownerId:t.ownerId}:{}))},{name:"delete_record",description:"Delete a record (soft delete: restorable until the data is compacted).",inputSchema:{type:"object",properties:{id:{type:"string"}},required:["id"]},mutating:!0,handler:(e,t)=>sf(e,xn(t,"id"))},{name:"merge_records",description:"Merge duplicate records into a primary one: empty fields are filled from the duplicates, relations and activities move to the primary, duplicates are removed.",inputSchema:{type:"object",properties:{primaryId:{type:"string"},duplicateIds:{type:"array",items:{type:"string"}}},required:["primaryId","duplicateIds"]},mutating:!0,handler:async(e,t)=>{const n=await Qw(e,xn(t,"primaryId"),t.duplicateIds??[]);return{record:Zo(e,n.record),merged:n.merged,movedActivities:n.movedActivities}}},{name:"add_note",description:"Add a note (markdown) to a record's timeline.",inputSchema:{type:"object",properties:{recordId:$9,body:{type:"string"},title:{type:"string"}},required:["recordId","body"]},mutating:!0,handler:async(e,t)=>Wo(await Rw(e,xn(t,"recordId"),xn(t,"body"),typeof t.title=="string"?t.title:void 0))},{name:"log_activity",description:"Log a call, email or meeting on one or more records.",inputSchema:{type:"object",properties:{type:{type:"string",enum:Xs.filter(e=>e!=="task")},title:{type:"string"},body:{type:"string"},recordIds:{type:"array",items:{type:"string"}},meta:{type:"object",additionalProperties:!0,description:"e.g. { durationMin } for calls, { startAt, endAt } (epoch ms) for meetings."}},required:["type","title","recordIds"]},mutating:!0,handler:async(e,t)=>{const n=(t.recordIds??[]).map(r=>({object:"",id:r}));return Wo(await ga(e,{type:xn(t,"type"),title:xn(t,"title"),body:typeof t.body=="string"?t.body:void 0,targets:n,meta:t.meta}))}},{name:"create_task",description:"Create a task, optionally attached to records, with a due date and an assignee.",inputSchema:{type:"object",properties:{title:{type:"string"},body:{type:"string"},dueAt:{type:"string",description:"ISO date or datetime."},assigneeId:{type:"string"},recordIds:{type:"array",items:{type:"string"}}},required:["title"]},mutating:!0,handler:async(e,t)=>Wo(await $w(e,{title:xn(t,"title"),body:typeof t.body=="string"?t.body:void 0,dueAt:typeof t.dueAt=="string"?t.dueAt:void 0,assigneeId:typeof t.assigneeId=="string"?t.assigneeId:void 0,targets:(t.recordIds??[]).map(n=>({object:"",id:n}))}))},{name:"complete_task",description:"Mark a task as done (or reopen it with done: false).",inputSchema:{type:"object",properties:{id:{type:"string"},done:{type:"boolean",default:!0}},required:["id"]},mutating:!0,handler:async(e,t)=>Wo(await Oc(e,xn(t,"id"),t.done!==!1))},{name:"list_tasks",description:"List tasks: open by default, optionally for one assignee / record, overdue only, or due within N days. Sorted by due date.",inputSchema:{type:"object",properties:{assigneeId:{type:"string"},recordId:{type:"string"},status:{type:"string",enum:["open","done","all"],default:"open"},overdue:{type:"boolean"},dueWithinDays:{type:"number"},limit:{type:"number",default:25,maximum:100}}},mutating:!1,handler:(e,t)=>{const n=Mw(e,{assigneeId:typeof t.assigneeId=="string"?t.assigneeId:void 0,target:typeof t.recordId=="string"?t.recordId:void 0,status:t.status??"open",overdue:t.overdue===!0,dueWithinDays:typeof t.dueWithinDays=="number"?t.dueWithinDays:void 0,limit:Math.min(100,hu(t,"limit",25))});return{total:n.total,tasks:n.items.map(Wo)}}},{name:"list_activities",description:"A record's timeline (notes, calls, emails, meetings, tasks), most recent first. includeRelated adds activities of linked records (e.g. a company's people and deals).",inputSchema:{type:"object",properties:{recordId:{type:"string"},types:{type:"array",items:{type:"string",enum:Xs}},includeRelated:{type:"boolean"},limit:{type:"number",default:20,maximum:100}}},mutating:!1,handler:(e,t)=>{const n=ul(e,{target:typeof t.recordId=="string"?t.recordId:void 0,types:t.types,includeRelated:t.includeRelated===!0,limit:Math.min(100,hu(t,"limit",20))});return{total:n.total,activities:n.items.map(Wo)}}},{name:"move_deal_stage",description:"Move a deal (or any pipeline record) to a stage, by stage id or label. Updates probability; lostReason for lost stages.",inputSchema:{type:"object",properties:{id:{type:"string"},stage:{type:"string"},lostReason:{type:"string"}},required:["id","stage"]},mutating:!0,handler:async(e,t)=>Zo(e,await Du(e,xn(t,"id"),xn(t,"stage"),{lostReason:typeof t.lostReason=="string"?t.lostReason:void 0}))},{name:"pipeline_summary",description:"Pipeline overview: per stage deal count, amount and weighted amount, plus open / weighted / won totals and open deals by close month.",inputSchema:{type:"object",properties:{pipelineId:{type:"string"},ownerId:{type:"string"}}},mutating:!1,handler:(e,t)=>({pipelines:_5(e).map(n=>({id:n.id,name:n.name})),...Cl(e,{pipelineId:typeof t.pipelineId=="string"?t.pipelineId:void 0,ownerId:typeof t.ownerId=="string"?t.ownerId:void 0})})},{name:"run_report",description:`Run a named report. Reports: ${Object.entries(mf).map(([e,t])=>`${e} (${t.description})`).join("; ")}`,inputSchema:{type:"object",properties:{name:{type:"string",enum:Object.keys(mf)},params:{type:"object",additionalProperties:!0,description:"Report parameters, e.g. { months: 6 } or { days: 30 }."}},required:["name"]},mutating:!1,handler:(e,t)=>aE(e,xn(t,"name"),t.params??{})},{name:"create_field",description:"Add a custom field to an object (admin only).",inputSchema:{type:"object",properties:{object:mu,label:{type:"string"},type:{type:"string",enum:af},options:{type:"array",items:{type:"string"},description:"Option labels for select / multiSelect."},relationObject:{type:"string",description:"Target object for relation fields."},cardinality:{type:"string",enum:["one","many"]},description:{type:"string"}},required:["object","label","type"]},mutating:!0,handler:(e,t)=>Fw(e,xn(t,"object"),{label:xn(t,"label"),type:xn(t,"type"),options:t.options,description:typeof t.description=="string"?t.description:void 0,...t.relationObject?{relation:{object:String(t.relationObject),cardinality:t.cardinality==="many"?"many":"one"}}:{}})},{name:"import_csv",description:"Import CSV text into an object. Columns are mapped to fields automatically (or via mapping {header: fieldId}); duplicates (people by email, companies by domain) are updated. Runs as a DRY RUN unless confirm is true — show the report to the user before confirming.",inputSchema:{type:"object",properties:{object:mu,csv:{type:"string"},mapping:{type:"object",additionalProperties:{type:"string"}},onDuplicate:{type:"string",enum:["update","skip","create"],default:"update"},confirm:{type:"boolean",default:!1}},required:["object","csv"]},mutating:!0,handler:async(e,t)=>{const n=await Zw(e,{object:xn(t,"object"),csv:String(t.csv??""),mapping:t.mapping,onDuplicate:t.onDuplicate??"update",dryRun:t.confirm!==!0});return{...n,rows:n.rows.slice(0,50),rowsTruncated:n.rows.length>50}}},..._9,...T9,...I9],Ac=new Map,nA=new Set,D9=/^[a-z][a-z0-9_]{1,63}$/;function Tv(e){if(!e||typeof e.name!="string"||!D9.test(e.name))throw new Error(`Invalid AI tool name "${String(e==null?void 0:e.name)}" (snake_case, ≤ 64 chars).`);if(typeof e.handler!="function")throw new Error(`AI tool "${e.name}" needs a handler.`);if(!e.inputSchema||e.inputSchema.type!=="object")throw new Error(`AI tool "${e.name}" needs an object inputSchema.`);if(bg.some(t=>t.name===e.name)||Ac.has(e.name))throw new Error(`AI tool "${e.name}" already exists.`);Ac.set(e.name,{...e,mutating:e.mutating!==!1});for(const t of[...nA])t();return()=>{if(Ac.delete(e.name))for(const t of[...nA])t()}}function Ok(){return Ac.size?[...bg,...Ac.values()]:bg}function Pk(e){return bg.find(t=>t.name===e)??Ac.get(e)}function Bu(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function Iv(e,t,n){const r=e.type===void 0?[]:Array.isArray(e.type)?e.type:[e.type];let s=t;if(r.length&&s!==null&&s!==void 0){const a=Bu(s),o=l=>l===a||l==="integer"&&a==="number"&&Number.isInteger(s);if(!r.some(o))if((r.includes("number")||r.includes("integer"))&&typeof s=="string"&&s.trim()!==""&&Number.isFinite(Number(s)))s=Number(s);else if(r.includes("boolean")&&(s==="true"||s==="false"))s=s==="true";else throw new he("validation",`${n} must be ${r.map(l=>l==="array"||l==="object"||l==="integer"?`an ${l}`:`a ${l}`).join(" or ")}, got ${a==="array"||a==="object"?`an ${a}`:`${a} ${JSON.stringify(s)}`.slice(0,80)}.`)}if(s==null)return s;if(e.enum&&!e.enum.includes(s))throw new he("validation",`${n} must be one of ${e.enum.map(a=>JSON.stringify(a)).join(", ")}, got ${JSON.stringify(s).slice(0,80)}.`);if(Array.isArray(s)&&e.items){const a=e.items;return s.map((o,l)=>Iv(a,o,`${n}[${l}]`))}if(Bu(s)==="object"&&(e.properties||e.required)){const a={...s};for(const o of e.required??[])if(a[o]===void 0||a[o]===null)throw new he("validation",`${n}: missing required "${o}".`);for(const[o,l]of Object.entries(e.properties??{}))a[o]!==void 0&&(a[o]=Iv(l,a[o],`${n}.${o}`));return a}return s}async function M9(e,t,n){const r=Pk(t);if(!r)throw new he("notFound",`Unknown tool "${t}". Tools: ${Ok().map(o=>o.name).join(", ")}.`);if(n!=null&&Bu(n)!=="object")throw new he("validation",`${t}: the input must be a JSON object, got ${Bu(n)==="array"?"an array":`a ${Bu(n)}`}.`);const s=n??{};for(const o of r.inputSchema.required??[])if(s[o]===void 0||s[o]===null)throw new he("validation",`${t}: missing required "${o}".`);const a=Iv({...r.inputSchema,required:[]},s,t);return r.handler(e,a)}function O9(e){return e}function P9(e){return e}function L9(e,t){l1(e,t)}function F9(){return S.useSyncExternalStore(zT,ng,ng)}function z9(e,t,n){return ki.addAction(e,t,n)}function U9(e,t){ki.removeAction(e,t)}function B9(e,t,n){return ki.addFilter(e,t,n)}function H9(e,t){ki.removeFilter(e,t)}function q9(e,...t){return ki.doAction(e,...t)}function V9(e,t,...n){return ki.applyFilters(e,t,...n)}function W9(e){return Tv(e)}const K9={apiVersion:b0,minApiVersion:O1,defineModule:O9,defineTheme:P9,ops:Cz,useCrm:ps,useOps:Xe,useCan:Ge,useCurrentUser:Ei,useCollection:mt,useObjects:un,useObject:gd,useRecords:Os,useRecord:Z1,useActivities:Ti,usePipelines:ms,useViews:tI,useUsers:sr,useSettings:di,useModuleConfig:Pz,useModuleEnabled:Cf,useAppearance:F9,useNavigate:dn,useParams:lo,useSearchParams:id,useLocation:ci,Link:Rn,NavLink:q_,paths:pt,recordHref:ip,addAction:z9,removeAction:U9,addFilter:B9,removeFilter:H9,doAction:q9,applyFilters:V9,registerAiTool:W9,registerAutomationAction:Jh,Button:ue,IconButton:dt,Input:Oe,Textarea:Cr,Select:Ve,Label:SI,FormField:Te,Checkbox:Ot,Switch:si,Modal:on,Drawer:cU,Card:Ke,Badge:tt,Avatar:$s,Tabs:bo,Tooltip:pU,Spinner:Ds,EmptyState:ut,PageHeader:Kr,Kbd:qr,Dropdown:Tr,Table:xo,THead:vo,TBody:wo,Tr:Vr,Th:_t,Td:bt,FieldValue:hp,FieldInput:hr,ObjectIcon:Mn,Markdown:vp,confirmDialog:qt,toast:ge,cn:ce,newId:Es,i18n:xt,addBundles:L9,activeLocale:f0,intlLocale:_r,formatFieldValue:_s,formatCurrency:Bf,formatNumber:$c,formatDate:Pw,formatDateTime:ti,formatRelative:eo,recordLabel:ct,coerceFieldValue:Uf,isEmptyFieldValue:vn};let sh=null;function G9(){const e=globalThis;if(sh&&e[cv]===sh)return sh;const t={apiVersion:b0,api:K9,modules:{react:h_,"react/jsx-runtime":GD,"react-dom":tM,"react-dom/client":sM,"react-i18next":FM},async prepare(n){if(n.includes("lucide-react")&&!t.modules["lucide-react"]){const r=await Sr(()=>import("./lucide-react.min-Djrg16BH.js").then(s=>s.l),[],import.meta.url);t.modules["lucide-react"]=r.default&&typeof r.default=="object"&&"createLucideIcon"in r.default?r.default:r}}};return e[cv]=t,sh=t,t}G9();function Ns(e){let t="";for(let r=0;r<e.length;r+=32768)t+=String.fromCharCode(...e.subarray(r,r+32768));return btoa(t)}function so(e){const t=atob(e.replace(/\s+/g,"")),n=new Uint8Array(t.length);for(let r=0;r<t.length;r++)n[r]=t.charCodeAt(r);return n}function J9(e){return Ns(new TextEncoder().encode(e))}function eR(e){return new TextDecoder().decode(so(e))}function Y9(e){return e.encoding==="base64"?so(e.content):new TextEncoder().encode(e.content)}function Lk(e,t="kv"){const n=new Map;let r=null;function s(){return r||(r=new Promise(o=>{try{if(typeof indexedDB>"u")return o(null);const l=indexedDB.open(e,1);l.onupgradeneeded=()=>l.result.createObjectStore(t),l.onsuccess=()=>o(l.result),l.onerror=()=>o(null),l.onblocked=()=>o(null)}catch{o(null)}})),r}function a(o,l){return s().then(d=>new Promise((f,p)=>{if(!d)return f(void 0);const m=d.transaction(t,o),h=l(m.objectStore(t));m.oncomplete=()=>f(h?h.result:void 0),m.onerror=()=>p(m.error),m.onabort=()=>p(m.error)}))}return{async get(o){return await s()?a("readonly",l=>l.get(o)):n.get(o)},async set(o,l){if(!await s())return void n.set(o,l);await a("readwrite",d=>void d.put(l,o))},async delete(o){if(!await s())return void n.delete(o);await a("readwrite",l=>void l.delete(o))},async keys(){return await s()?(await a("readonly",o=>o.getAllKeys())??[]).map(String):[...n.keys()]},async entries(){if(!await s())return[...n.entries()];const o=[];return await a("readonly",l=>{const d=l.openCursor();d.onsuccess=()=>{const f=d.result;f&&(o.push([String(f.key),f.value]),f.continue())}}),o},async clear(){if(!await s())return void n.clear();await a("readwrite",o=>void o.clear())}}}const za=Lk("agentcrm-site-mirror","files");function Z9(e){const t=(e.siteUrl??"").replace(/\/+$/,""),n=r=>r.replace(/^\/+/,"");return{id:"browser-mirror",model:"files",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0},async put(r){await za.set(n(r.path),{content:r.content,encoding:r.encoding==="base64"?"base64":"utf-8",updatedAt:Date.now()})},async get(r){const s=await za.get(n(r));if(!s)throw new Si(`File not found: ${r}`,404);return s.encoding==="base64"?eR(s.content):s.content},async getBytes(r){const s=await za.get(n(r));return s?s.encoding==="base64"?so(s.content):new TextEncoder().encode(s.content):null},delete:r=>za.delete(n(r)),async deletePrefix(r){const s=n(r).replace(/\/+$/,"")+"/";for(const a of await za.keys())a.startsWith(s)&&await za.delete(a)},async list(r,s){const a=(await za.keys()).sort().map(o=>({path:o,type:"file",url:t?`${t}/${o}`:`/${o}`}));return{items:a.slice((r-1)*s,r*s),page:r,per_page:s,total:a.length}},async listPrefix(r){const s=n(r);return(await za.keys()).filter(a=>a.startsWith(s)).sort()},async publicUrl(r){return t?`${t}/${n(r)}`:`/${n(r)}`}}}const Q9={id:"browser-mirror",create:Z9},X9="agentcrm-git-blobs",Tf="texts",Rv=new Map;let ih=null;function tR(){return ih||(ih=new Promise(e=>{try{if(typeof indexedDB>"u")return e(null);const t=indexedDB.open(X9,1);t.onupgradeneeded=()=>t.result.createObjectStore(Tf),t.onsuccess=()=>e(t.result),t.onerror=()=>e(null),t.onblocked=()=>e(null)}catch{e(null)}}),ih)}async function nR(e){const t=new Map,n=[];for(const s of e){const a=Rv.get(s);a!==void 0?t.set(s,a):n.push(s)}if(n.length===0)return t;const r=await tR();return r&&await new Promise(s=>{try{const a=r.transaction(Tf,"readonly"),o=a.objectStore(Tf);for(const l of n){const d=o.get(l);d.onsuccess=()=>{typeof d.result=="string"&&(t.set(l,d.result),Rv.set(l,d.result))}}a.oncomplete=()=>s(),a.onerror=()=>s(),a.onabort=()=>s()}catch{s()}}),t}async function rR(e){for(const[n,r]of e)Rv.set(n,r);const t=await tR();!t||e.size===0||await new Promise(n=>{try{const r=t.transaction(Tf,"readwrite"),s=r.objectStore(Tf);for(const[a,o]of e)s.put(o,a);r.oncomplete=()=>n(),r.onerror=()=>n(),r.onabort=()=>n()}catch{n()}})}class nl extends Error{constructor(t,n){super(t),this.currentHeadSha=n,this.name="GitConflictError"}}const rA=300,sA=50,eB=3;function tB(e){const t=(e.apiBaseUrl||"https://api.github.com").replace(/\/+$/,""),n=t.endsWith("/api/v3")?t.replace(/\/api\/v3$/,"/api/graphql"):`${t}/graphql`,r=`${t}/repos/${encodeURIComponent(e.owner)}/${encodeURIComponent(e.repo)}`,s=`heads/${e.branch.split("/").map(encodeURIComponent).join("/")}`,a={Authorization:`Bearer ${e.token}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28"},o={...a,"Content-Type":"application/json"};async function l(_,D="get"){return await(await Ys(D,_,{headers:a,cache:"no-store"})).json()}async function d(_,D,I="POST"){return await(await Ys("commit",_,{method:I,headers:o,body:JSON.stringify(D)})).json()}async function f(){var I;const _=await Ys("get",`${r}/git/ref/${s}`,{headers:a,cache:"no-store"},[404,409]);if(!_.ok)return"";const D=await _.json();return Array.isArray(D)?"":((I=D.object)==null?void 0:I.sha)??""}async function p(_){return(await l(`${r}/git/commits/${_}`)).tree.sha}async function m(_,D,I){const T=await l(`${r}/git/trees/${_}`,"list");for(const E of T.tree){const P=D+E.path;E.type==="blob"?I.push({path:P,sha:E.sha,size:E.size}):E.type==="tree"&&await m(E.sha,P+"/",I)}}async function h(_){if(!_)return{headSha:"",entries:[]};const D=await p(_),I=await l(`${r}/git/trees/${D}?recursive=1`,"list");if(!I.truncated)return{headSha:_,entries:I.tree.filter(E=>E.type==="blob").map(E=>({path:E.path,sha:E.sha,size:E.size}))};const T=[];return await m(D,"",T),{headSha:_,entries:T}}async function b(_){return(await l(`${r}/git/blobs/${_}`)).content}async function x(_){var I;const D=new Map;for(let T=0;T<_.length;T+=sA){const E=_.slice(T,T+sA),U=`query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { ${E.map((O,z)=>`b${z}: object(oid: "${O}") { ... on Blob { text isBinary isTruncated } }`).join(`
1131
1131
  `)} } }`;try{const O=await fetch(n,{method:"POST",headers:o,body:JSON.stringify({query:U,variables:{owner:e.owner,name:e.repo}})});if(!O.ok)continue;const R=(I=(await O.json()).data)==null?void 0:I.repository;if(!R)continue;E.forEach((V,X)=>{const Q=R[`b${X}`];Q&&!Q.isBinary&&!Q.isTruncated&&typeof Q.text=="string"&&D.set(V,Q.text)})}catch{}}return D}async function y(_){const D=[...new Set(_.map(U=>U.sha))],I=await nR(D),T=D.filter(U=>!I.has(U)),E=new Map;if(T.length>0){const U=await x(T);for(const[z,R]of U)E.set(z,R);const O=T.filter(z=>!E.has(z));await ml(O,6,async z=>{E.set(z,eR(await b(z)))}),await rR(E)}const P=new Map;for(const U of _){const O=I.get(U.sha)??E.get(U.sha);O!==void 0&&P.set(U.path,O)}return P}async function v(_){return so(await b(_.sha))}async function k(_){const D=await l(r),I=D.default_branch?await Ys("get",`${r}/git/ref/heads/${encodeURIComponent(D.default_branch)}`,{headers:a,cache:"no-store"},[404,409]):null;if(!I||!I.ok)return(await d(`${r}/contents/.gitkeep`,{message:_,content:"",branch:e.branch},"PUT")).commit.sha;const T=await d(`${r}/git/trees`,{tree:[{path:".gitkeep",mode:"100644",type:"blob",content:""}]}),E=await d(`${r}/git/commits`,{message:_,tree:T.sha,parents:[]});return await d(`${r}/git/refs`,{ref:`refs/heads/${e.branch}`,sha:E.sha}),E.sha}async function j(_,D){const I=new Map;for(let T=0;;T++){let E=await f();if(D.expectedHeadSha!==void 0&&E!==D.expectedHeadSha)throw new nl(`Branch ${e.branch} moved`,E);E||(E=await k("Initialize branch — AgentCRM"));for(const X of _)if(X.type==="put"&&X.encoding==="base64"&&!I.has(X.path)){const Q=await d(`${r}/git/blobs`,{content:X.content,encoding:"base64"});I.set(X.path,Q.sha)}const P=await p(E);let U=null;_.some(X=>X.type==="delete")&&(U=new Set((await h(E)).entries.map(X=>X.path)));const O=[];for(const X of _)X.type==="delete"?U!=null&&U.has(X.path)&&O.push({path:X.path,mode:"100644",type:"blob",sha:null}):X.encoding==="base64"?O.push({path:X.path,mode:"100644",type:"blob",sha:I.get(X.path)}):O.push({path:X.path,mode:"100644",type:"blob",content:X.content});let z=P;for(let X=0;X<O.length;X+=rA)z=(await d(`${r}/git/trees`,{base_tree:z,tree:O.slice(X,X+rA)})).sha;if(z===P)return E;const R=await d(`${r}/git/commits`,{message:D.message,tree:z,parents:[E]});if((await Ys("commit",`${r}/git/refs/${s}`,{method:"PATCH",headers:o,body:JSON.stringify({sha:R.sha,force:!1})},[409,422])).ok)return R.sha;if(D.expectedHeadSha!==void 0)throw new nl(`Branch ${e.branch} moved`,await f());if(T>=eB)throw new nl(`Branch ${e.branch} kept moving`,await f())}}async function C(_,D){const I=[];for(const U of _){const O=await d(`${r}/git/blobs`,{content:U.content,encoding:"base64"});I.push({path:U.path,mode:"100644",type:"blob",sha:O.sha})}const T=await d(`${r}/git/trees`,{tree:I}),E=await d(`${r}/git/commits`,{message:D.message,tree:T.sha,parents:[]}),P=await f();if(P!==D.expectedHeadSha)throw new nl(`Branch ${e.branch} moved`,P);return await Ys("commit",`${r}/git/refs/${s}`,{method:"PATCH",headers:o,body:JSON.stringify({sha:E.sha,force:!0})}),E.sha}async function A(){const[_,D]=await Promise.all([l(`${t}/user`),l(r)]),I=D.permissions??{},T=D.visibility==="public"||D.visibility==="private"||D.visibility==="internal"?D.visibility:typeof D.private=="boolean"?D.private?"private":"public":void 0;return{login:_.login,canWrite:!!(I.push||I.maintain||I.admin),isAdmin:!!(I.admin||I.maintain),visibility:T}}return{kind:"github",label:`${e.owner}/${e.repo}@${e.branch}`,headSha:f,listTree:async()=>h(await f()),readTexts:y,readBytes:v,commit:j,permissions:A,resetBranch:C}}const nB=3,rB=30,sB=40;function iB(e){const t=(e.apiBaseUrl||"https://gitlab.com/api/v4").replace(/\/+$/,""),n=`${t}/projects/${encodeURIComponent(e.project)}`,r={Authorization:`Bearer ${e.token}`},s={...r,"Content-Type":"application/json"},a=new Map;async function o(v,k="get"){return await(await Ys(k,v,{headers:r,cache:"no-store"})).json()}async function l(){var j;const v=await Ys("get",`${n}/repository/branches/${encodeURIComponent(e.branch)}`,{headers:r,cache:"no-store"},[404]);return v.ok?((j=(await v.json()).commit)==null?void 0:j.id)??"":""}async function d(v){if(!v)return{headSha:"",entries:[]};const k=[];for(let j=1;;j++){const C=`${n}/repository/tree?${new URLSearchParams({ref:v,recursive:"true",per_page:"100",page:String(j)})}`,A=await Ys("list",C,{headers:r,cache:"no-store"}),_=await A.json();for(const I of _)I.type==="blob"&&k.push({path:I.path,sha:I.id});if(!A.headers.get("x-next-page")||_.length===0)break}return a.set(v,new Set(k.map(j=>j.path))),{headSha:v,entries:k}}async function f(v){return Ys("get",`${n}/repository/blobs/${v}/raw`,{headers:r})}async function p(v){const k=[...new Set(v.map(D=>D.sha))],j=await nR(k),C=k.filter(D=>!j.has(D)),A=new Map;await ml(C,6,async D=>{A.set(D,await(await f(D)).text())}),await rR(A);const _=new Map;for(const D of v){const I=j.get(D.sha)??A.get(D.sha);I!==void 0&&_.set(D.path,I)}return _}async function m(v){return new Uint8Array(await(await f(v.sha)).arrayBuffer())}async function h(v){return v?a.get(v)??new Set((await d(v)).entries.map(k=>k.path)):new Set}async function b(){return(await o(n)).default_branch||void 0}async function x(v,k){for(let j=0;;j++){const C=await l();if(k.expectedHeadSha!==void 0&&C!==k.expectedHeadSha)throw new nl(`Branch ${e.branch} moved`,C);const A=await h(C),_=[],D=new Set(A);for(const E of v)if(E.type==="delete"){if(!A.has(E.path))continue;_.push({action:"delete",file_path:E.path}),D.delete(E.path)}else _.push({action:A.has(E.path)?"update":"create",file_path:E.path,encoding:"base64",content:E.encoding==="base64"?E.content:J9(E.content)}),D.add(E.path);if(_.length===0)return C;const I={branch:e.branch,commit_message:k.message,actions:_};if(!C){const E=await b();E&&E!==e.branch&&(I.start_branch=E)}const T=await Ys("commit",`${n}/repository/commits`,{method:"POST",headers:s,body:JSON.stringify(I)},[400]);if(T.ok){const E=await T.json();return a.set(E.id,D),E.id}if(a.delete(C),k.expectedHeadSha!==void 0||j>=nB)throw new nl(`Commit on ${e.branch} rejected: ${await T.text()}`,await l())}}async function y(){var _,D,I,T;const[v,k]=await Promise.all([o(`${t}/user`),o(n)]),j=Math.max(((D=(_=k.permissions)==null?void 0:_.project_access)==null?void 0:D.access_level)??0,((T=(I=k.permissions)==null?void 0:I.group_access)==null?void 0:T.access_level)??0),C=k.visibility,A=C==="public"||C==="private"||C==="internal"?C:void 0;return{login:v.username,canWrite:j>=rB,isAdmin:j>=sB,visibility:A}}return{kind:"gitlab",label:`${e.project}@${e.branch}`,headSha:l,listTree:async()=>d(await l()),readTexts:p,readBytes:m,commit:x,permissions:y}}const aB=new Set([".git","node_modules",".DS_Store","Thumbs.db"]);function oB(){return typeof window<"u"&&"showDirectoryPicker"in window}async function Fk(){const e=window.showDirectoryPicker;return e({mode:"readwrite",id:"agentcrm"})}async function wp(e,t){var s;const n=e,r={mode:"readwrite"};return await((s=n.queryPermission)==null?void 0:s.call(n,r))==="granted"?!0:!t||!n.requestPermission?!1:await n.requestPermission(r)==="granted"}function lB(e){let t=2166136261;for(const n of e){const r=`${n.path}\0${n.sha}
1132
1132
  `;for(let s=0;s<r.length;s++)t^=r.charCodeAt(s),t=Math.imul(t,16777619)}return`local-${e.length}-${(t>>>0).toString(16)}`}function cB(e){const t=e,n=new Map;async function r(m,h,b){for await(const[x,y]of m.entries()){if(aB.has(x))continue;const v=h+x;if(y.kind==="directory")await r(y,v+"/",b);else{const k=await y.getFile();n.set(v,y),b.push({path:v,sha:`${k.size}:${k.lastModified}`,size:k.size})}}}async function s(){n.clear();const m=[];return await r(t,"",m),m.sort((h,b)=>h.path<b.path?-1:h.path>b.path?1:0),{headSha:lB(m),entries:m}}async function a(m){const h=n.get(m);if(h)return h;const b=m.split("/");let x=t;for(const y of b.slice(0,-1))x=await x.getDirectoryHandle(y);return x.getFileHandle(b[b.length-1])}async function o(m){const h=new Map;for(const b of m)try{h.set(b.path,await(await(await a(b.path)).getFile()).text())}catch{}return h}async function l(m){const h=await(await a(m.path)).getFile();return new Uint8Array(await h.arrayBuffer())}async function d(m,h){const b=m.split("/");let x=t;for(const k of b.slice(0,-1))x=await x.getDirectoryHandle(k,{create:!0});const y=await x.getFileHandle(b[b.length-1],{create:!0}),v=await y.createWritable();await v.write(h),await v.close(),n.set(m,y)}async function f(m){const h=m.split("/");try{let b=t;for(const x of h.slice(0,-1))b=await b.getDirectoryHandle(x);await b.removeEntry(h[h.length-1])}catch{}n.delete(m)}async function p(m,h){if(h.expectedHeadSha!==void 0){const b=(await s()).headSha;if(b!==h.expectedHeadSha)throw new nl("Folder changed on disk",b)}for(const b of m)b.type==="delete"?await f(b.path):await d(b.path,Y9(b));return(await s()).headSha}return{kind:"local",label:t.name,headSha:async()=>(await s()).headSha,listTree:s,readTexts:o,readBytes:l,commit:p,permissions:async()=>({login:"local",canWrite:await wp(e,!1),isAdmin:!0})}}const dB="agentcrm-folder-handles",If="handles";function sR(){return new Promise((e,t)=>{const n=indexedDB.open(dB,1);n.onupgradeneeded=()=>n.result.createObjectStore(If),n.onsuccess=()=>e(n.result),n.onerror=()=>t(n.error)})}async function zk(e,t){const n=await sR();await new Promise((r,s)=>{const a=n.transaction(If,"readwrite");a.objectStore(If).put(t,e),a.oncomplete=()=>r(),a.onerror=()=>s(a.error)})}async function O0(e){try{const t=await sR();return await new Promise(n=>{const r=t.transaction(If,"readonly").objectStore(If).get(e);r.onsuccess=()=>n(r.result??null),r.onerror=()=>n(null)})}catch{return null}}function Uk(e){return e.provider==="github"?tB(e):iB(e)}function uB(e,t){const n=e.replace(/^\/+|\/+$/g,""),r=t.replace(/^\/+/,"");return n?`${n}/${r}`:r}function fB(e,t){return["# Generated by AgentCRM — publishes the static files with GitLab Pages.","# Safe to edit: AgentCRM only creates this file when the repo has none.","pages:"," stage: deploy"," script:",e==="public"?' - echo "Publishing public/"':` - rm -rf public && cp -r ${e} public`," artifacts:"," paths:"," - public"," rules:",` - if: $CI_COMMIT_BRANCH == "${t}"`,""].join(`
1133
1133
  `)}function iR(e){if(e.token)return e.token;const t=mr();return(t==null?void 0:t.backend)==="git-json"&&t.git.provider===e.provider?Ww(t.git)??"":""}const iA=new Map;function pB(e,t,n){const r=`${e.owner}/${e.repo}`;let s=iA.get(r);return s||(s=mB(e,t,n,r),iA.set(r,s)),s}async function mB(e,t,n,r){const a=`${(e.apiBaseUrl||"https://api.github.com").replace(/\/+$/,"")}/repos/${encodeURIComponent(e.owner??"")}/${encodeURIComponent(e.repo??"")}/pages`,o={Authorization:`Bearer ${t}`,Accept:"application/vnd.github+json"};try{if((await fetch(a,{headers:o,cache:"no-store"})).ok)return;if((await fetch(a,{method:"POST",headers:{...o,"Content-Type":"application/json"},body:JSON.stringify({source:{branch:e.branch,path:n==="docs"?"/docs":"/"}})})).ok){ge.success(xt.t("connectors.pages.enabled"));return}}catch{}ge.info(xt.t("connectors.pages.enableHint",{repo:r,branch:e.branch,folder:n==="docs"?"/docs":"/ (root)"}))}function hB(e){const t=iR(e);let n=String(e.dir??"").replace(/^\/+|\/+$/g,"");e.host==="gitlab-pages"&&!n&&(n="public");const r=Uk(e.provider==="github"?{provider:"github",owner:e.owner??"",repo:e.repo??"",branch:e.branch,token:t,apiBaseUrl:e.apiBaseUrl}:{provider:"gitlab",project:e.project??"",branch:e.branch,token:t,apiBaseUrl:e.apiBaseUrl}),s=(e.siteUrl??"").replace(/\/+$/,""),a=h=>uB(n,h),o=h=>n?h.slice(n.length+1):h,l=h=>!n||h.startsWith(n+"/");let d=null;async function f(){const h=await r.headSha();if(d&&d.head===h)return d;const b=await r.listTree();return d={head:b.headSha,files:new Map(b.entries.map(x=>[x.path,x]))},d}function p(h){if(e.host==="github-pages"){const b=a(".nojekyll");return h.has(b)?[]:[{type:"put",path:b,content:""}]}return e.host==="gitlab-pages"?h.has(".gitlab-ci.yml")?[]:[{type:"put",path:".gitlab-ci.yml",content:fB(n,e.branch)}]:[]}async function m(h){const{files:b}=await f(),x=[];let y=0;for(const A of h)if(A.type==="deletePrefix"){const _=a(A.path)+"/";for(const D of b.keys())D.startsWith(_)&&x.push({type:"delete",path:D})}else A.type==="delete"?b.has(a(A.path))&&x.push({type:"delete",path:a(A.path)}):(x.push({type:"put",path:a(A.path),content:A.content,encoding:A.encoding}),y++);x.push(...p(b));const v=x.filter(A=>A.type==="delete").length,k=[y&&`${y} updated`,v&&`${v} removed`].filter(Boolean).join(", "),j=e.branch==="agentcrm-data"||!e.host?" [skip ci]":"",C=e.host?"Publish files":"Update data";await r.commit(x,{message:`${C}${k?` (${k})`:""} — AgentCRM${j}`}),d=null,e.host==="github-pages"&&e.provider==="github"&&pB(e,t,n)}return{id:"git-pages",model:"commit",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0},put:h=>m([{type:"put",...h}]),delete:h=>m([{type:"delete",path:h}]),deletePrefix:h=>m([{type:"deletePrefix",path:h}]),commitBatch:m,async get(h){const{files:b}=await f(),x=b.get(a(h));if(!x)throw new Si(`File not found: ${h}`,404);const v=(await r.readTexts([x])).get(x.path);if(v===void 0)throw new Si(`File not found: ${h}`,404);return v},async getBytes(h){const{files:b}=await f(),x=b.get(a(h));return x?r.readBytes(x):null},async list(h,b){const{files:x}=await f(),y=[...x.values()].filter(v=>l(v.path)).map(v=>({path:o(v.path),type:"file",size:v.size,url:`${s}/${o(v.path)}`})).sort((v,k)=>v.path<k.path?-1:1);return{items:y.slice((h-1)*b,h*b),page:h,per_page:b,total:y.length}},async listPrefix(h){const{files:b}=await f(),x=a(h.replace(/^\/+/,""));return[...b.keys()].filter(y=>l(y)&&y.startsWith(x)).map(o).sort((y,v)=>y<v?-1:y>v?1:0)},async publicUrl(h){return`${s}/${h.replace(/^\/+/,"")}`}}}const gB={id:"git-pages",create:hB},yB="publish-target";function bB(e){const t=(e.siteUrl??"").replace(/\/+$/,"");let n=null;async function r(){if(n)return n;const a=await O0(e.handleKey||yB);if(!a||!await wp(a,!1)){const o=xt.t("storage.errors.folderAccess");throw ge.error(o),new Si(o,403)}return n=cB(a),n}async function s(a){return(await(await r()).listTree()).entries.find(l=>l.path===a.replace(/^\/+/,""))}return{id:"local-folder",model:"files",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0},async put(a){await(await r()).commit([{type:"put",...a,path:a.path.replace(/^\/+/,"")}],{message:""})},async get(a){const o=await s(a),l=o?(await(await r()).readTexts([o])).get(o.path):void 0;if(l===void 0)throw new Si(`File not found: ${a}`,404);return l},async getBytes(a){const o=await s(a);return o?(await r()).readBytes(o):null},async delete(a){await(await r()).commit([{type:"delete",path:a.replace(/^\/+/,"")}],{message:""})},async deletePrefix(a){const o=await r(),l=a.replace(/^\/+|\/+$/g,"")+"/",d=(await o.listTree()).entries.filter(f=>f.path.startsWith(l));await o.commit(d.map(f=>({type:"delete",path:f.path})),{message:""})},async list(a,o){const l=(await(await r()).listTree()).entries.map(d=>({path:d.path,type:"file",size:d.size,url:t?`${t}/${d.path}`:`/${d.path}`}));return{items:l.slice((a-1)*o,a*o),page:a,per_page:o,total:l.length}},async listPrefix(a){const o=a.replace(/^\/+/,"");return(await(await r()).listTree()).entries.map(l=>l.path).filter(l=>l.startsWith(o))},async publicUrl(a){const o=a.replace(/^\/+/,"");return t?`${t}/${o}`:`/${o}`}}}const xB={id:"local-folder",create:bB},vB={html:"text/html; charset=utf-8",htm:"text/html; charset=utf-8",css:"text/css; charset=utf-8",js:"text/javascript; charset=utf-8",mjs:"text/javascript; charset=utf-8",json:"application/json; charset=utf-8",webmanifest:"application/manifest+json; charset=utf-8",xml:"application/xml; charset=utf-8",xsl:"application/xslt+xml; charset=utf-8",txt:"text/plain; charset=utf-8",md:"text/markdown; charset=utf-8",svg:"image/svg+xml",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",avif:"image/avif",ico:"image/x-icon",pdf:"application/pdf",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf",mp4:"video/mp4",webm:"video/webm",mp3:"audio/mpeg",zip:"application/zip"};function wB(e){var n;const t=((n=e.split(".").pop())==null?void 0:n.toLowerCase())??"";return vB[t]??"application/octet-stream"}function kB(e){return/\.(html?|json|xml|xsl|txt|css|js|mjs|webmanifest)$/i.test(e)?"no-cache":"public, max-age=86400"}const Bk=new TextEncoder;function aR(e){return[...new Uint8Array(e)].map(t=>t.toString(16).padStart(2,"0")).join("")}async function jB(e){return aR(await crypto.subtle.digest("SHA-256",Bk.encode(e)))}async function gu(e,t){const n=await crypto.subtle.importKey("raw",e,{name:"HMAC",hash:"SHA-256"},!1,["sign"]);return crypto.subtle.sign("HMAC",n,Bk.encode(t))}function xg(e){return encodeURIComponent(e).replace(/[!'()*]/g,t=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`)}function SB(e){const t=e.toISOString().replace(/[:-]|\.\d{3}/g,"");return{amzDate:t,dateStamp:t.slice(0,8)}}async function aA(e){const t=new URL(e.url),{amzDate:n,dateStamp:r}=SB(e.date??new Date),s={...e.headers,"x-amz-date":n},a={host:t.host};for(const[C,A]of Object.entries(s))a[C.toLowerCase()]=String(A).trim().replace(/\s+/g," ");const o=Object.keys(a).sort(),l=o.map(C=>`${C}:${a[C]}
@@ -1136,8 +1136,8 @@ ${(d==null?void 0:d.name)??""}`;return{draft:{to:s.slice(0,10),subject:p,body:m}
1136
1136
  `);let k=await gu(Bk.encode(`AWS4${h}`),r);k=await gu(k,b),k=await gu(k,x),k=await gu(k,"aws4_request");const j=aR(await gu(k,v));return{...s,Authorization:`AWS4-HMAC-SHA256 Credential=${m}/${y}, SignedHeaders=${d}, Signature=${j}`}}const ah="UNSIGNED-PAYLOAD";function oh(e){return e.split("/").map(xg).join("/")}function oA(e){return e.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&amp;/g,"&")}function CB(e){const t=(e.endpoint||`https://s3.${e.region}.amazonaws.com`).replace(/\/+$/,"");let n;try{n=new URL(t)}catch{throw new Si(`Invalid S3 endpoint: ${t}`,400)}const s=e.forcePathStyle??!n.hostname.endsWith("amazonaws.com")?`${t}/${xg(e.bucket)}`:`${n.protocol}//${e.bucket}.${n.host}`,a=(e.prefix??"").replace(/^\/+|\/+$/g,""),o=(e.siteUrl??"").replace(/\/+$/,""),l={accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey,region:e.region||"us-east-1",service:"s3"},d=b=>a?`${a}/${b.replace(/^\/+/,"")}`:b.replace(/^\/+/,""),f=b=>a?b.slice(a.length+1):b;async function p(b,x,y,v={}){const k=await aA({method:x,url:y,headers:{"x-amz-content-sha256":ah,...v.headers??{}},payloadHash:ah,credentials:l});return Pu(b,()=>fetch(y,{method:x,headers:k,body:v.body,signal:v.signal,cache:v.cache}))}async function m(b){var v,k,j;const x=[];let y;do{const C=new URLSearchParams({"list-type":"2","max-keys":"1000"});b&&C.set("prefix",b),y&&C.set("continuation-token",y);const _=await(await p("list","GET",`${s}/?${C}`,{cache:"no-store"})).text();for(const I of _.match(/<Contents>[\s\S]*?<\/Contents>/g)??[]){const T=(v=I.match(/<Key>([\s\S]*?)<\/Key>/))==null?void 0:v[1],E=Number(((k=I.match(/<Size>(\d+)<\/Size>/))==null?void 0:k[1])??0);T&&x.push({key:oA(T),size:E})}y=/<IsTruncated>true<\/IsTruncated>/.test(_)?oA(((j=_.match(/<NextContinuationToken>([\s\S]*?)<\/NextContinuationToken>/))==null?void 0:j[1])??""):void 0}while(y);return x}async function h(b,x){try{await p("delete","DELETE",`${s}/${oh(b)}`,{signal:x})}catch(y){if(y instanceof Si&&y.status===404)return;throw y}}return{id:"s3",model:"files",capabilities:{list:!0,rename:!1,renameFolder:!1,folders:!1,deletePrefix:!0},async put(b,x){const y=b.encoding==="base64"?so(b.content):b.content;await p("upload","PUT",`${s}/${oh(d(b.path))}`,{headers:{"content-type":wB(b.path),"cache-control":kB(b.path),...e.publicRead?{"x-amz-acl":"public-read"}:{}},body:y,signal:x})},async get(b){return(await p("get","GET",`${s}/${oh(d(b))}`,{cache:"no-store"})).text()},async getBytes(b){const x=`${s}/${oh(d(b))}`,y=await aA({method:"GET",url:x,headers:{"x-amz-content-sha256":ah},payloadHash:ah,credentials:l}),v=await fetch(x,{headers:y,cache:"no-store"}).catch(j=>Pu("get",()=>Promise.reject(j)));if(v.status===404||v.status===403)return null;const k=v.ok?v:await Pu("get",async()=>v);return new Uint8Array(await k.arrayBuffer())},delete:(b,x)=>h(d(b),x),async deletePrefix(b){const x=await m(d(b).replace(/\/+$/,"")+"/");await ml(x,6,y=>h(y.key))},async list(b,x){const y=(await m(a?`${a}/`:"")).map(v=>({path:f(v.key),type:"file",size:v.size,url:`${o}/${f(v.key)}`}));return{items:y.slice((b-1)*x,b*x),page:b,per_page:x,total:y.length}},async listPrefix(b){const x=b.replace(/^\/+/,"");return(await m(d(x))).map(y=>f(y.key)).sort((y,v)=>y<v?-1:y>v?1:0)},async publicUrl(b){return`${o}/${b.replace(/^\/+/,"")}`}}}const NB={id:"s3",create:CB};let oR=async()=>null;function Hk(e){oR=e,Ss=null}function AB(){return oR()}const _B="browser-mirror";let Ss=null;const EB=new Map([gB,NB,Q9,xB].map(e=>[e.id,e]));function TB(e){return typeof e.create=="function"}function IB(){return _B}function ko(e,t){const n=EB.get(e);if(!n)throw new Si(xt.t("storage.errors.unknownConnector",{connector:e}),501);return TB(n)?n.create(t):n}async function RB(){let e=null;try{e=await AB()}catch(n){console.warn("[storage] could not read storage config, using the default target:",n)}const t=(e==null?void 0:e.connectorId)??IB();try{return ko(t,(e==null?void 0:e.settings)??{})}catch(n){throw ge.error(n.message),n}}async function P0(){if(!Ss){const e=RB();Ss={id:"",connector:e},e.then(t=>{(Ss==null?void 0:Ss.connector)===e&&(Ss.id=t.id)},()=>{(Ss==null?void 0:Ss.connector)===e&&(Ss=null)})}return Ss.connector}const $B=36**4-1,DB=24*36e5;function lA(e){return`${String(Math.floor(e.wall)).padStart(13,"0")}-${e.counter.toString(36).padStart(4,"0")}-${e.node}`}function MB(e){const t=/^(\d{13})-([0-9a-z]{4})-(.+)$/.exec(e);if(!t)throw new Error(`Invalid HLC timestamp "${e}"`);return{wall:Number(t[1]),counter:parseInt(t[2],36),node:t[3]}}function OB(e,t){return e?t?e>t?e:t:e:t}function PB(e,t=Date.now){if(!/^[0-9a-z]+$/i.test(e))throw new Error(`Invalid HLC node id "${e}"`);let n={wall:0,counter:0,node:e},r=!1;function s(a,o){o>$B?n={wall:a+1,counter:0,node:e}:n={wall:a,counter:o,node:e}}return{node:e,now(){const a=t();return a>n.wall?s(a,0):s(n.wall,n.counter+1),r=!0,lA(n)},receive(a){const o=MB(a),l=t();o.wall>l+DB||(o.wall>n.wall?s(o.wall,o.counter+1):o.wall===n.wall&&o.counter>=n.counter&&s(n.wall,o.counter+1),r=!0)},last(){return r?lA(n):""}}}const wi=new TextEncoder().encode("ACRMENC1"),Rf=wi.length+4+16+12,qk=6e5;class Yc extends Error{constructor(t){super(t==="missing"?"This data is encrypted: enter its passphrase.":"Wrong passphrase: the data could not be decrypted."),this.reason=t,this.name="PassphraseError"}}function Vk(e){return!!e&&e.length>=Rf&&wi.every((t,n)=>e[n]===t)}const cx=new Map;function LB(e){return[...e].map(t=>t.toString(16).padStart(2,"0")).join("")}function lR(e,t,n){const r=`${n}:${LB(t)}:${e}`;let s=cx.get(r);return s||(s=(async()=>{const a=await crypto.subtle.importKey("raw",new TextEncoder().encode(e.normalize("NFC")),"PBKDF2",!1,["deriveKey"]);return crypto.subtle.deriveKey({name:"PBKDF2",hash:"SHA-256",salt:t,iterations:n},a,{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])})(),s.catch(()=>cx.delete(r)),cx.set(r,s)),s}function Wk(e=qk){return{salt:crypto.getRandomValues(new Uint8Array(16)),iterations:e}}function FB(e){return{iterations:new DataView(e.buffer,e.byteOffset,e.byteLength).getUint32(wi.length),salt:e.slice(wi.length+4,wi.length+20)}}async function Kk(e,t,n){if(!t)throw new Yc("missing");const{salt:r,iterations:s}=n??Wk(),a=crypto.getRandomValues(new Uint8Array(12)),o=await lR(t,r,s),l=new Uint8Array(await crypto.subtle.encrypt({name:"AES-GCM",iv:a},o,e)),d=new Uint8Array(Rf+l.length);return d.set(wi,0),new DataView(d.buffer).setUint32(wi.length,s),d.set(r,wi.length+4),d.set(a,wi.length+20),d.set(l,Rf),d}async function Gk(e,t){if(!t)throw new Yc("missing");if(!Vk(e))throw new Error("Not an AgentCRM encrypted file (bad magic).");const{salt:n,iterations:r}=FB(e),s=e.slice(wi.length+20,Rf),a=await lR(t,n,r);try{return new Uint8Array(await crypto.subtle.decrypt({name:"AES-GCM",iv:s},a,e.slice(Rf)))}catch{throw new Yc("wrong")}}async function cR(e,t,n){return Kk(new TextEncoder().encode(e),t,n)}async function dR(e,t){return new TextDecoder().decode(await Gk(e,t))}function zB(){const e="abcdefghjkmnpqrstuvwxyz23456789",n=[...crypto.getRandomValues(new Uint8Array(30))].map(r=>e[r%e.length]);return Array.from({length:6},(r,s)=>n.slice(s*5,s*5+5).join("")).join("-")}function Jk(e){return!!e&&typeof e=="object"&&!Array.isArray(e)&&Object.getPrototypeOf(e)===Object.prototype}function L0(e){return e.split(".").filter(Boolean)}function Yk(e,t,n){if(t.length===0)return e;const[r,...s]=t,a={...e};if(s.length===0)return n===void 0?delete a[r]:a[r]=n,a;const o=Jk(a[r])?a[r]:{};return a[r]=Yk(o,s,n),a}function Sae(e,t){let n=e;for(const r of t){if(!Jk(n))return;n=n[r]}return n}function UB(e,t){let n={...e};for(const[r,s]of Object.entries(t)){const a=L0(r);a[0]!=="id"&&(n=Yk(n,a,s))}return n}function Zc(e){if(Array.isArray(e))return Object.freeze(e.map(Zc));if(Jk(e)){const t={};for(const[n,r]of Object.entries(e))r!==void 0&&(t[n]=Zc(r));return Object.freeze(t)}return e}function BB(e){return e===void 0?e:JSON.parse(JSON.stringify(e))}function $f(){return Object.fromEntries(In.map(e=>[e,new Map]))}function uR(e){return Object.fromEntries(In.map(t=>[t,new Map(e[t]??[])]))}function HB(e){const t=$f();for(const n of In)for(const r of e[n]??[])t[n].set(r.id,Zc(r));return t}function qB(e,t){const n=uR(e),r=new Set;for(const s of t)if(s.op==="set")n[s.collection].set(s.doc.id,Zc(s.doc)),r.add(s.collection);else if(s.op==="patch"){const a=n[s.collection].get(s.id);if(!a)continue;n[s.collection].set(s.id,Zc(UB(a,s.fields))),r.add(s.collection)}else n[s.collection].delete(s.id)&&r.add(s.collection);return{next:n,changed:r}}function VB(e,t){const n=new Set;for(const r of In){if(e[r].size!==t[r].size){n.add(r);continue}for(const[s,a]of e[r]){const o=t[r].get(s);if(o!==a&&(!o||JSON.stringify(o)!==JSON.stringify(a))){n.add(r);break}}}return n}function fR(e){return e.op==="set"?e.doc.id:e.id}function WB(e){for(const t of e){if(!In.includes(t.collection))throw new Error(`Unknown collection "${t.collection}".`);const n=fR(t);if(typeof n!="string"||!n)throw new Error(`Mutation on ${t.collection} without an id.`)}}function Zk(e){let t=$f(),n=null,r=!1,s=Promise.resolve(),a=0;const o=new Set;let l=null,d=null,f=!1;function p(k){if(k.size!==0)for(const j of[...o])try{j(k)}catch(C){console.error("[datastore] listener failed:",C)}}function m(k){if(a>0)return;const j=VB(t,k);t=k,p(j)}function h(){return n||(n=e.load().then(k=>{t=k,r=!0,p(new Set(In))},k=>{throw n=null,k})),n}async function b(){if(await h(),!e.poll||a>0)return;const k=await e.poll();k&&m(k)}function x(){var k;f||(e.watch&&!d&&(d=e.watch(j=>{h().then(()=>m(j))})),e.poll&&!l&&(l=setInterval(()=>{b().catch(j=>console.warn("[datastore] poll failed:",j))},e.pollIntervalMs??3e4),(k=l.unref)==null||k.call(l)))}function y(){l&&clearInterval(l),l=null,d==null||d(),d=null}const v={kind:e.kind,ready:h,refresh:b,identity:()=>e.identity(),list(k){var j;return[...((j=t[k])==null?void 0:j.values())??[]]},get(k,j){var C;return(C=t[k])==null?void 0:C.get(j)},async write(k,j){if(r||await h(),k.length===0)return;WB(k);const C=t,{next:A,changed:_}=qB(C,k);t=A,p(_),a++;const D=s.then(()=>e.persist(k,C,A,(j==null?void 0:j.message)??"Update data"));s=D.catch(()=>{});try{await D}catch(I){const T=uR(t);for(const E of k){const P=fR(E),U=C[E.collection].get(P);U?T[E.collection].set(P,U):T[E.collection].delete(P)}throw t=T,p(_),I}finally{a--}},subscribe(k){return o.add(k),x(),()=>{o.delete(k),o.size===0&&y()}},close(){var k;f=!0,y(),o.clear(),(k=e.close)==null||k.call(e)}};return e.compact&&(v.compact=async()=>{await h(),await s;const k=await e.compact(t);k&&m(k)}),v}function KB(e){const{connector:t,folder:n}=e,r=o=>`${n}${o}.bin`;async function s(o){const l=await e.key();return l?Kk(o,l.passphrase,l.params):o}const a=async(o,l)=>{sl(o);const d=await s(l);await t.put({path:r(o),content:Ns(d),encoding:"base64"})};return{kind:"journal",put:a,async putMany(o){for(const l of o)await a(l.id,l.bytes)},async get(o){sl(o);const l=await t.getBytes(r(o));return l?Vk(l)?Gk(l,e.passphrase()):l:null},async delete(o){sl(o),await t.delete(r(o))},async list(){return t.listPrefix?(await t.listPrefix(n)).filter(o=>o.endsWith(".bin")).map(o=>o.slice(n.length,-4)).filter(o=>!o.includes("/")):[]}}}const cA=[31,139];function pR(){return typeof CompressionStream<"u"&&typeof DecompressionStream<"u"}async function mR(){return await import("node:zlib")}async function hR(e,t){const n=new Blob([e]).stream().pipeThrough(t);return new Uint8Array(await new Response(n).arrayBuffer())}async function GB(e){return pR()?hR(e,new CompressionStream("gzip")):new Uint8Array((await mR()).gzipSync(e))}async function JB(e){return pR()?hR(e,new DecompressionStream("gzip")):new Uint8Array((await mR()).gunzipSync(e))}function YB(e){return e.length>2&&e[0]===cA[0]&&e[1]===cA[1]}async function vg(e,t){const n=await GB(new TextEncoder().encode(JSON.stringify(e)));return t?Kk(n,t.passphrase,t.params):n}async function wg(e,t){let n=e;return Vk(n)&&(n=await Gk(n,t)),YB(n)&&(n=await JB(n)),JSON.parse(new TextDecoder().decode(n))}function $v(){return Object.fromEntries(In.map(e=>[e,new Map]))}function ZB(e,t){return e.op==="set"?{t,op:"set",c:e.collection,doc:e.doc}:e.op==="delete"?{t,op:"delete",c:e.collection,id:e.id}:{t,op:"patch",c:e.collection,id:e.id,f:Object.entries(e.fields).filter(([n])=>L0(n)[0]!=="id").map(([n,r])=>r===void 0?[n]:[n,r])}}function gR(e,t,n){let r=e[t].get(n);return r||(r={e:{}},e[t].set(n,r)),r}function QB(e,t){return e.length>t.length&&e.startsWith(t)&&e[t.length]==="."}function Qk(e,t,n){if(e.reset&&n.t<e.reset)return!1;const r=L0(t);for(let s=1;s<=r.length;s++){const a=e.e[r.slice(0,s).join(".")];if(a&&(s===r.length?a.t>=n.t:a.t>n.t))return!1}for(const s of Object.keys(e.e))QB(s,t)&&e.e[s].t<n.t&&delete e.e[s];return e.e[t]=n,!0}function XB(e,t,n){if(e.reset&&e.reset>=t)return!1;e.reset=t;for(const[r,s]of Object.entries(e.e))s.t<t&&delete e.e[r];for(const[r,s]of Object.entries(n))r==="id"||s===void 0||Qk(e,r,{t,v:s});return!0}function eH(e,t){if(!e[t.c])return!1;const n=t.op==="set"?t.doc.id:t.id;if(typeof n!="string"||!n)return!1;const r=gR(e,t.c,n);if(t.op==="set")return XB(r,t.t,t.doc);if(t.op==="delete")return r.del&&r.del>=t.t?!1:(r.del=t.t,!0);let s=!1;for(const a of t.f){const o=a.length===1?{t:t.t,u:1}:{t:t.t,v:a[1]};Qk(r,a[0],o)&&(s=!0)}return s}function tH(e,t){const n=new Set;for(const r of In)for(const[s,a]of t[r]??[]){const o=gR(e,r,s);let l=!1;if(a.reset&&(!o.reset||a.reset>o.reset)){o.reset=a.reset;for(const[d,f]of Object.entries(o.e))f.t<a.reset&&delete o.e[d];l=!0}a.del&&(!o.del||a.del>o.del)&&(o.del=a.del,l=!0);for(const[d,f]of Object.entries(a.e).sort((p,m)=>p[1].t<m[1].t?-1:1))Qk(o,d,f)&&(l=!0);l&&n.add(`${r}/${s}`)}return n}function yR(e){return!!e.reset&&(!e.del||e.reset>e.del)}function dx(e,t){if(!yR(t))return null;let n={};const r=Object.entries(t.e).sort((s,a)=>s[1].t<a[1].t?-1:s[1].t>a[1].t?1:s[0].length-a[0].length);for(const[s,a]of r)n=Yk(n,L0(s),a.u?void 0:a.v);return n.id=e,Zc(n)}function nH(e){let t="";for(const n of In)for(const r of e[n].values()){r.reset&&r.reset>t&&(t=r.reset),r.del&&r.del>t&&(t=r.del);for(const s of Object.values(r.e))s.t>t&&(t=s.t)}return t}function rH(e){let t=0;for(const n of In)for(const[r,s]of e[n])yR(s)||((Object.keys(s.e).length||s.reset)&&t++,s.del?e[n].set(r,{del:s.del,e:{}}):e[n].delete(r));return t}function bR(e){const t={};for(const n of In)e[n].size!==0&&(t[n]=Object.fromEntries(e[n]));return t}function xR(e){const t=$v();for(const n of In)for(const[r,s]of Object.entries((e==null?void 0:e[n])??{}))t[n].set(r,{...s.reset?{reset:s.reset}:{},...s.del?{del:s.del}:{},e:{...s.e??{}}});return t}function sH(e){return xR(JSON.parse(JSON.stringify(bR(e))))}const kg="agentcrm-journal",Ch=1,iH=2e4,dA="agentcrm-keycheck";function uA(){return[...crypto.getRandomValues(new Uint8Array(6))].map(t=>(t%36).toString(36)).join("")+Date.now().toString(36).slice(-2)}function lh(e,t){const n=e.replace(/^\/+|\/+$/g,"");return n?`${n}/${t}`:t}function vR(e){const t=e.connector;if(!t.listPrefix)throw new Error(`The "${t.id}" storage can't list files: it can't hold a journal dataset.`);if(!t.getBytes)throw new Error(`The "${t.id}" storage can't read binary files: it can't hold a journal dataset.`);const n=t.listPrefix.bind(t),r=t.getBytes.bind(t),s=(e.clientId??uA()).toLowerCase().replace(/[^0-9a-z]/g,"")||uA(),a=PB(s,e.wallClock),o={keyinfo:lh(e.root,"keyinfo.json"),snapshot:lh(e.root,"snapshot.bin"),journal:lh(e.root,"journal/"),files:lh(e.root,"files/")},l=E=>`${o.journal}${E}`;let d=null,f=null,p=$v();const m=new Set;let h=new Set,b=$f();function x(){return(typeof e.passphrase=="function"?e.passphrase():e.passphrase)??null}async function y(E){const P=await r(E);return P?new TextDecoder().decode(P):null}async function v(){const E=await y(o.keyinfo);if(E){const O=JSON.parse(E);if(O.format!==kg)throw new Error(`${o.keyinfo} is not an AgentCRM journal key file.`);d=O}if(!(d?d.encrypted:e.encrypted!==!1)){f=null;return}const U=x();if(!U)throw new Yc("missing");if(d!=null&&d.kdf){const O={salt:so(d.kdf.salt),iterations:d.kdf.iterations};if(d.check&&await dR(so(d.check),U)!==dA)throw new Yc("wrong");f={passphrase:U,params:O}}else f={passphrase:U,params:Wk(e.iterations??qk)}}async function k(){if(d)return;const E={format:kg,version:Ch,encrypted:!!f,createdAt:Date.now()};f&&(E.kdf={name:"PBKDF2-SHA256",iterations:f.params.iterations,salt:Ns(f.params.salt)},E.check=Ns(await cR(dA,f.passphrase,f.params))),await t.put({path:o.keyinfo,content:JSON.stringify(E,null,2)+`
1137
1137
  `}),d=E}async function j(){const E=await r(o.snapshot);if(!E)return null;const P=await wg(E,x());if(P.format!=="agentcrm-snapshot")throw new Error(`${o.snapshot} is not an AgentCRM snapshot.`);return P}function C(E){if(!E)return new Set;E.hlc&&a.receive(E.hlc),h=new Set(E.applied);for(const P of E.applied)m.add(P);return tH(p,xR(E.state))}function A(E,P,U){for(const O of P.ops??[])In.includes(O.c)&&(a.receive(O.t),eH(p,O)&&U.add(`${O.c}/${O.op==="set"?O.doc.id:O.id}`));m.add(E)}async function _(E){const P=new Set,U=(await n(o.journal)).filter(z=>z.endsWith(".bin")).map(z=>z.slice(o.journal.length));if(E)for(const z of C(await j()))P.add(z);let O=U.filter(z=>!m.has(z)).sort();for(let z=0;O.length&&z<3;z++){const R=[],V=await ml(O,6,async X=>{const Q=await r(l(X));return Q?{name:X,seg:await wg(Q,x())}:(R.push(X),null)});for(const X of V)X&&A(X.name,X.seg,P);if(!R.length)break;for(const X of C(await j()))P.add(X);O=R.filter(X=>!m.has(X))}return P}function D(E){const P=$f();for(const U of In)if(E===null)for(const[O,z]of p[U]){const R=dx(O,z);R&&P[U].set(O,R)}else for(const[O,z]of b[U])P[U].set(O,z);if(E)for(const U of E){const O=U.indexOf("/"),z=U.slice(0,O),R=U.slice(O+1),V=p[z].get(R),X=V?dx(R,V):null;X?P[z].set(R,X):P[z].delete(R)}return b=P,P}const T=Zk({kind:"journal",pollIntervalMs:e.pollIntervalMs??iH,async load(){return await v(),p=$v(),m.clear(),await _(!0),D(null)},async persist(E,P,U,O){const z=E.filter(J=>J.op!=="patch"||P[J.collection].has(J.id));if(z.length===0)return;const R=z.map(J=>ZB(J,a.now())),V=`${R[0].t}.bin`,X={format:"agentcrm-segment",version:Ch,client:s,message:O,ops:R};await k();const Q=await vg(X,f);await t.put({path:l(V),content:Ns(Q),encoding:"base64"});const ee=new Set;A(V,X,ee),D(ee)},async poll(){const E=await _(!1);return E.size?D(E):null},async identity(){return e.identity===void 0?{uid:"owner",email:"",displayName:"Owner",role:"admin"}:e.identity},async compact(){await _(!0);const E=sH(p);rH(E);const P=(await n(o.journal)).filter(R=>R.endsWith(".bin")).map(R=>R.slice(o.journal.length)).filter(R=>m.has(R)),U=`${s}-${a.now()}`,O={format:"agentcrm-snapshot",version:Ch,hlc:OB(a.last(),nH(E))??"",applied:P.sort(),compactionId:U,createdAt:Date.now(),createdBy:s,state:bR(E)};await k(),await t.put({path:o.snapshot,content:Ns(await vg(O,f)),encoding:"base64"});const z=await j();return(z==null?void 0:z.compactionId)===U&&await ml(P,4,R=>t.delete(l(R))),p=E,h=new Set(P),D(null)}});return Object.defineProperty(T,"clientId",{value:s}),i1(T,KB({connector:t,folder:o.files,async key(){return!d&&!f&&await v(),await k(),f},passphrase:x})),T.stats=async()=>{const E=(await n(o.journal)).filter(O=>O.endsWith(".bin"));let P=0,U=0;for(const O of In)for(const z of p[O].values())dx("x",z)?P++:U++;return{segments:E.length,pendingSegments:E.filter(O=>!h.has(O.slice(o.journal.length))).length,snapshotSegments:h.size,documents:P,tombstones:U}},T}const wR="agentcrm-keycheck";function mc(e,t){const n=e.replace(/^\/+|\/+$/g,"");return n?`${n}/${t}`:t}async function kR(e,t){var s;const n=await((s=e.getBytes)==null?void 0:s.call(e,mc(t,"keyinfo.json")));if(!n)return null;const r=JSON.parse(new TextDecoder().decode(n));return r.format===kg?r:null}async function aH(e){var y,v,k,j,C,A,_;const{connector:t,root:n}=e;if(!t.getBytes||!t.listPrefix)throw new Error(`The "${t.id}" storage can't hold a journal dataset.`);const r=((y=e.newPassphrase)==null?void 0:y.trim())||null,s=await kR(t,n);if(!s)throw new Error("No AgentCRM dataset at this location.");(v=e.onProgress)==null||v.call(e,"compact");const a=vR({connector:t,root:n,encrypted:s.encrypted,passphrase:e.oldPassphrase,pollIntervalMs:36e5});try{await a.ready(),await a.compact()}finally{(k=a.close)==null||k.call(a)}const o=s.encrypted?e.oldPassphrase:null;if(s.encrypted&&!o)throw new Yc("missing");const l=r?{passphrase:r,params:Wk(e.iterations??qk)}:null;(j=e.onProgress)==null||j.call(e,"segments");const d=mc(n,"journal/");for(const D of(await t.listPrefix(d)).filter(I=>I.endsWith(".bin"))){const I=await t.getBytes(D);if(!I)continue;const T=await wg(I,o);await t.put({path:D,content:Ns(await vg(T,l)),encoding:"base64"})}(C=e.onProgress)==null||C.call(e,"snapshot");const f=mc(n,"snapshot.bin"),p=mc(n,"keyinfo.json"),m=await t.getBytes(f),h=mc(n,"keyinfo.json.rekey-backup"),b=mc(n,"snapshot.bin.rekey-backup");if(await t.put({path:h,content:JSON.stringify(s,null,2)+`
1138
1138
  `}),m){await t.put({path:b,content:Ns(m),encoding:"base64"});const D=await wg(m,o);await t.put({path:f,content:Ns(await vg(D,l)),encoding:"base64"})}(A=e.onProgress)==null||A.call(e,"keyinfo");const x={format:kg,version:Ch,encrypted:!!l,createdAt:s.createdAt??Date.now()};return l&&(x.kdf={name:"PBKDF2-SHA256",iterations:l.params.iterations,salt:Ns(l.params.salt)},x.check=Ns(await cR(wR,l.passphrase,l.params))),await t.put({path:p,content:JSON.stringify(x,null,2)+`
1139
- `}),await t.delete(h),m&&await t.delete(b),(_=e.onProgress)==null||_.call(e,"done"),{encrypted:!!l}}async function Xk(e,t,n){const r=await kR(e,t);if(!r)return{exists:!1,encrypted:!1,ok:!0};if(!r.encrypted)return{exists:!0,encrypted:!1,ok:!0};if(!n||!r.check)return{exists:!0,encrypted:!0,ok:!r.check&&!!n};try{return{exists:!0,encrypted:!0,ok:await dR(so(r.check),n)===wR}}catch{return{exists:!0,encrypted:!0,ok:!1}}}const jR={s3:["accessKeyId","secretAccessKey"],"git-pages":["token"],"local-folder":[],"browser-mirror":[]},oH="data-folder";async function SR(e,t){const n=(jR[e]??[]).filter(r=>typeof t[r]!="string"||!t[r].trim());if(e==="local-folder"){if(typeof indexedDB>"u")return n;const r=await O0(typeof t.handleKey=="string"&&t.handleKey?t.handleKey:oH);(!r||!await wp(r,!1).catch(()=>!1))&&n.push("folder")}return n}const lH="agentcrm-local-files";function cH(e={}){const t=Lk(e.dbName??lH,"files");return{kind:"local",async put(n,r){sl(n),await t.set(n,new Uint8Array(r))},async putMany(n){for(const r of n)sl(r.id),await t.set(r.id,new Uint8Array(r.bytes))},async get(n){const r=await t.get(n);return r?r instanceof Uint8Array?r:new Uint8Array(r):null},async delete(n){await t.delete(n)},async list(){return(await t.keys()).sort()}}}const dH="agentcrm-local-data",uH=(e,t)=>`${e}/${t}`;function fH(e={}){const t=Lk(e.dbName??dH,"docs"),n=Zk({kind:"local",async load(){const r=$f();for(const[s,a]of await t.entries()){const o=s.slice(0,s.indexOf("/"));tL(o)&&r[o].set(a.id,Object.freeze(a))}return r},async persist(r,s,a){const o=new Map;for(const l of r){const d=l.op==="set"?l.doc.id:l.id;o.set(uH(l.collection,d),{collection:l.collection,id:d})}for(const[l,{collection:d,id:f}]of o){const p=a[d].get(f);p?await t.set(l,BB(p)):await t.delete(l)}},async identity(){return{uid:"local",email:"admin@localhost",displayName:"Local admin",role:"admin"}}});return i1(n,cH({dbName:e.filesDbName}))}function pH(e={}){const t=Zk({kind:"memory",async load(){return HB(e.initial??{})},async persist(){var r;const n=(r=e.failNextWrite)==null?void 0:r.call(e);if(n)throw n},async identity(){return e.identity===void 0?{uid:"local",email:"admin@localhost",displayName:"Admin",role:"admin"}:e.identity}});return i1(t,ML(e.blobs))}const CR=new Map;function kp(e,t){CR.set(e,t)}function mH(e){return CR.get(e)}kp("local",()=>fH());kp("memory",()=>pH());kp("journal",(e,t)=>{const n=e.journal,r={...n.settings,...t.secrets??{}},s=ko(n.connectorId,r),a=vR({connector:s,root:n.root,encrypted:n.encrypted,passphrase:t.passphrase,clientId:t.clientId,pollIntervalMs:t.pollIntervalMs}),o=a.identity.bind(a);return a.identity=async()=>(await SR(n.connectorId,r)).length?null:o(),a});kp("firebase",async(e,t)=>(await Sr(async()=>{const{createFirebaseStore:n}=await import("./firebase-C1x_l9P9.js");return{createFirebaseStore:n}},[],import.meta.url)).createFirebaseStore(e,t));kp("git-json",async(e,t)=>(await Sr(async()=>{const{createGitJsonStore:n}=await import("./gitJson-CAUSxl8d.js");return{createGitJsonStore:n}},[],import.meta.url)).createGitJsonStore(e,t));async function NR(e,t={}){const n=mH(e.backend);if(!n)throw new Error(`Unknown data backend "${e.backend}".`);return n(e,t)}function hH(e){return{secrets:pl(e),passphrase:()=>Zf(e)}}let jr=null;function Dv(){const e=mr();if(!e)return Promise.reject(new Error("AgentCRM is not configured yet."));if(!jr||jr.config!==e){jr==null||jr.store.then(n=>{var r;return(r=n.close)==null?void 0:r.call(n)}).catch(()=>{});const t=NR(e,hH(e));jr={config:e,store:t},t.catch(()=>{(jr==null?void 0:jr.store)===t&&(jr=null)})}return jr.store}function jp(){jr==null||jr.store.then(e=>{var t;return(t=e.close)==null?void 0:t.call(e)}).catch(()=>{}),jr=null}const gH=new Set(["local","owner"]),fA={viewer:0,member:1,admin:2};function pA(e,t,n){return e.kind!=="git-json"?n:fA[t.role]<fA[n.role]?{...n,role:t.role}:n}function AR(e,t){if(!t)return null;const n=e.list("users"),r=n.find(a=>a.id===t.uid);if(r)return pA(e,t,r);const s=St(t.email);if(s){const a=n.find(o=>St(o.email)===s);if(a)return pA(e,t,a)}if(gH.has(t.uid)){const a=e.get("settings","general"),l=(a!=null&&a.ownerUserId?n.find(d=>d.id===a.ownerUserId):void 0)??n.find(d=>d.role==="admin"&&!d.disabled);if(l)return l}return{id:t.uid,email:t.email,name:t.displayName||t.email||"Owner",role:t.role}}const _R=new Map;function Cae(e,t){_R.set(e,t)}function yH(e){return _R.get(e)}const ER=S.createContext(null);function bH({backend:e,identity:t,user:n,onSignOut:r,children:s}){const a=S.useMemo(()=>({backend:e,identity:t,user:n,role:n.role,isAdmin:n.role==="admin",canSignOut:e!=="local",signOut:r}),[e,t,n,r]);return i.jsx(ER.Provider,{value:a,children:s})}function Oi(){const e=S.useContext(ER);if(!e)throw new Error("useAuth must be used inside <AuthProvider>");return e}function TR(){return S.useSyncExternalStore(zT,ng,ng)}function xH(){return TR(),jz()}const ta=typeof EventTarget<"u"?new EventTarget:null;function gr(e,t){ta==null||ta.dispatchEvent(new CustomEvent(e,{detail:t}))}function vH(e,t){const n=r=>t(r.detail);return ta==null||ta.addEventListener(e,n),()=>ta==null?void 0:ta.removeEventListener(e,n)}function Qa(e,t){const n=S.useRef(t);n.current=t,S.useEffect(()=>vH(e,r=>n.current(r)),[e])}const wH="agentcrm.theme";function kH(){return typeof document<"u"&&document.documentElement.classList.contains("dark")?"dark":"light"}function mA(e){document.documentElement.classList.toggle("dark",e==="dark");try{localStorage.setItem(wH,e)}catch{}window.dispatchEvent(new CustomEvent("agentcrm:theme",{detail:e}))}function IR(){const[e,t]=S.useState(kH);S.useEffect(()=>{const r=s=>t(s.detail);return window.addEventListener("agentcrm:theme",r),()=>window.removeEventListener("agentcrm:theme",r)},[]);const n=S.useCallback(r=>mA(r),[]);return{theme:e,setTheme:n,toggle:()=>mA(e==="dark"?"light":"dark")}}const RR="agentcrm.sidebarCollapsed";function jH(){try{return localStorage.getItem(RR)==="1"}catch{return!1}}function SH(e,t){return e.flatMap(n=>n.navItems??[]).filter(n=>!n.roles||n.roles.includes(t)).sort((n,r)=>(n.order??100)-(r.order??100))}function $R({to:e,icon:t,label:n,collapsed:r,badge:s,end:a}){return i.jsxs(q_,{to:e,end:a,title:r?n:void 0,className:({isActive:o})=>ce("group flex h-7 items-center gap-2 rounded-md px-2 text-[13px] font-medium transition-colors",o?"bg-surface-200/70 text-surface-900 dark:bg-surface-800 dark:text-white":"text-surface-600 hover:bg-surface-100 hover:text-surface-900 dark:text-surface-400 dark:hover:bg-surface-800/60 dark:hover:text-surface-100",r&&"justify-center px-0"),children:[i.jsx("span",{className:"flex h-4 w-4 shrink-0 items-center justify-center [&>svg]:h-4 [&>svg]:w-4",children:t}),!r&&i.jsx("span",{className:"min-w-0 flex-1 truncate",children:n}),!r&&s?i.jsx("span",{className:"rounded bg-surface-200 px-1 text-2xs text-surface-600 dark:bg-surface-700 dark:text-surface-300",children:s}):null]})}function ux({item:e,collapsed:t}){var a;const{t:n}=oe(),r=((a=e.useBadge)==null?void 0:a.call(e))??null,s=e.icon;return i.jsx($R,{to:e.to,icon:i.jsx(s,{}),label:n(e.label),collapsed:t,badge:r,end:e.to==="/"})}function fx({title:e,collapsed:t,children:n}){return i.jsxs("div",{className:"space-y-px",children:[e&&!t&&i.jsx("div",{className:"px-2 pb-1 pt-3 text-2xs font-medium uppercase tracking-wide text-surface-400",children:e}),e&&t&&i.jsx("div",{className:"mx-2 my-2 h-px bg-surface-200 dark:bg-surface-800"}),n]})}function CH(){const{t:e}=oe(),{user:t}=Oi(),n=un(),r=di(),s=Y1(),a=TR(),o=a.sidebar,[l,d]=S.useState(jH);S.useEffect(()=>{try{localStorage.setItem(RR,l?"1":"0")}catch{}},[l]);const f=SH(s,t.role),p=m=>f.filter(h=>(h.section??"main")===m);return i.jsxs("aside",{"data-sidebar":o,className:ce("flex h-full shrink-0 flex-col border-r transition-[width] duration-150",o==="default"?"border-surface-200 bg-surface-50 dark:border-surface-800 dark:bg-surface-900":"dark border-surface-800 bg-surface-900 [color-scheme:dark]",o==="accent"&&"acrm-sidebar-accent",l?"w-[52px]":"w-[220px]"),children:[i.jsxs("div",{className:ce("flex h-12 shrink-0 items-center gap-2 px-3",l&&"justify-center px-0"),children:[a.logo?i.jsx("img",{src:a.logo,alt:"",className:"h-6 w-6 shrink-0 rounded-md object-contain","data-testid":"workspace-logo"}):i.jsx("span",{className:"flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-surface-900 text-xs font-bold text-white dark:bg-white dark:text-surface-900",children:(r.name||"A").slice(0,1).toUpperCase()}),!l&&i.jsx("span",{className:"min-w-0 flex-1 truncate text-sm font-semibold text-surface-900 dark:text-white",children:r.name})]}),i.jsx("div",{className:"px-2 pb-1",children:i.jsxs("button",{type:"button",onClick:()=>gr("search.open"),title:l?e("topbar.search"):void 0,className:ce("flex h-7 w-full items-center gap-2 rounded-md px-2 text-[13px] text-surface-500 hover:bg-surface-100 dark:hover:bg-surface-800",l&&"justify-center px-0"),children:[i.jsx(Wr,{className:"h-4 w-4 shrink-0"}),!l&&i.jsxs(i.Fragment,{children:[i.jsx("span",{className:"flex-1 text-left",children:e("topbar.search")}),i.jsx(qr,{children:"⌘K"})]})]})}),i.jsxs("nav",{className:"min-h-0 flex-1 overflow-y-auto px-2 pb-2",children:[i.jsx(fx,{collapsed:l,children:p("main").map(m=>i.jsx(ux,{item:m,collapsed:l},m.id))}),i.jsx(fx,{title:e("nav.objects"),collapsed:l,children:n.map(m=>i.jsx($R,{to:pt.objectList(m.id),icon:i.jsx(Mn,{name:m.icon,color:m.color,tile:!0}),label:m.labelPlural,collapsed:l},m.id))}),p("workspace").length>0&&i.jsx(fx,{title:e("nav.workspace"),collapsed:l,children:p("workspace").map(m=>i.jsx(ux,{item:m,collapsed:l},m.id))})]}),i.jsxs("div",{className:"border-t border-surface-200 px-2 py-2 dark:border-surface-800",children:[p("bottom").map(m=>i.jsx(ux,{item:m,collapsed:l},m.id)),i.jsxs("button",{type:"button",onClick:()=>d(m=>!m),className:ce("mt-px flex h-7 w-full items-center gap-2 rounded-md px-2 text-[13px] text-surface-500 hover:bg-surface-100 dark:hover:bg-surface-800",l&&"justify-center px-0"),title:e(l?"nav.expand":"nav.collapse"),children:[l?i.jsx(i8,{className:"h-4 w-4"}):i.jsx(s8,{className:"h-4 w-4"}),!l&&i.jsx("span",{children:e("nav.collapse")})]})]})]})}function NH(){const{t:e,i18n:t}=oe(),{theme:n,toggle:r}=IR(),s=Oi(),a=il("topBar"),o=f0();return t.language,i.jsxs("header",{className:"flex h-12 shrink-0 items-center gap-2 border-b border-surface-200 bg-white px-4 dark:border-surface-800 dark:bg-surface-950",children:[i.jsxs("button",{type:"button",onClick:()=>gr("search.open"),className:"flex h-8 w-full max-w-sm items-center gap-2 rounded-md border border-surface-200 bg-surface-50 px-2.5 text-sm text-surface-400 hover:border-surface-300 dark:border-surface-800 dark:bg-surface-900 dark:hover:border-surface-700",children:[i.jsx(Wr,{className:"h-4 w-4"}),i.jsx("span",{className:"flex-1 text-left",children:e("topbar.search")}),i.jsx(qr,{children:"⌘K"})]}),i.jsxs("div",{className:"ml-auto flex items-center gap-1",children:[a.map((l,d)=>i.jsx(l,{},d)),i.jsx(dt,{label:e(n==="dark"?"topbar.lightMode":"topbar.darkMode"),icon:n==="dark"?i.jsx(yk,{}):i.jsx(ck,{}),onClick:r}),i.jsx(Tr,{align:"end",trigger:({ref:l,onClick:d})=>i.jsx(dt,{ref:l,label:e("topbar.language"),icon:i.jsx(pI,{}),onClick:d}),items:u0.map(l=>({id:l,label:o1[l],checked:l===o,onSelect:()=>void c1(l)}))}),i.jsx(Tr,{align:"end",header:i.jsxs("div",{className:"min-w-0",children:[i.jsx("div",{className:"truncate text-sm font-medium text-surface-900 dark:text-white",children:s.user.name}),i.jsx("div",{className:"truncate text-xs text-surface-500",children:s.user.email}),i.jsx("div",{className:"mt-0.5 text-2xs text-surface-400",children:e("topbar.role",{role:e(`roles.${s.role}`)})})]}),trigger:({ref:l,onClick:d})=>i.jsx("button",{ref:l,type:"button",onClick:d,"aria-label":e("topbar.userMenu"),className:"ml-1 rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500/60",children:i.jsx($s,{name:s.user.name,src:s.user.avatarUrl,size:"md"})}),items:[{id:"settings",label:e("nav.settings"),onSelect:()=>window.location.hash=`#${pt.settings()}`},...s.canSignOut?[{id:"signout",label:e("topbar.signOut"),icon:i.jsx(_0,{}),separator:!0,onSelect:()=>void s.signOut()}]:[]]})]})]})}function AH({children:e,banner:t}){const n=ci(),r=il("globalOverlays");return S.useEffect(()=>{const s=a=>{(a.metaKey||a.ctrlKey)&&a.key.toLowerCase()==="k"&&(a.preventDefault(),gr("search.open"))};return window.addEventListener("keydown",s),()=>window.removeEventListener("keydown",s)},[]),i.jsxs("div",{className:"flex h-screen w-full overflow-hidden bg-white text-surface-900 dark:bg-surface-950 dark:text-surface-100",children:[i.jsx(CH,{}),i.jsxs("div",{className:"flex min-w-0 flex-1 flex-col",children:[t,i.jsx(NH,{}),i.jsx("main",{className:"relative min-h-0 flex-1 overflow-auto",children:e},n.pathname.split("/").slice(0,3).join("/"))]}),r.map((s,a)=>i.jsx(s,{},a))]})}function _H(){const e=lp("appearance"),t=mt("extensions"),n=S.useSyncExternalStore(FT,tg,tg);S.useEffect(()=>{const r=e==null?void 0:e.themeId,a=!!r&&t.some(o=>o.id===r&&o.kind==="theme"&&o.enabled)?rp(r)??null:null;UT(q1(e,a),{theme:a})},[e,t,n])}const vl=new Map,Mv=new Set;let DR=[];function ej(){DR=[...vl.values()].map(e=>e.state).sort((e,t)=>e.id.localeCompare(t.id));for(const e of[...Mv])e()}function Ov(){return DR}function hA(e){var t;return(t=vl.get(e))==null?void 0:t.state}function EH(e){return Mv.add(e),()=>Mv.delete(e)}function ch(e,t,n){const r=vl.get(e.id);r&&r.dispose(),vl.set(e.id,{state:{id:e.id,kind:e.kind,version:e.manifest.version,status:t,...n?{error:n}:{}},dispose:()=>{}}),ej()}function MR(e){const t=vl.get(e);if(t){vl.delete(e);try{t.dispose()}catch(n){console.error(`[extensions] dispose of ${e} failed:`,n)}ej()}}function TH(e){const t=e,n=t&&typeof t=="object"&&"default"in t?t.default:null;return n&&typeof n=="object"?n:null}function IH(e,t){if(!t)throw new Error("bundle.js has no default export (export default defineModule({...}) / defineTheme({...})).");if(t.id!==e.id)throw new Error(`bundle id "${String(t.id)}" doesn't match manifest id "${e.id}".`);if(!pd(t.apiVersion))throw new Error(`bundle apiVersion "${String(t.apiVersion)}" is not supported.`)}function RH(e,t){if(!t||typeof document>"u")return()=>{};const n=document.createElement("style");return n.dataset.agentcrmExtension=e,n.textContent=t,document.head.appendChild(n),()=>n.remove()}function $H(e,t){var s;const n=[],r=a=>(n.push(a),a);try{const a=e.manifest,o={routes:[],i18n:{en:{}},...t.feature??{},id:e.id,module:{name:a.name,description:a.description,icon:a.icon??"Puzzle",category:a.category??"customisation",...(s=a.dependsOn)!=null&&s.length?{dependsOn:a.dependsOn}:{}},...t.settingsPage?{settingsPage:t.settingsPage}:{}};r(Tz(o));for(const l of t.aiTools??[])r(Tv(l));for(const l of t.automationActions??[])r(Jh(l));if(r(RH(e.id,e.files["style.css"])),typeof t.register=="function"){const l={moduleId:e.id,addAction:((f,p,m)=>r(ki.addAction(f,p,m))),addFilter:(f,p,m)=>r(ki.addFilter(f,p,m)),registerAiTool:f=>r(Tv(f)),registerAutomationAction:f=>r(Jh(f)),onDispose:f=>void n.push(f)},d=t.register(l);typeof d=="function"&&n.push(d)}}catch(a){for(const o of n.reverse())o();throw a}return()=>{for(const a of n.reverse())try{a()}catch(o){console.error(`[extensions] cleanup of ${e.id} failed:`,o)}}}function DH(e,t){if(!t.appearance||typeof t.appearance!="object")throw new Error("defineTheme({ appearance }) is required.");if(typeof t.name!="string"||!t.name)throw new Error("defineTheme({ name }) is required.");const n=[t.css,e.files["style.css"]].filter(Boolean).join(`
1140
- `);return fz({id:e.id,apiVersion:t.apiVersion,name:t.name,...t.description?{description:t.description}:{},appearance:{...t.appearance},...n?{css:n}:{}})}function MH(e,t,n){const r=TH(t);IH(e,r),MR(e.id);const s=e.kind==="theme"?DH(e,r):$H(e,r);vl.set(e.id,{state:{id:e.id,kind:e.kind,version:e.manifest.version,status:"loaded",fingerprint:n},dispose:s}),ej()}async function OH(e){var n,r;await((r=(n=globalThis[cv])==null?void 0:n.prepare)==null?void 0:r.call(n,e))}function PH(e){return async t=>{const n=document.baseURI,r=z6(t,a=>new URL(`${C6}/${lT[a]}`,n).href),s=URL.createObjectURL(new Blob([r],{type:"text/javascript"}));try{return await import(s)}finally{URL.revokeObjectURL(s)}}}let OR=!1;function LH(e=window){const t=r=>{(r.key==="Shift"||r.shiftKey)&&(OR=!0)};e.addEventListener("keydown",t);const n=setTimeout(()=>e.removeEventListener("keydown",t),2500);return()=>{clearTimeout(n),e.removeEventListener("keydown",t)}}function PR(e=typeof location<"u"?location:void 0){if(OR)return!0;if(!e)return!1;const t=e.hash.includes("?")?e.hash.slice(e.hash.indexOf("?")):"";return[e.search,t].some(n=>{const r=new URLSearchParams(n).get("safe");return r==="1"||r==="true"})}function FH(e){return e.list("extensions").filter(t=>t&&typeof t.id=="string"&&t.manifest)}async function zH(e,t){var s;const n=(s=e.files)==null?void 0:s["bundle.js"];if(typeof n!="string"||!n)throw new Error("bundle.js is missing (upload incomplete?).");await OH(uT(n));const r=await t(n,{id:e.id,version:e.manifest.version});MH(e,r,fT(e.manifest,e.files))}let gA=Promise.resolve();function LR(e,t={}){const n=async()=>{var d,f;const s={loaded:[],unloaded:[],failed:[],skipped:[]},a=t.importBundle??PH(),o=FH(e),l=new Set(o.map(p=>p.id));for(const p of Ov())l.has(p.id)||(p.status==="loaded"&&s.unloaded.push(p.id),MR(p.id));for(const p of o){const m=hA(p.id);if(t.safeMode){(m==null?void 0:m.status)!=="skipped"&&ch(p,"skipped"),s.skipped.push(p.id);continue}if(!p.enabled){(m==null?void 0:m.status)==="loaded"&&s.unloaded.push(p.id),(m==null?void 0:m.status)!=="disabled"&&ch(p,"disabled");continue}if(!pd(p.manifest.apiVersion)){(m==null?void 0:m.status)!=="incompatible"&&ch(p,"incompatible",`apiVersion ${p.manifest.apiVersion} is not supported.`);continue}const h=(d=p.files)!=null&&d["bundle.js"]?fT(p.manifest,p.files):"";if(!((m==null?void 0:m.status)==="loaded"&&m.fingerprint===h)&&!((m==null?void 0:m.status)==="error"&&m.fingerprint===h))try{await zH(p,a),s.loaded.push(p.id)}catch(b){const x=b instanceof Error?b:new Error(String(b));t.onError||console.error(`[extensions] ${p.id} failed to load:`,x),ch(p,"error",x.message);const y=hA(p.id);y&&(y.fingerprint=h),s.failed.push({id:p.id,error:x.message}),(f=t.onError)==null||f.call(t,p.id,x)}}return s},r=gA.then(n,n);return gA=r.catch(()=>{}),r}function UH(e,t={}){let n=!1;const r=()=>void LR(e,t).then(a=>{var o;n||(o=t.onSync)==null||o.call(t,a)}),s=e.subscribe(a=>{a.has("extensions")&&r()});return()=>{n=!0,s()}}const FR=S.createContext({reconfigure:()=>window.location.reload()});function xd(){return S.useContext(FR)}function BH(){const[e,t]=S.useState(0),n=S.useMemo(()=>(Jx(),mr()),[e]),r=S.useMemo(()=>({reconfigure:()=>{Jx(),jp(),t(s=>s+1)}}),[]);return i.jsx(E_,{i18n:xt,children:i.jsxs(FR.Provider,{value:r,children:[n?i.jsx(qH,{config:n},e):i.jsx(HH,{}),i.jsx(hU,{}),i.jsx(yU,{})]})})}function HH(){const{t:e}=oe(),t=J1().flatMap(n=>n.unconfiguredRoutes??[]);return i.jsx(H_,{children:i.jsxs(U_,{children:[t.map(n=>i.jsx(xi,{path:n.path,element:n.element},n.path)),!t.some(n=>n.path==="*"||n.path==="/*")&&i.jsx(xi,{path:"*",element:i.jsx(Il,{children:i.jsx(ut,{icon:i.jsx(ba,{}),title:e("setupRequired.title")})})})]})})}function Il({children:e}){return i.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-50 p-6 dark:bg-surface-950",children:e})}function qH({config:e}){const[t,n]=S.useState({phase:"loading"}),[r,s]=S.useState(0),a=S.useCallback(()=>s(l=>l+1),[]);S.useEffect(()=>{let l=!1;const d=f=>!l&&n(f);return(async()=>{let f;try{f=await Dv()}catch(p){return d({phase:"error",error:p})}try{const p=await f.identity();if(!p)return d({phase:"signIn",store:f});if(await f.ready(),f.list("objects").length===0)return d({phase:"empty",store:f,identity:p});const m=AR(f,p);if(!m)return d({phase:"signIn",store:f});m.role==="admin"&&!m.disabled&&await hE(la(f,m)).catch(x=>console.warn("[agentcrm] schema migration skipped:",x)),Hk(async()=>{const x=f.get("config","hosting");return x!=null&&x.connectorId?{connectorId:x.connectorId,settings:{...x.settings??{},...e0(e)}}:null}),Rz(f);const h=PR(),b=await LR(f,{safeMode:h});d({phase:"ready",store:f,identity:p,user:m,safeMode:h,extensionReport:b})}catch(p){const m=p;if(m.name==="PassphraseError")return d({phase:"passphrase",store:f,wrong:m.reason==="wrong"});d({phase:"error",error:m})}})(),()=>{l=!0}},[r,e]);const o=S.useCallback(async()=>{const l=yH(e.backend);l?await l.signOut():Gw(e),jp(),a()},[e,a]);switch(t.phase){case"loading":return i.jsx(Il,{children:i.jsx(Ds,{size:"lg"})});case"error":return i.jsx(YH,{error:t.error,onRetry:a});case"passphrase":return i.jsx(ZH,{config:e,wrong:t.wrong,onSubmit:a});case"signIn":return i.jsx(QH,{onSignedIn:a});case"empty":return i.jsx(XH,{store:t.store,identity:t.identity,onDone:a});case"ready":return i.jsx(bH,{backend:e.backend,identity:t.identity,user:t.user,onSignOut:o,children:i.jsx(Mz,{store:t.store,user:t.user,children:i.jsx(VH,{identity:t.identity,initial:t.user,children:l=>i.jsx(KH,{user:l,safeMode:t.safeMode,extensionReport:t.extensionReport})})})})}}function VH({identity:e,initial:t,children:n}){const{store:r}=ps(),[s,a]=S.useState(t);return S.useEffect(()=>r.subscribe(o=>{if(!o.has("users")&&!o.has("settings"))return;const l=AR(r,e);l&&JSON.stringify(l)!==JSON.stringify(s)&&a(l)}),[r,e,s]),i.jsx(i.Fragment,{children:n(s)})}function WH(e,t){const n=S.useRef(new Map);S.useEffect(()=>{const r=n.current;for(const[s,a]of[...r])e.includes(a.feature)||(typeof a.cleanup=="function"&&a.cleanup(),r.delete(s));for(const s of e)if(!(r.has(s.id)||!s.onStart))try{r.set(s.id,{feature:s,cleanup:s.onStart({user:t})})}catch(a){console.error(`[features] onStart of ${s.id} failed:`,a)}},[e,t]),S.useEffect(()=>{const r=n.current;return()=>{for(const s of r.values())typeof s.cleanup=="function"&&s.cleanup();r.clear()}},[t.id])}function KH({user:e,safeMode:t,extensionReport:n}){const{t:r}=oe(),{store:s}=ps(),a=Y1(),o=ap(),l=un();if(WH(a,e),_H(),S.useEffect(()=>{const x=y=>{y.failed.length&&ge.error(r("app.extensionErrors",{count:y.failed.length,list:y.failed.map(v=>`${v.id} (${v.error})`).join(", ")}))};return x(n),UH(s,{safeMode:t,onSync:x})},[s,t]),e.disabled)return i.jsx(Il,{children:i.jsx(ut,{icon:i.jsx(yo,{}),title:r("errors.forbidden")})});const d=x=>x.routes.filter(y=>!y.roles||y.roles.includes(e.role)),f=a.flatMap(d),p=new Set(a.map(x=>x.id)),m=k0().filter(x=>!p.has(x.id)).flatMap(x=>d(x).map(y=>({path:y.path,module:x.id}))).filter(x=>x.path!=="/"&&!f.some(y=>y.path===x.path)),h=o.filter(x=>!x.enabled).flatMap(x=>x.objects.map(y=>({object:y,module:x.id}))),b=f.some(x=>x.path==="/");return i.jsx(H_,{children:i.jsx(AH,{banner:t?i.jsx(GH,{}):void 0,children:i.jsxs(U_,{children:[f.map(x=>i.jsx(xi,{path:x.path,element:x.element},x.path)),m.map(x=>i.jsx(xi,{path:x.path,element:i.jsx(px,{moduleId:x.module})},`off:${x.path}`)),h.flatMap(x=>[i.jsx(xi,{path:`/objects/${x.object}`,element:i.jsx(px,{moduleId:x.module})},`off:${x.object}`),i.jsx(xi,{path:`/objects/${x.object}/*`,element:i.jsx(px,{moduleId:x.module})},`off:${x.object}/*`)]),!b&&l[0]&&i.jsx(xi,{path:"/",element:i.jsx(jC,{to:pt.objectList(l[0].id),replace:!0})}),i.jsx(xi,{path:"/setup/*",element:i.jsx(jC,{to:"/",replace:!0})}),i.jsx(xi,{path:"*",element:i.jsx(JH,{})})]})})})}function GH(){const{t:e}=oe(),t=()=>{const n=new URL(window.location.href);n.searchParams.delete("safe"),n.hash=n.hash.replace(/[?&]safe=[^&]*/,"").replace(/\?$/,""),window.location.replace(n.toString())};return i.jsxs("div",{role:"status",className:"flex items-center gap-2 border-b border-amber-200 bg-amber-50 px-4 py-1.5 text-xs text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-200",children:[i.jsx(hk,{className:"h-3.5 w-3.5 shrink-0"}),i.jsx("span",{className:"flex-1",children:e("app.safeMode.banner")}),i.jsx("button",{type:"button",onClick:t,className:"font-medium underline-offset-2 hover:underline",children:e("app.safeMode.exit")})]})}function px({moduleId:e}){const{t}=oe(),{role:n}=Oi(),s=ap().find(o=>o.id===e),a=s?s.nameKey?t(s.nameKey):s.name:e;return i.jsx(ut,{className:"py-24",icon:i.jsx(V8,{}),title:t("app.moduleDisabled.title"),description:n==="admin"?t("app.moduleDisabled.hint",{name:a}):t("app.moduleDisabled.hintMember",{name:a}),action:n==="admin"?i.jsx(ue,{variant:"outline",onClick:()=>window.location.hash=`#${pt.settings("modules")}`,children:t("app.moduleDisabled.open")}):void 0})}function JH(){const{t:e}=oe();return i.jsx(ut,{className:"py-24",title:e("app.notFound"),action:i.jsx(ue,{variant:"outline",onClick:()=>window.location.hash="#/",children:e("app.backHome")})})}function YH({error:e,onRetry:t}){const{t:n}=oe(),r=xd();return i.jsx(Il,{children:i.jsx(Ke,{className:"w-full max-w-md",children:i.jsx(ut,{icon:i.jsx(yo,{}),title:n("app.loadError"),description:i.jsx("span",{className:"break-words font-mono text-xs",children:e.message}),action:i.jsxs("div",{className:"flex gap-2",children:[i.jsx(ue,{variant:"primary",onClick:t,children:n("app.retry")}),i.jsx(ue,{variant:"ghost",onClick:()=>{ld(null),r.reconfigure()},children:n("app.resetSetup")})]})})})})}function ZH({config:e,wrong:t,onSubmit:n}){const{t:r}=oe(),[s,a]=S.useState("");return i.jsx(Il,{children:i.jsx(Ke,{className:"w-full max-w-sm",children:i.jsxs("form",{"data-form-type":"other",onSubmit:o=>{o.preventDefault(),cd(e,s.trim()),n()},className:"space-y-4",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(Rs,{className:"h-5 w-5 text-surface-500"}),i.jsx("h1",{className:"text-base font-semibold",children:r("app.passphraseTitle")})]}),i.jsx("p",{className:"text-sm text-surface-500",children:r("app.passphraseHint")}),i.jsx(Te,{label:r("app.passphrase"),htmlFor:"passphrase",error:t?r("app.passphraseWrong"):void 0,children:i.jsx(Oe,{id:"passphrase",type:"password",autoComplete:"off",autoFocus:!0,value:s,onChange:o=>a(o.target.value),invalid:t})}),i.jsx(ue,{type:"submit",variant:"primary",className:"w-full",disabled:!s.trim(),icon:i.jsx(Rs,{}),children:r("app.unlock")})]})})})}function QH({onSignedIn:e}){const{t}=oe(),n=XT("loginScreen")[0];return n?i.jsx(n,{onSignedIn:e}):i.jsx(Il,{children:i.jsx(ut,{icon:i.jsx(Rs,{}),title:t("errors.forbidden")})})}function XH({store:e,identity:t,onDone:n}){const{t:r,i18n:s}=oe(),[a,o]=S.useState(null),l=async d=>{o(d?"demo":"plain");try{await r1(la(e,null),{admin:{name:t.displayName||"Admin",email:t.email||"admin@localhost"},demo:d,locale:s.language,currency:cE(s.language)}),n()}finally{o(null)}};return i.jsx(Il,{children:i.jsx(Ke,{className:"w-full max-w-md",children:i.jsx(ut,{icon:i.jsx(ba,{}),title:r("app.emptyTitle"),description:r("app.emptyHint"),action:i.jsxs("div",{className:"flex gap-2",children:[i.jsx(ue,{variant:"primary",loading:a==="demo",disabled:!!a,onClick:()=>void l(!0),children:r("app.installDemo")}),i.jsx(ue,{variant:"outline",loading:a==="plain",disabled:!!a,onClick:()=>void l(!1),children:r("app.installEmpty")})]})})})})}const eq={dashboard:"Dashboard",reports:"Reports"},tq="Dashboard",nq="Welcome back, {{name}}",rq="You don't have access to reports.",sq="Open pipeline",iq="Weighted forecast",aq="{{pct}}% of open pipeline",oq="{{count}} open deal",lq="{{count}} open deals",cq="Won this month",dq="{{count}} deal",uq="{{count}} deals",fq="New people this month",pq="{{count}} lead",mq="{{count}} leads",hq="Overdue tasks",gq="{{count}} open task",yq="{{count}} open tasks",bq="No pipeline yet",xq="Create a pipeline in Settings to see deal reports.",vq="Pipeline by stage",wq="All reports",kq="Won / lost",jq="Won",Sq="Lost",Cq="Win rate",Nq="Win rate {{pct}}%",Aq="Lead sources",_q="People",Eq="Customers",Tq="Unknown",Iq="Activity by user",Rq="Unassigned",$q="Last {{count}} day",Dq="Last {{count}} days",Mq={note:"Notes",task:"Tasks",call:"Calls",email:"Emails",meeting:"Meetings"},Oq="Stale deals",Pq="Idle ≥ {{count}} day",Lq="Idle ≥ {{count}} days",Fq="{{count}} day idle",zq="{{count}} days idle",Uq="No stale deals — nice work.",Bq="My tasks today",Hq="All tasks",qq="Nothing due today.",Vq="Mark as done",Wq="Task completed",Kq="Today",Gq="Due {{date}}",Jq="Amount",Yq="Chart unavailable",Zq="No data for this period.",Qq="Reports",Xq="Export CSV",eV="Forecast by close month",tV="Open deals closing from the start of the period",nV="No close date",rV="Lifecycle conversion",sV="+ {{count}} more (in the CSV export)",iV="+ {{count}} more (in the CSV export)",aV={period:"Period",from:"From",to:"To",pipeline:"Pipeline"},oV={"30d":"Last 30 days","90d":"Last 90 days",ytd:"This year","12m":"Last 12 months",custom:"Custom range"},lV={stage:"Stage",kind:"Kind",count:"Count",amount:"Amount",weighted:"Weighted",total:"Total",month:"Month",wonCount:"Won",wonAmount:"Won amount",lostCount:"Lost",lostAmount:"Lost amount",winRate:"Win rate",user:"User",tasksDone:"Tasks done",tasksOpen:"Open tasks",source:"Source",people:"People",customers:"Customers",customerRate:"Customer rate",reached:"Reached",conversion:"Step conversion",deal:"Deal",owner:"Owner",idleDays:"Idle days",lastActivity:"Last activity"},cV={nav:eq,title:tq,greeting:nq,noAccess:rq,openPipeline:sq,weighted:iq,ofPipeline:aq,openDeals_one:oq,openDeals_other:lq,wonThisMonth:cq,dealsCount_one:dq,dealsCount_other:uq,newPeopleThisMonth:fq,leadsCount_one:pq,leadsCount_other:mq,overdueTasks:hq,openTasksCount_one:gq,openTasksCount_other:yq,noPipeline:bq,noPipelineHint:xq,byStage:vq,viewReports:wq,wonLost:kq,won:jq,lost:Sq,winRate:Cq,winRateValue:Nq,leadSources:Aq,people:_q,customers:Eq,unknown:Tq,activityByUser:Iq,unassigned:Rq,lastDays_one:$q,lastDays_other:Dq,activityTypes:Mq,staleDeals:Oq,idleFor_one:Pq,idleFor_other:Lq,idleDays_one:Fq,idleDays_other:zq,noStaleDeals:Uq,myTasksToday:Bq,allTasks:Hq,noTasksToday:qq,markDone:Vq,taskDone:Wq,today:Kq,overdueSince:Gq,amount:Jq,chartUnavailable:Yq,noData:Zq,reportsTitle:Qq,exportCsv:Xq,forecastByMonth:eV,forecastHint:tV,noCloseDate:nV,conversion:rV,moreRows_one:sV,moreRows_other:iV,filters:aV,range:oV,col:lV},dV={dashboard:"Tableau de bord",reports:"Rapports"},uV="Tableau de bord",fV="Bon retour, {{name}}",pV="Vous n'avez pas accès aux rapports.",mV="Pipeline ouvert",hV="Prévision pondérée",gV="{{pct}} % du pipeline ouvert",yV="{{count}} affaire ouverte",bV="{{count}} affaires ouvertes",xV="Gagné ce mois-ci",vV="{{count}} affaire",wV="{{count}} affaires",kV="Nouveaux contacts ce mois-ci",jV="{{count}} lead",SV="{{count}} leads",CV="Tâches en retard",NV="{{count}} tâche ouverte",AV="{{count}} tâches ouvertes",_V="Aucun pipeline",EV="Créez un pipeline dans les paramètres pour voir les rapports d'affaires.",TV="Pipeline par étape",IV="Tous les rapports",RV="Gagnées / perdues",$V="Gagnées",DV="Perdues",MV="Taux de réussite",OV="Taux de réussite {{pct}} %",PV="Sources de leads",LV="Contacts",FV="Clients",zV="Inconnue",UV="Activité par utilisateur",BV="Non assigné",HV="Dernier jour",qV="{{count}} derniers jours",VV={note:"Notes",task:"Tâches",call:"Appels",email:"E-mails",meeting:"Réunions"},WV="Affaires dormantes",KV="Inactives ≥ {{count}} jour",GV="Inactives ≥ {{count}} jours",JV="{{count}} jour d'inactivité",YV="{{count}} jours d'inactivité",ZV="Aucune affaire dormante, bravo.",QV="Mes tâches du jour",XV="Toutes les tâches",eW="Rien à faire aujourd'hui.",tW="Marquer comme faite",nW="Tâche terminée",rW="Aujourd'hui",sW="Échue le {{date}}",iW="Montant",aW="Graphique indisponible",oW="Aucune donnée pour cette période.",lW="Rapports",cW="Exporter en CSV",dW="Prévision par mois de clôture",uW="Affaires ouvertes clôturant à partir du début de la période",fW="Sans date de clôture",pW="Conversion du cycle de vie",mW="+ {{count}} de plus (dans l'export CSV)",hW="+ {{count}} de plus (dans l'export CSV)",gW={period:"Période",from:"Du",to:"Au",pipeline:"Pipeline"},yW={"30d":"30 derniers jours","90d":"90 derniers jours",ytd:"Cette année","12m":"12 derniers mois",custom:"Période personnalisée"},bW={stage:"Étape",kind:"Type",count:"Nombre",amount:"Montant",weighted:"Pondéré",total:"Total",month:"Mois",wonCount:"Gagnées",wonAmount:"Montant gagné",lostCount:"Perdues",lostAmount:"Montant perdu",winRate:"Taux de réussite",user:"Utilisateur",tasksDone:"Tâches faites",tasksOpen:"Tâches ouvertes",source:"Source",people:"Contacts",customers:"Clients",customerRate:"Taux de clients",reached:"Atteint",conversion:"Conversion d'étape",deal:"Affaire",owner:"Propriétaire",idleDays:"Jours d'inactivité",lastActivity:"Dernière activité"},xW={nav:dV,title:uV,greeting:fV,noAccess:pV,openPipeline:mV,weighted:hV,ofPipeline:gV,openDeals_one:yV,openDeals_other:bV,wonThisMonth:xV,dealsCount_one:vV,dealsCount_other:wV,newPeopleThisMonth:kV,leadsCount_one:jV,leadsCount_other:SV,overdueTasks:CV,openTasksCount_one:NV,openTasksCount_other:AV,noPipeline:_V,noPipelineHint:EV,byStage:TV,viewReports:IV,wonLost:RV,won:$V,lost:DV,winRate:MV,winRateValue:OV,leadSources:PV,people:LV,customers:FV,unknown:zV,activityByUser:UV,unassigned:BV,lastDays_one:HV,lastDays_other:qV,activityTypes:VV,staleDeals:WV,idleFor_one:KV,idleFor_other:GV,idleDays_one:JV,idleDays_other:YV,noStaleDeals:ZV,myTasksToday:QV,allTasks:XV,noTasksToday:eW,markDone:tW,taskDone:nW,today:rW,overdueSince:sW,amount:iW,chartUnavailable:aW,noData:oW,reportsTitle:lW,exportCsv:cW,forecastByMonth:dW,forecastHint:uW,noCloseDate:fW,conversion:pW,moreRows_one:mW,moreRows_other:hW,filters:gW,range:yW,col:bW},Hu=864e5;function fr(e){try{return e()}catch{return null}}function Pv(e,t=!0){const n=_r();return r=>Bf(r,e,n,t)}function Nn(e){return new Intl.NumberFormat(_r()).format(e)}function yA(e){const t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}`}function bA(e){const t=/^(\d{4})-(\d{2})$/.exec(e);return t?new Intl.DateTimeFormat(_r(),{month:"short",year:"2-digit"}).format(new Date(Number(t[1]),Number(t[2])-1,1)):e}const Nae={note:Xo("yellow"),task:Xo("blue"),call:Xo("green"),email:Xo("purple"),meeting:Xo("orange")};function na({children:e}){return i.jsx("div",{className:"flex h-32 items-center justify-center text-[13px] text-surface-400",children:e})}function fc({head:e,rows:t,align:n,foot:r}){const s=a=>(n==null?void 0:n[a])==="right"?"text-right tabular-nums":"text-left";return i.jsx("div",{className:"overflow-x-auto",children:i.jsxs("table",{className:"w-full text-[13px]",children:[i.jsx("thead",{children:i.jsx("tr",{className:"border-b border-surface-100 text-xs text-surface-500 dark:border-surface-800",children:e.map((a,o)=>i.jsx("th",{className:ce("whitespace-nowrap px-2 py-1.5 font-medium",s(o)),children:a},o))})}),i.jsx("tbody",{children:t.map((a,o)=>i.jsx("tr",{className:"border-b border-surface-100 last:border-0 dark:border-surface-800",children:a.map((l,d)=>i.jsx("td",{className:ce("whitespace-nowrap px-2 py-1.5 text-surface-700 dark:text-surface-200",s(d)),children:l},d))},o))}),r&&i.jsx("tfoot",{children:i.jsx("tr",{className:"border-t border-surface-200 font-medium text-surface-900 dark:border-surface-700 dark:text-white",children:r.map((a,o)=>i.jsx("td",{className:ce("whitespace-nowrap px-2 py-1.5",s(o)),children:a},o))})})]})})}function vW({stages:e,money:t}){return i.jsx("ul",{className:"mt-3 grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3",children:e.map(n=>i.jsxs("li",{className:"flex min-w-0 items-center gap-1.5 text-xs","data-stage":n.stageId,children:[i.jsx("span",{className:"h-2 w-2 shrink-0 rounded-sm",style:{background:Xo(n.color)}}),i.jsx("span",{className:"truncate text-surface-600 dark:text-surface-300",children:n.label}),i.jsxs("span",{className:"ml-auto shrink-0 tabular-nums text-surface-500",children:[n.count," · ",t(n.amount)]})]},n.stageId))})}function wW({stages:e,colors:t}){const n=Math.max(1,...e.map(r=>r.reached));return i.jsx("div",{className:"space-y-1.5",children:e.map(r=>i.jsxs("div",{className:"flex items-center gap-3 text-[13px]","data-funnel-stage":r.id,children:[i.jsx("span",{className:"w-28 shrink-0 truncate text-surface-600 dark:text-surface-300",children:r.label}),i.jsx("div",{className:"h-5 flex-1 rounded bg-surface-100 dark:bg-surface-800",children:i.jsx("div",{className:"h-5 rounded",style:{width:`${r.reached/n*100}%`,background:Xo((t==null?void 0:t[r.id])??"blue")}})}),i.jsx("span",{className:"w-12 shrink-0 text-right tabular-nums text-surface-700 dark:text-surface-200",children:Nn(r.reached)}),i.jsx("span",{className:"w-14 shrink-0 text-right tabular-nums text-xs text-surface-500",children:r.conversionFromPrevious===null?"—":`${r.conversionFromPrevious}%`})]},r.id))})}const kW=()=>Sr(()=>import("./chartsImpl-B45AAqnr.js"),[],import.meta.url);class jW extends S.Component{constructor(){super(...arguments);wt(this,"state",{failed:!1})}static getDerivedStateFromError(){return{failed:!0}}componentDidCatch(n,r){console.warn("Chart unavailable:",n.message,r.componentStack??"")}render(){return this.state.failed?i.jsx(SW,{height:this.props.height}):this.props.children}}function SW({height:e}){const{t}=oe("dashboard");return i.jsx("div",{style:{height:Math.min(e,96)},className:"flex items-center justify-center rounded-md border border-dashed border-surface-200 text-xs text-surface-400 dark:border-surface-800","data-chart-unavailable":"",children:t("chartUnavailable")})}function CW({height:e}){return i.jsx("div",{style:{height:e},className:"w-full animate-pulse rounded-md bg-surface-100 dark:bg-surface-800/60","aria-hidden":"true"})}function Sp(e,t=220){const n=S.lazy(async()=>({default:(await kW())[e]}));function r(s){const a=s.height??t;return i.jsx(jW,{height:a,children:i.jsx(S.Suspense,{fallback:i.jsx(CW,{height:a}),children:i.jsx(n,{...s})})})}return r.displayName=e,r}const zR=Sp("PipelineStageChart"),UR=Sp("WonLostChart"),BR=Sp("LeadSourcesChart",160),HR=Sp("ActivityByUserChart"),NW=Sp("ForecastMonthChart");function qR({deals:e,users:t,objectOf:n,money:r}){const{t:s}=oe("dashboard");return i.jsx("ul",{className:"divide-y divide-surface-100 dark:divide-surface-800",children:e.map(a=>{const o=a.ownerId?t.get(a.ownerId):void 0;return i.jsx("li",{"data-stale-deal":a.id,children:i.jsxs(Rn,{to:pt.record(n(a.id),a.id),className:"-mx-2 flex items-center gap-3 rounded-md px-2 py-1.5 text-[13px] hover:bg-surface-50 dark:hover:bg-surface-800/60",children:[i.jsxs("span",{className:"min-w-0 flex-1",children:[i.jsx("span",{className:"block truncate font-medium text-surface-900 dark:text-white",children:a.label}),i.jsx("span",{className:"block truncate text-xs text-surface-500",children:a.stage})]}),i.jsx("span",{className:"shrink-0 text-xs tabular-nums text-amber-600 dark:text-amber-400",children:s("idleDays",{count:a.idleDays})}),i.jsx("span",{className:"w-16 shrink-0 text-right tabular-nums text-surface-700 dark:text-surface-200",children:r(a.amount)}),i.jsx("span",{className:"w-5 shrink-0",title:o==null?void 0:o.name,children:o&&i.jsx($s,{name:o.name,src:o.avatarUrl,size:"sm"})})]})},a.id)})})}const AW={4:"col-span-12 md:col-span-6 lg:col-span-4",6:"col-span-12 md:col-span-6",8:"col-span-12 lg:col-span-8",12:"col-span-12"};function _W(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),1).getTime()}function EW(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()+1).getTime()-1}function yu({label:e,value:t,sub:n,icon:r,to:s,tone:a}){const o=i.jsxs("div",{className:ce("h-full rounded-lg border border-surface-200 bg-white px-4 py-3 shadow-card dark:border-surface-800 dark:bg-surface-900",s&&"transition-colors hover:border-surface-300 dark:hover:border-surface-700"),children:[i.jsxs("div",{className:"flex items-center gap-1.5 text-xs text-surface-500",children:[r&&i.jsx("span",{className:"[&>svg]:h-3.5 [&>svg]:w-3.5",children:r}),i.jsx("span",{className:"truncate",children:e})]}),i.jsx("div",{className:ce("mt-1 truncate text-xl font-semibold tabular-nums text-surface-900 dark:text-white",a==="danger"&&"text-red-600 dark:text-red-400"),children:t}),n&&i.jsx("div",{className:"mt-0.5 truncate text-xs text-surface-500",children:n})]});return s?i.jsx(Rn,{to:s,className:"block",children:o}):o}function TW(){const{t:e}=oe("dashboard"),t=Xe(),n=Ei(),r=di(),s=mt("records"),a=Ti(),o=ms(),l=sr({includeDisabled:!0}),d=mt("objects"),f=Ge("reports.read"),p=S.useMemo(()=>Pv(r.defaultCurrency),[r.defaultCurrency]),m=S.useMemo(()=>{var me,Se,Y;if(!f)return null;const O=t.now(),z=_W(O),R=fr(()=>oE(t)),V=fr(()=>Cl(t)),X=fr(()=>s0(t)),Q=fr(()=>pf(t,{months:6})),ee=((me=fr(()=>pf(t,{months:1})))==null?void 0:me.months[0])??null,se=s.filter(ve=>ve.object==="people"&&!ve.deletedAt).filter(ve=>ve.createdAt>=z),M=se.filter(ve=>ve.fields.lifecycleStage==="lead").length,F=(Se=d.find(ve=>ve.id==="people"))==null?void 0:Se.fields.find(ve=>ve.id==="leadSource"),Z=(((Y=fr(()=>a0(t)))==null?void 0:Y.sources)??[]).map(ve=>{var Fe,Ue;return{...ve,label:ve.id?ve.label:e("unknown"),color:(Ue=(Fe=F==null?void 0:F.options)==null?void 0:Fe.find(L=>L.id===ve.id))==null?void 0:Ue.color}}),de=fr(()=>i0(t,{days:30})),re=fr(()=>o0(t,{limit:6})),q=EW(O),ne=fr(()=>Mw(t,{assigneeId:n.id,status:"open"}).items.filter(ve=>ve.dueAt!==void 0&&ve.dueAt<=q))??[];return{now:O,stats:R,fc:V,byStage:X,wl:Q,thisMonth:ee,newPeople:se.length,newLeads:M,sources:Z,activity:de,stale:re,myTasks:ne}},[t,f,s,a,o,l,d,r,n.id,e]),h=S.useMemo(()=>new Map(l.map(O=>[O.id,O])),[l]),b=S.useMemo(()=>{const O=new Map(s.map(z=>[z.id,z.object]));return z=>O.get(z)??"deals"},[s]),x=il("dashboardWidgets"),y=Cf("deals"),v=Cf("reports");if(!m)return i.jsxs("div",{children:[i.jsx(Kr,{title:e("title"),icon:i.jsx(Fu,{})}),i.jsx(ut,{className:"py-24",icon:i.jsx(Fu,{}),title:e("noAccess")})]});const{stats:k,fc:j,byStage:C,wl:A,thisMonth:_,sources:D,activity:I,stale:T,myTasks:E}=m,P=!!j&&y,U=(I==null?void 0:I.users.filter(O=>O.total>0))??[];return i.jsxs("div",{children:[i.jsx(Kr,{title:e("title"),icon:i.jsx(Fu,{}),description:e("greeting",{name:n.name.split(" ")[0]})}),i.jsxs("div",{className:"space-y-4 p-4 sm:p-6",children:[i.jsxs("div",{className:ce("grid grid-cols-2 gap-3 md:grid-cols-3",y?"xl:grid-cols-5":"xl:grid-cols-2"),"data-testid":"kpis",children:[y&&i.jsxs(i.Fragment,{children:[i.jsx(yu,{icon:i.jsx(eU,{}),label:e("openPipeline"),value:j?p(j.openAmount):"—",sub:j?e("openDeals",{count:j.openCount}):e("noPipeline")}),i.jsx(yu,{icon:i.jsx(xI,{}),label:e("weighted"),value:j?p(j.weightedAmount):"—",sub:j&&j.openAmount?e("ofPipeline",{pct:Math.round(j.weightedAmount/j.openAmount*100)}):void 0}),i.jsx(yu,{icon:i.jsx(bk,{}),label:e("wonThisMonth"),value:_?p(_.wonAmount):"—",sub:_?e("dealsCount",{count:_.wonCount}):void 0})]}),i.jsx(yu,{icon:i.jsx(R0,{}),label:e("newPeopleThisMonth"),value:Nn(m.newPeople),sub:e("leadsCount",{count:m.newLeads})}),i.jsx(yu,{icon:i.jsx(yo,{}),label:e("overdueTasks"),value:Nn((k==null?void 0:k.overdueTasks)??0),sub:e("openTasksCount",{count:(k==null?void 0:k.openTasks)??0}),to:pt.tasks(),tone:k!=null&&k.overdueTasks?"danger":void 0})]}),i.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-12",children:[P&&C&&i.jsxs(Ke,{className:"md:col-span-2 lg:col-span-7",title:e("byStage"),actions:v?i.jsx(Rn,{to:pt.reports(),className:"text-xs text-surface-500 hover:text-surface-900 dark:hover:text-white",children:e("viewReports")}):void 0,children:[i.jsx(zR,{stages:C.stages,money:p}),i.jsx(vW,{stages:C.stages,money:p})]}),P&&A&&i.jsx(Ke,{className:"lg:col-span-5",title:e("wonLost"),actions:i.jsx("span",{className:"text-xs text-surface-500",children:A.totals.winRate===null?"":e("winRateValue",{pct:A.totals.winRate})}),children:i.jsx(UR,{months:A.months,money:p})}),i.jsx(Ke,{className:"lg:col-span-5",title:e("leadSources"),children:D.length?i.jsx(BR,{sources:D}):i.jsx(na,{children:e("noData")})}),i.jsx(Ke,{className:"lg:col-span-7",title:e("activityByUser"),actions:i.jsx("span",{className:"text-xs text-surface-500",children:e("lastDays",{count:30})}),children:U.length?i.jsx(HR,{users:U}):i.jsx(na,{children:e("noData")})}),P&&T&&i.jsx(Ke,{className:"lg:col-span-6",title:e("staleDeals"),actions:i.jsx("span",{className:"text-xs text-surface-500",children:e("idleFor",{count:T.days})}),children:T.deals.length?i.jsx(qR,{deals:T.deals,users:h,objectOf:b,money:p}):i.jsx(na,{children:e("noStaleDeals")})}),i.jsx(Ke,{className:ce(P?"lg:col-span-6":"md:col-span-2 lg:col-span-12"),title:e("myTasksToday"),actions:i.jsx(Rn,{to:pt.tasks(),className:"text-xs text-surface-500 hover:text-surface-900 dark:hover:text-white",children:e("allTasks")}),children:i.jsx(IW,{tasks:E,now:m.now})})]}),x.length>0&&i.jsx("div",{className:"grid grid-cols-12 gap-4",children:x.map(O=>i.jsx("div",{className:AW[O.span??12]??"col-span-12",children:i.jsx(O.component,{})},O.id))})]})]})}function IW({tasks:e,now:t}){const{t:n}=oe("dashboard"),r=Xe(),s=Ge("activities.write"),a=ya(),[o,l]=S.useState(null);if(!e.length)return i.jsx(na,{children:n("noTasksToday")});const d=async p=>{l(p);try{await Oc(r,p),ge.success(n("taskDone"))}catch(m){ge.error(m instanceof Error?m.message:String(m))}finally{l(null)}},f=new Date(t).toDateString();return i.jsx("ul",{className:"divide-y divide-surface-100 dark:divide-surface-800",children:e.map(p=>{const m=p.dueAt!==void 0&&p.dueAt<t&&new Date(p.dueAt).toDateString()!==f;return i.jsxs("li",{className:"flex items-start gap-2.5 py-1.5 text-[13px]","data-task":p.id,children:[i.jsx(Ot,{className:"mt-0.5",checked:!1,disabled:!s||o===p.id,"aria-label":n("markDone"),onChange:()=>void d(p.id)}),i.jsxs("div",{className:"min-w-0 flex-1",children:[i.jsx("div",{className:"truncate text-surface-900 dark:text-white",children:p.title}),p.targets.length>0&&i.jsx("div",{className:"flex flex-wrap gap-x-2 text-xs",children:p.targets.map(h=>i.jsx(Rn,{to:pt.record(h.object,h.id),className:"truncate text-surface-500 hover:text-accent-600 hover:underline",children:a(h.id)??h.id},h.id))})]}),i.jsx("span",{className:ce("shrink-0 text-xs tabular-nums",m?"text-red-600 dark:text-red-400":"text-surface-500"),children:m?n("overdueSince",{date:Pw(p.dueAt,_r())}):n("today")})]},p.id)})})}const RW={id:"dashboard",module:fs("dashboard"),routes:[{path:"/",element:S.createElement(TW)}],navItems:[{id:"dashboard",label:"dashboard:nav.dashboard",icon:Fu,to:"/",section:"main",order:0}],i18n:{en:cV,fr:xW}},$W={title:"Tasks"},DW="Tasks",MW="New task",OW="Unassigned",PW="No open tasks",LW="Tasks created on records show up here.",FW="Due {{date}}",zW={mine:"My tasks",all:"All tasks",overdue:"Overdue",upcoming:"Upcoming",done:"Done"},UW={mine:"You're all caught up — no open tasks.",all:"No open tasks.",overdue:"Nothing overdue.",upcoming:"No upcoming tasks.",done:"No completed tasks yet."},BW={search:"Filter tasks…",assignee:"Assignee",anyone:"Anyone",me:"{{name}} (me)",noMatch:"No task matches this filter."},HW={all:"Tasks",overdue:"Overdue",today:"Today",tomorrow:"Tomorrow",thisWeek:"This week",later:"Later",noDate:"No date",doneToday:"Completed today",doneYesterday:"Completed yesterday",doneThisWeek:"Completed this week",doneEarlier:"Completed earlier"},qW={today:"Today",tomorrow:"Tomorrow",yesterday:"Yesterday",nextWeek:"Next week",inTwoWeeks:"In 2 weeks"},VW={empty:"No tasks",complete:"Complete “{{title}}”",reopen:"Reopen “{{title}}”",actions:"Task actions",edit:"Edit",markDone:"Mark as done",markOpen:"Mark as not done",delete:"Delete",deleteConfirm:"Delete the task “{{title}}”?",dueDate:"Due date",dueOn:"Due {{date}}",setDue:"Set a due date",noDue:"Due date",clearDue:"Remove due date",assignedTo:"Assigned to {{name}}",searchUsers:"Assign to…",noUsers:"No matching user",unassign:"Unassign",attachments_one:"{{count}} attachment",attachments_other:"{{count}} attachments"},WW={newTitle:"New task",editTitle:"Edit task",title:"Title",titlePlaceholder:"Call back about the proposal",titleRequired:"Give the task a title.",description:"Description",markdownHint:"Markdown supported",descriptionPlaceholder:"Details, links, checklist…",preview:"Preview",write:"Write",nothingToPreview:"Nothing to preview.",dueDate:"Due date",dueTime:"Due time",assignee:"Assignee",related:"Related records",object:"Object",addRecord:"Link a {{object}}…",removeTarget:"Remove",cancel:"Cancel",save:"Save",create:"Create task",attachments:"Attachments",attach:"Attach files"},KW={created:"Task created",updated:"Task updated",deleted:"Task deleted"},GW={nav:$W,title:DW,newTask:MW,unassigned:OW,empty:PW,emptyHint:LW,due:FW,views:zW,emptyViews:UW,filter:BW,groups:HW,quick:qW,list:VW,editor:WW,toast:KW},JW={title:"Tâches"},YW="Tâches",ZW="Nouvelle tâche",QW="Non assignée",XW="Aucune tâche ouverte",eK="Les tâches créées sur les fiches apparaissent ici.",tK="Échéance {{date}}",nK={mine:"Mes tâches",all:"Toutes les tâches",overdue:"En retard",upcoming:"À venir",done:"Terminées"},rK={mine:"Vous êtes à jour — aucune tâche ouverte.",all:"Aucune tâche ouverte.",overdue:"Rien en retard.",upcoming:"Aucune tâche à venir.",done:"Aucune tâche terminée pour l'instant."},sK={search:"Filtrer les tâches…",assignee:"Assignée à",anyone:"Tout le monde",me:"{{name}} (moi)",noMatch:"Aucune tâche ne correspond à ce filtre."},iK={all:"Tâches",overdue:"En retard",today:"Aujourd'hui",tomorrow:"Demain",thisWeek:"Cette semaine",later:"Plus tard",noDate:"Sans date",doneToday:"Terminées aujourd'hui",doneYesterday:"Terminées hier",doneThisWeek:"Terminées cette semaine",doneEarlier:"Terminées plus tôt"},aK={today:"Aujourd'hui",tomorrow:"Demain",yesterday:"Hier",nextWeek:"Semaine prochaine",inTwoWeeks:"Dans 2 semaines"},oK={empty:"Aucune tâche",complete:"Terminer « {{title}} »",reopen:"Rouvrir « {{title}} »",actions:"Actions de la tâche",edit:"Modifier",markDone:"Marquer comme terminée",markOpen:"Marquer comme non terminée",delete:"Supprimer",deleteConfirm:"Supprimer la tâche « {{title}} » ?",dueDate:"Échéance",dueOn:"Échéance {{date}}",setDue:"Définir une échéance",noDue:"Échéance",clearDue:"Retirer l'échéance",assignedTo:"Assignée à {{name}}",searchUsers:"Assigner à…",noUsers:"Aucun utilisateur correspondant",unassign:"Retirer l'assignation",attachments_one:"{{count}} pièce jointe",attachments_other:"{{count}} pièces jointes"},lK={newTitle:"Nouvelle tâche",editTitle:"Modifier la tâche",title:"Titre",titlePlaceholder:"Rappeler au sujet de la proposition",titleRequired:"Donnez un titre à la tâche.",description:"Description",markdownHint:"Markdown pris en charge",descriptionPlaceholder:"Détails, liens, checklist…",preview:"Aperçu",write:"Écrire",nothingToPreview:"Rien à afficher.",dueDate:"Échéance",dueTime:"Heure d'échéance",assignee:"Assignée à",related:"Fiches liées",object:"Objet",addRecord:"Lier : {{object}}…",removeTarget:"Retirer",cancel:"Annuler",save:"Enregistrer",create:"Créer la tâche",attachments:"Pièces jointes",attach:"Joindre des fichiers"},cK={created:"Tâche créée",updated:"Tâche mise à jour",deleted:"Tâche supprimée"},dK={nav:JW,title:YW,newTask:ZW,unassigned:QW,empty:XW,emptyHint:eK,due:tK,views:nK,emptyViews:rK,filter:sK,groups:iK,quick:aK,list:oK,editor:lK,toast:cK},tj="09:00",uK=["overdue","today","tomorrow","thisWeek","later","noDate"],fK=["doneToday","doneYesterday","doneThisWeek","doneEarlier"];function F0(e){const t=new Date(e);return t.setHours(0,0,0,0),t.getTime()}function ei(e,t){const n=new Date(e);return n.setDate(n.getDate()+t),n.getTime()}function pK(e,t){return!e.doneAt&&e.dueAt!==void 0&&e.dueAt<t}function mK(e,t){if(e.dueAt===void 0)return"noDate";if(e.dueAt<t)return"overdue";const n=F0(t);return e.dueAt<ei(n,1)?"today":e.dueAt<ei(n,2)?"tomorrow":e.dueAt<ei(n,7)?"thisWeek":"later"}function hK(e,t){const n=e.doneAt??0,r=F0(t);return n>=r?"doneToday":n>=ei(r,-1)?"doneYesterday":n>=ei(r,-7)?"doneThisWeek":"doneEarlier"}function VR(e,t){return(e.dueAt??1/0)-(t.dueAt??1/0)||e.createdAt-t.createdAt}function WR(e,t){return(t.doneAt??0)-(e.doneAt??0)}function gK(e,t){var a,o;const n=new Map,r=new Map;for(const l of e)if(l.doneAt){const d=hK(l,t);r.set(d,[...r.get(d)??[],l])}else{const d=mK(l,t);n.set(d,[...n.get(d)??[],l])}const s=[];for(const l of uK)(a=n.get(l))!=null&&a.length&&s.push({id:l,tasks:n.get(l).sort(VR)});for(const l of fK)(o=r.get(l))!=null&&o.length&&s.push({id:l,tasks:r.get(l).sort(WR)});return s}function yK(e){const t=e.filter(r=>!r.doneAt).sort(VR),n=e.filter(r=>!!r.doneAt).sort(WR);return[...t,...n]}const jg=e=>String(e).padStart(2,"0");function nj(e){if(e===void 0)return"";const t=new Date(e);return`${t.getFullYear()}-${jg(t.getMonth()+1)}-${jg(t.getDate())}`}function rj(e){if(e===void 0)return"";const t=new Date(e);return`${jg(t.getHours())}:${jg(t.getMinutes())}`}function sj(e,t){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return;const[n,r,s]=e.split("-").map(Number),[a,o]=(t&&/^\d{2}:\d{2}$/.test(t)?t:tj).split(":").map(Number);return new Date(n,r-1,s,a,o,0,0).getTime()}function xA(e,t){return sj(nj(e),t!==void 0?rj(t):tj)}function bK(e){return e!==void 0&&rj(e)!==tj}const xK={id:"assignee",label:"",type:"user"};function ij({open:e,onClose:t,task:n,defaultTargets:r,defaultAssigneeId:s,defaultTitle:a,onSaved:o}){var q;const{t:l}=oe("tasks"),d=Xe(),f=Ei(),p=un(),m=ya(),[h,b]=S.useState(""),[x,y]=S.useState(""),[v,k]=S.useState(!1),[j,C]=S.useState(""),[A,_]=S.useState(""),[D,I]=S.useState(void 0),[T,E]=S.useState([]),[P,U]=S.useState(""),[O,z]=S.useState(!1),[R,V]=S.useState(null),[X,Q]=S.useState([]),ee=D0();S.useEffect(()=>{var me,Se;if(!e)return;b((n==null?void 0:n.title)??a??""),y((n==null?void 0:n.body)??""),k(!1),C(nj(n==null?void 0:n.dueAt)),_(bK(n==null?void 0:n.dueAt)?rj(n==null?void 0:n.dueAt):""),I(n?n.assigneeId:s??f.id);const ne=(n==null?void 0:n.targets)??r??[];E(ne),U(((me=ne[0])==null?void 0:me.object)??((Se=p[0])==null?void 0:Se.id)??""),V(null),z(!1),Q((n==null?void 0:n.attachments)??[]),ee.reset()},[e,n==null?void 0:n.id]);const J=ne=>y(me=>`${me}${me&&!me.endsWith(`
1139
+ `}),await t.delete(h),m&&await t.delete(b),(_=e.onProgress)==null||_.call(e,"done"),{encrypted:!!l}}async function Xk(e,t,n){const r=await kR(e,t);if(!r)return{exists:!1,encrypted:!1,ok:!0};if(!r.encrypted)return{exists:!0,encrypted:!1,ok:!0};if(!n||!r.check)return{exists:!0,encrypted:!0,ok:!r.check&&!!n};try{return{exists:!0,encrypted:!0,ok:await dR(so(r.check),n)===wR}}catch{return{exists:!0,encrypted:!0,ok:!1}}}const jR={s3:["accessKeyId","secretAccessKey"],"git-pages":["token"],"local-folder":[],"browser-mirror":[]},oH="data-folder";async function SR(e,t){const n=(jR[e]??[]).filter(r=>typeof t[r]!="string"||!t[r].trim());if(e==="local-folder"){if(typeof indexedDB>"u")return n;const r=await O0(typeof t.handleKey=="string"&&t.handleKey?t.handleKey:oH);(!r||!await wp(r,!1).catch(()=>!1))&&n.push("folder")}return n}const lH="agentcrm-local-files";function cH(e={}){const t=Lk(e.dbName??lH,"files");return{kind:"local",async put(n,r){sl(n),await t.set(n,new Uint8Array(r))},async putMany(n){for(const r of n)sl(r.id),await t.set(r.id,new Uint8Array(r.bytes))},async get(n){const r=await t.get(n);return r?r instanceof Uint8Array?r:new Uint8Array(r):null},async delete(n){await t.delete(n)},async list(){return(await t.keys()).sort()}}}const dH="agentcrm-local-data",uH=(e,t)=>`${e}/${t}`;function fH(e={}){const t=Lk(e.dbName??dH,"docs"),n=Zk({kind:"local",async load(){const r=$f();for(const[s,a]of await t.entries()){const o=s.slice(0,s.indexOf("/"));tL(o)&&r[o].set(a.id,Object.freeze(a))}return r},async persist(r,s,a){const o=new Map;for(const l of r){const d=l.op==="set"?l.doc.id:l.id;o.set(uH(l.collection,d),{collection:l.collection,id:d})}for(const[l,{collection:d,id:f}]of o){const p=a[d].get(f);p?await t.set(l,BB(p)):await t.delete(l)}},async identity(){return{uid:"local",email:"admin@localhost",displayName:"Local admin",role:"admin"}}});return i1(n,cH({dbName:e.filesDbName}))}function pH(e={}){const t=Zk({kind:"memory",async load(){return HB(e.initial??{})},async persist(){var r;const n=(r=e.failNextWrite)==null?void 0:r.call(e);if(n)throw n},async identity(){return e.identity===void 0?{uid:"local",email:"admin@localhost",displayName:"Admin",role:"admin"}:e.identity}});return i1(t,ML(e.blobs))}const CR=new Map;function kp(e,t){CR.set(e,t)}function mH(e){return CR.get(e)}kp("local",()=>fH());kp("memory",()=>pH());kp("journal",(e,t)=>{const n=e.journal,r={...n.settings,...t.secrets??{}},s=ko(n.connectorId,r),a=vR({connector:s,root:n.root,encrypted:n.encrypted,passphrase:t.passphrase,clientId:t.clientId,pollIntervalMs:t.pollIntervalMs}),o=a.identity.bind(a);return a.identity=async()=>(await SR(n.connectorId,r)).length?null:o(),a});kp("firebase",async(e,t)=>(await Sr(async()=>{const{createFirebaseStore:n}=await import("./firebase-U38f5kc9.js");return{createFirebaseStore:n}},[],import.meta.url)).createFirebaseStore(e,t));kp("git-json",async(e,t)=>(await Sr(async()=>{const{createGitJsonStore:n}=await import("./gitJson-wy2Tytfd.js");return{createGitJsonStore:n}},[],import.meta.url)).createGitJsonStore(e,t));async function NR(e,t={}){const n=mH(e.backend);if(!n)throw new Error(`Unknown data backend "${e.backend}".`);return n(e,t)}function hH(e){return{secrets:pl(e),passphrase:()=>Zf(e)}}let jr=null;function Dv(){const e=mr();if(!e)return Promise.reject(new Error("AgentCRM is not configured yet."));if(!jr||jr.config!==e){jr==null||jr.store.then(n=>{var r;return(r=n.close)==null?void 0:r.call(n)}).catch(()=>{});const t=NR(e,hH(e));jr={config:e,store:t},t.catch(()=>{(jr==null?void 0:jr.store)===t&&(jr=null)})}return jr.store}function jp(){jr==null||jr.store.then(e=>{var t;return(t=e.close)==null?void 0:t.call(e)}).catch(()=>{}),jr=null}const gH=new Set(["local","owner"]),fA={viewer:0,member:1,admin:2};function pA(e,t,n){return e.kind!=="git-json"?n:fA[t.role]<fA[n.role]?{...n,role:t.role}:n}function AR(e,t){if(!t)return null;const n=e.list("users"),r=n.find(a=>a.id===t.uid);if(r)return pA(e,t,r);const s=St(t.email);if(s){const a=n.find(o=>St(o.email)===s);if(a)return pA(e,t,a)}if(gH.has(t.uid)){const a=e.get("settings","general"),l=(a!=null&&a.ownerUserId?n.find(d=>d.id===a.ownerUserId):void 0)??n.find(d=>d.role==="admin"&&!d.disabled);if(l)return l}return{id:t.uid,email:t.email,name:t.displayName||t.email||"Owner",role:t.role}}const _R=new Map;function Cae(e,t){_R.set(e,t)}function yH(e){return _R.get(e)}const ER=S.createContext(null);function bH({backend:e,identity:t,user:n,onSignOut:r,children:s}){const a=S.useMemo(()=>({backend:e,identity:t,user:n,role:n.role,isAdmin:n.role==="admin",canSignOut:e!=="local",signOut:r}),[e,t,n,r]);return i.jsx(ER.Provider,{value:a,children:s})}function Oi(){const e=S.useContext(ER);if(!e)throw new Error("useAuth must be used inside <AuthProvider>");return e}function TR(){return S.useSyncExternalStore(zT,ng,ng)}function xH(){return TR(),jz()}const ta=typeof EventTarget<"u"?new EventTarget:null;function gr(e,t){ta==null||ta.dispatchEvent(new CustomEvent(e,{detail:t}))}function vH(e,t){const n=r=>t(r.detail);return ta==null||ta.addEventListener(e,n),()=>ta==null?void 0:ta.removeEventListener(e,n)}function Qa(e,t){const n=S.useRef(t);n.current=t,S.useEffect(()=>vH(e,r=>n.current(r)),[e])}const wH="agentcrm.theme";function kH(){return typeof document<"u"&&document.documentElement.classList.contains("dark")?"dark":"light"}function mA(e){document.documentElement.classList.toggle("dark",e==="dark");try{localStorage.setItem(wH,e)}catch{}window.dispatchEvent(new CustomEvent("agentcrm:theme",{detail:e}))}function IR(){const[e,t]=S.useState(kH);S.useEffect(()=>{const r=s=>t(s.detail);return window.addEventListener("agentcrm:theme",r),()=>window.removeEventListener("agentcrm:theme",r)},[]);const n=S.useCallback(r=>mA(r),[]);return{theme:e,setTheme:n,toggle:()=>mA(e==="dark"?"light":"dark")}}const RR="agentcrm.sidebarCollapsed";function jH(){try{return localStorage.getItem(RR)==="1"}catch{return!1}}function SH(e,t){return e.flatMap(n=>n.navItems??[]).filter(n=>!n.roles||n.roles.includes(t)).sort((n,r)=>(n.order??100)-(r.order??100))}function $R({to:e,icon:t,label:n,collapsed:r,badge:s,end:a}){return i.jsxs(q_,{to:e,end:a,title:r?n:void 0,className:({isActive:o})=>ce("group flex h-7 items-center gap-2 rounded-md px-2 text-[13px] font-medium transition-colors",o?"bg-surface-200/70 text-surface-900 dark:bg-surface-800 dark:text-white":"text-surface-600 hover:bg-surface-100 hover:text-surface-900 dark:text-surface-400 dark:hover:bg-surface-800/60 dark:hover:text-surface-100",r&&"justify-center px-0"),children:[i.jsx("span",{className:"flex h-4 w-4 shrink-0 items-center justify-center [&>svg]:h-4 [&>svg]:w-4",children:t}),!r&&i.jsx("span",{className:"min-w-0 flex-1 truncate",children:n}),!r&&s?i.jsx("span",{className:"rounded bg-surface-200 px-1 text-2xs text-surface-600 dark:bg-surface-700 dark:text-surface-300",children:s}):null]})}function ux({item:e,collapsed:t}){var a;const{t:n}=oe(),r=((a=e.useBadge)==null?void 0:a.call(e))??null,s=e.icon;return i.jsx($R,{to:e.to,icon:i.jsx(s,{}),label:n(e.label),collapsed:t,badge:r,end:e.to==="/"})}function fx({title:e,collapsed:t,children:n}){return i.jsxs("div",{className:"space-y-px",children:[e&&!t&&i.jsx("div",{className:"px-2 pb-1 pt-3 text-2xs font-medium uppercase tracking-wide text-surface-400",children:e}),e&&t&&i.jsx("div",{className:"mx-2 my-2 h-px bg-surface-200 dark:bg-surface-800"}),n]})}function CH(){const{t:e}=oe(),{user:t}=Oi(),n=un(),r=di(),s=Y1(),a=TR(),o=a.sidebar,[l,d]=S.useState(jH);S.useEffect(()=>{try{localStorage.setItem(RR,l?"1":"0")}catch{}},[l]);const f=SH(s,t.role),p=m=>f.filter(h=>(h.section??"main")===m);return i.jsxs("aside",{"data-sidebar":o,className:ce("flex h-full shrink-0 flex-col border-r transition-[width] duration-150",o==="default"?"border-surface-200 bg-surface-50 dark:border-surface-800 dark:bg-surface-900":"dark border-surface-800 bg-surface-900 [color-scheme:dark]",o==="accent"&&"acrm-sidebar-accent",l?"w-[52px]":"w-[220px]"),children:[i.jsxs("div",{className:ce("flex h-12 shrink-0 items-center gap-2 px-3",l&&"justify-center px-0"),children:[a.logo?i.jsx("img",{src:a.logo,alt:"",className:"h-6 w-6 shrink-0 rounded-md object-contain","data-testid":"workspace-logo"}):i.jsx("span",{className:"flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-surface-900 text-xs font-bold text-white dark:bg-white dark:text-surface-900",children:(r.name||"A").slice(0,1).toUpperCase()}),!l&&i.jsx("span",{className:"min-w-0 flex-1 truncate text-sm font-semibold text-surface-900 dark:text-white",children:r.name})]}),i.jsx("div",{className:"px-2 pb-1",children:i.jsxs("button",{type:"button",onClick:()=>gr("search.open"),title:l?e("topbar.search"):void 0,className:ce("flex h-7 w-full items-center gap-2 rounded-md px-2 text-[13px] text-surface-500 hover:bg-surface-100 dark:hover:bg-surface-800",l&&"justify-center px-0"),children:[i.jsx(Wr,{className:"h-4 w-4 shrink-0"}),!l&&i.jsxs(i.Fragment,{children:[i.jsx("span",{className:"flex-1 text-left",children:e("topbar.search")}),i.jsx(qr,{children:"⌘K"})]})]})}),i.jsxs("nav",{className:"min-h-0 flex-1 overflow-y-auto px-2 pb-2",children:[i.jsx(fx,{collapsed:l,children:p("main").map(m=>i.jsx(ux,{item:m,collapsed:l},m.id))}),i.jsx(fx,{title:e("nav.objects"),collapsed:l,children:n.map(m=>i.jsx($R,{to:pt.objectList(m.id),icon:i.jsx(Mn,{name:m.icon,color:m.color,tile:!0}),label:m.labelPlural,collapsed:l},m.id))}),p("workspace").length>0&&i.jsx(fx,{title:e("nav.workspace"),collapsed:l,children:p("workspace").map(m=>i.jsx(ux,{item:m,collapsed:l},m.id))})]}),i.jsxs("div",{className:"border-t border-surface-200 px-2 py-2 dark:border-surface-800",children:[p("bottom").map(m=>i.jsx(ux,{item:m,collapsed:l},m.id)),i.jsxs("button",{type:"button",onClick:()=>d(m=>!m),className:ce("mt-px flex h-7 w-full items-center gap-2 rounded-md px-2 text-[13px] text-surface-500 hover:bg-surface-100 dark:hover:bg-surface-800",l&&"justify-center px-0"),title:e(l?"nav.expand":"nav.collapse"),children:[l?i.jsx(i8,{className:"h-4 w-4"}):i.jsx(s8,{className:"h-4 w-4"}),!l&&i.jsx("span",{children:e("nav.collapse")})]})]})]})}function NH(){const{t:e,i18n:t}=oe(),{theme:n,toggle:r}=IR(),s=Oi(),a=il("topBar"),o=f0();return t.language,i.jsxs("header",{className:"flex h-12 shrink-0 items-center gap-2 border-b border-surface-200 bg-white px-4 dark:border-surface-800 dark:bg-surface-950",children:[i.jsxs("button",{type:"button",onClick:()=>gr("search.open"),className:"flex h-8 w-full max-w-sm items-center gap-2 rounded-md border border-surface-200 bg-surface-50 px-2.5 text-sm text-surface-400 hover:border-surface-300 dark:border-surface-800 dark:bg-surface-900 dark:hover:border-surface-700",children:[i.jsx(Wr,{className:"h-4 w-4"}),i.jsx("span",{className:"flex-1 text-left",children:e("topbar.search")}),i.jsx(qr,{children:"⌘K"})]}),i.jsxs("div",{className:"ml-auto flex items-center gap-1",children:[a.map((l,d)=>i.jsx(l,{},d)),i.jsx(dt,{label:e(n==="dark"?"topbar.lightMode":"topbar.darkMode"),icon:n==="dark"?i.jsx(yk,{}):i.jsx(ck,{}),onClick:r}),i.jsx(Tr,{align:"end",trigger:({ref:l,onClick:d})=>i.jsx(dt,{ref:l,label:e("topbar.language"),icon:i.jsx(pI,{}),onClick:d}),items:u0.map(l=>({id:l,label:o1[l],checked:l===o,onSelect:()=>void c1(l)}))}),i.jsx(Tr,{align:"end",header:i.jsxs("div",{className:"min-w-0",children:[i.jsx("div",{className:"truncate text-sm font-medium text-surface-900 dark:text-white",children:s.user.name}),i.jsx("div",{className:"truncate text-xs text-surface-500",children:s.user.email}),i.jsx("div",{className:"mt-0.5 text-2xs text-surface-400",children:e("topbar.role",{role:e(`roles.${s.role}`)})})]}),trigger:({ref:l,onClick:d})=>i.jsx("button",{ref:l,type:"button",onClick:d,"aria-label":e("topbar.userMenu"),className:"ml-1 rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500/60",children:i.jsx($s,{name:s.user.name,src:s.user.avatarUrl,size:"md"})}),items:[{id:"settings",label:e("nav.settings"),onSelect:()=>window.location.hash=`#${pt.settings()}`},...s.canSignOut?[{id:"signout",label:e("topbar.signOut"),icon:i.jsx(_0,{}),separator:!0,onSelect:()=>void s.signOut()}]:[]]})]})]})}function AH({children:e,banner:t}){const n=ci(),r=il("globalOverlays");return S.useEffect(()=>{const s=a=>{(a.metaKey||a.ctrlKey)&&a.key.toLowerCase()==="k"&&(a.preventDefault(),gr("search.open"))};return window.addEventListener("keydown",s),()=>window.removeEventListener("keydown",s)},[]),i.jsxs("div",{className:"flex h-screen w-full overflow-hidden bg-white text-surface-900 dark:bg-surface-950 dark:text-surface-100",children:[i.jsx(CH,{}),i.jsxs("div",{className:"flex min-w-0 flex-1 flex-col",children:[t,i.jsx(NH,{}),i.jsx("main",{className:"relative min-h-0 flex-1 overflow-auto",children:e},n.pathname.split("/").slice(0,3).join("/"))]}),r.map((s,a)=>i.jsx(s,{},a))]})}function _H(){const e=lp("appearance"),t=mt("extensions"),n=S.useSyncExternalStore(FT,tg,tg);S.useEffect(()=>{const r=e==null?void 0:e.themeId,a=!!r&&t.some(o=>o.id===r&&o.kind==="theme"&&o.enabled)?rp(r)??null:null;UT(q1(e,a),{theme:a})},[e,t,n])}const vl=new Map,Mv=new Set;let DR=[];function ej(){DR=[...vl.values()].map(e=>e.state).sort((e,t)=>e.id.localeCompare(t.id));for(const e of[...Mv])e()}function Ov(){return DR}function hA(e){var t;return(t=vl.get(e))==null?void 0:t.state}function EH(e){return Mv.add(e),()=>Mv.delete(e)}function ch(e,t,n){const r=vl.get(e.id);r&&r.dispose(),vl.set(e.id,{state:{id:e.id,kind:e.kind,version:e.manifest.version,status:t,...n?{error:n}:{}},dispose:()=>{}}),ej()}function MR(e){const t=vl.get(e);if(t){vl.delete(e);try{t.dispose()}catch(n){console.error(`[extensions] dispose of ${e} failed:`,n)}ej()}}function TH(e){const t=e,n=t&&typeof t=="object"&&"default"in t?t.default:null;return n&&typeof n=="object"?n:null}function IH(e,t){if(!t)throw new Error("bundle.js has no default export (export default defineModule({...}) / defineTheme({...})).");if(t.id!==e.id)throw new Error(`bundle id "${String(t.id)}" doesn't match manifest id "${e.id}".`);if(!pd(t.apiVersion))throw new Error(`bundle apiVersion "${String(t.apiVersion)}" is not supported.`)}function RH(e,t){if(!t||typeof document>"u")return()=>{};const n=document.createElement("style");return n.dataset.agentcrmExtension=e,n.textContent=t,document.head.appendChild(n),()=>n.remove()}function $H(e,t){var s;const n=[],r=a=>(n.push(a),a);try{const a=e.manifest,o={routes:[],i18n:{en:{}},...t.feature??{},id:e.id,module:{name:a.name,description:a.description,icon:a.icon??"Puzzle",category:a.category??"customisation",...(s=a.dependsOn)!=null&&s.length?{dependsOn:a.dependsOn}:{}},...t.settingsPage?{settingsPage:t.settingsPage}:{}};r(Tz(o));for(const l of t.aiTools??[])r(Tv(l));for(const l of t.automationActions??[])r(Jh(l));if(r(RH(e.id,e.files["style.css"])),typeof t.register=="function"){const l={moduleId:e.id,addAction:((f,p,m)=>r(ki.addAction(f,p,m))),addFilter:(f,p,m)=>r(ki.addFilter(f,p,m)),registerAiTool:f=>r(Tv(f)),registerAutomationAction:f=>r(Jh(f)),onDispose:f=>void n.push(f)},d=t.register(l);typeof d=="function"&&n.push(d)}}catch(a){for(const o of n.reverse())o();throw a}return()=>{for(const a of n.reverse())try{a()}catch(o){console.error(`[extensions] cleanup of ${e.id} failed:`,o)}}}function DH(e,t){if(!t.appearance||typeof t.appearance!="object")throw new Error("defineTheme({ appearance }) is required.");if(typeof t.name!="string"||!t.name)throw new Error("defineTheme({ name }) is required.");const n=[t.css,e.files["style.css"]].filter(Boolean).join(`
1140
+ `);return fz({id:e.id,apiVersion:t.apiVersion,name:t.name,...t.description?{description:t.description}:{},appearance:{...t.appearance},...n?{css:n}:{}})}function MH(e,t,n){const r=TH(t);IH(e,r),MR(e.id);const s=e.kind==="theme"?DH(e,r):$H(e,r);vl.set(e.id,{state:{id:e.id,kind:e.kind,version:e.manifest.version,status:"loaded",fingerprint:n},dispose:s}),ej()}async function OH(e){var n,r;await((r=(n=globalThis[cv])==null?void 0:n.prepare)==null?void 0:r.call(n,e))}function PH(e){return async t=>{const n=document.baseURI,r=z6(t,a=>new URL(`${C6}/${lT[a]}`,n).href),s=URL.createObjectURL(new Blob([r],{type:"text/javascript"}));try{return await import(s)}finally{URL.revokeObjectURL(s)}}}let OR=!1;function LH(e=window){const t=r=>{(r.key==="Shift"||r.shiftKey)&&(OR=!0)};e.addEventListener("keydown",t);const n=setTimeout(()=>e.removeEventListener("keydown",t),2500);return()=>{clearTimeout(n),e.removeEventListener("keydown",t)}}function PR(e=typeof location<"u"?location:void 0){if(OR)return!0;if(!e)return!1;const t=e.hash.includes("?")?e.hash.slice(e.hash.indexOf("?")):"";return[e.search,t].some(n=>{const r=new URLSearchParams(n).get("safe");return r==="1"||r==="true"})}function FH(e){return e.list("extensions").filter(t=>t&&typeof t.id=="string"&&t.manifest)}async function zH(e,t){var s;const n=(s=e.files)==null?void 0:s["bundle.js"];if(typeof n!="string"||!n)throw new Error("bundle.js is missing (upload incomplete?).");await OH(uT(n));const r=await t(n,{id:e.id,version:e.manifest.version});MH(e,r,fT(e.manifest,e.files))}let gA=Promise.resolve();function LR(e,t={}){const n=async()=>{var d,f;const s={loaded:[],unloaded:[],failed:[],skipped:[]},a=t.importBundle??PH(),o=FH(e),l=new Set(o.map(p=>p.id));for(const p of Ov())l.has(p.id)||(p.status==="loaded"&&s.unloaded.push(p.id),MR(p.id));for(const p of o){const m=hA(p.id);if(t.safeMode){(m==null?void 0:m.status)!=="skipped"&&ch(p,"skipped"),s.skipped.push(p.id);continue}if(!p.enabled){(m==null?void 0:m.status)==="loaded"&&s.unloaded.push(p.id),(m==null?void 0:m.status)!=="disabled"&&ch(p,"disabled");continue}if(!pd(p.manifest.apiVersion)){(m==null?void 0:m.status)!=="incompatible"&&ch(p,"incompatible",`apiVersion ${p.manifest.apiVersion} is not supported.`);continue}const h=(d=p.files)!=null&&d["bundle.js"]?fT(p.manifest,p.files):"";if(!((m==null?void 0:m.status)==="loaded"&&m.fingerprint===h)&&!((m==null?void 0:m.status)==="error"&&m.fingerprint===h))try{await zH(p,a),s.loaded.push(p.id)}catch(b){const x=b instanceof Error?b:new Error(String(b));t.onError||console.error(`[extensions] ${p.id} failed to load:`,x),ch(p,"error",x.message);const y=hA(p.id);y&&(y.fingerprint=h),s.failed.push({id:p.id,error:x.message}),(f=t.onError)==null||f.call(t,p.id,x)}}return s},r=gA.then(n,n);return gA=r.catch(()=>{}),r}function UH(e,t={}){let n=!1;const r=()=>void LR(e,t).then(a=>{var o;n||(o=t.onSync)==null||o.call(t,a)}),s=e.subscribe(a=>{a.has("extensions")&&r()});return()=>{n=!0,s()}}const FR=S.createContext({reconfigure:()=>window.location.reload()});function xd(){return S.useContext(FR)}function BH(){const[e,t]=S.useState(0),n=S.useMemo(()=>(Jx(),mr()),[e]),r=S.useMemo(()=>({reconfigure:()=>{Jx(),jp(),t(s=>s+1)}}),[]);return i.jsx(E_,{i18n:xt,children:i.jsxs(FR.Provider,{value:r,children:[n?i.jsx(qH,{config:n},e):i.jsx(HH,{}),i.jsx(hU,{}),i.jsx(yU,{})]})})}function HH(){const{t:e}=oe(),t=J1().flatMap(n=>n.unconfiguredRoutes??[]);return i.jsx(H_,{children:i.jsxs(U_,{children:[t.map(n=>i.jsx(xi,{path:n.path,element:n.element},n.path)),!t.some(n=>n.path==="*"||n.path==="/*")&&i.jsx(xi,{path:"*",element:i.jsx(Il,{children:i.jsx(ut,{icon:i.jsx(ba,{}),title:e("setupRequired.title")})})})]})})}function Il({children:e}){return i.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-50 p-6 dark:bg-surface-950",children:e})}function qH({config:e}){const[t,n]=S.useState({phase:"loading"}),[r,s]=S.useState(0),a=S.useCallback(()=>s(l=>l+1),[]);S.useEffect(()=>{let l=!1;const d=f=>!l&&n(f);return(async()=>{let f;try{f=await Dv()}catch(p){return d({phase:"error",error:p})}try{const p=await f.identity();if(!p)return d({phase:"signIn",store:f});if(await f.ready(),f.list("objects").length===0)return d({phase:"empty",store:f,identity:p});const m=AR(f,p);if(!m)return d({phase:"signIn",store:f});m.role==="admin"&&!m.disabled&&await hE(la(f,m)).catch(x=>console.warn("[agentcrm] schema migration skipped:",x)),Hk(async()=>{const x=f.get("config","hosting");return x!=null&&x.connectorId?{connectorId:x.connectorId,settings:{...x.settings??{},...e0(e)}}:null}),Rz(f);const h=PR(),b=await LR(f,{safeMode:h});d({phase:"ready",store:f,identity:p,user:m,safeMode:h,extensionReport:b})}catch(p){const m=p;if(m.name==="PassphraseError")return d({phase:"passphrase",store:f,wrong:m.reason==="wrong"});d({phase:"error",error:m})}})(),()=>{l=!0}},[r,e]);const o=S.useCallback(async()=>{const l=yH(e.backend);l?await l.signOut():Gw(e),jp(),a()},[e,a]);switch(t.phase){case"loading":return i.jsx(Il,{children:i.jsx(Ds,{size:"lg"})});case"error":return i.jsx(YH,{error:t.error,onRetry:a});case"passphrase":return i.jsx(ZH,{config:e,wrong:t.wrong,onSubmit:a});case"signIn":return i.jsx(QH,{onSignedIn:a});case"empty":return i.jsx(XH,{store:t.store,identity:t.identity,onDone:a});case"ready":return i.jsx(bH,{backend:e.backend,identity:t.identity,user:t.user,onSignOut:o,children:i.jsx(Mz,{store:t.store,user:t.user,children:i.jsx(VH,{identity:t.identity,initial:t.user,children:l=>i.jsx(KH,{user:l,safeMode:t.safeMode,extensionReport:t.extensionReport})})})})}}function VH({identity:e,initial:t,children:n}){const{store:r}=ps(),[s,a]=S.useState(t);return S.useEffect(()=>r.subscribe(o=>{if(!o.has("users")&&!o.has("settings"))return;const l=AR(r,e);l&&JSON.stringify(l)!==JSON.stringify(s)&&a(l)}),[r,e,s]),i.jsx(i.Fragment,{children:n(s)})}function WH(e,t){const n=S.useRef(new Map);S.useEffect(()=>{const r=n.current;for(const[s,a]of[...r])e.includes(a.feature)||(typeof a.cleanup=="function"&&a.cleanup(),r.delete(s));for(const s of e)if(!(r.has(s.id)||!s.onStart))try{r.set(s.id,{feature:s,cleanup:s.onStart({user:t})})}catch(a){console.error(`[features] onStart of ${s.id} failed:`,a)}},[e,t]),S.useEffect(()=>{const r=n.current;return()=>{for(const s of r.values())typeof s.cleanup=="function"&&s.cleanup();r.clear()}},[t.id])}function KH({user:e,safeMode:t,extensionReport:n}){const{t:r}=oe(),{store:s}=ps(),a=Y1(),o=ap(),l=un();if(WH(a,e),_H(),S.useEffect(()=>{const x=y=>{y.failed.length&&ge.error(r("app.extensionErrors",{count:y.failed.length,list:y.failed.map(v=>`${v.id} (${v.error})`).join(", ")}))};return x(n),UH(s,{safeMode:t,onSync:x})},[s,t]),e.disabled)return i.jsx(Il,{children:i.jsx(ut,{icon:i.jsx(yo,{}),title:r("errors.forbidden")})});const d=x=>x.routes.filter(y=>!y.roles||y.roles.includes(e.role)),f=a.flatMap(d),p=new Set(a.map(x=>x.id)),m=k0().filter(x=>!p.has(x.id)).flatMap(x=>d(x).map(y=>({path:y.path,module:x.id}))).filter(x=>x.path!=="/"&&!f.some(y=>y.path===x.path)),h=o.filter(x=>!x.enabled).flatMap(x=>x.objects.map(y=>({object:y,module:x.id}))),b=f.some(x=>x.path==="/");return i.jsx(H_,{children:i.jsx(AH,{banner:t?i.jsx(GH,{}):void 0,children:i.jsxs(U_,{children:[f.map(x=>i.jsx(xi,{path:x.path,element:x.element},x.path)),m.map(x=>i.jsx(xi,{path:x.path,element:i.jsx(px,{moduleId:x.module})},`off:${x.path}`)),h.flatMap(x=>[i.jsx(xi,{path:`/objects/${x.object}`,element:i.jsx(px,{moduleId:x.module})},`off:${x.object}`),i.jsx(xi,{path:`/objects/${x.object}/*`,element:i.jsx(px,{moduleId:x.module})},`off:${x.object}/*`)]),!b&&l[0]&&i.jsx(xi,{path:"/",element:i.jsx(jC,{to:pt.objectList(l[0].id),replace:!0})}),i.jsx(xi,{path:"/setup/*",element:i.jsx(jC,{to:"/",replace:!0})}),i.jsx(xi,{path:"*",element:i.jsx(JH,{})})]})})})}function GH(){const{t:e}=oe(),t=()=>{const n=new URL(window.location.href);n.searchParams.delete("safe"),n.hash=n.hash.replace(/[?&]safe=[^&]*/,"").replace(/\?$/,""),window.location.replace(n.toString())};return i.jsxs("div",{role:"status",className:"flex items-center gap-2 border-b border-amber-200 bg-amber-50 px-4 py-1.5 text-xs text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-200",children:[i.jsx(hk,{className:"h-3.5 w-3.5 shrink-0"}),i.jsx("span",{className:"flex-1",children:e("app.safeMode.banner")}),i.jsx("button",{type:"button",onClick:t,className:"font-medium underline-offset-2 hover:underline",children:e("app.safeMode.exit")})]})}function px({moduleId:e}){const{t}=oe(),{role:n}=Oi(),s=ap().find(o=>o.id===e),a=s?s.nameKey?t(s.nameKey):s.name:e;return i.jsx(ut,{className:"py-24",icon:i.jsx(V8,{}),title:t("app.moduleDisabled.title"),description:n==="admin"?t("app.moduleDisabled.hint",{name:a}):t("app.moduleDisabled.hintMember",{name:a}),action:n==="admin"?i.jsx(ue,{variant:"outline",onClick:()=>window.location.hash=`#${pt.settings("modules")}`,children:t("app.moduleDisabled.open")}):void 0})}function JH(){const{t:e}=oe();return i.jsx(ut,{className:"py-24",title:e("app.notFound"),action:i.jsx(ue,{variant:"outline",onClick:()=>window.location.hash="#/",children:e("app.backHome")})})}function YH({error:e,onRetry:t}){const{t:n}=oe(),r=xd();return i.jsx(Il,{children:i.jsx(Ke,{className:"w-full max-w-md",children:i.jsx(ut,{icon:i.jsx(yo,{}),title:n("app.loadError"),description:i.jsx("span",{className:"break-words font-mono text-xs",children:e.message}),action:i.jsxs("div",{className:"flex gap-2",children:[i.jsx(ue,{variant:"primary",onClick:t,children:n("app.retry")}),i.jsx(ue,{variant:"ghost",onClick:()=>{ld(null),r.reconfigure()},children:n("app.resetSetup")})]})})})})}function ZH({config:e,wrong:t,onSubmit:n}){const{t:r}=oe(),[s,a]=S.useState("");return i.jsx(Il,{children:i.jsx(Ke,{className:"w-full max-w-sm",children:i.jsxs("form",{"data-form-type":"other",onSubmit:o=>{o.preventDefault(),cd(e,s.trim()),n()},className:"space-y-4",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx(Rs,{className:"h-5 w-5 text-surface-500"}),i.jsx("h1",{className:"text-base font-semibold",children:r("app.passphraseTitle")})]}),i.jsx("p",{className:"text-sm text-surface-500",children:r("app.passphraseHint")}),i.jsx(Te,{label:r("app.passphrase"),htmlFor:"passphrase",error:t?r("app.passphraseWrong"):void 0,children:i.jsx(Oe,{id:"passphrase",type:"password",autoComplete:"off",autoFocus:!0,value:s,onChange:o=>a(o.target.value),invalid:t})}),i.jsx(ue,{type:"submit",variant:"primary",className:"w-full",disabled:!s.trim(),icon:i.jsx(Rs,{}),children:r("app.unlock")})]})})})}function QH({onSignedIn:e}){const{t}=oe(),n=XT("loginScreen")[0];return n?i.jsx(n,{onSignedIn:e}):i.jsx(Il,{children:i.jsx(ut,{icon:i.jsx(Rs,{}),title:t("errors.forbidden")})})}function XH({store:e,identity:t,onDone:n}){const{t:r,i18n:s}=oe(),[a,o]=S.useState(null),l=async d=>{o(d?"demo":"plain");try{await r1(la(e,null),{admin:{name:t.displayName||"Admin",email:t.email||"admin@localhost"},demo:d,locale:s.language,currency:cE(s.language)}),n()}finally{o(null)}};return i.jsx(Il,{children:i.jsx(Ke,{className:"w-full max-w-md",children:i.jsx(ut,{icon:i.jsx(ba,{}),title:r("app.emptyTitle"),description:r("app.emptyHint"),action:i.jsxs("div",{className:"flex gap-2",children:[i.jsx(ue,{variant:"primary",loading:a==="demo",disabled:!!a,onClick:()=>void l(!0),children:r("app.installDemo")}),i.jsx(ue,{variant:"outline",loading:a==="plain",disabled:!!a,onClick:()=>void l(!1),children:r("app.installEmpty")})]})})})})}const eq={dashboard:"Dashboard",reports:"Reports"},tq="Dashboard",nq="Welcome back, {{name}}",rq="You don't have access to reports.",sq="Open pipeline",iq="Weighted forecast",aq="{{pct}}% of open pipeline",oq="{{count}} open deal",lq="{{count}} open deals",cq="Won this month",dq="{{count}} deal",uq="{{count}} deals",fq="New people this month",pq="{{count}} lead",mq="{{count}} leads",hq="Overdue tasks",gq="{{count}} open task",yq="{{count}} open tasks",bq="No pipeline yet",xq="Create a pipeline in Settings to see deal reports.",vq="Pipeline by stage",wq="All reports",kq="Won / lost",jq="Won",Sq="Lost",Cq="Win rate",Nq="Win rate {{pct}}%",Aq="Lead sources",_q="People",Eq="Customers",Tq="Unknown",Iq="Activity by user",Rq="Unassigned",$q="Last {{count}} day",Dq="Last {{count}} days",Mq={note:"Notes",task:"Tasks",call:"Calls",email:"Emails",meeting:"Meetings"},Oq="Stale deals",Pq="Idle ≥ {{count}} day",Lq="Idle ≥ {{count}} days",Fq="{{count}} day idle",zq="{{count}} days idle",Uq="No stale deals — nice work.",Bq="My tasks today",Hq="All tasks",qq="Nothing due today.",Vq="Mark as done",Wq="Task completed",Kq="Today",Gq="Due {{date}}",Jq="Amount",Yq="Chart unavailable",Zq="No data for this period.",Qq="Reports",Xq="Export CSV",eV="Forecast by close month",tV="Open deals closing from the start of the period",nV="No close date",rV="Lifecycle conversion",sV="+ {{count}} more (in the CSV export)",iV="+ {{count}} more (in the CSV export)",aV={period:"Period",from:"From",to:"To",pipeline:"Pipeline"},oV={"30d":"Last 30 days","90d":"Last 90 days",ytd:"This year","12m":"Last 12 months",custom:"Custom range"},lV={stage:"Stage",kind:"Kind",count:"Count",amount:"Amount",weighted:"Weighted",total:"Total",month:"Month",wonCount:"Won",wonAmount:"Won amount",lostCount:"Lost",lostAmount:"Lost amount",winRate:"Win rate",user:"User",tasksDone:"Tasks done",tasksOpen:"Open tasks",source:"Source",people:"People",customers:"Customers",customerRate:"Customer rate",reached:"Reached",conversion:"Step conversion",deal:"Deal",owner:"Owner",idleDays:"Idle days",lastActivity:"Last activity"},cV={nav:eq,title:tq,greeting:nq,noAccess:rq,openPipeline:sq,weighted:iq,ofPipeline:aq,openDeals_one:oq,openDeals_other:lq,wonThisMonth:cq,dealsCount_one:dq,dealsCount_other:uq,newPeopleThisMonth:fq,leadsCount_one:pq,leadsCount_other:mq,overdueTasks:hq,openTasksCount_one:gq,openTasksCount_other:yq,noPipeline:bq,noPipelineHint:xq,byStage:vq,viewReports:wq,wonLost:kq,won:jq,lost:Sq,winRate:Cq,winRateValue:Nq,leadSources:Aq,people:_q,customers:Eq,unknown:Tq,activityByUser:Iq,unassigned:Rq,lastDays_one:$q,lastDays_other:Dq,activityTypes:Mq,staleDeals:Oq,idleFor_one:Pq,idleFor_other:Lq,idleDays_one:Fq,idleDays_other:zq,noStaleDeals:Uq,myTasksToday:Bq,allTasks:Hq,noTasksToday:qq,markDone:Vq,taskDone:Wq,today:Kq,overdueSince:Gq,amount:Jq,chartUnavailable:Yq,noData:Zq,reportsTitle:Qq,exportCsv:Xq,forecastByMonth:eV,forecastHint:tV,noCloseDate:nV,conversion:rV,moreRows_one:sV,moreRows_other:iV,filters:aV,range:oV,col:lV},dV={dashboard:"Tableau de bord",reports:"Rapports"},uV="Tableau de bord",fV="Bon retour, {{name}}",pV="Vous n'avez pas accès aux rapports.",mV="Pipeline ouvert",hV="Prévision pondérée",gV="{{pct}} % du pipeline ouvert",yV="{{count}} affaire ouverte",bV="{{count}} affaires ouvertes",xV="Gagné ce mois-ci",vV="{{count}} affaire",wV="{{count}} affaires",kV="Nouveaux contacts ce mois-ci",jV="{{count}} lead",SV="{{count}} leads",CV="Tâches en retard",NV="{{count}} tâche ouverte",AV="{{count}} tâches ouvertes",_V="Aucun pipeline",EV="Créez un pipeline dans les paramètres pour voir les rapports d'affaires.",TV="Pipeline par étape",IV="Tous les rapports",RV="Gagnées / perdues",$V="Gagnées",DV="Perdues",MV="Taux de réussite",OV="Taux de réussite {{pct}} %",PV="Sources de leads",LV="Contacts",FV="Clients",zV="Inconnue",UV="Activité par utilisateur",BV="Non assigné",HV="Dernier jour",qV="{{count}} derniers jours",VV={note:"Notes",task:"Tâches",call:"Appels",email:"E-mails",meeting:"Réunions"},WV="Affaires dormantes",KV="Inactives ≥ {{count}} jour",GV="Inactives ≥ {{count}} jours",JV="{{count}} jour d'inactivité",YV="{{count}} jours d'inactivité",ZV="Aucune affaire dormante, bravo.",QV="Mes tâches du jour",XV="Toutes les tâches",eW="Rien à faire aujourd'hui.",tW="Marquer comme faite",nW="Tâche terminée",rW="Aujourd'hui",sW="Échue le {{date}}",iW="Montant",aW="Graphique indisponible",oW="Aucune donnée pour cette période.",lW="Rapports",cW="Exporter en CSV",dW="Prévision par mois de clôture",uW="Affaires ouvertes clôturant à partir du début de la période",fW="Sans date de clôture",pW="Conversion du cycle de vie",mW="+ {{count}} de plus (dans l'export CSV)",hW="+ {{count}} de plus (dans l'export CSV)",gW={period:"Période",from:"Du",to:"Au",pipeline:"Pipeline"},yW={"30d":"30 derniers jours","90d":"90 derniers jours",ytd:"Cette année","12m":"12 derniers mois",custom:"Période personnalisée"},bW={stage:"Étape",kind:"Type",count:"Nombre",amount:"Montant",weighted:"Pondéré",total:"Total",month:"Mois",wonCount:"Gagnées",wonAmount:"Montant gagné",lostCount:"Perdues",lostAmount:"Montant perdu",winRate:"Taux de réussite",user:"Utilisateur",tasksDone:"Tâches faites",tasksOpen:"Tâches ouvertes",source:"Source",people:"Contacts",customers:"Clients",customerRate:"Taux de clients",reached:"Atteint",conversion:"Conversion d'étape",deal:"Affaire",owner:"Propriétaire",idleDays:"Jours d'inactivité",lastActivity:"Dernière activité"},xW={nav:dV,title:uV,greeting:fV,noAccess:pV,openPipeline:mV,weighted:hV,ofPipeline:gV,openDeals_one:yV,openDeals_other:bV,wonThisMonth:xV,dealsCount_one:vV,dealsCount_other:wV,newPeopleThisMonth:kV,leadsCount_one:jV,leadsCount_other:SV,overdueTasks:CV,openTasksCount_one:NV,openTasksCount_other:AV,noPipeline:_V,noPipelineHint:EV,byStage:TV,viewReports:IV,wonLost:RV,won:$V,lost:DV,winRate:MV,winRateValue:OV,leadSources:PV,people:LV,customers:FV,unknown:zV,activityByUser:UV,unassigned:BV,lastDays_one:HV,lastDays_other:qV,activityTypes:VV,staleDeals:WV,idleFor_one:KV,idleFor_other:GV,idleDays_one:JV,idleDays_other:YV,noStaleDeals:ZV,myTasksToday:QV,allTasks:XV,noTasksToday:eW,markDone:tW,taskDone:nW,today:rW,overdueSince:sW,amount:iW,chartUnavailable:aW,noData:oW,reportsTitle:lW,exportCsv:cW,forecastByMonth:dW,forecastHint:uW,noCloseDate:fW,conversion:pW,moreRows_one:mW,moreRows_other:hW,filters:gW,range:yW,col:bW},Hu=864e5;function fr(e){try{return e()}catch{return null}}function Pv(e,t=!0){const n=_r();return r=>Bf(r,e,n,t)}function Nn(e){return new Intl.NumberFormat(_r()).format(e)}function yA(e){const t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}`}function bA(e){const t=/^(\d{4})-(\d{2})$/.exec(e);return t?new Intl.DateTimeFormat(_r(),{month:"short",year:"2-digit"}).format(new Date(Number(t[1]),Number(t[2])-1,1)):e}const Nae={note:Xo("yellow"),task:Xo("blue"),call:Xo("green"),email:Xo("purple"),meeting:Xo("orange")};function na({children:e}){return i.jsx("div",{className:"flex h-32 items-center justify-center text-[13px] text-surface-400",children:e})}function fc({head:e,rows:t,align:n,foot:r}){const s=a=>(n==null?void 0:n[a])==="right"?"text-right tabular-nums":"text-left";return i.jsx("div",{className:"overflow-x-auto",children:i.jsxs("table",{className:"w-full text-[13px]",children:[i.jsx("thead",{children:i.jsx("tr",{className:"border-b border-surface-100 text-xs text-surface-500 dark:border-surface-800",children:e.map((a,o)=>i.jsx("th",{className:ce("whitespace-nowrap px-2 py-1.5 font-medium",s(o)),children:a},o))})}),i.jsx("tbody",{children:t.map((a,o)=>i.jsx("tr",{className:"border-b border-surface-100 last:border-0 dark:border-surface-800",children:a.map((l,d)=>i.jsx("td",{className:ce("whitespace-nowrap px-2 py-1.5 text-surface-700 dark:text-surface-200",s(d)),children:l},d))},o))}),r&&i.jsx("tfoot",{children:i.jsx("tr",{className:"border-t border-surface-200 font-medium text-surface-900 dark:border-surface-700 dark:text-white",children:r.map((a,o)=>i.jsx("td",{className:ce("whitespace-nowrap px-2 py-1.5",s(o)),children:a},o))})})]})})}function vW({stages:e,money:t}){return i.jsx("ul",{className:"mt-3 grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3",children:e.map(n=>i.jsxs("li",{className:"flex min-w-0 items-center gap-1.5 text-xs","data-stage":n.stageId,children:[i.jsx("span",{className:"h-2 w-2 shrink-0 rounded-sm",style:{background:Xo(n.color)}}),i.jsx("span",{className:"truncate text-surface-600 dark:text-surface-300",children:n.label}),i.jsxs("span",{className:"ml-auto shrink-0 tabular-nums text-surface-500",children:[n.count," · ",t(n.amount)]})]},n.stageId))})}function wW({stages:e,colors:t}){const n=Math.max(1,...e.map(r=>r.reached));return i.jsx("div",{className:"space-y-1.5",children:e.map(r=>i.jsxs("div",{className:"flex items-center gap-3 text-[13px]","data-funnel-stage":r.id,children:[i.jsx("span",{className:"w-28 shrink-0 truncate text-surface-600 dark:text-surface-300",children:r.label}),i.jsx("div",{className:"h-5 flex-1 rounded bg-surface-100 dark:bg-surface-800",children:i.jsx("div",{className:"h-5 rounded",style:{width:`${r.reached/n*100}%`,background:Xo((t==null?void 0:t[r.id])??"blue")}})}),i.jsx("span",{className:"w-12 shrink-0 text-right tabular-nums text-surface-700 dark:text-surface-200",children:Nn(r.reached)}),i.jsx("span",{className:"w-14 shrink-0 text-right tabular-nums text-xs text-surface-500",children:r.conversionFromPrevious===null?"—":`${r.conversionFromPrevious}%`})]},r.id))})}const kW=()=>Sr(()=>import("./chartsImpl-qlHW3VOv.js"),[],import.meta.url);class jW extends S.Component{constructor(){super(...arguments);wt(this,"state",{failed:!1})}static getDerivedStateFromError(){return{failed:!0}}componentDidCatch(n,r){console.warn("Chart unavailable:",n.message,r.componentStack??"")}render(){return this.state.failed?i.jsx(SW,{height:this.props.height}):this.props.children}}function SW({height:e}){const{t}=oe("dashboard");return i.jsx("div",{style:{height:Math.min(e,96)},className:"flex items-center justify-center rounded-md border border-dashed border-surface-200 text-xs text-surface-400 dark:border-surface-800","data-chart-unavailable":"",children:t("chartUnavailable")})}function CW({height:e}){return i.jsx("div",{style:{height:e},className:"w-full animate-pulse rounded-md bg-surface-100 dark:bg-surface-800/60","aria-hidden":"true"})}function Sp(e,t=220){const n=S.lazy(async()=>({default:(await kW())[e]}));function r(s){const a=s.height??t;return i.jsx(jW,{height:a,children:i.jsx(S.Suspense,{fallback:i.jsx(CW,{height:a}),children:i.jsx(n,{...s})})})}return r.displayName=e,r}const zR=Sp("PipelineStageChart"),UR=Sp("WonLostChart"),BR=Sp("LeadSourcesChart",160),HR=Sp("ActivityByUserChart"),NW=Sp("ForecastMonthChart");function qR({deals:e,users:t,objectOf:n,money:r}){const{t:s}=oe("dashboard");return i.jsx("ul",{className:"divide-y divide-surface-100 dark:divide-surface-800",children:e.map(a=>{const o=a.ownerId?t.get(a.ownerId):void 0;return i.jsx("li",{"data-stale-deal":a.id,children:i.jsxs(Rn,{to:pt.record(n(a.id),a.id),className:"-mx-2 flex items-center gap-3 rounded-md px-2 py-1.5 text-[13px] hover:bg-surface-50 dark:hover:bg-surface-800/60",children:[i.jsxs("span",{className:"min-w-0 flex-1",children:[i.jsx("span",{className:"block truncate font-medium text-surface-900 dark:text-white",children:a.label}),i.jsx("span",{className:"block truncate text-xs text-surface-500",children:a.stage})]}),i.jsx("span",{className:"shrink-0 text-xs tabular-nums text-amber-600 dark:text-amber-400",children:s("idleDays",{count:a.idleDays})}),i.jsx("span",{className:"w-16 shrink-0 text-right tabular-nums text-surface-700 dark:text-surface-200",children:r(a.amount)}),i.jsx("span",{className:"w-5 shrink-0",title:o==null?void 0:o.name,children:o&&i.jsx($s,{name:o.name,src:o.avatarUrl,size:"sm"})})]})},a.id)})})}const AW={4:"col-span-12 md:col-span-6 lg:col-span-4",6:"col-span-12 md:col-span-6",8:"col-span-12 lg:col-span-8",12:"col-span-12"};function _W(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),1).getTime()}function EW(e){const t=new Date(e);return new Date(t.getFullYear(),t.getMonth(),t.getDate()+1).getTime()-1}function yu({label:e,value:t,sub:n,icon:r,to:s,tone:a}){const o=i.jsxs("div",{className:ce("h-full rounded-lg border border-surface-200 bg-white px-4 py-3 shadow-card dark:border-surface-800 dark:bg-surface-900",s&&"transition-colors hover:border-surface-300 dark:hover:border-surface-700"),children:[i.jsxs("div",{className:"flex items-center gap-1.5 text-xs text-surface-500",children:[r&&i.jsx("span",{className:"[&>svg]:h-3.5 [&>svg]:w-3.5",children:r}),i.jsx("span",{className:"truncate",children:e})]}),i.jsx("div",{className:ce("mt-1 truncate text-xl font-semibold tabular-nums text-surface-900 dark:text-white",a==="danger"&&"text-red-600 dark:text-red-400"),children:t}),n&&i.jsx("div",{className:"mt-0.5 truncate text-xs text-surface-500",children:n})]});return s?i.jsx(Rn,{to:s,className:"block",children:o}):o}function TW(){const{t:e}=oe("dashboard"),t=Xe(),n=Ei(),r=di(),s=mt("records"),a=Ti(),o=ms(),l=sr({includeDisabled:!0}),d=mt("objects"),f=Ge("reports.read"),p=S.useMemo(()=>Pv(r.defaultCurrency),[r.defaultCurrency]),m=S.useMemo(()=>{var me,Se,Y;if(!f)return null;const O=t.now(),z=_W(O),R=fr(()=>oE(t)),V=fr(()=>Cl(t)),X=fr(()=>s0(t)),Q=fr(()=>pf(t,{months:6})),ee=((me=fr(()=>pf(t,{months:1})))==null?void 0:me.months[0])??null,se=s.filter(ve=>ve.object==="people"&&!ve.deletedAt).filter(ve=>ve.createdAt>=z),M=se.filter(ve=>ve.fields.lifecycleStage==="lead").length,F=(Se=d.find(ve=>ve.id==="people"))==null?void 0:Se.fields.find(ve=>ve.id==="leadSource"),Z=(((Y=fr(()=>a0(t)))==null?void 0:Y.sources)??[]).map(ve=>{var Fe,Ue;return{...ve,label:ve.id?ve.label:e("unknown"),color:(Ue=(Fe=F==null?void 0:F.options)==null?void 0:Fe.find(L=>L.id===ve.id))==null?void 0:Ue.color}}),de=fr(()=>i0(t,{days:30})),re=fr(()=>o0(t,{limit:6})),q=EW(O),ne=fr(()=>Mw(t,{assigneeId:n.id,status:"open"}).items.filter(ve=>ve.dueAt!==void 0&&ve.dueAt<=q))??[];return{now:O,stats:R,fc:V,byStage:X,wl:Q,thisMonth:ee,newPeople:se.length,newLeads:M,sources:Z,activity:de,stale:re,myTasks:ne}},[t,f,s,a,o,l,d,r,n.id,e]),h=S.useMemo(()=>new Map(l.map(O=>[O.id,O])),[l]),b=S.useMemo(()=>{const O=new Map(s.map(z=>[z.id,z.object]));return z=>O.get(z)??"deals"},[s]),x=il("dashboardWidgets"),y=Cf("deals"),v=Cf("reports");if(!m)return i.jsxs("div",{children:[i.jsx(Kr,{title:e("title"),icon:i.jsx(Fu,{})}),i.jsx(ut,{className:"py-24",icon:i.jsx(Fu,{}),title:e("noAccess")})]});const{stats:k,fc:j,byStage:C,wl:A,thisMonth:_,sources:D,activity:I,stale:T,myTasks:E}=m,P=!!j&&y,U=(I==null?void 0:I.users.filter(O=>O.total>0))??[];return i.jsxs("div",{children:[i.jsx(Kr,{title:e("title"),icon:i.jsx(Fu,{}),description:e("greeting",{name:n.name.split(" ")[0]})}),i.jsxs("div",{className:"space-y-4 p-4 sm:p-6",children:[i.jsxs("div",{className:ce("grid grid-cols-2 gap-3 md:grid-cols-3",y?"xl:grid-cols-5":"xl:grid-cols-2"),"data-testid":"kpis",children:[y&&i.jsxs(i.Fragment,{children:[i.jsx(yu,{icon:i.jsx(eU,{}),label:e("openPipeline"),value:j?p(j.openAmount):"—",sub:j?e("openDeals",{count:j.openCount}):e("noPipeline")}),i.jsx(yu,{icon:i.jsx(xI,{}),label:e("weighted"),value:j?p(j.weightedAmount):"—",sub:j&&j.openAmount?e("ofPipeline",{pct:Math.round(j.weightedAmount/j.openAmount*100)}):void 0}),i.jsx(yu,{icon:i.jsx(bk,{}),label:e("wonThisMonth"),value:_?p(_.wonAmount):"—",sub:_?e("dealsCount",{count:_.wonCount}):void 0})]}),i.jsx(yu,{icon:i.jsx(R0,{}),label:e("newPeopleThisMonth"),value:Nn(m.newPeople),sub:e("leadsCount",{count:m.newLeads})}),i.jsx(yu,{icon:i.jsx(yo,{}),label:e("overdueTasks"),value:Nn((k==null?void 0:k.overdueTasks)??0),sub:e("openTasksCount",{count:(k==null?void 0:k.openTasks)??0}),to:pt.tasks(),tone:k!=null&&k.overdueTasks?"danger":void 0})]}),i.jsxs("div",{className:"grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-12",children:[P&&C&&i.jsxs(Ke,{className:"md:col-span-2 lg:col-span-7",title:e("byStage"),actions:v?i.jsx(Rn,{to:pt.reports(),className:"text-xs text-surface-500 hover:text-surface-900 dark:hover:text-white",children:e("viewReports")}):void 0,children:[i.jsx(zR,{stages:C.stages,money:p}),i.jsx(vW,{stages:C.stages,money:p})]}),P&&A&&i.jsx(Ke,{className:"lg:col-span-5",title:e("wonLost"),actions:i.jsx("span",{className:"text-xs text-surface-500",children:A.totals.winRate===null?"":e("winRateValue",{pct:A.totals.winRate})}),children:i.jsx(UR,{months:A.months,money:p})}),i.jsx(Ke,{className:"lg:col-span-5",title:e("leadSources"),children:D.length?i.jsx(BR,{sources:D}):i.jsx(na,{children:e("noData")})}),i.jsx(Ke,{className:"lg:col-span-7",title:e("activityByUser"),actions:i.jsx("span",{className:"text-xs text-surface-500",children:e("lastDays",{count:30})}),children:U.length?i.jsx(HR,{users:U}):i.jsx(na,{children:e("noData")})}),P&&T&&i.jsx(Ke,{className:"lg:col-span-6",title:e("staleDeals"),actions:i.jsx("span",{className:"text-xs text-surface-500",children:e("idleFor",{count:T.days})}),children:T.deals.length?i.jsx(qR,{deals:T.deals,users:h,objectOf:b,money:p}):i.jsx(na,{children:e("noStaleDeals")})}),i.jsx(Ke,{className:ce(P?"lg:col-span-6":"md:col-span-2 lg:col-span-12"),title:e("myTasksToday"),actions:i.jsx(Rn,{to:pt.tasks(),className:"text-xs text-surface-500 hover:text-surface-900 dark:hover:text-white",children:e("allTasks")}),children:i.jsx(IW,{tasks:E,now:m.now})})]}),x.length>0&&i.jsx("div",{className:"grid grid-cols-12 gap-4",children:x.map(O=>i.jsx("div",{className:AW[O.span??12]??"col-span-12",children:i.jsx(O.component,{})},O.id))})]})]})}function IW({tasks:e,now:t}){const{t:n}=oe("dashboard"),r=Xe(),s=Ge("activities.write"),a=ya(),[o,l]=S.useState(null);if(!e.length)return i.jsx(na,{children:n("noTasksToday")});const d=async p=>{l(p);try{await Oc(r,p),ge.success(n("taskDone"))}catch(m){ge.error(m instanceof Error?m.message:String(m))}finally{l(null)}},f=new Date(t).toDateString();return i.jsx("ul",{className:"divide-y divide-surface-100 dark:divide-surface-800",children:e.map(p=>{const m=p.dueAt!==void 0&&p.dueAt<t&&new Date(p.dueAt).toDateString()!==f;return i.jsxs("li",{className:"flex items-start gap-2.5 py-1.5 text-[13px]","data-task":p.id,children:[i.jsx(Ot,{className:"mt-0.5",checked:!1,disabled:!s||o===p.id,"aria-label":n("markDone"),onChange:()=>void d(p.id)}),i.jsxs("div",{className:"min-w-0 flex-1",children:[i.jsx("div",{className:"truncate text-surface-900 dark:text-white",children:p.title}),p.targets.length>0&&i.jsx("div",{className:"flex flex-wrap gap-x-2 text-xs",children:p.targets.map(h=>i.jsx(Rn,{to:pt.record(h.object,h.id),className:"truncate text-surface-500 hover:text-accent-600 hover:underline",children:a(h.id)??h.id},h.id))})]}),i.jsx("span",{className:ce("shrink-0 text-xs tabular-nums",m?"text-red-600 dark:text-red-400":"text-surface-500"),children:m?n("overdueSince",{date:Pw(p.dueAt,_r())}):n("today")})]},p.id)})})}const RW={id:"dashboard",module:fs("dashboard"),routes:[{path:"/",element:S.createElement(TW)}],navItems:[{id:"dashboard",label:"dashboard:nav.dashboard",icon:Fu,to:"/",section:"main",order:0}],i18n:{en:cV,fr:xW}},$W={title:"Tasks"},DW="Tasks",MW="New task",OW="Unassigned",PW="No open tasks",LW="Tasks created on records show up here.",FW="Due {{date}}",zW={mine:"My tasks",all:"All tasks",overdue:"Overdue",upcoming:"Upcoming",done:"Done"},UW={mine:"You're all caught up — no open tasks.",all:"No open tasks.",overdue:"Nothing overdue.",upcoming:"No upcoming tasks.",done:"No completed tasks yet."},BW={search:"Filter tasks…",assignee:"Assignee",anyone:"Anyone",me:"{{name}} (me)",noMatch:"No task matches this filter."},HW={all:"Tasks",overdue:"Overdue",today:"Today",tomorrow:"Tomorrow",thisWeek:"This week",later:"Later",noDate:"No date",doneToday:"Completed today",doneYesterday:"Completed yesterday",doneThisWeek:"Completed this week",doneEarlier:"Completed earlier"},qW={today:"Today",tomorrow:"Tomorrow",yesterday:"Yesterday",nextWeek:"Next week",inTwoWeeks:"In 2 weeks"},VW={empty:"No tasks",complete:"Complete “{{title}}”",reopen:"Reopen “{{title}}”",actions:"Task actions",edit:"Edit",markDone:"Mark as done",markOpen:"Mark as not done",delete:"Delete",deleteConfirm:"Delete the task “{{title}}”?",dueDate:"Due date",dueOn:"Due {{date}}",setDue:"Set a due date",noDue:"Due date",clearDue:"Remove due date",assignedTo:"Assigned to {{name}}",searchUsers:"Assign to…",noUsers:"No matching user",unassign:"Unassign",attachments_one:"{{count}} attachment",attachments_other:"{{count}} attachments"},WW={newTitle:"New task",editTitle:"Edit task",title:"Title",titlePlaceholder:"Call back about the proposal",titleRequired:"Give the task a title.",description:"Description",markdownHint:"Markdown supported",descriptionPlaceholder:"Details, links, checklist…",preview:"Preview",write:"Write",nothingToPreview:"Nothing to preview.",dueDate:"Due date",dueTime:"Due time",assignee:"Assignee",related:"Related records",object:"Object",addRecord:"Link a {{object}}…",removeTarget:"Remove",cancel:"Cancel",save:"Save",create:"Create task",attachments:"Attachments",attach:"Attach files"},KW={created:"Task created",updated:"Task updated",deleted:"Task deleted"},GW={nav:$W,title:DW,newTask:MW,unassigned:OW,empty:PW,emptyHint:LW,due:FW,views:zW,emptyViews:UW,filter:BW,groups:HW,quick:qW,list:VW,editor:WW,toast:KW},JW={title:"Tâches"},YW="Tâches",ZW="Nouvelle tâche",QW="Non assignée",XW="Aucune tâche ouverte",eK="Les tâches créées sur les fiches apparaissent ici.",tK="Échéance {{date}}",nK={mine:"Mes tâches",all:"Toutes les tâches",overdue:"En retard",upcoming:"À venir",done:"Terminées"},rK={mine:"Vous êtes à jour — aucune tâche ouverte.",all:"Aucune tâche ouverte.",overdue:"Rien en retard.",upcoming:"Aucune tâche à venir.",done:"Aucune tâche terminée pour l'instant."},sK={search:"Filtrer les tâches…",assignee:"Assignée à",anyone:"Tout le monde",me:"{{name}} (moi)",noMatch:"Aucune tâche ne correspond à ce filtre."},iK={all:"Tâches",overdue:"En retard",today:"Aujourd'hui",tomorrow:"Demain",thisWeek:"Cette semaine",later:"Plus tard",noDate:"Sans date",doneToday:"Terminées aujourd'hui",doneYesterday:"Terminées hier",doneThisWeek:"Terminées cette semaine",doneEarlier:"Terminées plus tôt"},aK={today:"Aujourd'hui",tomorrow:"Demain",yesterday:"Hier",nextWeek:"Semaine prochaine",inTwoWeeks:"Dans 2 semaines"},oK={empty:"Aucune tâche",complete:"Terminer « {{title}} »",reopen:"Rouvrir « {{title}} »",actions:"Actions de la tâche",edit:"Modifier",markDone:"Marquer comme terminée",markOpen:"Marquer comme non terminée",delete:"Supprimer",deleteConfirm:"Supprimer la tâche « {{title}} » ?",dueDate:"Échéance",dueOn:"Échéance {{date}}",setDue:"Définir une échéance",noDue:"Échéance",clearDue:"Retirer l'échéance",assignedTo:"Assignée à {{name}}",searchUsers:"Assigner à…",noUsers:"Aucun utilisateur correspondant",unassign:"Retirer l'assignation",attachments_one:"{{count}} pièce jointe",attachments_other:"{{count}} pièces jointes"},lK={newTitle:"Nouvelle tâche",editTitle:"Modifier la tâche",title:"Titre",titlePlaceholder:"Rappeler au sujet de la proposition",titleRequired:"Donnez un titre à la tâche.",description:"Description",markdownHint:"Markdown pris en charge",descriptionPlaceholder:"Détails, liens, checklist…",preview:"Aperçu",write:"Écrire",nothingToPreview:"Rien à afficher.",dueDate:"Échéance",dueTime:"Heure d'échéance",assignee:"Assignée à",related:"Fiches liées",object:"Objet",addRecord:"Lier : {{object}}…",removeTarget:"Retirer",cancel:"Annuler",save:"Enregistrer",create:"Créer la tâche",attachments:"Pièces jointes",attach:"Joindre des fichiers"},cK={created:"Tâche créée",updated:"Tâche mise à jour",deleted:"Tâche supprimée"},dK={nav:JW,title:YW,newTask:ZW,unassigned:QW,empty:XW,emptyHint:eK,due:tK,views:nK,emptyViews:rK,filter:sK,groups:iK,quick:aK,list:oK,editor:lK,toast:cK},tj="09:00",uK=["overdue","today","tomorrow","thisWeek","later","noDate"],fK=["doneToday","doneYesterday","doneThisWeek","doneEarlier"];function F0(e){const t=new Date(e);return t.setHours(0,0,0,0),t.getTime()}function ei(e,t){const n=new Date(e);return n.setDate(n.getDate()+t),n.getTime()}function pK(e,t){return!e.doneAt&&e.dueAt!==void 0&&e.dueAt<t}function mK(e,t){if(e.dueAt===void 0)return"noDate";if(e.dueAt<t)return"overdue";const n=F0(t);return e.dueAt<ei(n,1)?"today":e.dueAt<ei(n,2)?"tomorrow":e.dueAt<ei(n,7)?"thisWeek":"later"}function hK(e,t){const n=e.doneAt??0,r=F0(t);return n>=r?"doneToday":n>=ei(r,-1)?"doneYesterday":n>=ei(r,-7)?"doneThisWeek":"doneEarlier"}function VR(e,t){return(e.dueAt??1/0)-(t.dueAt??1/0)||e.createdAt-t.createdAt}function WR(e,t){return(t.doneAt??0)-(e.doneAt??0)}function gK(e,t){var a,o;const n=new Map,r=new Map;for(const l of e)if(l.doneAt){const d=hK(l,t);r.set(d,[...r.get(d)??[],l])}else{const d=mK(l,t);n.set(d,[...n.get(d)??[],l])}const s=[];for(const l of uK)(a=n.get(l))!=null&&a.length&&s.push({id:l,tasks:n.get(l).sort(VR)});for(const l of fK)(o=r.get(l))!=null&&o.length&&s.push({id:l,tasks:r.get(l).sort(WR)});return s}function yK(e){const t=e.filter(r=>!r.doneAt).sort(VR),n=e.filter(r=>!!r.doneAt).sort(WR);return[...t,...n]}const jg=e=>String(e).padStart(2,"0");function nj(e){if(e===void 0)return"";const t=new Date(e);return`${t.getFullYear()}-${jg(t.getMonth()+1)}-${jg(t.getDate())}`}function rj(e){if(e===void 0)return"";const t=new Date(e);return`${jg(t.getHours())}:${jg(t.getMinutes())}`}function sj(e,t){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return;const[n,r,s]=e.split("-").map(Number),[a,o]=(t&&/^\d{2}:\d{2}$/.test(t)?t:tj).split(":").map(Number);return new Date(n,r-1,s,a,o,0,0).getTime()}function xA(e,t){return sj(nj(e),t!==void 0?rj(t):tj)}function bK(e){return e!==void 0&&rj(e)!==tj}const xK={id:"assignee",label:"",type:"user"};function ij({open:e,onClose:t,task:n,defaultTargets:r,defaultAssigneeId:s,defaultTitle:a,onSaved:o}){var q;const{t:l}=oe("tasks"),d=Xe(),f=Ei(),p=un(),m=ya(),[h,b]=S.useState(""),[x,y]=S.useState(""),[v,k]=S.useState(!1),[j,C]=S.useState(""),[A,_]=S.useState(""),[D,I]=S.useState(void 0),[T,E]=S.useState([]),[P,U]=S.useState(""),[O,z]=S.useState(!1),[R,V]=S.useState(null),[X,Q]=S.useState([]),ee=D0();S.useEffect(()=>{var me,Se;if(!e)return;b((n==null?void 0:n.title)??a??""),y((n==null?void 0:n.body)??""),k(!1),C(nj(n==null?void 0:n.dueAt)),_(bK(n==null?void 0:n.dueAt)?rj(n==null?void 0:n.dueAt):""),I(n?n.assigneeId:s??f.id);const ne=(n==null?void 0:n.targets)??r??[];E(ne),U(((me=ne[0])==null?void 0:me.object)??((Se=p[0])==null?void 0:Se.id)??""),V(null),z(!1),Q((n==null?void 0:n.attachments)??[]),ee.reset()},[e,n==null?void 0:n.id]);const J=ne=>y(me=>`${me}${me&&!me.endsWith(`
1141
1141
  `)?`
1142
1142
  `:""}${t1(ne.name,ne.id)}
1143
1143
  `),se=async ne=>{for(const me of await ee.add(ne))c0(me.mime)&&J(me)},M=S.useMemo(()=>new Map(p.map(ne=>[ne.id,ne])),[p]),F=S.useMemo(()=>({id:"x",label:"",type:"relation",relation:{object:P,cardinality:"many"}}),[P]),Z=T.filter(ne=>ne.object===P).map(ne=>ne.id),de=ne=>{const me=(Array.isArray(ne)?ne:ne?[ne]:[]).map(String);E(Se=>{const Y=Se.filter(Ue=>Ue.object!==P),ve=Se.filter(Ue=>Ue.object===P&&me.includes(Ue.id)),Fe=me.filter(Ue=>!ve.some(L=>L.id===Ue)).map(Ue=>({object:P,id:Ue}));return[...Y,...ve,...Fe]})},re=async ne=>{if(ne.preventDefault(),!h.trim()){V(l("editor.titleRequired"));return}if(ee.busy)return;z(!0),V(null);const me=sj(j,A),Se=[...X,...ee.ids.filter(Y=>!X.includes(Y))];try{const Y=n?await Xa(d,n.id,{title:h.trim(),body:x,dueAt:me??null,assigneeId:D??null,targets:T,attachments:Se}):await ga(d,{type:"task",title:h.trim(),body:x||void 0,dueAt:me??null,assigneeId:D??null,targets:T,...Se.length?{attachments:Se}:{}});ge.success(l(n?"toast.updated":"toast.created")),o==null||o(Y),t()}catch(Y){V(Y instanceof Error?Y.message:String(Y)),z(!1)}};return i.jsx(on,{open:e,onClose:t,size:"lg",title:l(n?"editor.editTitle":"editor.newTitle"),dismissible:!1,children:i.jsx(pp,{onFiles:ne=>void ee.add(ne),disabled:!ee.available,children:i.jsxs("form",{"data-form-type":"other",onSubmit:ne=>void re(ne),className:"space-y-3 text-[13px]",children:[i.jsx(Te,{label:l("editor.title"),htmlFor:"task-title",error:R??void 0,children:i.jsx(Oe,{id:"task-title",autoFocus:!0,value:h,placeholder:l("editor.titlePlaceholder"),onChange:ne=>b(ne.target.value),invalid:!!R})}),i.jsxs("div",{children:[i.jsxs("div",{className:"mb-1 flex items-center justify-between",children:[i.jsxs("label",{htmlFor:"task-body",className:"text-xs font-medium text-surface-600 dark:text-surface-300",children:[l("editor.description"),i.jsx("span",{className:"ml-1 font-normal text-surface-400",children:l("editor.markdownHint")})]}),i.jsxs("button",{type:"button",onClick:()=>k(ne=>!ne),className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-xs text-surface-500 hover:bg-surface-100 hover:text-surface-800 dark:hover:bg-surface-800 dark:hover:text-surface-100",children:[i.jsx("span",{className:ce("inline-flex",v&&"hidden"),children:i.jsx(A0,{className:"h-3.5 w-3.5"})}),i.jsx("span",{className:ce("inline-flex",!v&&"hidden"),children:i.jsx(ui,{className:"h-3.5 w-3.5"})}),i.jsx("span",{children:l(v?"editor.write":"editor.preview")})]})]}),i.jsx("div",{className:ce(v&&"hidden"),children:i.jsx(Cr,{id:"task-body",rows:4,value:x,placeholder:l("editor.descriptionPlaceholder"),onChange:ne=>y(ne.target.value),onPaste:ne=>{const me=ee.available?TI(ne):[];me.length&&(ne.preventDefault(),se(me))}})}),i.jsx("div",{className:ce("min-h-[92px] rounded-md border border-surface-200 px-2.5 py-1.5 dark:border-surface-700",!v&&"hidden"),children:x.trim()?i.jsx(vp,{source:x}):i.jsx("span",{className:"text-sm text-surface-400",children:l("editor.nothingToPreview")})})]}),i.jsxs("div",{className:"grid grid-cols-1 gap-3 sm:grid-cols-2",children:[i.jsx(Te,{label:l("editor.dueDate"),htmlFor:"task-due",children:i.jsxs("div",{className:"flex gap-2",children:[i.jsx(Oe,{id:"task-due",type:"date",value:j,onChange:ne=>C(ne.target.value),className:"min-w-0 flex-1"}),i.jsx(Oe,{"aria-label":l("editor.dueTime"),type:"time",value:A,disabled:!j,onChange:ne=>_(ne.target.value),className:"w-28"})]})}),i.jsx(Te,{label:l("editor.assignee"),children:i.jsx(hr,{field:xK,value:D,onChange:ne=>I(typeof ne=="string"?ne:void 0),placeholder:l("unassigned")})})]}),i.jsx(Te,{label:l("editor.related"),children:i.jsxs("div",{className:"space-y-2",children:[T.length>0&&i.jsx("div",{className:"flex flex-wrap gap-1","data-testid":"task-targets",children:T.map(ne=>{const me=M.get(ne.object);return i.jsxs("span",{className:"inline-flex max-w-full items-center gap-1 rounded border border-surface-200 bg-surface-50 py-0.5 pl-1 pr-0.5 text-xs dark:border-surface-700 dark:bg-surface-800",children:[i.jsx(Mn,{name:me==null?void 0:me.icon,color:me==null?void 0:me.color,tile:!0,className:"h-4 w-4"}),i.jsx("span",{className:"truncate",children:m(ne.id)??ne.id}),i.jsx("button",{type:"button","aria-label":l("editor.removeTarget"),onClick:()=>E(Se=>Se.filter(Y=>Y.id!==ne.id)),className:"rounded p-0.5 text-surface-400 hover:bg-surface-200 hover:text-surface-700 dark:hover:bg-surface-700",children:i.jsx(an,{className:"h-3 w-3"})})]},ne.id)})}),i.jsxs("div",{className:"flex gap-2",children:[i.jsx(Ve,{"aria-label":l("editor.object"),className:"w-40 shrink-0",value:P,onChange:ne=>U(ne.target.value),options:p.map(ne=>({value:ne.id,label:ne.labelPlural}))}),P&&i.jsx(hr,{field:F,value:Z,onChange:de,placeholder:l("editor.addRecord",{object:((q=M.get(P))==null?void 0:q.labelSingular)??""}),className:"min-w-0 flex-1"},P)]})]})}),ee.available&&i.jsx(Te,{label:l("editor.attachments"),children:i.jsxs("div",{className:"space-y-2","data-testid":"task-attachments",children:[i.jsx(Ef,{ids:X,size:"sm",onRemove:ne=>Q(me=>me.filter(Se=>Se!==ne.id))}),i.jsx(M0,{uploads:ee,onInsertInline:J}),i.jsx(mp,{size:"xs",variant:"outline",onFiles:ne=>void ee.add(ne),label:l("editor.attach"),testId:"task-file-input"})]})}),i.jsxs("div",{className:"-mx-5 -mb-4 mt-4 flex items-center justify-end gap-2 border-t border-surface-100 px-5 py-3 dark:border-surface-800",children:[i.jsx(ue,{variant:"ghost",onClick:t,children:l("editor.cancel")}),i.jsx(ue,{type:"submit",variant:"primary",icon:n?i.jsx(Er,{}):i.jsx($t,{}),loading:O,disabled:ee.busy,children:l(n?"editor.save":"editor.create")})]})]})})})}function vK(){return Date.now()}function KR({tasks:e,showTargets:t=!1,emptyText:n,groupByDue:r=!1}){const{t:s}=oe("tasks"),a=vK(),[o,l]=S.useState(null),d=S.useMemo(()=>r?gK(e,a):[{id:"all",tasks:yK(e)}],[e,r,a]);return e.length===0?i.jsx(ut,{className:"py-10",icon:i.jsx($i,{}),title:n??s("list.empty")}):i.jsxs("div",{className:"text-[13px]",children:[d.map(f=>i.jsxs("section",{"aria-label":r?s(`groups.${f.id}`):void 0,children:[r&&i.jsxs("h3",{className:ce("sticky top-0 z-[1] flex items-center gap-2 border-b border-surface-100 bg-surface-50/95 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide backdrop-blur dark:border-surface-800 dark:bg-surface-900/95",f.id==="overdue"?"text-red-600 dark:text-red-400":"text-surface-500"),children:[s(`groups.${f.id}`),i.jsx("span",{className:"rounded bg-surface-200/70 px-1 text-2xs font-medium text-surface-600 dark:bg-surface-800 dark:text-surface-300",children:f.tasks.length})]}),i.jsx("ul",{className:"divide-y divide-surface-100 dark:divide-surface-800",children:f.tasks.map(p=>i.jsx(wK,{task:p,now:a,showTargets:t,onEdit:()=>l(p)},p.id))})]},f.id)),i.jsx(ij,{open:!!o,task:o??void 0,onClose:()=>l(null)})]})}function wK({task:e,now:t,showTargets:n,onEdit:r}){const{t:s}=oe("tasks"),a=Xe(),o=Ge("activities.write"),l=ya(),d=un(),f=sr({includeDisabled:!0}),p=f.find(C=>C.id===e.assigneeId),m=!!e.doneAt,h=Ms(),[b,x]=S.useState(!1),y=h?(e.attachments??[]).filter(C=>{const A=h.meta(C);return!!A&&!A.deletedAt}):[],v=async C=>{try{await C()}catch(A){ge.error(A instanceof Error?A.message:String(A))}},k=()=>v(()=>Oc(a,e.id,!m)),j=async()=>{await qt({title:s("list.deleteConfirm",{title:e.title}),danger:!0,confirmLabel:s("list.delete")})&&await v(async()=>{await Dw(a,e.id),ge.success(s("toast.deleted"))})};return i.jsxs("li",{className:"group px-4 py-1.5 hover:bg-surface-50 dark:hover:bg-surface-900/60","data-task-id":e.id,children:[i.jsxs("div",{className:"flex min-h-[28px] items-center gap-3",children:[i.jsx(Ot,{checked:m,disabled:!o,onChange:()=>void k(),"aria-label":m?s("list.reopen",{title:e.title}):s("list.complete",{title:e.title})}),i.jsxs("div",{className:"flex min-w-0 flex-1 flex-wrap items-center gap-x-2 gap-y-1",children:[i.jsx("button",{type:"button",onClick:r,disabled:!o,className:ce("min-w-0 max-w-full truncate text-left font-medium text-surface-800 hover:underline disabled:cursor-default disabled:no-underline dark:text-surface-100",m&&"text-surface-400 line-through dark:text-surface-500"),children:e.title}),n&&e.targets.map(C=>{const A=d.find(_=>_.id===C.object);return i.jsxs("a",{href:ip(C.object,C.id),className:"inline-flex max-w-[180px] items-center gap-1 rounded border border-surface-200 py-px pl-0.5 pr-1.5 text-xs text-surface-600 hover:bg-surface-100 dark:border-surface-700 dark:text-surface-300 dark:hover:bg-surface-800",children:[i.jsx(Mn,{name:A==null?void 0:A.icon,color:A==null?void 0:A.color,tile:!0,className:"h-4 w-4"}),i.jsx("span",{className:"truncate",children:l(C.id)??C.id})]},C.id)}),y.length>0&&i.jsxs("button",{type:"button",onClick:()=>x(C=>!C),"aria-expanded":b,title:s("list.attachments",{count:y.length}),className:"inline-flex items-center gap-0.5 rounded px-1 py-px text-xs text-surface-500 hover:bg-surface-100 hover:text-surface-800 dark:hover:bg-surface-800 dark:hover:text-surface-100",children:[i.jsx(T0,{className:"h-3 w-3"}),y.length]})]}),i.jsx(kK,{task:e,now:t,disabled:!o||m,onChange:C=>v(()=>Xa(a,e.id,{dueAt:C}))}),i.jsx(jK,{assignee:p,users:f,disabled:!o,onChange:C=>v(()=>Xa(a,e.id,{assigneeId:C}))}),o?i.jsx(Tr,{align:"end",trigger:({ref:C,onClick:A})=>i.jsx(dt,{ref:C,onClick:A,label:s("list.actions"),icon:i.jsx(mo,{}),size:"xs",className:"opacity-60 group-hover:opacity-100 focus:opacity-100"}),items:[{id:"edit",label:s("list.edit"),icon:i.jsx(ui,{}),onSelect:r},{id:"toggle",label:s(m?"list.markOpen":"list.markDone"),icon:i.jsx($i,{}),onSelect:()=>void k()},{id:"delete",label:s("list.delete"),icon:i.jsx(Rt,{}),danger:!0,separator:!0,onSelect:()=>void j()}]}):i.jsx("span",{className:"w-6"})]}),b&&y.length>0&&i.jsx(Ef,{ids:y,size:"sm",className:"ml-7 mt-1.5 pb-1",onRemove:o?C=>v(()=>ud(a,C.id)):void 0})]})}function kK({task:e,now:t,disabled:n,onChange:r}){const{t:s}=oe("tasks"),a=br(),o=pK(e,t),l=F0(t),d=SK(e.dueAt,t,s),f=p=>{a.close(),r(p)};return i.jsxs(i.Fragment,{children:[i.jsxs("button",{ref:a.anchorRef,type:"button",disabled:n,onClick:a.toggle,title:s("list.dueDate"),"aria-label":e.dueAt!==void 0?s("list.dueOn",{date:d}):s("list.setDue"),className:ce("inline-flex h-6 shrink-0 items-center gap-1 rounded px-1.5 text-xs tabular-nums transition-colors disabled:cursor-default",o?"bg-red-50 text-red-700 dark:bg-red-500/10 dark:text-red-400":e.dueAt!==void 0?"text-surface-600 dark:text-surface-300":"text-surface-400",!n&&"hover:bg-surface-100 dark:hover:bg-surface-800",e.dueAt===void 0&&!n&&"opacity-0 group-hover:opacity-100 focus:opacity-100"),children:[i.jsx(iI,{className:"h-3.5 w-3.5"}),i.jsx("span",{className:ce(e.dueAt===void 0&&"hidden sm:inline"),children:e.dueAt!==void 0?d:s("list.noDue")})]}),i.jsx(yr,{open:a.open,onClose:a.close,anchor:a.anchor,align:"end",children:i.jsxs("div",{className:"w-56 p-2 text-[13px]",children:[i.jsx(Oe,{type:"date","aria-label":s("list.dueDate"),defaultValue:nj(e.dueAt),onChange:p=>{const m=sj(p.target.value);m!==void 0&&f(xA(m,e.dueAt))}}),i.jsx("div",{className:"mt-2 grid grid-cols-2 gap-1",children:[["today",0],["tomorrow",1],["nextWeek",7],["inTwoWeeks",14]].map(([p,m])=>i.jsx("button",{type:"button",onClick:()=>f(xA(ei(l,m),e.dueAt)),className:"rounded px-2 py-1 text-left text-xs text-surface-700 hover:bg-surface-100 dark:text-surface-200 dark:hover:bg-surface-800",children:s(`quick.${p}`)},p))}),e.dueAt!==void 0&&i.jsxs("button",{type:"button",onClick:()=>f(null),className:"mt-1 flex w-full items-center gap-1.5 border-t border-surface-100 px-2 pt-2 text-left text-xs text-surface-500 hover:text-surface-800 dark:border-surface-800 dark:hover:text-surface-100",children:[i.jsx(an,{className:"h-3.5 w-3.5"})," ",s("list.clearDue")]})]})})]})}function jK({assignee:e,users:t,disabled:n,onChange:r}){const{t:s}=oe("tasks"),a=br(),[o,l]=S.useState(""),d=t.filter(p=>!p.disabled&&`${p.name} ${p.email}`.toLowerCase().includes(o.trim().toLowerCase())),f=p=>{a.close(),l(""),r(p)};return i.jsxs(i.Fragment,{children:[i.jsx("button",{ref:a.anchorRef,type:"button",disabled:n,onClick:a.toggle,title:e?s("list.assignedTo",{name:e.name}):s("unassigned"),"aria-label":e?s("list.assignedTo",{name:e.name}):s("unassigned"),className:"inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full hover:ring-2 hover:ring-surface-200 disabled:cursor-default disabled:hover:ring-0 dark:hover:ring-surface-700",children:e?i.jsx($s,{name:e.name,src:e.avatarUrl,size:"sm"}):i.jsx("span",{className:"inline-flex h-5 w-5 items-center justify-center rounded-full border border-dashed border-surface-300 text-surface-400 dark:border-surface-600",children:i.jsx(vI,{className:"h-3 w-3"})})}),i.jsx(yr,{open:a.open,onClose:a.close,anchor:a.anchor,align:"end",children:i.jsxs("div",{className:"w-60 text-[13px]",children:[i.jsx("input",{autoFocus:!0,value:o,onChange:p=>l(p.target.value),onKeyDown:p=>{p.key==="Enter"&&d[0]&&(p.preventDefault(),f(d[0].id))},placeholder:s("list.searchUsers"),className:"h-9 w-full border-b border-surface-100 bg-transparent px-3 text-sm outline-none placeholder:text-surface-400 dark:border-surface-800"}),i.jsxs("div",{className:"max-h-60 overflow-y-auto py-1",children:[d.map(p=>i.jsxs("button",{type:"button",onClick:()=>f(p.id),className:ce("flex w-full items-center gap-2 px-3 py-1.5 text-left hover:bg-surface-100 dark:hover:bg-surface-800",p.id===(e==null?void 0:e.id)&&"font-medium"),children:[i.jsx($s,{name:p.name,src:p.avatarUrl,size:"sm"}),i.jsx("span",{className:"min-w-0 flex-1 truncate",children:p.name}),p.id===(e==null?void 0:e.id)&&i.jsx("span",{className:"text-accent-600",children:"✓"})]},p.id)),d.length===0&&i.jsx("div",{className:"px-3 py-2 text-surface-400",children:s("list.noUsers")})]}),e&&i.jsxs("button",{type:"button",onClick:()=>f(null),className:"flex w-full items-center gap-1.5 border-t border-surface-100 px-3 py-2 text-left text-xs text-surface-500 hover:bg-surface-50 dark:border-surface-800 dark:hover:bg-surface-800",children:[i.jsx(an,{className:"h-3.5 w-3.5"})," ",s("list.unassign")]})]})})]})}function SK(e,t,n){if(e===void 0)return"";const r=_r(),s=F0(t),a=new Date(e),o=a.getHours()!==9||a.getMinutes()!==0?` ${new Intl.DateTimeFormat(r,{hour:"2-digit",minute:"2-digit"}).format(a)}`:"";if(e>=s&&e<ei(s,1))return`${n("quick.today")}${o}`;if(e>=ei(s,1)&&e<ei(s,2))return`${n("quick.tomorrow")}${o}`;if(e>=ei(s,-1)&&e<s)return`${n("quick.yesterday")}${o}`;if(e>=s&&e<ei(s,7))return`${new Intl.DateTimeFormat(r,{weekday:"short"}).format(a)}${o}`;const l=a.getFullYear()===new Date(t).getFullYear();return new Intl.DateTimeFormat(r,l?{month:"short",day:"numeric"}:{month:"short",day:"numeric",year:"numeric"}).format(a)}const Lv=["mine","all","overdue","upcoming","done"],GR="agentcrm.tasks.view";function JR(e,t){return!e.assigneeId||e.assigneeId===t}function CK(){const e=Ei();return Ti().filter(r=>r.type==="task"&&!r.doneAt&&JR(r,e.id)).length||null}function vA(e,t,n,r){switch(t){case"mine":return e.filter(s=>!s.doneAt&&JR(s,n));case"all":return e.filter(s=>!s.doneAt);case"overdue":return e.filter(s=>!s.doneAt&&s.dueAt!==void 0&&s.dueAt<r);case"upcoming":return e.filter(s=>!s.doneAt&&s.dueAt!==void 0&&s.dueAt>=r);case"done":return e.filter(s=>!!s.doneAt)}}function NK(){try{const e=localStorage.getItem(GR);if(e&&Lv.includes(e))return e}catch{}return"mine"}function AK(){const{t:e}=oe("tasks"),t=Ei(),n=Ge("activities.write"),r=Ti(),s=sr(),a=ya(),[o,l]=S.useState(NK),[d,f]=S.useState(""),[p,m]=S.useState(""),[h,b]=S.useState(!1),x=Date.now(),y=_=>{l(_);try{localStorage.setItem(GR,_)}catch{}},v=S.useMemo(()=>r.filter(_=>_.type==="task"),[r]),k=o!=="mine",j=S.useMemo(()=>p?v.filter(_=>p==="none"?!_.assigneeId:_.assigneeId===p):v,[v,p]),C=S.useMemo(()=>{const _={};for(const D of Lv)_[D]=vA(D==="mine"?v:j,D,t.id,x).length;return _},[v,j,t.id]),A=S.useMemo(()=>{const _=vA(k?j:v,o,t.id,x),D=d.trim().toLowerCase();return D?_.filter(I=>[I.title,I.body??"",...I.targets.map(E=>a(E.id)??"")].join(" ").toLowerCase().includes(D)):_},[v,j,o,t.id,d,a,k]);return i.jsxs("div",{className:"flex h-full min-h-0 flex-col",children:[i.jsx(Kr,{title:e("title"),icon:i.jsx($i,{}),actions:n&&i.jsx(ue,{variant:"primary",size:"sm",icon:i.jsx($t,{}),onClick:()=>b(!0),children:e("newTask")}),children:i.jsxs("div",{className:"-mb-3 mt-2 flex flex-wrap items-end justify-between gap-x-4 gap-y-2",children:[i.jsx(bo,{className:"-mb-px border-b-0",value:o,onChange:_=>y(_),tabs:Lv.map(_=>({id:_,label:e(`views.${_}`),count:C[_]}))}),i.jsxs("div",{className:"mb-2 flex items-center gap-2",children:[i.jsx(Oe,{icon:i.jsx(Wr,{}),value:d,onChange:_=>f(_.target.value),placeholder:e("filter.search"),"aria-label":e("filter.search"),className:"w-48 sm:w-56"}),k&&i.jsx(Ve,{"aria-label":e("filter.assignee"),className:"w-40",value:p,onChange:_=>m(_.target.value),options:[{value:"",label:e("filter.anyone")},{value:"none",label:e("unassigned")},...s.map(_=>({value:_.id,label:_.id===t.id?e("filter.me",{name:_.name}):_.name}))]})]})]})}),i.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto bg-white dark:bg-surface-950",children:i.jsx(KR,{tasks:A,showTargets:!0,groupByDue:!0,emptyText:d.trim()?e("filter.noMatch"):e(`emptyViews.${o}`)})}),i.jsx(ij,{open:h,onClose:()=>b(!1),defaultAssigneeId:t.id})]})}function _K(){const[e,t]=S.useState(null);return Qa("tasks.create",n=>{const r=n&&typeof n=="object"?n:{};t(s=>({key:((s==null?void 0:s.key)??0)+1,detail:{targets:Array.isArray(r.targets)?r.targets:void 0,title:typeof r.title=="string"?r.title:void 0}}))}),e?i.jsx(ij,{open:!0,onClose:()=>t(null),defaultTargets:e.detail.targets,defaultTitle:e.detail.title},e.key):null}const EK={id:"tasks",module:fs("tasks"),routes:[{path:"/tasks",element:S.createElement(AK)}],navItems:[{id:"tasks",label:"tasks:nav.title",icon:$i,to:"/tasks",section:"main",order:10,useBadge:CK}],i18n:{en:GW,fr:dK},slots:{globalOverlays:[_K]}},TK={new:"New",empty:"No {{object}} yet",emptyHint:"Create the first one, or import a CSV.",count_one:"{{count}} record",count_other:"{{count}} records",countFiltered:"{{count}} of {{total}}",unknownObject:"Unknown object",unknownObjectHint:"This object doesn't exist (anymore). Check Settings → Data model.",untitled:"Untitled",search:"Search {{object}}…",more:"More actions",exportView:"Export view as CSV",import:"Import CSV",trash:"Deleted records"},IK={title:"Views",new:"New view",name:"View name",rename:"Rename view",duplicate:"Duplicate",delete:"Delete view",deleted:"View deleted",created:"View created",saved:"View saved",save:"Save view",saveAsNew:"Save as new view",reset:"Reset",copyName:"{{name}} (copy)",menu:"View options",share:"Share with the team",makePrivate:"Make private",private:"Private view",sharedHint:"Shared with the whole team"},RK={add:"Filter",pickField:"Filter by…",remove:"Remove filter",clearAll:"Clear filters",operator:"Operator",valuePlaceholder:"Value…",withinDaysHint:"Positive: next N days. Negative: last N days.",days_one:"{{count}} day",days_other:"{{count}} days",ops:{eq:"is",neq:"is not",contains:"contains",notContains:"does not contain",empty:"is empty",notEmpty:"is not empty",gt:">",gte:"≥",lt:"<",lte:"≤",in:"is any of",notIn:"is none of",before:"is before",after:"is after",withinDays:"within"},relative:{today:"Today","-7d":"7 days ago","+7d":"In 7 days","-30d":"30 days ago"}},$K={title:"Sort",count_one:"{{count}} sort",count_other:"{{count}} sorts",none:"No sort: newest first.",field:"Sort field",asc:"Sort ascending",desc:"Sort descending",remove:"Remove sort",add:"Add sort"},DK={title:"Fields",visible:"Visible",hidden:"Hidden",drag:"Reorder {{name}}",hide:"Hide {{name}}",show:"Show {{name}}",hideColumn:"Hide column",resize:"Resize column"},MK={title:"Options",layout:"Layout",table:"Table",kanban:"Kanban",groupBy:"Group by",pipeline:"Pipeline",noGroupable:"Kanban needs a select, user or checkbox field.",hint:"Changes apply to this view; save to keep them."},OK={selectAll:"Select all",selectRow:"Select {{name}}",open:"Open",addRow:"New record",newLabel:"New record {{field}}",noRows:"No records match this view.",hintNavigate:"move",hintEdit:"edit",hintOpen:"open",hintSelect:"select",keySpace:"Space"},PK={title:"Bulk actions",selected_one:"{{count}} selected",selected_other:"{{count}} selected",update:"Update field",field:"Field",apply:"Apply",updateHint_one:"Sets this value on {{count}} record.",updateHint_other:"Sets this value on {{count}} records.",updated_one:"{{count}} record updated",updated_other:"{{count}} records updated",partial:"{{ok}} updated, {{failed}} failed: {{message}}",assign:"Assign owner",assigned_one:"{{count}} record assigned to {{name}}",assigned_other:"{{count}} records assigned to {{name}}",nobody:"nobody",unassign:"Remove owner",export:"Export CSV",exported_one:"{{count}} record exported",exported_other:"{{count}} records exported",deleteTitle_one:"Delete {{count}} record?",deleteTitle_other:"Delete {{count}} records?",deleteHint:"They go to the trash and can be restored.",deleted_one:"{{count}} record moved to the trash",deleted_other:"{{count}} records moved to the trash",clear:"Clear selection"},LK={noValue:"No value",new:"New",quickAdd:"New record in {{column}}",cardMenu:"Actions for {{name}}",moveTo:"Move to {{column}}",weighted:"Weighted forecast (amount × probability)",weightedShort:"weighted",noGroup:"No group field",noGroupHint:"Pick a select, user or checkbox field to group by in Options.",wonTitle:"Mark {{name}} as won?",wonHint:"The deal moves to a won stage and its probability becomes 100%.",markWon:"Mark as won",wonToast:"{{name}} won 🎉",lostTitle:"Mark {{name}} as lost",lostHint:"Why was this deal lost? It helps the reports.",lostReason:"Lost reason",markLost:"Mark as lost",reasons:{price:"Price",competitor:"Competitor",budget:"No budget",timing:"Timing",noDecision:"No decision",other:"Other"}},FK={fields:"Fields",timeline:"Timeline",notes:"Notes",tasks:"Tasks",notFound:"Record not found",notFoundHint:"It may have been deleted permanently or merged.",back:"Back to {{object}}",breadcrumb:"Breadcrumb",deleted:"This record is in the trash.",related:"Related",noActivity:"No activity yet.",delete:"Delete record",deleteHint:"It goes to the trash and can be restored.",deletedToast:"{{name}} moved to the trash",rename:"Rename",updatedAgo:"Updated {{when}}",log:"Log",actions:"Record actions",copyLink:"Copy link",merge:"Merge duplicates…",owner:"Owner",created:"Created",updated:"Updated",editField:"Edit {{field}}",emptyValue:"Empty",showEmpty_one:"Show {{count}} empty field",showEmpty_other:"Show {{count}} empty fields",hideEmpty:"Hide empty fields",files:"Files"},zK={log:"Log a note, call, email, meeting or task…",all:"All",includeRelated:"Include related records",empty:"No activity yet",emptyHint:"Notes, calls, emails, meetings and tasks on this record show up here.",created:"{{object}} created {{when}} by {{by}}",system:"the system",menu:"Activity actions",complete:"Mark as done",reopen:"Mark as not done",duration_one:"{{count}} min",duration_other:"{{count}} min",due:"Due {{date}}",assignedTo:"Assigned to {{name}}",showMore:"Show more",showLess:"Show less"},UK={type:"Activity type",title:"Title",body:"Details",empty:"Write a title or some details first.",logged:"{{type}} logged",submit:"Log {{type}}",submitHint:"⌘↵ to submit · Markdown supported",duration:"Duration (min)",outcome:"Outcome",direction:"Direction",start:"Start",length:"Length",minutes_one:"{{count}} minute",minutes_other:"{{count}} minutes",due:"Due date",assignee:"Assignee",outcomes:{connected:"Connected",voicemail:"Left voicemail",noAnswer:"No answer",busy:"Busy"},directions:{outbound:"Outbound",inbound:"Inbound"},titlePlaceholder:{note:"Title (optional)",call:"Call summary",email:"Subject",meeting:"Meeting title",task:"What needs to be done?"},bodyPlaceholder:{note:"Write a note… (Markdown)",call:"What was said?",email:"Email content or summary",meeting:"Agenda, notes, next steps",task:"Details (optional)"},defaultTitle:{note:"Note",call:"Call",email:"Email",meeting:"Meeting",task:"Task",attachment:"Attachment"},waitUploads:"Wait for the uploads to finish."},BK={write:"Write",preview:"Preview",hint:"Markdown",body:"Text",nothing:"Nothing to preview."},HK={empty:"No notes yet",emptyHint:"Write the first one above."},qK={new:"New task",empty:"No tasks on this record."},VK={via:"{{object}} linked through “{{field}}”",link:"Link existing",linked:"Linked",new:"New {{object}}",unlink:"Unlink",empty:"No {{object}} linked yet.",search:"Search {{object}}…",noMatch:"No match"},WK={title:"Merge duplicates into {{name}}",hint:"The selected records are merged into this one: empty fields are filled, relations and activities move here, then the duplicates are deleted.",suggested:"Suggested duplicates",none:"No obvious duplicate found.",search:"Search other {{object}}…",submit_one:"Merge {{count}} record",submit_other:"Merge {{count}} records",done_one:"{{count}} record merged ({{activities}} activities moved)",done_other:"{{count}} records merged ({{activities}} activities moved)",warning:"Merging can't be undone.",reasons:{email:"Same email",domain:"Same domain",name:"Same name",phone:"Same phone"}},KK={title:"New {{object}}",created:"{{object}} created",createAndOpen:"Create & open"},GK={title:"Log {{type}}",pickHint:"Pick the record this activity is about.",object:"Object",pickRecord:"Pick a record…"},JK={title:"Deleted {{object}}",hint:"Deleted records stay here until restored or purged (Settings → Danger zone purges them for good).",nothing:"The trash is empty",nothingHint:"Deleted records show up here.",deletedAt:"Deleted",restore:"Restore",restored:"{{name}} restored",restoredCount_one:"{{count}} record restored",restoredCount_other:"{{count}} records restored",restoreSelected:"Restore ({{count}})",hardDelete:"Delete permanently",hardDeleteTitle:"Delete {{name}} permanently?",purgeTitle_one:"Delete {{count}} record permanently?",purgeTitle_other:"Delete {{count}} records permanently?",purgeSelected:"Delete permanently ({{count}})",empty:"Empty trash",purged_one:"{{count}} record deleted permanently",purged_other:"{{count}} records deleted permanently"},YK={generic:"Something went wrong."},ZK={add:"Add a picture",change:"Change the picture",replace:"Replace the picture",replaceLogo:"Replace the logo",remove:"Remove",crop:"Adjust the picture",cropLogo:"Adjust the logo",saved:"Picture updated",logoSaved:"Logo updated",notImage:"Choose an image file (PNG, JPEG, WebP, SVG…)."},QK={unavailable:"This data backend can't store files.",search:"Search files",sort:"Sort",sortBy:{newest:"Newest",oldest:"Oldest",name:"Name",size:"Size"},layout:"Layout",grid:"Grid",list:"List",upload:"Upload",includeRelated:"Include files of activities and related records",empty:"No files yet",emptyHint:"Drop files here or use Upload. Files attached to notes and tasks show up here too.",noMatch:"No file matches",onActivity:"On “{{title}}”",fromRelated:"From {{name}}",open:"Open",download:"Download",delete:"Delete",deleteTitle:"Delete “{{name}}”?",deleteHint:"It disappears from the CRM now; its bytes are erased from the storage at the next compaction.",deleted:"{{name}} deleted"},XK={list:TK,views:IK,filters:RK,sorts:$K,columns:DK,options:MK,table:OK,bulk:PK,kanban:LK,detail:FK,timeline:zK,composer:UK,markdown:BK,notes:HK,tasks:qK,related:VK,merge:WK,create:KK,log:GK,trash:JK,errors:YK,avatar:ZK,files:QK},eG={new:"Nouveau",empty:"Aucun enregistrement ({{object}})",emptyHint:"Créez le premier, ou importez un CSV.",count_one:"{{count}} enregistrement",count_other:"{{count}} enregistrements",countFiltered:"{{count}} sur {{total}}",unknownObject:"Objet inconnu",unknownObjectHint:"Cet objet n'existe pas (ou plus). Voir Paramètres → Modèle de données.",untitled:"Sans titre",search:"Rechercher ({{object}})…",more:"Plus d'actions",exportView:"Exporter la vue en CSV",import:"Importer un CSV",trash:"Enregistrements supprimés",count_many:"{{count}} enregistrements"},tG={title:"Vues",new:"Nouvelle vue",name:"Nom de la vue",rename:"Renommer la vue",duplicate:"Dupliquer",delete:"Supprimer la vue",deleted:"Vue supprimée",created:"Vue créée",saved:"Vue enregistrée",save:"Enregistrer la vue",saveAsNew:"Enregistrer comme nouvelle vue",reset:"Réinitialiser",copyName:"{{name}} (copie)",menu:"Options de la vue",share:"Partager avec l'équipe",makePrivate:"Rendre privée",private:"Vue privée",sharedHint:"Partagée avec toute l'équipe"},nG={add:"Filtrer",pickField:"Filtrer par…",remove:"Retirer le filtre",clearAll:"Effacer les filtres",operator:"Opérateur",valuePlaceholder:"Valeur…",withinDaysHint:"Positif : N prochains jours. Négatif : N derniers jours.",days_one:"{{count}} jour",days_other:"{{count}} jours",ops:{eq:"est",neq:"n'est pas",contains:"contient",notContains:"ne contient pas",empty:"est vide",notEmpty:"n'est pas vide",gt:">",gte:"≥",lt:"<",lte:"≤",in:"est parmi",notIn:"n'est pas parmi",before:"est avant",after:"est après",withinDays:"dans les"},relative:{today:"Aujourd'hui","-7d":"Il y a 7 jours","+7d":"Dans 7 jours","-30d":"Il y a 30 jours"},days_many:"{{count}} jours"},rG={title:"Trier",count_one:"{{count}} tri",count_other:"{{count}} tris",none:"Aucun tri : les plus récents d'abord.",field:"Champ de tri",asc:"Tri croissant",desc:"Tri décroissant",remove:"Retirer le tri",add:"Ajouter un tri",count_many:"{{count}} tris"},sG={title:"Champs",visible:"Visibles",hidden:"Masqués",drag:"Déplacer {{name}}",hide:"Masquer {{name}}",show:"Afficher {{name}}",hideColumn:"Masquer la colonne",resize:"Redimensionner la colonne"},iG={title:"Options",layout:"Affichage",table:"Tableau",kanban:"Kanban",groupBy:"Regrouper par",pipeline:"Pipeline",noGroupable:"Le kanban nécessite un champ de sélection, utilisateur ou case à cocher.",hint:"Les changements s'appliquent à cette vue ; enregistrez pour les garder."},aG={selectAll:"Tout sélectionner",selectRow:"Sélectionner {{name}}",open:"Ouvrir",addRow:"Nouvel enregistrement",newLabel:"Nouvel enregistrement : {{field}}",noRows:"Aucun enregistrement ne correspond à cette vue.",hintNavigate:"naviguer",hintEdit:"modifier",hintOpen:"ouvrir",hintSelect:"sélectionner",keySpace:"Espace"},oG={title:"Actions groupées",selected_one:"{{count}} sélectionné",selected_other:"{{count}} sélectionnés",update:"Modifier un champ",field:"Champ",apply:"Appliquer",updateHint_one:"Applique cette valeur à {{count}} enregistrement.",updateHint_other:"Applique cette valeur à {{count}} enregistrements.",updated_one:"{{count}} enregistrement modifié",updated_other:"{{count}} enregistrements modifiés",partial:"{{ok}} modifiés, {{failed}} en échec : {{message}}",assign:"Attribuer",assigned_one:"{{count}} enregistrement attribué à {{name}}",assigned_other:"{{count}} enregistrements attribués à {{name}}",nobody:"personne",unassign:"Retirer le propriétaire",export:"Exporter en CSV",exported_one:"{{count}} enregistrement exporté",exported_other:"{{count}} enregistrements exportés",deleteTitle_one:"Supprimer {{count}} enregistrement ?",deleteTitle_other:"Supprimer {{count}} enregistrements ?",deleteHint:"Ils vont dans la corbeille et peuvent être restaurés.",deleted_one:"{{count}} enregistrement mis à la corbeille",deleted_other:"{{count}} enregistrements mis à la corbeille",clear:"Désélectionner",selected_many:"{{count}} sélectionnés",updateHint_many:"Applique cette valeur à {{count}} enregistrements.",updated_many:"{{count}} enregistrements modifiés",assigned_many:"{{count}} enregistrements attribués à {{name}}",exported_many:"{{count}} enregistrements exportés",deleteTitle_many:"Supprimer {{count}} enregistrements ?",deleted_many:"{{count}} enregistrements mis à la corbeille"},lG={noValue:"Sans valeur",new:"Nouveau",quickAdd:"Nouvel enregistrement dans {{column}}",cardMenu:"Actions pour {{name}}",moveTo:"Déplacer vers {{column}}",weighted:"Prévision pondérée (montant × probabilité)",weightedShort:"pondéré",noGroup:"Aucun champ de regroupement",noGroupHint:"Choisissez un champ de sélection, utilisateur ou case à cocher dans Options.",wonTitle:"Marquer {{name}} comme gagnée ?",wonHint:"L'affaire passe dans une étape gagnée et sa probabilité devient 100 %.",markWon:"Marquer gagnée",wonToast:"{{name}} gagnée 🎉",lostTitle:"Marquer {{name}} comme perdue",lostHint:"Pourquoi cette affaire est-elle perdue ? Cela alimente les rapports.",lostReason:"Raison de la perte",markLost:"Marquer perdue",reasons:{price:"Prix",competitor:"Concurrent",budget:"Pas de budget",timing:"Calendrier",noDecision:"Pas de décision",other:"Autre"}},cG={fields:"Champs",timeline:"Chronologie",notes:"Notes",tasks:"Tâches",notFound:"Enregistrement introuvable",notFoundHint:"Il a peut-être été supprimé définitivement ou fusionné.",back:"Retour : {{object}}",breadcrumb:"Fil d'Ariane",deleted:"Cet enregistrement est dans la corbeille.",related:"Liés",noActivity:"Aucune activité.",delete:"Supprimer l'enregistrement",deleteHint:"Il va dans la corbeille et peut être restauré.",deletedToast:"{{name}} mis à la corbeille",rename:"Renommer",updatedAgo:"Modifié {{when}}",log:"Consigner",actions:"Actions",copyLink:"Copier le lien",merge:"Fusionner des doublons…",owner:"Propriétaire",created:"Créé",updated:"Modifié",editField:"Modifier {{field}}",emptyValue:"Vide",showEmpty_one:"Afficher {{count}} champ vide",showEmpty_other:"Afficher {{count}} champs vides",hideEmpty:"Masquer les champs vides",showEmpty_many:"Afficher {{count}} champs vides",files:"Fichiers"},dG={log:"Consigner une note, un appel, un e-mail, une réunion ou une tâche…",all:"Tout",includeRelated:"Inclure les enregistrements liés",empty:"Aucune activité",emptyHint:"Les notes, appels, e-mails, réunions et tâches de cet enregistrement apparaissent ici.",created:"{{object}} créé le {{when}} par {{by}}",system:"le système",menu:"Actions de l'activité",complete:"Marquer comme faite",reopen:"Marquer comme non faite",duration_one:"{{count}} min",duration_other:"{{count}} min",due:"Échéance {{date}}",assignedTo:"Assignée à {{name}}",showMore:"Afficher plus",showLess:"Afficher moins",duration_many:"{{count}} min"},uG={type:"Type d'activité",title:"Titre",body:"Détails",empty:"Écrivez d'abord un titre ou des détails.",logged:"{{type}} consigné(e)",submit:"Consigner : {{type}}",submitHint:"⌘↵ pour valider · Markdown accepté",duration:"Durée (min)",outcome:"Résultat",direction:"Sens",start:"Début",length:"Durée",minutes_one:"{{count}} minute",minutes_other:"{{count}} minutes",due:"Échéance",assignee:"Assigné à",outcomes:{connected:"Joint",voicemail:"Message laissé",noAnswer:"Pas de réponse",busy:"Occupé"},directions:{outbound:"Sortant",inbound:"Entrant"},titlePlaceholder:{note:"Titre (facultatif)",call:"Résumé de l'appel",email:"Objet",meeting:"Titre de la réunion",task:"Que faut-il faire ?"},bodyPlaceholder:{note:"Écrire une note… (Markdown)",call:"Qu'est-ce qui a été dit ?",email:"Contenu ou résumé de l'e-mail",meeting:"Ordre du jour, notes, prochaines étapes",task:"Détails (facultatif)"},defaultTitle:{note:"Note",call:"Appel",email:"E-mail",meeting:"Réunion",task:"Tâche",attachment:"Pièce jointe"},minutes_many:"{{count}} minutes",waitUploads:"Attendez la fin des envois."},fG={write:"Écrire",preview:"Aperçu",hint:"Markdown",body:"Texte",nothing:"Rien à afficher."},pG={empty:"Aucune note",emptyHint:"Écrivez la première ci-dessus."},mG={new:"Nouvelle tâche",empty:"Aucune tâche sur cet enregistrement."},hG={via:"{{object}} liés via « {{field}} »",link:"Lier un existant",linked:"Lié",new:"Nouveau : {{object}}",unlink:"Délier",empty:"Aucun lien ({{object}}).",search:"Rechercher ({{object}})…",noMatch:"Aucun résultat"},gG={title:"Fusionner des doublons dans {{name}}",hint:"Les enregistrements sélectionnés sont fusionnés dans celui-ci : les champs vides sont complétés, relations et activités sont déplacées ici, puis les doublons sont supprimés.",suggested:"Doublons suggérés",none:"Aucun doublon évident.",search:"Rechercher d'autres ({{object}})…",submit_one:"Fusionner {{count}} enregistrement",submit_other:"Fusionner {{count}} enregistrements",done_one:"{{count}} enregistrement fusionné ({{activities}} activités déplacées)",done_other:"{{count}} enregistrements fusionnés ({{activities}} activités déplacées)",warning:"La fusion est irréversible.",reasons:{email:"Même e-mail",domain:"Même domaine",name:"Même nom",phone:"Même téléphone"},submit_many:"Fusionner {{count}} enregistrements",done_many:"{{count}} enregistrements fusionnés ({{activities}} activités déplacées)"},yG={title:"Nouveau : {{object}}",created:"{{object}} créé(e)",createAndOpen:"Créer et ouvrir"},bG={title:"Consigner : {{type}}",pickHint:"Choisissez l'enregistrement concerné.",object:"Objet",pickRecord:"Choisir un enregistrement…"},xG={title:"Corbeille : {{object}}",hint:"Les enregistrements supprimés restent ici jusqu'à restauration ou purge (Paramètres → Zone de danger les supprime définitivement).",nothing:"La corbeille est vide",nothingHint:"Les enregistrements supprimés apparaissent ici.",deletedAt:"Supprimé",restore:"Restaurer",restored:"{{name}} restauré",restoredCount_one:"{{count}} enregistrement restauré",restoredCount_other:"{{count}} enregistrements restaurés",restoreSelected:"Restaurer ({{count}})",hardDelete:"Supprimer définitivement",hardDeleteTitle:"Supprimer définitivement {{name}} ?",purgeTitle_one:"Supprimer définitivement {{count}} enregistrement ?",purgeTitle_other:"Supprimer définitivement {{count}} enregistrements ?",purgeSelected:"Supprimer définitivement ({{count}})",empty:"Vider la corbeille",purged_one:"{{count}} enregistrement supprimé définitivement",purged_other:"{{count}} enregistrements supprimés définitivement",restoredCount_many:"{{count}} enregistrements restaurés",purgeTitle_many:"Supprimer définitivement {{count}} enregistrements ?",purged_many:"{{count}} enregistrements supprimés définitivement"},vG={generic:"Une erreur est survenue."},wG={add:"Ajouter une photo",change:"Changer la photo",replace:"Remplacer la photo",replaceLogo:"Remplacer le logo",remove:"Retirer",crop:"Ajuster la photo",cropLogo:"Ajuster le logo",saved:"Photo mise à jour",logoSaved:"Logo mis à jour",notImage:"Choisissez un fichier image (PNG, JPEG, WebP, SVG…)."},kG={unavailable:"Ce stockage de données ne peut pas contenir de fichiers.",search:"Rechercher un fichier",sort:"Trier",sortBy:{newest:"Plus récents",oldest:"Plus anciens",name:"Nom",size:"Taille"},layout:"Affichage",grid:"Grille",list:"Liste",upload:"Envoyer",includeRelated:"Inclure les fichiers des activités et des fiches liées",empty:"Aucun fichier pour l’instant",emptyHint:"Déposez des fichiers ici ou utilisez Envoyer. Les fichiers joints aux notes et tâches apparaissent aussi ici.",noMatch:"Aucun fichier ne correspond",onActivity:"Sur « {{title}} »",fromRelated:"De {{name}}",open:"Ouvrir",download:"Télécharger",delete:"Supprimer",deleteTitle:"Supprimer « {{name}} » ?",deleteHint:"Il disparaît du CRM tout de suite ; son contenu est effacé du stockage à la prochaine compaction.",deleted:"{{name}} supprimé"},jG={list:eG,views:tG,filters:nG,sorts:rG,columns:sG,options:iG,table:aG,bulk:oG,kanban:lG,detail:cG,timeline:dG,composer:uG,markdown:fG,notes:pG,tasks:mG,related:hG,merge:gG,create:yG,log:bG,trash:xG,errors:vG,avatar:wG,files:kG},YR=["ownerId","createdAt","updatedAt"];function oa(e,t){return Nr(e,t)}function SG(e,t){const n=t.filter(r=>r!==e.labelField&&!!Nr(e,r));return[e.labelField,...new Set(n)]}function ZR(e){return[...e.fields.filter(n=>!n.hidden&&n.id!==e.labelField),...YR.map(n=>Nr(e,n)).filter(Boolean)]}function CG(e){return[...e.fields.filter(t=>!t.hidden),...YR.map(t=>Nr(e,t)).filter(Boolean)]}const NG=["contains","notContains","eq","neq","empty","notEmpty"],AG=["eq","neq","gt","gte","lt","lte","empty","notEmpty"],_G=["eq","before","after","withinDays","empty","notEmpty"],EG=["in","notIn","eq","neq","empty","notEmpty"],TG=["eq","neq","in","notIn","empty","notEmpty"];function QR(e){switch(e){case"number":case"currency":case"percent":case"rating":return AG;case"date":case"datetime":return _G;case"select":case"user":return EG;case"multiSelect":case"tags":return TG;case"relation":return["eq","neq","contains","notContains","empty","notEmpty"];case"boolean":return["eq","neq"];case"address":case"longText":return["contains","notContains","empty","notEmpty"];default:return NG}}function Cp(e){return e!=="empty"&&e!=="notEmpty"}function XR(e,t){if(Cp(t)){if(t==="in"||t==="notIn")return[];if(t==="withinDays")return 7;if(e.type==="boolean")return!0}}function qu(e){return Cp(e.op)?Array.isArray(e.value)?e.value.length>0:e.value!==void 0&&e.value!==null&&e.value!=="":!0}function Fv(e,t){var r,s;const n={};for(const a of t){const o=e.fields.find(l=>l.id===a.field);if(o)if(a.op==="eq"&&["select","user","boolean","text","relation"].includes(o.type)&&a.value!==void 0&&a.value!=="")if(o.type==="select"){const l=(r=o.options)==null?void 0:r.find(d=>d.id===a.value||d.label.toLowerCase()===String(a.value).toLowerCase());l&&(n[o.id]=l.id)}else o.type==="relation"?n[o.id]=((s=o.relation)==null?void 0:s.cardinality)==="many"?[String(a.value)]:String(a.value):n[o.id]=a.value;else a.op==="in"&&Array.isArray(a.value)&&a.value.length===1&&(o.type==="select"||o.type==="user")&&(n[o.id]=a.value[0])}return n}function IG(e,t,n,r){const s={...r,object:t};let a=yw(e,n.filters.filter(qu),s);const o=n.search.trim().toLowerCase();if(o){const l=t.fields.filter(d=>["text","email","phone","url","tags","longText"].includes(d.type));a=a.filter(d=>ct(t,d).toLowerCase().includes(o)?!0:l.some(f=>{const p=d.fields[f.id];return Array.isArray(p)?p.some(m=>String(m).toLowerCase().includes(o)):typeof p=="string"&&p.toLowerCase().includes(o)}))}return Dh(a,n.sorts.length?n.sorts:[{field:"createdAt",dir:"desc"}],s)}function e3(e){return e.fields.filter(t=>!t.hidden&&(t.type==="select"||t.type==="user"||t.type==="boolean"))}function RG(e,t){return t.pipeline&&t.pipeline.stageField===e.id?t.pipeline.stages.map(n=>({key:n.id,label:n.label,color:n.color,stage:n})):e.type==="select"?[...(e.options??[]).map(n=>({key:n.id,label:n.label,color:n.color})),{key:"",label:t.noValueLabel,color:"gray"}]:e.type==="boolean"?[{key:"true",label:t.yes??"Yes",color:"green"},{key:"false",label:t.no??"No",color:"gray"}]:e.type==="user"?[...(t.users??[]).filter(n=>!n.disabled).map(n=>({key:n.id,label:n.name,color:"blue"})),{key:"",label:t.noValueLabel,color:"gray"}]:[{key:"",label:t.noValueLabel,color:"gray"}]}function wA(e,t){const n=qf(e,t.id);return t.type==="boolean"?n?"true":"false":vn(t,n)?"":Array.isArray(n)?String(n[0]):String(n)}function kA(e,t){return e.type==="boolean"?t==="true":t===""?null:t}function $G(e){return e.fields.find(t=>t.id==="amount"&&(t.type==="currency"||t.type==="number"))??e.fields.find(t=>t.type==="currency")}function DG(e,t,n){let r=0,s=0;for(const a of e){const o=t?a.fields[t.id]:void 0,l=typeof o=="number"?o:0;if(r+=l,n){const d=n.kind==="won"?100:n.kind==="lost"?0:typeof a.fields.probability=="number"?a.fields.probability:n.probability;s+=l*d/100}}return{count:e.length,amount:r,weighted:Math.round(s*100)/100}}function MG(e,t){if(!(t!=null&&t.length))return e;const n=new Map(t.map((a,o)=>[a,o])),r=e.filter(a=>n.has(a.id)).sort((a,o)=>n.get(a.id)-n.get(o.id)),s=e.filter(a=>!n.has(a.id));return[...r,...s]}function jA(e){return JSON.stringify({type:e.type,columns:e.columns,filters:e.filters,sorts:e.sorts,groupBy:e.groupBy??null,pipelineId:e.pipelineId??null})}function OG(){const e=ya(),t=sr({includeDisabled:!0});return S.useMemo(()=>{const n=new Map(t.map(r=>[r.id,r.name]));return{now:Date.now(),recordLabel:(r,s)=>e(s),userName:r=>n.get(r)}},[e,t])}function PG(e,t){const n=S.useMemo(()=>t??(e?bw(e):void 0),[t,e]),[r,s]=S.useState(n),a=n?jA(n):"",o=S.useRef({id:n==null?void 0:n.id,sig:a});S.useEffect(()=>{(o.current.id!==(n==null?void 0:n.id)||o.current.sig!==a)&&(o.current={id:n==null?void 0:n.id,sig:a},s(n))},[n,a]);const l=r&&r.id===(n==null?void 0:n.id)?r:n,d=S.useCallback(p=>s(m=>m&&{...m,...p}),[]),f=S.useCallback(()=>s(n),[n]);return{saved:t,draft:l,dirty:!!l&&!!n&&jA(l)!==a,set:d,reset:f}}function t3(){const{t:e}=oe("records");return S.useCallback(async(t,n)=>{try{const r=await t();return n&&ge.success(n),r}catch(r){ge.error(r.message||e("errors.generic"));return}},[e])}function n3(e,t){const n=S.useCallback(()=>{try{const o=localStorage.getItem(e);return o?JSON.parse(o):t}catch{return t}},[e]),[r,s]=S.useState(n);S.useEffect(()=>s(n()),[n]);const a=S.useCallback(o=>{s(l=>{const d=typeof o=="function"?o(l):o;try{localStorage.setItem(e,JSON.stringify(d))}catch{}return d})},[e]);return[r,a]}function LG(){const{t:e}=oe("records"),{t}=oe(),n=On();return(r,s)=>{if(!r)return s.field;const a=e(`filters.ops.${s.op}`);if(!Cp(s.op))return`${r.label} ${a}`;const o=d=>{var f,p,m;return d==null||d===""?"…":r.type==="select"||r.type==="multiSelect"?((p=(f=r.options)==null?void 0:f.find(h=>h.id===d))==null?void 0:p.label)??String(d):r.type==="user"?((m=n.users.find(h=>h.id===d))==null?void 0:m.name)??String(d):r.type==="relation"&&(s.op==="eq"||s.op==="neq")?n.recordLabel(String(d))??String(d):r.type==="boolean"?t(d===!0||d==="true"?"common.yes":"common.no"):s.op==="withinDays"?e("filters.days",{count:Number(d)}):r.type==="date"||r.type==="datetime"?typeof d=="string"&&!/^\d{4}-/.test(d)?d:_s({...r,type:"date"},d,{locale:n.locale}):String(d)},l=Array.isArray(s.value)?s.value.length?s.value.map(o).join(", "):"…":o(s.value);return`${r.label} ${a} ${l}`}}function FG({field:e,filter:t,onChange:n}){const{t:r}=oe("records"),{t:s}=oe(),a=On(),[o,l]=S.useState("");if(!Cp(t.op))return null;if(t.op==="withinDays")return i.jsxs("div",{className:"space-y-1",children:[i.jsx(Oe,{inputMode:"numeric",autoFocus:!0,value:t.value===void 0?"":String(t.value),onChange:d=>n(d.target.value===""?void 0:Number(d.target.value)||0)}),i.jsx("p",{className:"text-2xs text-surface-400",children:r("filters.withinDaysHint")})]});if(t.op==="in"||t.op==="notIn"){const d=(Array.isArray(t.value)?t.value:[]).map(String),f=e.type==="user"?a.users.filter(m=>!m.disabled).map(m=>({id:m.id,label:m.name,color:void 0})):(e.options??[]).map(m=>({id:m.id,label:m.label,color:m.color})),p=f.filter(m=>m.label.toLowerCase().includes(o.toLowerCase()));return i.jsxs("div",{className:"space-y-1.5",children:[f.length>8&&i.jsx(Oe,{icon:i.jsx(Wr,{}),value:o,onChange:m=>l(m.target.value),placeholder:s("common.search")}),i.jsx("div",{className:"max-h-56 space-y-0.5 overflow-y-auto",children:p.map(m=>i.jsxs("label",{className:"flex cursor-pointer items-center gap-2 rounded px-1.5 py-1 text-[13px] hover:bg-surface-100 dark:hover:bg-surface-800",children:[i.jsx(Ot,{checked:d.includes(m.id),onChange:h=>n(h.target.checked?[...d,m.id]:d.filter(b=>b!==m.id))}),m.color!==void 0?i.jsx(tt,{color:m.color,children:m.label}):i.jsx("span",{className:"truncate",children:m.label})]},m.id))})]})}switch(e.type){case"boolean":return i.jsx(Ve,{value:t.value===!1||t.value==="false"?"false":"true",onChange:d=>n(d.target.value==="true"),options:[{value:"true",label:s("common.yes")},{value:"false",label:s("common.no")}]});case"select":case"multiSelect":return i.jsx(hr,{field:{...e,type:"select"},value:t.value,onChange:n});case"user":return i.jsx(hr,{field:e,value:t.value,onChange:n});case"relation":return t.op==="eq"||t.op==="neq"?i.jsx(hr,{field:{...e,relation:{...e.relation,cardinality:"one"}},value:t.value,onChange:n}):i.jsx(Oe,{autoFocus:!0,value:String(t.value??""),onChange:d=>n(d.target.value)});case"date":case"datetime":return i.jsxs("div",{className:"space-y-1",children:[i.jsx(Oe,{type:"date",autoFocus:!0,value:typeof t.value=="string"&&/^\d{4}-/.test(t.value)?t.value.slice(0,10):"",onChange:d=>n(d.target.value||void 0)}),i.jsx("div",{className:"flex gap-1",children:["today","-7d","+7d","-30d"].map(d=>i.jsx("button",{type:"button",onClick:()=>n(d),className:ce("rounded border px-1.5 py-0.5 text-2xs",t.value===d?"border-accent-500 text-accent-700 dark:text-accent-300":"border-surface-200 text-surface-500 dark:border-surface-700"),children:r(`filters.relative.${d}`)},d))})]});case"number":case"currency":case"percent":case"rating":return i.jsx(Oe,{inputMode:"decimal",autoFocus:!0,value:t.value===void 0?"":String(t.value),onChange:d=>n(d.target.value===""?void 0:d.target.value)});default:return i.jsx(Oe,{autoFocus:!0,value:String(t.value??""),onChange:d=>n(d.target.value),placeholder:r("filters.valuePlaceholder")})}}function zG({object:e,filter:t,onChange:n,onRemove:r}){const{t:s}=oe("records"),a=oa(e,t.field);if(!a)return null;const o=QR(a.type);return i.jsxs("div",{className:"w-72 space-y-2 p-3","data-testid":"filter-editor",children:[i.jsxs("div",{className:"flex items-center gap-2",children:[i.jsx("span",{className:"min-w-0 flex-1 truncate text-xs font-medium text-surface-600 dark:text-surface-300",children:a.label}),i.jsx("button",{type:"button",onClick:r,className:"text-xs text-surface-400 hover:text-red-600",children:s("filters.remove")})]}),i.jsx(Ve,{"aria-label":s("filters.operator"),value:t.op,onChange:l=>{const d=l.target.value,f=Cp(d)&&Array.isArray(t.value)===(d==="in"||d==="notIn")&&d!=="withinDays"&&t.op!=="withinDays";n({...t,op:d,value:f?t.value:XR(a,d)})},options:o.map(l=>({value:l,label:s(`filters.ops.${l}`)}))}),i.jsx(FG,{field:a,filter:t,onChange:l=>n({...t,value:l})})]})}function UG({object:e,filter:t,index:n,onChange:r,onRemove:s,autoOpen:a,readOnly:o}){const{t:l}=oe("records"),d=br(),f=LG(),{setOpen:p,anchor:m}=d;S.useEffect(()=>{a&&m&&p(!0)},[a,m,p]);const h=oa(e,t.field),b=qu(t);return i.jsxs(i.Fragment,{children:[i.jsxs("span",{ref:d.anchorRef,"data-testid":`filter-chip-${n}`,className:ce("inline-flex h-6 max-w-[280px] items-center gap-1 rounded-md border pl-2 pr-1 text-xs",b?"border-accent-200 bg-accent-50 text-accent-800 dark:border-accent-500/30 dark:bg-accent-500/10 dark:text-accent-200":"border-dashed border-surface-300 text-surface-500 dark:border-surface-700"),children:[i.jsx("button",{type:"button",disabled:o,className:"min-w-0 truncate",onClick:d.toggle,children:f(h,t)}),!o&&i.jsx("button",{type:"button","aria-label":l("filters.remove"),onClick:s,className:"rounded p-0.5 opacity-60 hover:opacity-100",children:i.jsx(an,{className:"h-3 w-3"})})]}),i.jsx(yr,{open:d.open,onClose:d.close,anchor:d.anchor,children:i.jsx(zG,{object:e,filter:t,onChange:r,onRemove:()=>{d.close(),s()}})})]})}function r3({fields:e,onPick:t,placeholder:n}){const{t:r}=oe(),[s,a]=S.useState(""),[o,l]=S.useState(0),d=S.useMemo(()=>e.filter(f=>f.label.toLowerCase().includes(s.toLowerCase())),[e,s]);return i.jsxs("div",{className:"w-60",children:[i.jsxs("div",{className:"flex items-center gap-2 border-b border-surface-100 px-2.5 dark:border-surface-800",children:[i.jsx(Wr,{className:"h-4 w-4 shrink-0 text-surface-400"}),i.jsx("input",{autoFocus:!0,value:s,placeholder:n,onChange:f=>{a(f.target.value),l(0)},onKeyDown:f=>{f.key==="ArrowDown"?(f.preventDefault(),l(p=>Math.min(p+1,d.length-1))):f.key==="ArrowUp"?(f.preventDefault(),l(p=>Math.max(p-1,0))):f.key==="Enter"&&d[o]&&(f.preventDefault(),t(d[o]))},className:"h-9 w-full bg-transparent text-sm outline-none placeholder:text-surface-400"})]}),i.jsx("div",{className:"max-h-72 overflow-y-auto py-1",children:d.map((f,p)=>i.jsxs("button",{type:"button",onMouseEnter:()=>l(p),onClick:()=>t(f),className:ce("flex w-full items-center justify-between gap-2 px-2.5 py-1.5 text-left text-[13px]",p===o&&"bg-surface-100 dark:bg-surface-800"),children:[i.jsx("span",{className:"truncate",children:f.label}),i.jsx("span",{className:"shrink-0 text-2xs text-surface-400",children:r(`fieldTypes.${f.type}`)})]},f.id))})]})}function BG({object:e,filters:t,onChange:n,readOnly:r}){const{t:s}=oe("records"),a=br(),[o,l]=S.useState(null),d=f=>{const p=QR(f.type)[0];n([...t,{field:f.id,op:p,value:XR(f,p)}]),l(t.length),a.close()};return i.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[t.map((f,p)=>i.jsx(UG,{index:p,object:e,filter:f,autoOpen:o===p,readOnly:r,onChange:m=>n(t.map((h,b)=>b===p?m:h)),onRemove:()=>{l(null),n(t.filter((m,h)=>h!==p))}},`${p}-${f.field}`)),!r&&i.jsxs(i.Fragment,{children:[i.jsx(ue,{ref:a.anchorRef,size:"xs",variant:"ghost",icon:t.length?i.jsx($t,{}):i.jsx(w8,{}),onClick:a.toggle,children:s("filters.add")}),i.jsx(yr,{open:a.open,onClose:a.close,anchor:a.anchor,children:i.jsx(r3,{fields:CG(e),onPick:d,placeholder:s("filters.pickField")})})]}),t.length>0&&!r&&i.jsx("button",{type:"button",onClick:()=>n([]),className:"ml-1 text-xs text-surface-400 hover:text-surface-700 dark:hover:text-surface-200",children:s("filters.clearAll")})]})}function HG(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];return S.useMemo(()=>r=>{t.forEach(s=>s(r))},t)}const z0=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function vd(e){const t=Object.prototype.toString.call(e);return t==="[object Window]"||t==="[object global]"}function aj(e){return"nodeType"in e}function Ir(e){var t,n;return e?vd(e)?e:aj(e)&&(t=(n=e.ownerDocument)==null?void 0:n.defaultView)!=null?t:window:window}function oj(e){const{Document:t}=Ir(e);return e instanceof t}function Np(e){return vd(e)?!1:e instanceof Ir(e).HTMLElement}function s3(e){return e instanceof Ir(e).SVGElement}function wd(e){return e?vd(e)?e.document:aj(e)?oj(e)?e:Np(e)||s3(e)?e.ownerDocument:document:document:document}const ii=z0?S.useLayoutEffect:S.useEffect;function U0(e){const t=S.useRef(e);return ii(()=>{t.current=e}),S.useCallback(function(){for(var n=arguments.length,r=new Array(n),s=0;s<n;s++)r[s]=arguments[s];return t.current==null?void 0:t.current(...r)},[])}function qG(){const e=S.useRef(null),t=S.useCallback((r,s)=>{e.current=setInterval(r,s)},[]),n=S.useCallback(()=>{e.current!==null&&(clearInterval(e.current),e.current=null)},[]);return[t,n]}function Df(e,t){t===void 0&&(t=[e]);const n=S.useRef(e);return ii(()=>{n.current!==e&&(n.current=e)},t),n}function Ap(e,t){const n=S.useRef();return S.useMemo(()=>{const r=e(n.current);return n.current=r,r},[...t])}function Sg(e){const t=U0(e),n=S.useRef(null),r=S.useCallback(s=>{s!==n.current&&(t==null||t(s,n.current)),n.current=s},[]);return[n,r]}function Cg(e){const t=S.useRef();return S.useEffect(()=>{t.current=e},[e]),t.current}let mx={};function _p(e,t){return S.useMemo(()=>{if(t)return t;const n=mx[e]==null?0:mx[e]+1;return mx[e]=n,e+"-"+n},[e,t])}function i3(e){return function(t){for(var n=arguments.length,r=new Array(n>1?n-1:0),s=1;s<n;s++)r[s-1]=arguments[s];return r.reduce((a,o)=>{const l=Object.entries(o);for(const[d,f]of l){const p=a[d];p!=null&&(a[d]=p+e*f)}return a},{...t})}}const _c=i3(1),Mf=i3(-1);function VG(e){return"clientX"in e&&"clientY"in e}function B0(e){if(!e)return!1;const{KeyboardEvent:t}=Ir(e.target);return t&&e instanceof t}function WG(e){if(!e)return!1;const{TouchEvent:t}=Ir(e.target);return t&&e instanceof t}function Ng(e){if(WG(e)){if(e.touches&&e.touches.length){const{clientX:t,clientY:n}=e.touches[0];return{x:t,y:n}}else if(e.changedTouches&&e.changedTouches.length){const{clientX:t,clientY:n}=e.changedTouches[0];return{x:t,y:n}}}return VG(e)?{x:e.clientX,y:e.clientY}:null}const Ai=Object.freeze({Translate:{toString(e){if(!e)return;const{x:t,y:n}=e;return"translate3d("+(t?Math.round(t):0)+"px, "+(n?Math.round(n):0)+"px, 0)"}},Scale:{toString(e){if(!e)return;const{scaleX:t,scaleY:n}=e;return"scaleX("+t+") scaleY("+n+")"}},Transform:{toString(e){if(e)return[Ai.Translate.toString(e),Ai.Scale.toString(e)].join(" ")}},Transition:{toString(e){let{property:t,duration:n,easing:r}=e;return t+" "+n+"ms "+r}}}),SA="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function KG(e){return e.matches(SA)?e:e.querySelector(SA)}const GG={display:"none"};function JG(e){let{id:t,value:n}=e;return Yt.createElement("div",{id:t,style:GG},n)}function YG(e){let{id:t,announcement:n,ariaLiveType:r="assertive"}=e;const s={position:"fixed",top:0,left:0,width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)",whiteSpace:"nowrap"};return Yt.createElement("div",{id:t,style:s,role:"status","aria-live":r,"aria-atomic":!0},n)}function ZG(){const[e,t]=S.useState("");return{announce:S.useCallback(r=>{r!=null&&t(r)},[]),announcement:e}}const a3=S.createContext(null);function QG(e){const t=S.useContext(a3);S.useEffect(()=>{if(!t)throw new Error("useDndMonitor must be used within a children of <DndContext>");return t(e)},[e,t])}function XG(){const[e]=S.useState(()=>new Set),t=S.useCallback(r=>(e.add(r),()=>e.delete(r)),[e]);return[S.useCallback(r=>{let{type:s,event:a}=r;e.forEach(o=>{var l;return(l=o[s])==null?void 0:l.call(o,a)})},[e]),t]}const eJ={draggable:`
@@ -1171,11 +1171,11 @@ Ada,Lovelace,ada@example.com,Analytical Engines`,onChange:ne=>{f(ne.target.value
1171
1171
  `).length-1)}))}catch(_){ge.error(as(_))}},[v,k]=S.useState(!1),j=async()=>{k(!0);try{const{zip:_,report:D}=await WT(t);EI(`${x}-backup-${Sc()}.zip`,new Blob([_],{type:"application/zip"})),ge.success(e("export.zipDone",{count:D.files,size:Is(_.length)})),D.missing.length&&ge.warn(e("export.zipMissing",{count:D.missing.length}))}catch(_){ge.error(as(_))}finally{k(!1)}},C=()=>{try{const _=Qf(t);wU(`${x}-backup-${Sc()}.json`,_),ge.success(e("export.jsonDone"))}catch(_){ge.error(as(_))}};return i.jsxs("div",{className:"max-w-3xl space-y-4",children:[i.jsx(li,{title:e("export.title"),description:e("export.description")}),i.jsxs(Ke,{title:e("export.csvTitle"),children:[i.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[i.jsx(Te,{label:e("export.object"),htmlFor:"export-object",children:i.jsx(Ve,{id:"export-object",value:o,options:n.map(_=>({value:_.id,label:_.labelPlural})),onChange:_=>l(_.target.value)})}),i.jsx(Te,{label:e("export.values"),htmlFor:"export-values",children:i.jsx(Ve,{id:"export-values",value:d,options:[{value:"labels",label:e("export.valuesLabels")},{value:"raw",label:e("export.valuesRaw")}],onChange:_=>f(_.target.value==="raw"?"raw":"labels")})}),i.jsxs("div",{className:"flex flex-wrap gap-x-5 gap-y-2 sm:col-span-2",children:[i.jsx(Ot,{label:e("export.includeId"),checked:p,onChange:_=>m(_.target.checked)}),i.jsx(Ot,{label:e("export.includeDeleted"),checked:h,onChange:_=>b(_.target.checked)})]})]}),i.jsx("div",{className:"mt-4 flex justify-end",children:i.jsx(ue,{variant:"primary",icon:i.jsx(En,{}),onClick:y,disabled:!o,children:e("export.downloadCsv")})})]}),i.jsxs(Ke,{title:e("export.jsonTitle"),children:[i.jsx("p",{className:"mb-3 text-[13px] text-surface-600 dark:text-surface-300",children:e("export.jsonHelp")}),i.jsxs("div",{className:"flex flex-wrap justify-end gap-2",children:[i.jsx(ue,{icon:i.jsx(g8,{}),onClick:C,children:e("export.downloadJson")}),i.jsx(ue,{variant:"primary",icon:i.jsx(cI,{}),loading:v,onClick:()=>void j(),"data-testid":"export-zip",children:e("export.downloadZip")})]}),i.jsx("p",{className:"mt-2 text-xs text-surface-500",children:e("export.zipHelp")})]}),a&&i.jsx(zre,{})]})}function zre(){const{t:e}=oe("settings"),{t}=oe(),n=Xe(),r=S.useRef(null),[s,a]=S.useState(null),[o,l]=S.useState(null),[d,f]=S.useState(0),[p,m]=S.useState(""),[h,b]=S.useState("merge"),[x,y]=S.useState(!1),[v,k]=S.useState(""),[j,C]=S.useState(!1),A=e("export.restoreKeyword"),_=async I=>{try{if(/\.zip$/i.test(I.name)||I.type==="application/zip"){const E=new Uint8Array(await I.arrayBuffer()),P=await K1(E);a(P.data),l(E),f(P.files),m(I.name);return}l(null),f(0);const T=JSON.parse(await I.text());if((T==null?void 0:T.format)!=="agentcrm-export")throw new Error(e("export.notAnExport"));a(T),m(I.name)}catch(T){ge.error(as(T))}},D=s?Object.entries(s.collections).map(([I,T])=>`${I}: ${(T==null?void 0:T.length)??0}`):[];return i.jsxs(Ke,{title:e("export.restoreTitle"),children:[i.jsx("p",{className:"mb-3 text-[13px] text-surface-600 dark:text-surface-300",children:e("export.restoreHelp")}),i.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[i.jsx("input",{ref:r,type:"file",accept:".json,application/json,.zip,application/zip",className:"hidden",onChange:I=>{var E;const T=(E=I.target.files)==null?void 0:E[0];T&&_(T),I.target.value=""}}),i.jsx(ue,{icon:i.jsx(ro,{}),onClick:()=>{var I;return(I=r.current)==null?void 0:I.click()},children:p||e("export.chooseBackup")}),i.jsx(Te,{label:e("export.mode"),htmlFor:"restore-mode",children:i.jsx(Ve,{id:"restore-mode",value:h,options:[{value:"merge",label:e("export.modeMerge")},{value:"replace",label:e("export.modeReplace")}],onChange:I=>b(I.target.value==="replace"?"replace":"merge")})}),i.jsx(ue,{variant:"danger",icon:i.jsx(fa,{}),disabled:!s,onClick:()=>y(!0),children:e("export.restore")})]}),s&&i.jsxs("p",{className:"mt-2 text-xs text-surface-500",children:[e("export.backupInfo",{date:s.exportedAt,counts:D.join(" · ")}),o?` · ${e("export.zipFiles",{count:d})}`:""]}),i.jsxs(on,{open:x,onClose:()=>y(!1),size:"sm",title:e("export.restoreConfirmTitle"),footer:i.jsxs(i.Fragment,{children:[i.jsx(ue,{variant:"ghost",onClick:()=>y(!1),children:t("common.cancel")}),i.jsx(ue,{variant:"danger",icon:i.jsx(fa,{}),loading:j,disabled:v.trim().toUpperCase()!==A.toUpperCase(),onClick:async()=>{if(s){C(!0);try{const I=o?await KT(n,o,{mode:h}):await r0(n,s,{mode:h});ge.success(e("export.restored",{written:I.written,deleted:I.deleted})),y(!1),a(null),l(null),m(""),k("")}catch(I){ge.error(as(I))}finally{C(!1)}}},children:e("export.restore")})]}),children:[i.jsx("p",{className:"mb-3 text-[13px] text-surface-600 dark:text-surface-300",children:e(h==="replace"?"export.restoreReplaceWarning":"export.restoreMergeWarning")}),i.jsx(Te,{label:e("export.typeToConfirm",{keyword:A}),htmlFor:"restore-confirm",children:i.jsx(Oe,{id:"restore-confirm",value:v,onChange:I=>k(I.target.value),autoComplete:"off"})})]})]})}const Tx=30;function Ix({icon:e,title:t,description:n,children:r}){return i.jsxs("div",{className:"flex flex-col gap-3 border-b border-surface-100 px-4 py-3 last:border-b-0 sm:flex-row sm:items-center dark:border-surface-800",children:[i.jsx("span",{className:"hidden text-surface-400 sm:block [&>svg]:h-5 [&>svg]:w-5",children:e}),i.jsxs("div",{className:"min-w-0 flex-1",children:[i.jsx("div",{className:"text-[13px] font-medium text-surface-900 dark:text-white",children:t}),i.jsx("div",{className:"text-xs text-surface-500",children:n})]}),i.jsx("div",{className:"flex shrink-0 gap-2",children:r})]})}function Ure(){const{t:e}=oe("settings"),t=Xe(),n=Ei(),r=di(),s=Ge("compact"),a=Ge("records.write"),o=Ge("settings.write"),l=a&&o,[d,f]=S.useState(null),[p,m]=S.useState(null);if(!s)return i.jsxs("div",{className:"max-w-3xl",children:[i.jsx(li,{title:e("danger.title"),description:e("danger.description")}),i.jsx(xa,{children:e("danger.adminOnly")})]});const h=async()=>{m("preview");try{f(await Lu(t,{dryRun:!0,olderThanDays:Tx}))}catch(y){ge.error(as(y))}finally{m(null)}},b=async y=>{const v=y?0:Tx;let k;try{k=await Lu(t,{dryRun:!0,olderThanDays:v})}catch(C){ge.error(as(C));return}if(f(k),!!await qt({title:e(y?"danger.purgeConfirmTitle":"danger.compactConfirmTitle"),description:e("danger.compactConfirm",{records:k.purgedRecords.length,activities:k.purgedActivities,runs:k.purgedRuns}),confirmLabel:e(y?"danger.purge":"danger.compact"),danger:!0})){m(y?"purge":"compact");try{const C=await Lu(t,{olderThanDays:v});f(C),ge.success(e("danger.compacted",{records:C.purgedRecords.length,activities:C.purgedActivities}))}catch(C){ge.error(as(C))}finally{m(null)}}},x=async()=>{if(await qt({title:e("danger.demoConfirmTitle"),description:e("danger.demoConfirm"),confirmLabel:e("danger.loadDemo"),danger:!0})){m("demo");try{const v=await s1(t,{ownerId:n.id,currency:r.defaultCurrency});!v.companies&&!v.people&&!v.deals?ge.info(e("danger.demoAlready")):ge.success(e("danger.demoLoaded",{companies:v.companies,people:v.people,deals:v.deals}))}catch(v){ge.error(as(v))}finally{m(null)}}};return i.jsxs("div",{className:"max-w-3xl space-y-4",children:[i.jsx(li,{title:e("danger.title"),description:e("danger.description")}),i.jsxs("div",{className:"overflow-hidden rounded-lg border border-red-200 bg-white dark:border-red-500/30 dark:bg-surface-900",children:[i.jsxs(Ix,{icon:i.jsx(X1,{}),title:e("danger.compactTitle"),description:e("danger.compactHelp",{days:Tx}),children:[i.jsx(ue,{size:"sm",icon:i.jsx(tk,{}),loading:p==="preview",onClick:()=>void h(),children:e("danger.preview")}),i.jsx(ue,{size:"sm",variant:"danger",icon:i.jsx(ba,{}),loading:p==="compact",onClick:()=>void b(!1),children:e("danger.compact")})]}),i.jsx(Ix,{icon:i.jsx(wv,{}),title:e("danger.purgeTitle"),description:e("danger.purgeHelp"),children:i.jsx(ue,{size:"sm",variant:"danger",icon:i.jsx(wv,{}),loading:p==="purge",onClick:()=>void b(!0),children:e("danger.purge")})}),l&&i.jsx(Ix,{icon:i.jsx(Ni,{}),title:e("danger.demoTitle"),description:e("danger.demoHelp"),children:i.jsx(ue,{size:"sm",variant:"danger",icon:i.jsx(Ni,{}),loading:p==="demo",onClick:()=>void x(),children:e("danger.loadDemo")})})]}),d&&i.jsx(Ke,{title:d.dryRun?e("danger.reportDry"):e("danger.reportDone"),"data-testid":"compact-report",children:i.jsxs("div",{className:"grid grid-cols-2 gap-2 sm:grid-cols-4",children:[i.jsx(ra,{label:e("danger.records"),value:d.purgedRecords.length}),i.jsx(ra,{label:e("danger.activities"),value:d.purgedActivities}),i.jsx(ra,{label:e("danger.runs"),value:d.purgedRuns}),i.jsx(ra,{label:e("danger.storage"),value:d.dryRun?"—":d.storageCompacted?e("danger.yes"):e("danger.notSupported")})]})})]})}const Bre=[{id:"general",labelKey:"nav.general",icon:yI,component:bre,group:"workspace"},{id:"users",labelKey:"nav.users",icon:wI,component:$re,group:"workspace"},{id:"data-model",labelKey:"nav.dataModel",icon:ba,component:jre,group:"data"},{id:"pipelines",labelKey:"nav.pipelines",icon:go,component:_re,group:"data",module:"deals"},{id:"import",labelKey:"nav.import",icon:ro,component:Pre,group:"data"},{id:"export",labelKey:"nav.export",icon:En,component:Fre,group:"data"},{id:"danger",labelKey:"nav.danger",icon:yo,component:Ure,group:"danger",roles:["admin"]}];function Rx(){const{t:e}=oe("settings"),{t}=oe(),{section:n="general"}=lo(),r=dn(),{role:s}=Oi(),a=Cf("deals"),o=Bre.filter(b=>(!b.roles||b.roles.includes(s))&&(b.module!=="deals"||a)).map(b=>({id:b.id,label:e(b.labelKey),icon:b.icon,component:b.component,group:b.group})),l=il("settingsSections").filter(b=>!b.roles||b.roles.includes(s)).filter(b=>!o.some(x=>x.id===b.id)).map(b=>({id:b.id,label:t(b.label),icon:b.icon,component:b.component,group:b.group??"extra"})),d=[...o.filter(b=>b.group!=="danger"),...l,...o.filter(b=>b.group==="danger")],f=d.find(b=>b.id===n)??d[0],p=f.component,m=b=>r(pt.settings(b==="general"?void 0:b)),h=[{id:"workspace",label:e("nav.groupWorkspace")},{id:"data",label:e("nav.groupData")},{id:"extra",label:e("nav.groupMore")},{id:"danger",label:""}];return i.jsxs("div",{className:"flex min-h-full flex-col",children:[i.jsx(Kr,{title:e("title"),icon:i.jsx(mk,{}),description:f.label,children:i.jsx(bo,{className:"-mb-3 mt-2 border-b-0 lg:hidden",tabs:d.map(b=>({id:b.id,label:b.label,icon:b.icon?i.jsx(b.icon,{}):void 0})),value:f.id,onChange:m})}),i.jsxs("div",{className:"flex min-h-0 flex-1",children:[i.jsx("nav",{"aria-label":e("title"),className:"hidden w-56 shrink-0 border-r border-surface-200 bg-surface-50/60 px-2 py-4 lg:block dark:border-surface-800 dark:bg-surface-950",children:h.map(b=>{const x=d.filter(y=>y.group===b.id);return x.length?i.jsxs("div",{className:"mb-4",children:[b.label&&i.jsx("div",{className:"mb-1 px-2 text-2xs font-medium uppercase tracking-wide text-surface-400",children:b.label}),i.jsx("ul",{className:"space-y-0.5",children:x.map(y=>{const v=y.icon,k=y.id===f.id;return i.jsx("li",{children:i.jsxs("button",{type:"button",onClick:()=>m(y.id),"aria-current":k?"page":void 0,className:ce("flex h-7 w-full items-center gap-2 rounded-md px-2 text-left text-[13px] transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500/60",k?"bg-white font-medium text-surface-900 shadow-sm dark:bg-surface-800 dark:text-white":"text-surface-600 hover:bg-surface-100 hover:text-surface-900 dark:text-surface-300 dark:hover:bg-surface-800/60",y.group==="danger"&&!k&&"text-red-600 dark:text-red-400"),children:[v&&i.jsx(v,{className:"h-4 w-4 shrink-0 opacity-80"}),i.jsx("span",{className:"truncate",children:y.label})]})},y.id)})})]},b.id):null})}),i.jsx("main",{className:"min-w-0 flex-1 p-4 sm:p-6","data-testid":`settings-section-${f.id}`,children:i.jsx(p,{})})]})]})}const Hre={id:"settings",module:fs("settings"),routes:[{path:"/settings",element:S.createElement(Rx)},{path:"/settings/:section",element:S.createElement(Rx)},{path:"/settings/:section/:sub",element:S.createElement(Rx)}],navItems:[{id:"settings",label:"settings:nav.title",icon:mk,to:"/settings",section:"bottom",order:100}],i18n:{en:ere,fr:pre}},qre={back:"Back",cancel:"Cancel",continue:"Continue",save:"Save",copy:"Copy",copied:"Copied to the clipboard.",copyFailed:"Could not copy — select the text and copy it by hand.",show:"Show",hide:"Hide",recommended:"Recommended",testConnection:"Test connection"},Vre={title:"Set up AgentCRM",subtitle:"Your CRM, your storage. Nothing runs on our servers — there are none.",language:"Language",steps:{terms:"Welcome",data:"Data",location:"Location",hosting:"Admin hosting",workspace:"Workspace",install:"Install"}},Wre={title:"Before you start",hint:"AgentCRM is a static app: it runs in your browser (or in the agentcrm CLI) and talks directly to storage you own.",points:{static:"No AgentCRM server: the admin is static files, your data goes straight from this browser to your storage.",yourData:"You choose where the data lives (your bucket, your repository, your Firebase project, this browser) and you can move it later.",secrets:"Keys, tokens and passphrases stay in each browser (or the CLI credentials file). They are never written to config.js nor to the data.",gdpr:"You are the controller of the personal data you store. Files are encrypted by default, and deleted records can be purged physically.",warranty:"The software is provided as is, without warranty. Keep backups (Settings → Data backend → Export)."},accept:"I understand and want to continue",start:"Get started",quickTitle:"Just trying it out?",quickHint:"Use This browser: no account, no storage to configure, demo data included.",quickStart:"Try in this browser"},Kre={title:"Where should your CRM data live?",hint:"You can transfer everything to another backend later (Settings → Data backend), ids preserved.",models:{journal:{title:"Encrypted file on my storage",description:"An S3 / R2 / OVH bucket, a private git repo or a local folder. End-to-end encrypted with your passphrase.",details:"Each change is appended as an encrypted file; teammates who have the storage keys and the passphrase see each other's edits within seconds. No account system: whoever has the keys + passphrase is admin."},firebase:{title:"Firebase",description:"Firestore + Firebase Auth in your own Google project. Real-time, accounts with admin / member / viewer roles.",details:"Best for teams: everyone signs in with email/password or Google, roles are enforced by Firestore security rules generated for you. Free tier is plenty for a small team."},"git-json":{title:"Private git repository",description:"One JSON file per record in a private GitHub / GitLab repo (or a local clone). One commit per change.",details:"Each user signs in with their own token; their repository permission becomes their role. Full history and diffs — but the history keeps every past version of personal data."},local:{title:"This browser",description:"Data stays in this browser (IndexedDB). Single user, no account — ideal to try AgentCRM.",details:"Nothing leaves this browser. Clearing the site data deletes the CRM: export or transfer it to a real backend before relying on it."}}},Gre={journalTitle:"Choose the storage",journalHint:"Use a PRIVATE location dedicated to this CRM. The browser talks to it directly (CORS must allow the admin's origin — see docs/hosting.md).",options:{s3:{title:"S3-compatible bucket",description:"AWS S3, Cloudflare R2, OVHcloud, Scaleway, MinIO…"},github:{title:"GitHub repository",description:"A private repo; encrypted files are committed with your token."},gitlab:{title:"GitLab repository",description:"A private project on gitlab.com or self-managed."},"local-folder":{title:"Local folder",description:"A folder on this computer (Chrome / Edge), e.g. synced by Dropbox or a NAS."}},provider:"Provider",s3Presets:{aws:"AWS S3",r2:"Cloudflare R2",ovh:"OVHcloud",scaleway:"Scaleway",minio:"MinIO",other:"Other"},s3PresetHints:{aws:"Create a private bucket and an IAM user limited to it (s3:GetObject, PutObject, DeleteObject, ListBucket).",r2:"Endpoint: https://<ACCOUNT_ID>.r2.cloudflarestorage.com — create an R2 API token with Object Read & Write on this bucket only. Region: auto.",ovh:"Endpoint: https://s3.<region>.io.cloud.ovh.net (e.g. gra, sbg, de). Create S3 credentials for a user limited to this container.",scaleway:"Endpoint: https://s3.<region>.scw.cloud (fr-par, nl-ams, pl-waw). Use an API key scoped to Object Storage.",minio:"Self-hosted MinIO: use an access key limited to this bucket. Path-style addressing is required.",other:"Any S3-compatible service with SigV4 signing and CORS support."},localFolderHint:"The browser keeps access to this folder; after a reload you'll be asked to re-grant it with one click.",pickFolder:"Choose a folder",changeFolder:"Change folder",folderUnsupported:"This browser can't open local folders (File System Access API). Use Chrome or Edge, or choose another storage.",root:"Folder inside the storage",rootHelp:"The CRM files go under this path (e.g. agentcrm). Use another path to keep several CRMs on the same storage.",fillRequired:"Fill in the required fields first.",testOk:"Connection works ({{detail}}).",publicRepoEncrypted:"Warning: this repository is PUBLIC. Your files are encrypted, but make the repository private anyway.",existingTitle:"An AgentCRM workspace already exists here",existingEncrypted:"It is encrypted. Join it with its passphrase, or use another folder to create a new CRM.",existingPlain:"It is not encrypted. Join it, or use another folder to create a new CRM.",existingGit:"{{name}} — {{count}} documents. You'll join this workspace.",existingFirebase:"This Firebase project already holds a CRM — you'll join it.",joinExisting:"Join this workspace",useAnotherFolder:"Use another folder",gitTitle:"Private git repository",gitHint:"Create an EMPTY private repository for the CRM data (not the repo hosting the admin).",gitGithub:"github.com or GitHub Enterprise",gitGitlab:"gitlab.com or self-managed",gitLocal:"Local clone",gitLocalHint:"A folder that is a git clone you sync yourself (Chrome / Edge).",gitDir:"Data folder in the repo",gitDirHelp:"Where the JSON files go (e.g. crm). Leave empty for the repository root.",gitHistoryTitle:"Git keeps history",gitHistoryBody:"Every past version of every record stays in the git history, including personal data you later delete. Erasing it for good means rewriting the history (or moving to an encrypted backend).",gitOk:"Connected as {{login}} — role: {{role}}.",gitRoles:"Roles come from repository permissions: admin / maintain → admin, write → member, read → viewer.",firebaseTitle:"Connect your Firebase project",firebaseHint:"Everything runs in YOUR Google project; AgentCRM only needs its public web config.",firebaseSteps:{project:"Create a project at console.firebase.google.com (Analytics not needed).",app:"Project settings → Your apps → add a Web app, copy its config below.",auth:"Authentication → Sign-in method: enable Email/Password (and Google if wanted); Users → add your admin account; Settings → Authorized domains: add the domain hosting the admin.",firestore:"Firestore Database → Create database (production mode, region near you).",rules:"Firestore → Rules: paste the rules generated below, then Publish."},firebaseSnippet:"Paste the config snippet (optional)",firebaseSnippetHelp:"The fields below fill in automatically.",firebaseAdmin:"Admin account",firebaseAdminHint:"The account you created in Authentication → Users. Its email is pinned as bootstrap admin in the rules.",methodPassword:"Email & password sign-in",methodGoogle:"Google sign-in",signup:"Who can join",signupModes:{invite:"Invited people only",domain:"Anyone with an allowed domain",open:"Anyone who signs in (not recommended)"},signupHelp:{invite:"Admins add people in Settings → Users; they join with that role on first sign-in.",domain:"Verified addresses of these domains join as members.",open:"Any Google / password account can join as member — your CRM data would be readable by strangers."},allowedDomains:"Allowed domains",rulesTitle:"Firestore security rules",rulesHint:"They are the real access control: viewers read only, members edit records and activities, admins everything. Publish them before verifying.",rulesShow:"Show the rules",rulesHide:"Hide the rules",rulesNeedEmail:"Enter the admin email to generate the rules.",firebaseVerify:"Sign in & verify",firebaseOk:"Signed in as {{email}} — role: {{role}}."},Jre={encryptTitle:"Encrypt my data",encryptHint:"AES-256-GCM with a key derived from your passphrase (PBKDF2, 600 000 rounds). The storage provider only sees random bytes.",label:"Passphrase",confirm:"Confirm passphrase",mismatch:"The passphrases don't match.",generate:"Generate a strong one",generatedCopied:"Passphrase generated and copied — store it in your password manager now.",strengthHint:"At least 10 characters; a few random words work well.",strength:{0:"Too weak",1:"Weak",2:"Fair",3:"Strong",4:"Very strong"},lostTitle:"A lost passphrase means lost data",lostBody:"Nobody — not us, not your storage provider — can recover it. Keep it in a password manager and share it only with the people who should access the CRM.",plainWarning:"Without encryption, anyone who can read the storage (provider, leaked key, misconfigured bucket) can read your contacts.",existingLabel:"Passphrase",existingHelp:"The passphrase chosen when this workspace was created."},Yre={title:"Host the admin for your team (optional)",hint:"Publish this admin to a static host so teammates open it at a URL. config.js (public, no secrets) is written next to it.",securityTitle:"Keep the data and the admin apart",securityBody:"The admin is public static files — that's fine, it holds no data and no secret. Your DATA bucket / repository must stay PRIVATE and separate from the one hosting the admin. To restrict who can even load the admin, put it behind Cloudflare Access or basic auth (docs/hosting.md).",options:{none:{title:"Not now",description:"Keep using this admin. Download config.js later to host it anywhere."},"github-pages":{title:"GitHub Pages",description:"A repo served by GitHub Pages (free; public repo on free plans)."},"cloudflare-pages":{title:"Cloudflare Pages",description:"A Pages project connected to a repo (works with private repos)."},"gitlab-pages":{title:"GitLab Pages",description:"A GitLab project with Pages (a CI file is added)."},s3:{title:"S3 static website",description:"A bucket with static website hosting / a CDN in front."},"local-folder":{title:"Local folder",description:"A folder served by a local web server or synced to a host."},zip:{title:"Download a ZIP",description:"The admin + config.js as a ZIP to upload anywhere by hand."}},howTo:{"github-pages":{title:"GitHub Pages",body:"Use a repo dedicated to the admin (never the data repo). Token: fine-grained, Contents read & write (+ Pages read & write to enable Pages automatically). Leave the token empty to reuse your data token."},"cloudflare-pages":{title:"Cloudflare Pages",body:"Connect the repo to a Pages project (no build command, output directory = the repo folder). Add Cloudflare Access to require a login before the admin loads."},"gitlab-pages":{title:"GitLab Pages",body:"The admin goes under public/ and a minimal .gitlab-ci.yml publishes it. Project access token with write_repository."},s3:{title:"S3 static website",body:"Use a DIFFERENT bucket than the data. Enable static website hosting (or a CDN like CloudFront / R2 custom domain) and allow public reads on it only."},"local-folder":{title:"Local folder",body:"Pick the folder your web server serves; the admin is written into the sub-folder below."}},folder:"Admin folder",folderHelp:"The admin is published under this folder of the site (e.g. admin → https://…/admin/).",testOk:"Target works ({{detail}}).",zipHint:"The ZIP is generated at install from this (built) admin. Unzip it on any static host; config.js inside points at your data.",noneHint:"You can deploy later from Settings → Admin hosting, or download config.js and copy the dist/admin files yourself.",skip:"Skip"},Zre={title:"Your workspace",hint:"You'll be the first admin. Other people are added later in Settings → Users.",joinTitle:"Join the workspace",joinHint:"Tell the CRM who you are on this browser.",name:"Workspace name",currency:"Currency",adminName:"Your name",adminEmail:"Your email",gitEmailHelp:"Used to match your git login with your CRM user (kept in this browser).",demo:"Load demo data (30 companies, 80 people, 40 deals)"},Qre={title:"Ready to install",hint:"Nothing has been written yet. Review and install.",hintFirebase:"Nothing has been written yet (except the Firebase admin record). Review and install.",summary:{model:"Data",location:"Location",encryption:"Encryption",encrypted:"Encrypted",notEncrypted:"Not encrypted",hosting:"Admin hosting",mode:"Workspace",join:"Join the existing workspace",create:"Create a new, empty CRM",createDemo:"Create a new CRM with demo data",admin:"Admin"},steps:{connect:"Connecting to the data…",seed:"Creating objects, pipeline and your admin user…",hostingConfig:"Saving the hosting target…",deploy:"Publishing the admin…",zip:"Packing the admin ZIP…",config:"Saving the configuration in this browser…"},run:"Install",retry:"Retry",failed:"Install failed",doneTitle:"AgentCRM is ready",doneHint:"This browser is configured. Teammates open the hosted admin (or your config.js) and enter their own access.",adminDeployed:"Admin published",zipDone:"The admin ZIP was downloaded — upload its content to your static host.",configJsTitle:"Share this CRM",configJsBody:"Put this config.js next to the admin files (dist/admin) on any static host so teammates land on this CRM. It contains no secret.",open:"Open AgentCRM"},Xre={missingFields:"Some required fields are empty.",connection:"Connection failed.",publicRepo:"This repository is PUBLIC: the CRM would expose personal data. Make it private first.",readOnly:"{{detail}} only has read access — a new CRM needs write access.",wrongPassphrase:"Wrong passphrase: the data could not be decrypted.",passphraseRequired:"This workspace is encrypted: enter its passphrase.",folderRequired:"Choose (or re-grant access to) the folder first.",firebaseAuth:"Firebase sign-in failed (check the API key, the Email/Password provider and the credentials).",firebaseUnverified:"Your email address is not verified yet. We sent a verification email to {{detail}} — open the link, then verify again.",firebaseWrongEmail:"The signed-in account doesn't match the admin email.",firebaseRules:"Firestore refused the admin: publish the generated rules (with this admin email) and check Firestore is created.",firebaseNotAdmin:"Signed in, but the rules don't recognise you as admin (role: {{detail}}). Check the email pinned in the rules.",noManifest:"admin-files.json not found — deploy from a built admin (npm run build / preview), not npm run dev.",generic:"Something went wrong."},ese={endpoint:"Endpoint",endpointHelp:"The S3 API URL of your provider (not the public website URL).",region:"Region",bucket:"Bucket",bucketHelp:"A private bucket dedicated to this CRM.",accessKeyId:"Access key ID",secretAccessKey:"Secret access key",forcePathStyle:"Path-style addressing",forcePathStyleHelp:"https://endpoint/bucket/key — needed by R2, MinIO and most S3-compatibles.",publicRead:"Send public-read ACL on upload",publicReadHelp:"For OVHcloud / Scaleway buckets that aren't public through a policy. Leave off on AWS.",owner:"Owner (user or organisation)",repo:"Repository",project:"Project path",branch:"Branch",token:"Access token",tokenHelp:"GitHub: fine-grained token on this repo only, Contents read & write. GitLab: project access token with api / write_repository. Stays in this browser.",apiBaseUrl:"API URL (Enterprise / self-managed)",siteUrl:"Public URL of the site",siteUrlHelp:"Where the host serves the files, e.g. https://my-company.github.io/crm-admin.",provider:"Git provider",apiKey:"API key",authDomain:"Auth domain",projectId:"Project ID",storageBucket:"Storage bucket",messagingSenderId:"Messaging sender ID",appId:"App ID",adminEmail:"Admin email",adminPassword:"Admin password",options:{github:"GitHub",gitlab:"GitLab"}},tse={admin:"Admin",member:"Member",viewer:"Viewer",adminHint:"Everything: data model, pipelines, settings, users, automations, forms, hosting.",memberHint:"Create, edit and delete records, activities and tasks; own views; import / export.",viewerHint:"Read only."},nse={otherCrm:"Use another CRM",signIn:"Sign in",signOut:"Sign out",or:"or",email:"Email",password:"Password",reconnectFolder:"Reconnect the folder",folderDenied:"Access to the folder was not granted.",storedHere:"Stored in this browser only — never in config.js nor in the data.",firebase:{title:"Sign in to {{name}}",hint:"Use the account your admin invited.",google:"Continue with Google",forgot:"Forgot your password?",resetNeedsEmail:"Enter your email first.",resetSent:"A reset link was sent to {{email}}.",unverifiedTitle:"Verify your email",unverifiedBody:"Open the verification link we emailed you, then continue.",notInvitedTitle:"No access to this CRM",notInvitedBody:"This account has not been invited. Ask an admin to add your email in Settings → Users, then sign in again.",errorTitle:"Could not open your account",errorBody:"Firestore refused the request. Check your connection, or ask an admin to check the security rules.",verified:"I've verified it",resend:"Resend the email",verificationSent:"Verification email sent."},firebaseErrors:{invalidEmail:"This email address is not valid.",invalidCredentials:"Wrong email or password.",tooManyRequests:"Too many attempts. Wait a moment and try again.",userDisabled:"This account is disabled.",network:"Network error — check your connection.",popupClosed:"The sign-in window was closed.",popupBlocked:"The browser blocked the sign-in window. Allow pop-ups for this site.",unauthorizedDomain:"This domain is not authorized in Firebase (Authentication → Settings → Authorized domains).",methodDisabled:"This sign-in method is disabled in Firebase.",generic:"Sign-in failed."},git:{title:"Connect to the data repository",hint:"Enter your own access token for {{repo}}. Your repository permission decides your role.",token:"Personal access token",githubTokenHelp:"github.com → Settings → Developer settings → Fine-grained tokens: this repository only, Contents read & write (read-only → viewer).",gitlabTokenHelp:"Project → Settings → Access tokens (or a personal token) with api or write_repository scope.",email:"Your email in this CRM",emailHelp:"Matches your git login with your CRM user (assignments, owner).",connect:"Connect",tokenRequired:"Enter a token.",invalidToken:"This token can't access the repository."},journal:{title:"Unlock this CRM on this browser",hint:"Data at {{location}}. Enter the access keys and passphrase your admin shared with you (once per browser).",hintFolder:"Data in a {{location}}. Pick the folder and enter the passphrase your admin shared with you (once per browser).",localFolder:"local folder",passphraseHelp:"The workspace passphrase.",unlock:"Unlock",folderHint:"Browsers forget folder permissions on reload: re-grant access with one click.",noDataset:"No AgentCRM workspace found at this location (or the keys can't read it).",wrongPassphrase:"Wrong passphrase: the data could not be decrypted."}},rse={sections:{data:"Data backend",hosting:"Admin hosting",security:"Security"},data:{title:"Data backend",backend:"Backend",location:"Location",encryption:"Encryption",storage:"Storage",stats:"{{documents}} documents · {{segments}} journal files ({{pendingSegments}} not compacted) · {{tombstones}} deleted entries",encryptionTitle:"Encryption",encryptionOnHint:"Files are encrypted with the workspace passphrase. Changing it re-encrypts everything; every browser then needs the new one.",encryptionOffHint:"Files are stored unencrypted. Turn encryption on to protect personal data from anyone who can read the storage.",changePassphrase:"Change passphrase",enableEncryption:"Turn encryption on",disableEncryption:"Turn encryption off",disableEncryptionCheck:"Store the data unencrypted instead",currentPassphrase:"Current passphrase",applyPassphrase:"Re-encrypt",rekeyWarning:"Make sure nobody else is editing: the data is compacted then re-encrypted. Other browsers and the CLI will be asked for the new passphrase.",rekeyDone:"Data re-encrypted with the new passphrase.",decryptDone:"Encryption turned off.",maintenanceTitle:"Maintenance",compact:"Compact & purge",compactHint:"Physically deletes records in the trash, their activities and old automation runs.",compactHintJournal:"Purges deleted records and rewrites the storage as one snapshot (removes history of deleted data — GDPR erasure).",compactNow:"Compact now",compactConfirmTitle:"Compact the data?",compactConfirmBody:"Deleted records and their activities are purged for good. This can't be undone.",compactDone:"Compacted: {{records}} records and {{activities}} activities purged.",export:"Export",exportHint:"Every object, record, activity, pipeline, view and setting as one JSON file (ids preserved).",exportJson:"Export JSON",transfer:"Move to another backend",transferHint:"Copy the whole CRM to another backend or location, ids preserved, then switch to it.",transferStart:"Transfer…",transferExplain:"Everything is copied into the destination (which must be empty). The current data is left untouched — delete it yourself once the move is verified.",transferNotEmpty:"The destination already holds a CRM: pick an empty location.",transferFirebaseUsers:"Users other than you become invitations in Firebase: they join with their role on first sign-in.",transferRun:"Copy the data",transferDone:"{{count}} documents copied.",transferDoneHint:"Switch this browser to the new backend now? If the admin is hosted, its config.js is updated too.",stayHere:"Not now",switchNow:"Switch to it",configJsUpdated:"config.js updated on the admin hosting.",configJsFailed:"Could not update config.js on the hosting: {{detail}}",rulesTitle:"Firestore security rules",rulesHint:"Re-generate and publish them in the Firebase console after changing who can join."},hosting:{title:"Admin hosting",deploy:"Deploy / update admin",deployed:"{{count}} files published (version {{version}}).",saved:"Hosting target saved.",currentUrl:"Admin URL",zip:"Download admin ZIP",devNote:"Deploying copies THIS admin build (admin-files.json) — run it from a built admin (npm run build / preview), not npm run dev."},security:{roleTitle:"Your access",signedInAs:"Signed in as {{email}}",enforcement:{local:"Single user: this browser holds the data, no roles to enforce.",journal:"Shared storage: anyone with the storage keys and the passphrase has full access. Roles in Users are informative only.","git-json":"Enforced by the repository: your token's permission is the ceiling of your role (admin / maintain → admin, write → member, read → viewer).",firebase:"Enforced by the Firestore security rules on every request."},secretsTitle:"Secrets on this browser",secretsHint:"What this browser keeps in its local storage for this CRM:",secrets:{connector:"Storage access keys / token",passphrase:"Encryption passphrase",gitToken:"Your git access token",firebaseSession:"Firebase session (managed by Firebase Auth)",hosting:"Admin hosting keys / token"},neverShared:"Secrets are never written to config.js, to the CRM data or to git. Other browsers enter their own.",forget:"Forget secrets on this browser",forgetConfirmTitle:"Forget this browser's secrets?",forgetConfirmBody:"Keys, tokens and the passphrase are removed from this browser. You'll need them again to open the CRM here.",lock:"Lock"}},sse={common:qre,wizard:Vre,terms:Wre,data:Kre,location:Gre,passphrase:Jre,hosting:Yre,workspace:Zre,install:Qre,errors:Xre,fields:ese,roles:tse,access:nse,settings:rse},ise={back:"Retour",cancel:"Annuler",continue:"Continuer",save:"Enregistrer",copy:"Copier",copied:"Copié dans le presse-papiers.",copyFailed:"Copie impossible — sélectionnez le texte et copiez-le à la main.",show:"Afficher",hide:"Masquer",recommended:"Recommandé",testConnection:"Tester la connexion"},ase={title:"Configurer AgentCRM",subtitle:"Votre CRM, votre stockage. Rien ne tourne sur nos serveurs — il n'y en a pas.",language:"Langue",steps:{terms:"Bienvenue",data:"Données",location:"Emplacement",hosting:"Hébergement de l'admin",workspace:"Espace de travail",install:"Installation"}},ose={title:"Avant de commencer",hint:"AgentCRM est une application statique : elle tourne dans votre navigateur (ou dans la CLI agentcrm) et parle directement au stockage qui vous appartient.",points:{static:"Aucun serveur AgentCRM : l'admin est un ensemble de fichiers statiques, vos données vont directement de ce navigateur à votre stockage.",yourData:"Vous choisissez où vivent les données (votre bucket, votre dépôt, votre projet Firebase, ce navigateur) et vous pourrez les déplacer plus tard.",secrets:"Les clés, jetons et phrases secrètes restent dans chaque navigateur (ou dans le fichier d'identifiants de la CLI). Ils ne sont jamais écrits dans config.js ni dans les données.",gdpr:"Vous êtes responsable de traitement des données personnelles stockées. Les fichiers sont chiffrés par défaut et les fiches supprimées peuvent être purgées physiquement.",warranty:"Le logiciel est fourni tel quel, sans garantie. Faites des sauvegardes (Paramètres → Stockage des données → Export)."},accept:"J'ai compris et je souhaite continuer",start:"Commencer",quickTitle:"Vous voulez juste essayer ?",quickHint:"Utilisez Ce navigateur : pas de compte, pas de stockage à configurer, données de démo incluses.",quickStart:"Essayer dans ce navigateur"},lse={title:"Où doivent vivre les données de votre CRM ?",hint:"Vous pourrez tout transférer vers un autre stockage plus tard (Paramètres → Stockage des données), identifiants conservés.",models:{journal:{title:"Fichier chiffré sur mon stockage",description:"Un bucket S3 / R2 / OVH, un dépôt git privé ou un dossier local. Chiffré de bout en bout avec votre phrase secrète.",details:"Chaque modification est ajoutée sous forme de fichier chiffré ; les collègues qui ont les clés du stockage et la phrase secrète voient les modifications des autres en quelques secondes. Pas de comptes : quiconque possède les clés et la phrase secrète est admin."},firebase:{title:"Firebase",description:"Firestore + Firebase Auth dans votre propre projet Google. Temps réel, comptes avec rôles admin / membre / lecteur.",details:"Idéal pour les équipes : chacun se connecte par e-mail/mot de passe ou Google, les rôles sont appliqués par des règles de sécurité Firestore générées pour vous. Le niveau gratuit suffit largement pour une petite équipe."},"git-json":{title:"Dépôt git privé",description:"Un fichier JSON par fiche dans un dépôt GitHub / GitLab privé (ou un clone local). Un commit par modification.",details:"Chaque utilisateur se connecte avec son propre jeton ; sa permission sur le dépôt devient son rôle. Historique et diffs complets — mais l'historique conserve toutes les versions passées des données personnelles."},local:{title:"Ce navigateur",description:"Les données restent dans ce navigateur (IndexedDB). Un seul utilisateur, sans compte — idéal pour essayer AgentCRM.",details:"Rien ne quitte ce navigateur. Effacer les données du site supprime le CRM : exportez-le ou transférez-le vers un vrai stockage avant de vous en servir sérieusement."}}},cse={journalTitle:"Choisissez le stockage",journalHint:"Utilisez un emplacement PRIVÉ dédié à ce CRM. Le navigateur lui parle directement (le CORS doit autoriser l'origine de l'admin — voir docs/hosting.md).",options:{s3:{title:"Bucket compatible S3",description:"AWS S3, Cloudflare R2, OVHcloud, Scaleway, MinIO…"},github:{title:"Dépôt GitHub",description:"Un dépôt privé ; les fichiers chiffrés sont committés avec votre jeton."},gitlab:{title:"Dépôt GitLab",description:"Un projet privé sur gitlab.com ou auto-hébergé."},"local-folder":{title:"Dossier local",description:"Un dossier de cet ordinateur (Chrome / Edge), par ex. synchronisé par Dropbox ou un NAS."}},provider:"Fournisseur",s3Presets:{aws:"AWS S3",r2:"Cloudflare R2",ovh:"OVHcloud",scaleway:"Scaleway",minio:"MinIO",other:"Autre"},s3PresetHints:{aws:"Créez un bucket privé et un utilisateur IAM limité à celui-ci (s3:GetObject, PutObject, DeleteObject, ListBucket).",r2:"Endpoint : https://<ACCOUNT_ID>.r2.cloudflarestorage.com — créez un jeton d'API R2 en lecture & écriture d'objets sur ce seul bucket. Région : auto.",ovh:"Endpoint : https://s3.<région>.io.cloud.ovh.net (par ex. gra, sbg, de). Créez des identifiants S3 pour un utilisateur limité à ce conteneur.",scaleway:"Endpoint : https://s3.<région>.scw.cloud (fr-par, nl-ams, pl-waw). Utilisez une clé d'API limitée à l'Object Storage.",minio:"MinIO auto-hébergé : utilisez une clé d'accès limitée à ce bucket. L'adressage en chemin est obligatoire.",other:"Tout service compatible S3 avec signature SigV4 et prise en charge du CORS."},localFolderHint:"Le navigateur garde l'accès à ce dossier ; après un rechargement, il vous sera demandé de le ré-autoriser en un clic.",pickFolder:"Choisir un dossier",changeFolder:"Changer de dossier",folderUnsupported:"Ce navigateur ne peut pas ouvrir de dossiers locaux (API File System Access). Utilisez Chrome ou Edge, ou choisissez un autre stockage.",root:"Dossier dans le stockage",rootHelp:"Les fichiers du CRM sont placés sous ce chemin (par ex. agentcrm). Utilisez un autre chemin pour héberger plusieurs CRM sur le même stockage.",fillRequired:"Remplissez d'abord les champs obligatoires.",testOk:"La connexion fonctionne ({{detail}}).",publicRepoEncrypted:"Attention : ce dépôt est PUBLIC. Vos fichiers sont chiffrés, mais rendez quand même le dépôt privé.",existingTitle:"Un espace AgentCRM existe déjà ici",existingEncrypted:"Il est chiffré. Rejoignez-le avec sa phrase secrète, ou utilisez un autre dossier pour créer un nouveau CRM.",existingPlain:"Il n'est pas chiffré. Rejoignez-le, ou utilisez un autre dossier pour créer un nouveau CRM.",existingGit:"{{name}} — {{count}} documents. Vous allez rejoindre cet espace.",existingFirebase:"Ce projet Firebase contient déjà un CRM — vous allez le rejoindre.",joinExisting:"Rejoindre cet espace",useAnotherFolder:"Utiliser un autre dossier",gitTitle:"Dépôt git privé",gitHint:"Créez un dépôt privé VIDE pour les données du CRM (pas le dépôt qui héberge l'admin).",gitGithub:"github.com ou GitHub Enterprise",gitGitlab:"gitlab.com ou auto-hébergé",gitLocal:"Clone local",gitLocalHint:"Un dossier qui est un clone git que vous synchronisez vous-même (Chrome / Edge).",gitDir:"Dossier des données dans le dépôt",gitDirHelp:"Où vont les fichiers JSON (par ex. crm). Laissez vide pour la racine du dépôt.",gitHistoryTitle:"Git conserve l'historique",gitHistoryBody:"Chaque version passée de chaque fiche reste dans l'historique git, y compris les données personnelles supprimées ensuite. Les effacer définitivement implique de réécrire l'historique (ou de passer à un stockage chiffré).",gitOk:"Connecté en tant que {{login}} — rôle : {{role}}.",gitRoles:"Les rôles viennent des permissions du dépôt : admin / maintain → admin, write → membre, read → lecteur.",firebaseTitle:"Connectez votre projet Firebase",firebaseHint:"Tout tourne dans VOTRE projet Google ; AgentCRM n'a besoin que de sa configuration web publique.",firebaseSteps:{project:"Créez un projet sur console.firebase.google.com (Analytics inutile).",app:"Paramètres du projet → Vos applications → ajoutez une application Web, copiez sa configuration ci-dessous.",auth:"Authentication → Mode de connexion : activez E-mail/Mot de passe (et Google si besoin) ; Utilisateurs → ajoutez votre compte admin ; Paramètres → Domaines autorisés : ajoutez le domaine qui héberge l'admin.",firestore:"Firestore Database → Créer une base de données (mode production, région proche de vous).",rules:"Firestore → Règles : collez les règles générées ci-dessous, puis Publiez."},firebaseSnippet:"Collez l'extrait de configuration (facultatif)",firebaseSnippetHelp:"Les champs ci-dessous se remplissent automatiquement.",firebaseAdmin:"Compte administrateur",firebaseAdminHint:"Le compte créé dans Authentication → Utilisateurs. Son e-mail est fixé comme admin initial dans les règles.",methodPassword:"Connexion par e-mail et mot de passe",methodGoogle:"Connexion avec Google",signup:"Qui peut rejoindre",signupModes:{invite:"Personnes invitées uniquement",domain:"Toute personne d'un domaine autorisé",open:"Toute personne qui se connecte (déconseillé)"},signupHelp:{invite:"Les admins ajoutent les personnes dans Paramètres → Utilisateurs ; elles rejoignent avec ce rôle à leur première connexion.",domain:"Les adresses vérifiées de ces domaines rejoignent en tant que membres.",open:"N'importe quel compte Google / mot de passe peut rejoindre comme membre — les données de votre CRM seraient lisibles par des inconnus."},allowedDomains:"Domaines autorisés",rulesTitle:"Règles de sécurité Firestore",rulesHint:"Elles sont le vrai contrôle d'accès : les lecteurs lisent seulement, les membres modifient fiches et activités, les admins tout. Publiez-les avant de vérifier.",rulesShow:"Afficher les règles",rulesHide:"Masquer les règles",rulesNeedEmail:"Saisissez l'e-mail de l'admin pour générer les règles.",firebaseVerify:"Se connecter et vérifier",firebaseOk:"Connecté en tant que {{email}} — rôle : {{role}}."},dse={encryptTitle:"Chiffrer mes données",encryptHint:"AES-256-GCM avec une clé dérivée de votre phrase secrète (PBKDF2, 600 000 itérations). Le fournisseur de stockage ne voit que des octets aléatoires.",label:"Phrase secrète",confirm:"Confirmer la phrase secrète",mismatch:"Les phrases secrètes ne correspondent pas.",generate:"En générer une solide",generatedCopied:"Phrase secrète générée et copiée — enregistrez-la tout de suite dans votre gestionnaire de mots de passe.",strengthHint:"Au moins 10 caractères ; quelques mots au hasard fonctionnent bien.",strength:{0:"Trop faible",1:"Faible",2:"Correcte",3:"Solide",4:"Très solide"},lostTitle:"Phrase secrète perdue = données perdues",lostBody:"Personne — ni nous, ni votre fournisseur de stockage — ne peut la récupérer. Gardez-la dans un gestionnaire de mots de passe et ne la partagez qu'avec les personnes qui doivent accéder au CRM.",plainWarning:"Sans chiffrement, toute personne pouvant lire le stockage (fournisseur, clé divulguée, bucket mal configuré) peut lire vos contacts.",existingLabel:"Phrase secrète",existingHelp:"La phrase secrète choisie à la création de cet espace."},use={title:"Héberger l'admin pour votre équipe (facultatif)",hint:"Publiez cet admin sur un hébergeur statique pour que vos collègues l'ouvrent depuis une URL. config.js (public, sans secret) est écrit à côté.",securityTitle:"Séparez les données et l'admin",securityBody:"L'admin est un ensemble de fichiers statiques publics — c'est normal, il ne contient ni données ni secret. Votre bucket / dépôt de DONNÉES doit rester PRIVÉ et distinct de celui qui héberge l'admin. Pour restreindre qui peut même charger l'admin, placez-le derrière Cloudflare Access ou une authentification basique (docs/hosting.md).",options:{none:{title:"Pas maintenant",description:"Continuez avec cet admin. Téléchargez config.js plus tard pour l'héberger où vous voulez."},"github-pages":{title:"GitHub Pages",description:"Un dépôt servi par GitHub Pages (gratuit ; dépôt public sur les offres gratuites)."},"cloudflare-pages":{title:"Cloudflare Pages",description:"Un projet Pages connecté à un dépôt (fonctionne avec des dépôts privés)."},"gitlab-pages":{title:"GitLab Pages",description:"Un projet GitLab avec Pages (un fichier CI est ajouté)."},s3:{title:"Site statique S3",description:"Un bucket avec hébergement de site statique / un CDN devant."},"local-folder":{title:"Dossier local",description:"Un dossier servi par un serveur web local ou synchronisé vers un hébergeur."},zip:{title:"Télécharger un ZIP",description:"L'admin + config.js dans un ZIP à téléverser où vous voulez."}},howTo:{"github-pages":{title:"GitHub Pages",body:"Utilisez un dépôt dédié à l'admin (jamais le dépôt des données). Jeton : fine-grained, Contents en lecture & écriture (+ Pages en lecture & écriture pour activer Pages automatiquement). Laissez le jeton vide pour réutiliser votre jeton de données."},"cloudflare-pages":{title:"Cloudflare Pages",body:"Connectez le dépôt à un projet Pages (sans commande de build, dossier de sortie = le dossier du dépôt). Ajoutez Cloudflare Access pour exiger une connexion avant le chargement de l'admin."},"gitlab-pages":{title:"GitLab Pages",body:"L'admin est placé sous public/ et un .gitlab-ci.yml minimal le publie. Jeton d'accès au projet avec write_repository."},s3:{title:"Site statique S3",body:"Utilisez un bucket DIFFÉRENT de celui des données. Activez l'hébergement de site statique (ou un CDN comme CloudFront / un domaine personnalisé R2) et autorisez la lecture publique sur celui-ci uniquement."},"local-folder":{title:"Dossier local",body:"Choisissez le dossier servi par votre serveur web ; l'admin est écrit dans le sous-dossier ci-dessous."}},folder:"Dossier de l'admin",folderHelp:"L'admin est publié dans ce dossier du site (par ex. admin → https://…/admin/).",testOk:"La cible fonctionne ({{detail}}).",zipHint:"Le ZIP est généré à l'installation à partir de cet admin (compilé). Décompressez-le sur n'importe quel hébergeur statique ; le config.js inclus pointe vers vos données.",noneHint:"Vous pourrez déployer plus tard depuis Paramètres → Hébergement de l'admin, ou télécharger config.js et copier vous-même les fichiers de dist/admin.",skip:"Passer"},fse={title:"Votre espace de travail",hint:"Vous serez le premier admin. Les autres personnes s'ajoutent ensuite dans Paramètres → Utilisateurs.",joinTitle:"Rejoindre l'espace",joinHint:"Indiquez au CRM qui vous êtes sur ce navigateur.",name:"Nom de l'espace",currency:"Devise",adminName:"Votre nom",adminEmail:"Votre e-mail",gitEmailHelp:"Sert à associer votre identifiant git à votre utilisateur CRM (conservé dans ce navigateur).",demo:"Charger des données de démo (30 entreprises, 80 personnes, 40 affaires)"},pse={title:"Prêt à installer",hint:"Rien n'a encore été écrit. Vérifiez puis installez.",hintFirebase:"Rien n'a encore été écrit (sauf la fiche admin Firebase). Vérifiez puis installez.",summary:{model:"Données",location:"Emplacement",encryption:"Chiffrement",encrypted:"Chiffré",notEncrypted:"Non chiffré",hosting:"Hébergement de l'admin",mode:"Espace",join:"Rejoindre l'espace existant",create:"Créer un nouveau CRM vide",createDemo:"Créer un nouveau CRM avec des données de démo",admin:"Admin"},steps:{connect:"Connexion aux données…",seed:"Création des objets, du pipeline et de votre utilisateur admin…",hostingConfig:"Enregistrement de la cible d'hébergement…",deploy:"Publication de l'admin…",zip:"Création du ZIP de l'admin…",config:"Enregistrement de la configuration dans ce navigateur…"},run:"Installer",retry:"Réessayer",failed:"L'installation a échoué",doneTitle:"AgentCRM est prêt",doneHint:"Ce navigateur est configuré. Vos collègues ouvrent l'admin hébergé (ou votre config.js) et saisissent leurs propres accès.",adminDeployed:"Admin publié",zipDone:"Le ZIP de l'admin a été téléchargé — téléversez son contenu sur votre hébergeur statique.",configJsTitle:"Partager ce CRM",configJsBody:"Placez ce config.js à côté des fichiers de l'admin (dist/admin) sur n'importe quel hébergeur statique pour que vos collègues arrivent sur ce CRM. Il ne contient aucun secret.",open:"Ouvrir AgentCRM"},mse={missingFields:"Certains champs obligatoires sont vides.",connection:"La connexion a échoué.",publicRepo:"Ce dépôt est PUBLIC : le CRM exposerait des données personnelles. Rendez-le d'abord privé.",readOnly:"{{detail}} n'a qu'un accès en lecture — un nouveau CRM nécessite un accès en écriture.",wrongPassphrase:"Phrase secrète incorrecte : les données n'ont pas pu être déchiffrées.",passphraseRequired:"Cet espace est chiffré : saisissez sa phrase secrète.",folderRequired:"Choisissez d'abord le dossier (ou ré-autorisez l'accès).",firebaseAuth:"La connexion Firebase a échoué (vérifiez la clé d'API, le fournisseur E-mail/Mot de passe et les identifiants).",firebaseUnverified:"Votre adresse e-mail n'est pas encore vérifiée. Un e-mail de vérification a été envoyé à {{detail}} — ouvrez le lien, puis vérifiez à nouveau.",firebaseWrongEmail:"Le compte connecté ne correspond pas à l'e-mail de l'admin.",firebaseRules:"Firestore a refusé l'admin : publiez les règles générées (avec cet e-mail d'admin) et vérifiez que Firestore est créé.",firebaseNotAdmin:"Connecté, mais les règles ne vous reconnaissent pas comme admin (rôle : {{detail}}). Vérifiez l'e-mail fixé dans les règles.",noManifest:"admin-files.json introuvable — déployez depuis un admin compilé (npm run build / preview), pas depuis npm run dev.",generic:"Une erreur s'est produite."},hse={endpoint:"Endpoint",endpointHelp:"L'URL de l'API S3 de votre fournisseur (pas l'URL publique du site).",region:"Région",bucket:"Bucket",bucketHelp:"Un bucket privé dédié à ce CRM.",accessKeyId:"ID de clé d'accès",secretAccessKey:"Clé d'accès secrète",forcePathStyle:"Adressage en chemin (path-style)",forcePathStyleHelp:"https://endpoint/bucket/clé — requis par R2, MinIO et la plupart des compatibles S3.",publicRead:"Envoyer l'ACL public-read au téléversement",publicReadHelp:"Pour les buckets OVHcloud / Scaleway qui ne sont pas publics via une politique. À laisser désactivé sur AWS.",owner:"Propriétaire (utilisateur ou organisation)",repo:"Dépôt",project:"Chemin du projet",branch:"Branche",token:"Jeton d'accès",tokenHelp:"GitHub : jeton fine-grained limité à ce dépôt, Contents en lecture & écriture. GitLab : jeton d'accès au projet avec api / write_repository. Reste dans ce navigateur.",apiBaseUrl:"URL de l'API (Enterprise / auto-hébergé)",siteUrl:"URL publique du site",siteUrlHelp:"L'adresse où l'hébergeur sert les fichiers, par ex. https://mon-entreprise.github.io/crm-admin.",provider:"Fournisseur git",apiKey:"Clé d'API",authDomain:"Domaine d'authentification",projectId:"ID du projet",storageBucket:"Bucket de stockage",messagingSenderId:"ID d'expéditeur",appId:"ID d'application",adminEmail:"E-mail de l'admin",adminPassword:"Mot de passe de l'admin",options:{github:"GitHub",gitlab:"GitLab"}},gse={admin:"Admin",member:"Membre",viewer:"Lecteur",adminHint:"Tout : modèle de données, pipelines, paramètres, utilisateurs, automatisations, formulaires, hébergement.",memberHint:"Créer, modifier et supprimer fiches, activités et tâches ; vues personnelles ; import / export.",viewerHint:"Lecture seule."},yse={otherCrm:"Utiliser un autre CRM",signIn:"Se connecter",signOut:"Se déconnecter",or:"ou",email:"E-mail",password:"Mot de passe",reconnectFolder:"Reconnecter le dossier",folderDenied:"L'accès au dossier n'a pas été accordé.",storedHere:"Conservé uniquement dans ce navigateur — jamais dans config.js ni dans les données.",firebase:{title:"Connexion à {{name}}",hint:"Utilisez le compte que votre admin a invité.",google:"Continuer avec Google",forgot:"Mot de passe oublié ?",resetNeedsEmail:"Saisissez d'abord votre e-mail.",resetSent:"Un lien de réinitialisation a été envoyé à {{email}}.",unverifiedTitle:"Vérifiez votre e-mail",unverifiedBody:"Ouvrez le lien de vérification que nous vous avons envoyé, puis continuez.",notInvitedTitle:"Pas d'accès à ce CRM",notInvitedBody:"Ce compte n'a pas été invité. Demandez à un admin d'ajouter votre e-mail dans Paramètres → Utilisateurs, puis reconnectez-vous.",errorTitle:"Impossible d'ouvrir votre compte",errorBody:"Firestore a refusé la requête. Vérifiez votre connexion, ou demandez à un admin de vérifier les règles de sécurité.",verified:"C'est fait",resend:"Renvoyer l'e-mail",verificationSent:"E-mail de vérification envoyé."},firebaseErrors:{invalidEmail:"Cette adresse e-mail n'est pas valide.",invalidCredentials:"E-mail ou mot de passe incorrect.",tooManyRequests:"Trop de tentatives. Patientez un instant puis réessayez.",userDisabled:"Ce compte est désactivé.",network:"Erreur réseau — vérifiez votre connexion.",popupClosed:"La fenêtre de connexion a été fermée.",popupBlocked:"Le navigateur a bloqué la fenêtre de connexion. Autorisez les pop-ups pour ce site.",unauthorizedDomain:"Ce domaine n'est pas autorisé dans Firebase (Authentication → Paramètres → Domaines autorisés).",methodDisabled:"Ce mode de connexion est désactivé dans Firebase.",generic:"La connexion a échoué."},git:{title:"Connexion au dépôt de données",hint:"Saisissez votre propre jeton d'accès pour {{repo}}. Votre permission sur le dépôt détermine votre rôle.",token:"Jeton d'accès personnel",githubTokenHelp:"github.com → Settings → Developer settings → Fine-grained tokens : ce dépôt uniquement, Contents en lecture & écriture (lecture seule → lecteur).",gitlabTokenHelp:"Projet → Paramètres → Jetons d'accès (ou un jeton personnel) avec la portée api ou write_repository.",email:"Votre e-mail dans ce CRM",emailHelp:"Associe votre identifiant git à votre utilisateur CRM (attributions, propriétaire).",connect:"Se connecter",tokenRequired:"Saisissez un jeton.",invalidToken:"Ce jeton n'a pas accès au dépôt."},journal:{title:"Déverrouiller ce CRM sur ce navigateur",hint:"Données sur {{location}}. Saisissez les clés d'accès et la phrase secrète que votre admin vous a communiquées (une fois par navigateur).",hintFolder:"Données dans un {{location}}. Choisissez le dossier et saisissez la phrase secrète que votre admin vous a communiquée (une fois par navigateur).",localFolder:"dossier local",passphraseHelp:"La phrase secrète de l'espace.",unlock:"Déverrouiller",folderHint:"Les navigateurs oublient les permissions de dossier au rechargement : ré-autorisez l'accès en un clic.",noDataset:"Aucun espace AgentCRM trouvé à cet emplacement (ou les clés ne permettent pas de le lire).",wrongPassphrase:"Phrase secrète incorrecte : les données n'ont pas pu être déchiffrées."}},bse={sections:{data:"Stockage des données",hosting:"Hébergement de l'admin",security:"Sécurité"},data:{title:"Stockage des données",backend:"Type",location:"Emplacement",encryption:"Chiffrement",storage:"Stockage",stats:"{{documents}} documents · {{segments}} fichiers de journal ({{pendingSegments}} non compactés) · {{tombstones}} entrées supprimées",encryptionTitle:"Chiffrement",encryptionOnHint:"Les fichiers sont chiffrés avec la phrase secrète de l'espace. La changer rechiffre tout ; chaque navigateur aura ensuite besoin de la nouvelle.",encryptionOffHint:"Les fichiers sont stockés en clair. Activez le chiffrement pour protéger les données personnelles de toute personne pouvant lire le stockage.",changePassphrase:"Changer la phrase secrète",enableEncryption:"Activer le chiffrement",disableEncryption:"Désactiver le chiffrement",disableEncryptionCheck:"Stocker plutôt les données en clair",currentPassphrase:"Phrase secrète actuelle",applyPassphrase:"Rechiffrer",rekeyWarning:"Assurez-vous que personne d'autre ne modifie le CRM : les données sont compactées puis rechiffrées. Les autres navigateurs et la CLI devront saisir la nouvelle phrase secrète.",rekeyDone:"Données rechiffrées avec la nouvelle phrase secrète.",decryptDone:"Chiffrement désactivé.",maintenanceTitle:"Maintenance",compact:"Compacter et purger",compactHint:"Supprime physiquement les fiches de la corbeille, leurs activités et les anciennes exécutions d'automatisations.",compactHintJournal:"Purge les fiches supprimées et réécrit le stockage en un seul instantané (supprime l'historique des données effacées — droit à l'effacement RGPD).",compactNow:"Compacter maintenant",compactConfirmTitle:"Compacter les données ?",compactConfirmBody:"Les fiches supprimées et leurs activités sont purgées définitivement. Action irréversible.",compactDone:"Compactage terminé : {{records}} fiches et {{activities}} activités purgées.",export:"Export",exportHint:"Tous les objets, fiches, activités, pipelines, vues et paramètres dans un fichier JSON (identifiants conservés).",exportJson:"Exporter en JSON",transfer:"Changer de stockage",transferHint:"Copiez tout le CRM vers un autre stockage ou emplacement, identifiants conservés, puis basculez dessus.",transferStart:"Transférer…",transferExplain:"Tout est copié vers la destination (qui doit être vide). Les données actuelles ne sont pas modifiées — supprimez-les vous-même une fois le transfert vérifié.",transferNotEmpty:"La destination contient déjà un CRM : choisissez un emplacement vide.",transferFirebaseUsers:"Les utilisateurs autres que vous deviennent des invitations dans Firebase : ils rejoignent avec leur rôle à leur première connexion.",transferRun:"Copier les données",transferDone:"{{count}} documents copiés.",transferDoneHint:"Basculer ce navigateur sur le nouveau stockage maintenant ? Si l'admin est hébergé, son config.js est aussi mis à jour.",stayHere:"Pas maintenant",switchNow:"Basculer",configJsUpdated:"config.js mis à jour sur l'hébergement de l'admin.",configJsFailed:"Impossible de mettre à jour config.js sur l'hébergement : {{detail}}",rulesTitle:"Règles de sécurité Firestore",rulesHint:"Régénérez-les et publiez-les dans la console Firebase après avoir changé qui peut rejoindre."},hosting:{title:"Hébergement de l'admin",deploy:"Déployer / mettre à jour l'admin",deployed:"{{count}} fichiers publiés (version {{version}}).",saved:"Cible d'hébergement enregistrée.",currentUrl:"URL de l'admin",zip:"Télécharger le ZIP de l'admin",devNote:"Le déploiement copie CETTE version compilée de l'admin (admin-files.json) — lancez-le depuis un admin compilé (npm run build / preview), pas depuis npm run dev."},security:{roleTitle:"Votre accès",signedInAs:"Connecté en tant que {{email}}",enforcement:{local:"Un seul utilisateur : ce navigateur contient les données, aucun rôle à appliquer.",journal:"Stockage partagé : quiconque possède les clés du stockage et la phrase secrète a un accès complet. Les rôles des utilisateurs sont seulement indicatifs.","git-json":"Appliqué par le dépôt : la permission de votre jeton plafonne votre rôle (admin / maintain → admin, write → membre, read → lecteur).",firebase:"Appliqué par les règles de sécurité Firestore à chaque requête."},secretsTitle:"Secrets dans ce navigateur",secretsHint:"Ce que ce navigateur conserve dans son stockage local pour ce CRM :",secrets:{connector:"Clés d'accès / jeton du stockage",passphrase:"Phrase secrète de chiffrement",gitToken:"Votre jeton d'accès git",firebaseSession:"Session Firebase (gérée par Firebase Auth)",hosting:"Clés / jeton de l'hébergement de l'admin"},neverShared:"Les secrets ne sont jamais écrits dans config.js, dans les données du CRM ni dans git. Chaque navigateur saisit les siens.",forget:"Oublier les secrets de ce navigateur",forgetConfirmTitle:"Oublier les secrets de ce navigateur ?",forgetConfirmBody:"Les clés, jetons et la phrase secrète sont supprimés de ce navigateur. Vous en aurez de nouveau besoin pour ouvrir le CRM ici.",lock:"Verrouiller"}},xse={common:ise,wizard:ase,terms:ose,data:lse,location:cse,passphrase:dse,hosting:use,workspace:fse,install:pse,errors:mse,fields:hse,roles:gse,access:yse,settings:bse},vse="admin",Y0="admin-files.json";function $j(e){return e.trim().replace(/^\/+|\/+$/g,"")}function B4(e,t){const n=typeof e.siteUrl=="string"?e.siteUrl.trim().replace(/\/+$/,""):"";if(!n)return null;const r=$j(t);return r?`${n}/${r}/`:`${n}/`}async function wse(){try{const e=await fetch(new URL(Y0,document.baseURI).href,{cache:"no-store"});if(!e.ok)return null;const t=await e.json();return Array.isArray(t.files)?t:null}catch{return null}}async function Dj(e,t){const n=new URL(e,document.baseURI);n.searchParams.set("v",t);const r=await fetch(n.href,{cache:"no-store"});if(!r.ok)throw new Error(`Could not read admin file ${e} (${r.status})`);return new Uint8Array(await r.arrayBuffer())}function kse(e,t){const n=new Set([...t,"config.js",Y0]);return[...e.matchAll(/(?:src|href)="\.\/([^"?#]+)"/g)].map(s=>s[1]).filter(s=>!n.has(s))}async function H4(e){const t=await wse();if(!t)throw new Error("admin-files.json not found — deploy from a built admin (npm run build / preview), not npm run dev.");const n=await Dj("index.html",e),r=kse(new TextDecoder().decode(n),t.files);if(r.length)throw new Error(`This admin's files don't match its build (${r.join(", ")}). Reload this page (Cmd/Ctrl + Shift + R) and try again.`);return{manifest:t,indexBytes:n}}async function q4(e,t,n,r){const s=String(Date.now()),{manifest:a,indexBytes:o}=await H4(s),l=$j(t),d=f=>l?`${l}/${f}`:f;return Hk(async()=>e),await wj(async()=>{let f=0;const p=[...a.files.filter(m=>m!=="index.html"),"index.html"];for(const m of p){const h=m==="index.html"?o:await Dj(m,s);await Gu({path:d(m),content:Ns(h),encoding:"base64"}),r==null||r(++f,p.length)}await Gu({path:d(Y0),content:JSON.stringify(a,null,2)+`
1172
1172
  `}),await Gu({path:d("config.js"),content:Jf(n)})}),{files:a.files.length,version:a.version,url:B4(e.settings,t)}}async function jse(e,t,n){const r=$j(t);Hk(async()=>e),await wj(()=>Gu({path:r?`${r}/config.js`:"config.js",content:Jf(n)}))}async function V4(e,t){const n=String(Date.now()),{manifest:r,indexBytes:s}=await H4(n),a=new md;let o=0;for(const l of r.files)a.file(l,l==="index.html"?s:await Dj(l,n)),t==null||t(++o,r.files.length);return a.file(Y0,JSON.stringify(r,null,2)+`
1173
1173
  `),a.file("config.js",Jf(e)),a.generateAsync({type:"blob",compression:"DEFLATE"})}function Mj(e,t){const n=URL.createObjectURL(e),r=document.createElement("a");r.href=n,r.download=t,r.click(),setTimeout(()=>URL.revokeObjectURL(n),1e4)}function rl(e,t,n="text/plain"){Mj(new Blob([e],{type:n}),t)}function W4(e){rl(Jf(e),"config.js","text/javascript")}const ku=".agentcrm-probe.txt",$x={"git-pages":e=>[...e.provider==="gitlab"?["project"]:["owner","repo"],"branch","siteUrl"],s3:()=>["bucket","accessKeyId","secretAccessKey","siteUrl"]};function Sse(e,t,n=[]){var s;return(((s=$x[e])==null?void 0:s.call($x,t))??[]).filter(a=>!n.includes(a)).filter(a=>typeof t[a]!="string"||!t[a].trim())}async function K4(e,t,n={}){const r=Sse(e,t,n.ignore);if(r.length)return{ok:!1,detail:`missing: ${r.join(", ")}`};try{if(e==="git-pages"){const l=t,d=iR(l),f=Uk(l.provider==="github"?{provider:"github",owner:l.owner??"",repo:l.repo??"",branch:l.branch,token:d,apiBaseUrl:l.apiBaseUrl}:{provider:"gitlab",project:l.project??"",branch:l.branch,token:d,apiBaseUrl:l.apiBaseUrl}),p=await f.permissions();return p.canWrite?{ok:!0,detail:`${p.login} → ${f.label}`}:{ok:!1,detail:`${p.login}: read-only access`}}const s=ko(e,t);if(e==="browser-mirror")return{ok:!0,detail:"browser"};await s.put({path:ku,content:`AgentCRM connection test ${new Date().toISOString()}
1174
- `});const a=await s.get(ku).catch(()=>null),o=s.listPrefix?await s.listPrefix(".agentcrm-").catch(()=>null):[ku];return await s.delete(ku),a===null?{ok:!1,detail:"write succeeded but read-back failed"}:!o||!o.includes(ku)?{ok:!1,detail:"write succeeded but listing failed (ListBucket permission / CORS)"}:{ok:!0,detail:await s.publicUrl("")}}catch(s){const a=s instanceof Si?` (${s.status})`:"";return{ok:!1,detail:`${s.message}${a}`}}}const rw=[{id:"aws",settings:{endpoint:"",region:"eu-west-3",forcePathStyle:!1},endpointPlaceholder:"(derived from the region)",regionPlaceholder:"eu-west-3",consoleUrl:"https://console.aws.amazon.com/s3/"},{id:"r2",settings:{endpoint:"",region:"auto",forcePathStyle:!0},endpointPlaceholder:"https://<ACCOUNT_ID>.r2.cloudflarestorage.com",regionPlaceholder:"auto",consoleUrl:"https://dash.cloudflare.com/?to=/:account/r2"},{id:"ovh",settings:{endpoint:"https://s3.gra.io.cloud.ovh.net",region:"gra",forcePathStyle:!0},endpointPlaceholder:"https://s3.<region>.io.cloud.ovh.net",regionPlaceholder:"gra",consoleUrl:"https://www.ovh.com/manager/#/public-cloud"},{id:"scaleway",settings:{endpoint:"https://s3.fr-par.scw.cloud",region:"fr-par",forcePathStyle:!0},endpointPlaceholder:"https://s3.<region>.scw.cloud",regionPlaceholder:"fr-par",consoleUrl:"https://console.scaleway.com/object-storage/buckets"},{id:"minio",settings:{endpoint:"http://localhost:9000",region:"us-east-1",forcePathStyle:!0},endpointPlaceholder:"http://localhost:9000",regionPlaceholder:"us-east-1"},{id:"other",settings:{endpoint:"",region:"us-east-1",forcePathStyle:!0},endpointPlaceholder:"https://s3.example.com",regionPlaceholder:"us-east-1"}];function sw(e){return rw.find(t=>t.id===e)??rw[0]}const iw=[{id:"s3",connectorId:"s3",preset:{...sw("r2").settings,s3Preset:"r2"}},{id:"github",connectorId:"git-pages",preset:{provider:"github",branch:"main"}},{id:"gitlab",connectorId:"git-pages",preset:{provider:"gitlab",branch:"main"}},{id:"local-folder",connectorId:"local-folder",preset:{handleKey:"data-folder"}}];function ed(e){return iw.find(t=>t.id===e)??iw[0]}const Ff={s3:[{key:"endpoint",type:"text",help:!0,required:!0,show:e=>e.s3Preset!=="aws"},{key:"region",type:"text",required:!0},{key:"bucket",type:"text",required:!0,help:!0},{key:"accessKeyId",type:"text",required:!0},{key:"secretAccessKey",type:"password",required:!0},{key:"forcePathStyle",type:"checkbox",help:!0}],github:[{key:"owner",type:"text",placeholder:"my-company",required:!0},{key:"repo",type:"text",placeholder:"crm-data",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",required:!0,help:!0},{key:"apiBaseUrl",type:"text",placeholder:"https://api.github.com"}],gitlab:[{key:"project",type:"text",placeholder:"group/crm-data",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",required:!0,help:!0},{key:"apiBaseUrl",type:"text",placeholder:"https://gitlab.com/api/v4"}],"local-folder":[]},Tc=[{id:"none",connectorId:null,preset:{}},{id:"github-pages",connectorId:"git-pages",preset:{host:"github-pages",provider:"github",branch:"main"}},{id:"cloudflare-pages",connectorId:"git-pages",preset:{host:"cloudflare-pages",provider:"github",branch:"main"}},{id:"gitlab-pages",connectorId:"git-pages",preset:{host:"gitlab-pages",provider:"gitlab",branch:"main",dir:"public"}},{id:"s3",connectorId:"s3",preset:{region:"auto",forcePathStyle:!0}},{id:"local-folder",connectorId:"local-folder",preset:{handleKey:"publish-target"}},{id:"zip",connectorId:"browser-mirror",preset:{}}];function td(e){return Tc.find(t=>t.id===e)??Tc[0]}function G4(e,t){return e?e==="git-pages"?td(String(t.host??"github-pages")):Tc.find(n=>n.connectorId===e)??Tc[0]:Tc[0]}const J4={"github-pages":[{key:"owner",type:"text",placeholder:"my-company",required:!0},{key:"repo",type:"text",placeholder:"crm-admin",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",help:!0},{key:"siteUrl",type:"text",placeholder:"https://my-company.github.io/crm-admin",required:!0,help:!0}],"cloudflare-pages":[{key:"provider",type:"select",options:["github","gitlab"]},{key:"owner",type:"text",placeholder:"my-company",show:e=>e.provider!=="gitlab",required:!0},{key:"repo",type:"text",placeholder:"crm-admin",show:e=>e.provider!=="gitlab",required:!0},{key:"project",type:"text",placeholder:"group/crm-admin",show:e=>e.provider==="gitlab",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",help:!0},{key:"siteUrl",type:"text",placeholder:"https://crm-admin.pages.dev",required:!0,help:!0}],"gitlab-pages":[{key:"project",type:"text",placeholder:"group/crm-admin",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",help:!0},{key:"siteUrl",type:"text",placeholder:"https://group.gitlab.io/crm-admin",required:!0,help:!0}],s3:[{key:"endpoint",type:"text",placeholder:"https://<ACCOUNT_ID>.r2.cloudflarestorage.com",help:!0},{key:"region",type:"text",placeholder:"auto",required:!0},{key:"bucket",type:"text",required:!0},{key:"accessKeyId",type:"text",required:!0},{key:"secretAccessKey",type:"password",required:!0},{key:"siteUrl",type:"text",placeholder:"https://crm.example.com",required:!0,help:!0},{key:"forcePathStyle",type:"checkbox"},{key:"publicRead",type:"checkbox",help:!0}],"local-folder":[{key:"siteUrl",type:"text",placeholder:"http://localhost:8080",help:!0}],zip:[]};function Oj(e,t){return e.filter(n=>n.required&&(!n.show||n.show(t))).filter(n=>typeof t[n.key]!="string"||!t[n.key].trim()).map(n=>n.key)}function Pj(e,t,n="local folder"){return e==="s3"?[t.endpoint?String(t.endpoint).replace(/^https?:\/\//,""):`s3.${t.region}`,t.bucket].filter(Boolean).join(" · "):e==="git-pages"?t.provider==="gitlab"?`gitlab · ${t.project}`:`github · ${t.owner}/${t.repo}`:e==="local-folder"?n:e==="browser-mirror"?"ZIP":e}class _n extends Error{constructor(t,n){super(n??t),this.kind=t,this.detail=n,this.name="SetupError"}}function Cse(e,t){const n=ed(e.locationId),{publicSettings:r,secrets:s}=Jg({...n.preset,...e.settings}),a=e.root.trim().replace(/^\/+|\/+$/g,"");return{runtime:{backend:"journal",...t?{name:t}:{},journal:{connectorId:n.connectorId,settings:r,root:a,encrypted:e.encrypted}},secrets:s}}function Y4(e,t){return{backend:"git-json",...t?{name:t}:{},git:{provider:e.provider,...e.provider==="github"?{owner:e.owner.trim(),repo:e.repo.trim()}:{},...e.provider==="gitlab"?{project:e.project.trim()}:{},branch:e.branch.trim()||"main",...e.apiBaseUrl.trim()?{apiBaseUrl:e.apiBaseUrl.trim()}:{},dir:e.dir.trim().replace(/^\/+|\/+$/g,"")}}}function Nse(e){return{apiKey:e.apiKey.trim(),authDomain:e.authDomain.trim(),projectId:e.projectId.trim(),...e.storageBucket.trim()?{storageBucket:e.storageBucket.trim()}:{},...e.messagingSenderId.trim()?{messagingSenderId:e.messagingSenderId.trim()}:{},appId:e.appId.trim()}}function Z4(e,t){return{backend:"firebase",...t?{name:t}:{},firebase:Nse(e),...e.signInMethods.length?{signInMethods:e.signInMethods}:{}}}function Ase(e){const t={};for(const n of["apiKey","authDomain","projectId","storageBucket","messagingSenderId","appId","measurementId"]){const r=new RegExp(`["']?${n}["']?\\s*:\\s*["']([^"']+)["']`).exec(e);r&&(t[n]=r[1])}return t}const _se=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;function Ese(e){return[e.apiKey,e.authDomain,e.projectId,e.appId,e.adminPassword].every(t=>t.trim())&&_se.test(e.adminEmail.trim())}async function Tse(e){const t=ed(e.locationId),n={...t.preset,...e.settings};if(Oj(Ff[t.id],n).length)throw new _n("missingFields");let r;if(t.connectorId==="git-pages"){const d=String(n.token??""),f=Uk(n.provider==="gitlab"?{provider:"gitlab",project:String(n.project??""),branch:String(n.branch??"main"),token:d,apiBaseUrl:n.apiBaseUrl||void 0}:{provider:"github",owner:String(n.owner??""),repo:String(n.repo??""),branch:String(n.branch??"main"),token:d,apiBaseUrl:n.apiBaseUrl||void 0});try{const p=await f.permissions();if(!p.canWrite)throw new _n("readOnly",p.login);r=p.visibility==="public"}catch(p){throw p instanceof _n?p:new _n("connection",p.message)}}const s=await K4(t.connectorId,n,{ignore:["siteUrl"]});if(!s.ok)throw new _n(t.connectorId==="local-folder"?"folderRequired":"connection",s.detail);const a=ko(t.connectorId,n),o=e.root.trim().replace(/^\/+|\/+$/g,""),l=await Xk(a,o,e.passphrase||null);return{detail:s.detail,existing:{exists:l.exists,encrypted:l.encrypted},publicRepo:r}}async function Ise(e){const t=ed(e.locationId),n=ko(t.connectorId,{...t.preset,...e.settings});return(await Xk(n,e.root.trim().replace(/^\/+|\/+$/g,""),e.passphrase||null)).ok}async function Rse(e){const{openGitJsonTransport:t,inspectGitJsonFolder:n,roleFromPermissions:r}=await Sr(async()=>{const{openGitJsonTransport:o,inspectGitJsonFolder:l,roleFromPermissions:d}=await import("./gitJson-CAUSxl8d.js");return{openGitJsonTransport:o,inspectGitJsonFolder:l,roleFromPermissions:d}},[],import.meta.url),s=Y4(e);if(e.provider!=="local"&&(!e.token.trim()||(e.provider==="github"?!e.owner.trim()||!e.repo.trim():!e.project.trim())))throw new _n("missingFields");const a=await t(s.git,e.token.trim());if(!a)throw new _n(e.provider==="local"?"folderRequired":"missingFields");try{const o=await a.permissions(),l=e.provider==="local"?"admin":r(o),d=await n(a,s.git.dir);return{login:o.login,role:l,publicRepo:o.visibility==="public",existing:{exists:d.exists,name:d.name,documents:d.documents}}}catch(o){throw new _n("connection",o.message)}}function d_(e){const t=e;return[t.code,t.message].filter(Boolean).join(": ")}async function $se(e){var l,d;if(!Ese(e))throw new _n("missingFields");const{firebaseApiFor:t,createFirebaseStoreWith:n}=await Sr(async()=>{const{firebaseApiFor:f,createFirebaseStoreWith:p}=await import("./firebase-C1x_l9P9.js");return{firebaseApiFor:f,createFirebaseStoreWith:p}},[],import.meta.url),r=Z4(e),s=await t(r);let a;try{a=await s.auth.signInWithPassword(e.adminEmail.trim(),e.adminPassword)}catch(f){throw new _n("firebaseAuth",d_(f))}if((a.email??"").toLowerCase()!==e.adminEmail.trim().toLowerCase())throw new _n("firebaseWrongEmail");if(!a.emailVerified){const f=await s.auth.reload().catch(()=>a);if(!(f!=null&&f.emailVerified))throw await s.auth.sendVerificationEmail().catch(()=>{}),new _n("firebaseUnverified",a.email??"")}const o=n({api:s});try{const f=await o.identity();if(!f)throw new _n("firebaseRules",(l=o.accessError())==null?void 0:l.message);let p=0;try{p=(await s.listCollection("objects")).length}catch(m){throw new _n("firebaseRules",d_(m))}if(f.role!=="admin"&&p===0)throw new _n("firebaseNotAdmin",f.role);return{identity:f,existing:{exists:p>0,documents:p}}}finally{(d=o.close)==null||d.call(o)}}function Dse(e){const t=e.workspace.name.trim()||void 0;switch(e.model){case"journal":return Cse(e.journal,t);case"git-json":return{runtime:Y4(e.git,t),secrets:{}};case"firebase":return{runtime:Z4(e.firebase,t),secrets:{}};default:return{runtime:{backend:"local",...t?{name:t}:{}},secrets:{}}}}async function Mse(e,t,n){if(t.backend==="journal"&&(Xg(t,Object.keys(n).length?n:null),cd(t,t.journal.encrypted?e.journal.passphrase:null)),t.backend==="git-json"){t.git.provider!=="local"&&Kw(t.git,e.git.token);const{setGitUserEmail:r}=await Sr(async()=>{const{setGitUserEmail:s}=await import("./gitJson-CAUSxl8d.js");return{setGitUserEmail:s}},[],import.meta.url);r(t,e.workspace.adminEmail)}}function Z0(e){const t=td(e.optionId);return t.connectorId?{connectorId:t.connectorId,settings:{...t.preset,...e.settings}}:null}function Q4(e){if(e.optionId==="none"||e.optionId==="zip")return[];const t=td(e.optionId);return Oj(J4[e.optionId],{...t.preset,...e.settings})}async function Ose(e){const t=Z0(e);if(!t||e.optionId==="zip")return"";if(Q4(e).length)throw new _n("missingFields");const n=await K4(t.connectorId,t.settings,{ignore:t.connectorId==="local-folder"?["siteUrl"]:[]});if(!n.ok)throw new _n("connection",n.detail);return n.detail}async function aw(e,t,n,r=null){const s=Z0(n);if(!s||n.optionId==="zip")return;const{publicSettings:a,secrets:o}=Jg(s.settings);Vw(t,Object.keys(o).length?o:null),await df(la(e,r),"hosting",{connectorId:s.connectorId,optionId:n.optionId,settings:a,folder:n.folder.trim().replace(/^\/+|\/+$/g,"")})}function Pse(e,t,n){return e.backend==="journal"?{secrets:n,passphrase:e.journal.encrypted?t.journal.passphrase:null}:e.backend==="git-json"?{secrets:{token:t.git.token,email:t.workspace.adminEmail}}:{}}async function X4(e){var s;const{runtime:t,secrets:n}=Dse(e);await Mse(e,t,n);const r=await NR(t,Pse(t,e,n));try{const a=await r.identity();if(!a)throw new _n("connection","no access");return await r.ready(),{runtime:t,store:r,identity:a}}catch(a){throw(s=r.close)==null||s.call(r),a}}async function Lse(e,t){var o;t.step("connect");const{runtime:n,store:r,identity:s}=await X4(e);let a=!1;try{t.done("connect");const l=r.list("objects").length===0;if(!e.join||l){t.step("seed");const m=e.workspace,h=n.backend==="firebase"||n.backend==="git-json"?s.uid:void 0;await r1(la(r,null),{name:m.name.trim()||void 0,currency:m.currency.trim().toUpperCase()||void 0,locale:m.locale,admin:{...h?{id:h}:{},name:m.adminName.trim()||s.displayName||"Admin",email:m.adminEmail.trim()||s.email},demo:m.demo}),a=!0,t.done("seed")}let d=null,f=!1;const p=Z0(e.hosting);return p&&e.hosting.optionId!=="zip"?(t.step("hostingConfig"),await aw(r,n,e.hosting),t.done("hostingConfig"),t.step("deploy"),d=(await q4(p,e.hosting.folder||vse,n,(h,b)=>t.step("deploy",`${h}/${b}`))).url,t.done("deploy")):e.hosting.optionId==="zip"&&(t.step("zip"),Mj(await V4(n,(m,h)=>t.step("zip",`${m}/${h}`)),"agentcrm-admin.zip"),f=!0,t.done("zip")),t.step("config"),ld(n),t.done("config"),{runtime:n,adminUrl:d,zipDownloaded:f,seeded:a}}finally{(o=r.close)==null||o.call(r)}}const Fse=["password","passphrase","agentcrm","123456","azerty","qwerty","letmein","admin","welcome","secret"];function e$(e){const t=e.trim();if(!t)return{score:0,bits:0};let n=0;/[a-z]/.test(t)&&(n+=26),/[A-Z]/.test(t)&&(n+=26),/[0-9]/.test(t)&&(n+=10),/[^a-zA-Z0-9]/.test(t)&&(n+=33);const r=new Set(t.toLowerCase()).size,s=Math.min(t.length,r*2.5);let a=Math.log2(Math.max(n,2))*s;const o=t.split(/[\s\-_.]+/).filter(d=>d.length>=3);return o.length>=4&&(a=Math.max(a,o.length*12)),Fse.some(d=>t.toLowerCase().includes(d))&&(a-=20),a=Math.max(0,Math.round(a)),{score:a<28?0:a<40?1:a<60?2:a<80?3:4,bits:a}}const zse=2,Use=10;function t$(e){return e.trim().length>=Use&&e$(e).score>=zse}function Mp({choices:e,value:t,onChange:n,columns:r=2}){return i.jsx("div",{className:ce("grid gap-2",r===2&&"sm:grid-cols-2",r===3&&"sm:grid-cols-3"),role:"radiogroup",children:e.map(s=>{const a=s.id===t;return i.jsxs("button",{type:"button",role:"radio","aria-checked":a,disabled:s.disabled,onClick:()=>n(s.id),className:ce("group relative flex items-start gap-3 rounded-lg border p-3 text-left transition-all disabled:cursor-not-allowed disabled:opacity-50",a?"border-accent-500 bg-accent-50/60 ring-1 ring-accent-500 dark:bg-accent-500/10":"border-surface-200 bg-white hover:border-surface-300 hover:shadow-sm dark:border-surface-800 dark:bg-surface-900 dark:hover:border-surface-700"),children:[i.jsx("span",{className:ce("mt-0.5 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md [&>svg]:h-4 [&>svg]:w-4",a?"bg-accent-600 text-white":"bg-surface-100 text-surface-600 dark:bg-surface-800 dark:text-surface-300"),children:s.icon}),i.jsxs("span",{className:"min-w-0 flex-1",children:[i.jsxs("span",{className:"flex flex-wrap items-center gap-1.5 text-sm font-medium text-surface-900 dark:text-white",children:[s.title,s.badge]}),s.description&&i.jsx("span",{className:"mt-0.5 block text-xs leading-relaxed text-surface-500",children:s.description})]}),i.jsx("span",{className:ce("absolute right-2.5 top-2.5 text-accent-600 [&>svg]:h-4 [&>svg]:w-4",!a&&"invisible"),children:i.jsx(Er,{})})]},s.id)})})}function n$(){const{t:e}=oe("setup");return i.jsx(tt,{color:"green",className:"text-[10px]",children:e("common.recommended")})}function Bse({steps:e,current:t}){const n=e.findIndex(r=>r.id===t);return i.jsx("ol",{className:"flex items-center gap-1 overflow-x-auto pb-1 text-xs","aria-label":"progress",children:e.map((r,s)=>{const a=s<n,o=s===n;return i.jsxs("li",{className:"flex shrink-0 items-center gap-1",children:[i.jsxs("span",{className:ce("inline-flex h-5 w-5 items-center justify-center rounded-full text-[10px] font-semibold [&_svg]:h-3 [&_svg]:w-3",a&&"bg-accent-600 text-white",o&&"bg-surface-900 text-white dark:bg-white dark:text-surface-900",!a&&!o&&"bg-surface-200 text-surface-500 dark:bg-surface-800"),children:[i.jsx("span",{className:ce(!a&&"hidden"),children:i.jsx(Er,{})}),i.jsx("span",{className:ce(a&&"hidden"),children:s+1})]}),i.jsx("span",{className:ce("font-medium",o?"text-surface-900 dark:text-white":"text-surface-500"),children:r.label}),s<e.length-1&&i.jsx("span",{className:"mx-1 h-px w-3 bg-surface-300 dark:bg-surface-700 sm:w-5"})]},r.id)})})}function Mt({tone:e="info",title:t,children:n,className:r}){const s={info:"border-sky-200 bg-sky-50 text-sky-900 dark:border-sky-500/30 dark:bg-sky-500/10 dark:text-sky-100",warning:"border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-100",danger:"border-red-200 bg-red-50 text-red-900 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-100",success:"border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-100"}[e],a=e==="success"?to:e==="info"?ak:yo;return i.jsxs("div",{className:ce("flex gap-2.5 rounded-lg border px-3 py-2.5 text-xs leading-relaxed",s,r),children:[i.jsx(a,{className:"mt-0.5 h-4 w-4 shrink-0"}),i.jsxs("div",{className:"min-w-0 space-y-1",children:[t&&i.jsx("p",{className:"font-semibold",children:t}),n&&i.jsx("div",{className:"break-words",children:n})]})]})}function Q0({state:e}){return e.status==="idle"||e.status==="running"?null:i.jsxs("p",{className:ce("flex items-start gap-1.5 text-xs",e.status==="ok"?"text-emerald-700 dark:text-emerald-400":"text-red-600 dark:text-red-400"),children:[i.jsx("span",{className:"mt-0.5 shrink-0 [&>svg]:h-3.5 [&>svg]:w-3.5",children:e.status==="ok"?i.jsx(to,{}):i.jsx(C0,{})}),i.jsx("span",{className:"min-w-0 break-words",children:e.detail})]})}function ao({id:e,value:t,onChange:n,placeholder:r,invalid:s}){const{t:a}=oe("setup"),[o,l]=S.useState(!1);return i.jsxs("div",{className:"relative",children:[i.jsx(Oe,{id:e,type:o?"text":"password",autoComplete:"off",spellCheck:!1,value:t,placeholder:r,invalid:s,onChange:d=>n(d.target.value),className:"pr-9"}),i.jsxs("button",{type:"button",onClick:()=>l(d=>!d),"aria-label":a(o?"common.hide":"common.show"),className:"absolute right-1.5 top-1/2 inline-flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded text-surface-400 hover:text-surface-700 [&>svg]:h-3.5 [&>svg]:w-3.5",children:[i.jsx("span",{className:ce("inline-flex",o&&"hidden"),children:i.jsx(A0,{})}),i.jsx("span",{className:ce("inline-flex",!o&&"hidden"),children:i.jsx(dp,{})})]})]})}function Lj({fields:e,value:t,onChange:n,idPrefix:r,placeholders:s={},missing:a=[]}){const{t:o}=oe("setup"),l=(f,p)=>n({...t,[f]:p}),d=e.filter(f=>!f.show||f.show(t));return i.jsx("div",{className:"grid gap-3 sm:grid-cols-2",children:d.map(f=>{const p=`${r}-${f.key}`,m=i.jsxs(i.Fragment,{children:[o(`fields.${f.key}`),f.required&&i.jsx("span",{className:"ml-0.5 text-red-500",children:"*"})]}),h=f.help?o(`fields.${f.key}Help`):void 0,b=typeof t[f.key]=="string"?t[f.key]:"";if(f.type==="checkbox")return i.jsxs("div",{className:"sm:col-span-2",children:[i.jsx(Ot,{id:p,label:o(`fields.${f.key}`),checked:t[f.key]===!0,onChange:y=>l(f.key,y.target.checked)}),h&&i.jsx("p",{className:"ml-6 mt-0.5 text-xs text-surface-500",children:h})]},f.key);const x=a.includes(f.key);return i.jsx(Te,{label:m,htmlFor:p,help:h,className:ce((f.key==="token"||f.key==="secretAccessKey"||f.key==="endpoint"||f.key==="siteUrl")&&"sm:col-span-2"),children:f.type==="password"?i.jsx(ao,{id:p,value:b,onChange:y=>l(f.key,y),invalid:x,placeholder:s[f.key]??f.placeholder}):f.type==="select"?i.jsx(Ve,{id:p,value:b,onChange:y=>l(f.key,y.target.value),options:(f.options??[]).map(y=>({value:y,label:o(`fields.options.${y}`,{defaultValue:y})}))}):i.jsx(Oe,{id:p,autoComplete:"off",spellCheck:!1,value:b,invalid:x,placeholder:s[f.key]??f.placeholder,onChange:y=>l(f.key,y.target.value)})},f.key)})})}function Fj({handleKey:e,onPicked:t,picked:n}){const{t:r}=oe("setup"),[s,a]=S.useState(!1);if(!oB())return i.jsx(Mt,{tone:"warning",children:r("location.folderUnsupported")});const o=async()=>{a(!0);try{const l=await Fk();await zk(e,l),t(l.name)}catch(l){l.name!=="AbortError"&&ge.error(l.message)}finally{a(!1)}};return i.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[i.jsx(ue,{icon:i.jsx(no,{}),onClick:()=>void o(),loading:s,children:r(n?"location.changeFolder":"location.pickFolder")}),n&&i.jsxs("span",{className:"inline-flex items-center gap-1 text-xs text-emerald-700 dark:text-emerald-400",children:[i.jsx(to,{className:"h-3.5 w-3.5"})," ",n]})]})}const Hse=["bg-red-500","bg-orange-500","bg-amber-500","bg-lime-500","bg-emerald-500"];function qse({value:e}){const{t}=oe("setup"),{score:n}=e$(e);return i.jsxs("div",{className:"space-y-1",children:[i.jsx("div",{className:"flex gap-1","aria-hidden":"true",children:[0,1,2,3].map(r=>i.jsx("span",{className:ce("h-1 flex-1 rounded-full",e&&r<Math.max(n,1)?Hse[n]:"bg-surface-200 dark:bg-surface-800")},r))}),i.jsx("p",{className:"text-[11px] text-surface-500",children:t(e?`passphrase.strength.${n}`:"passphrase.strengthHint")})]})}function r$({passphrase:e,confirm:t,onChange:n,idPrefix:r,withConfirm:s=!0}){const{t:a}=oe("setup"),o=s&&!!t&&t!==e;return i.jsxs("div",{className:"space-y-3",children:[i.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[i.jsx(Te,{label:a("passphrase.label"),htmlFor:`${r}-pass`,children:i.jsx(ao,{id:`${r}-pass`,value:e,onChange:l=>n({passphrase:l,confirm:t})})}),s&&i.jsx(Te,{label:a("passphrase.confirm"),htmlFor:`${r}-confirm`,error:o?a("passphrase.mismatch"):void 0,children:i.jsx(ao,{id:`${r}-confirm`,value:t,onChange:l=>n({passphrase:e,confirm:l}),invalid:o})})]}),i.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[i.jsx("div",{className:"min-w-[12rem] flex-1",children:i.jsx(qse,{value:e})}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(Ni,{}),onClick:()=>{var d;const l=zB();n({passphrase:l,confirm:l}),(d=navigator.clipboard)==null||d.writeText(l).then(()=>ge.success(a("passphrase.generatedCopied")),()=>{})},children:a("passphrase.generate")})]})]})}function Vse({enabled:e,onChange:t,disabled:n}){const{t:r}=oe("setup");return i.jsxs("div",{className:"flex items-start justify-between gap-4 rounded-lg border border-surface-200 p-3 dark:border-surface-800",children:[i.jsxs("div",{children:[i.jsx("p",{className:"text-sm font-medium",children:r("passphrase.encryptTitle")}),i.jsx("p",{className:"text-xs text-surface-500",children:r("passphrase.encryptHint")})]}),i.jsx(si,{checked:e,onChange:t,disabled:n})]})}function s$({text:e,label:t,maxHeight:n="16rem"}){const{t:r}=oe("setup");return i.jsxs("div",{className:"relative",children:[i.jsx("pre",{className:"overflow-auto rounded-lg border border-surface-200 bg-surface-50 p-3 pr-10 font-mono text-[11px] leading-relaxed text-surface-800 dark:border-surface-800 dark:bg-surface-950 dark:text-surface-200",style:{maxHeight:n},children:e}),i.jsx(ue,{size:"xs",variant:"outline",icon:i.jsx(cp,{}),className:"absolute right-2 top-2","aria-label":t??r("common.copy"),onClick:()=>{var s;return void((s=navigator.clipboard)==null?void 0:s.writeText(e).then(()=>ge.success(r("common.copied")),()=>ge.error(r("common.copyFailed"))))},children:r("common.copy")})]})}function X0({onClick:e,running:t,label:n}){const{t:r}=oe("setup");return i.jsx(ue,{icon:i.jsx(Vc,{}),loading:t,onClick:e,children:n??r("common.testConnection")})}function ni({children:e,hint:t}){return i.jsxs("div",{children:[i.jsx("h3",{className:"text-sm font-semibold text-surface-900 dark:text-white",children:e}),t&&i.jsx("p",{className:"mt-0.5 text-xs text-surface-500",children:t})]})}const ju={maxFields:60,maxMetaKeys:10,formIdPattern:"^[A-Za-z0-9_-]{1,64}$",clockSkewMs:864e5},Wse=/^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/,Kse=/^[a-z0-9-]+(\.[a-z0-9-]+)+$/;function i$(e){const t=e.adminEmail.trim().toLowerCase();if(!Wse.test(t))throw new Error(`"${e.adminEmail}" is not a valid admin email for the rules.`);const n=(e.allowedDomains??[]).map(s=>s.trim().toLowerCase().replace(/^@/,"")).filter(Boolean);for(const s of n)if(!Kse.test(s))throw new Error(`"${s}" is not a valid domain.`);const r=e.signup??(n.length?"domain":"invite");if(r==="domain"&&!n.length)throw new Error('Sign-up "domain" needs at least one allowed domain.');return{adminEmail:t,signup:r,allowedDomains:n,requireVerifiedEmail:e.requireVerifiedEmail!==!1}}const a$=["objects","pipelines","forms","settings","config","extensions"],o$=["records","activities"];function l$(e){const t=i$(e),n=t.requireVerifiedEmail?" && request.auth.token.email_verified == true":"",r=t.signup==="open"?"true":t.signup==="domain"?`callerEmail().matches('^[^@]+@(${t.allowedDomains.map(a=>a.replace(/\./g,"[.]")).join("|")})$')`:"false",s=["rules_version = '2';","","// Generated by AgentCRM (src/ops/firebaseRules.ts) — see docs/firebase.md.",`// Sign-up: ${t.signup}${t.signup==="domain"?` (${t.allowedDomains.join(", ")})`:""}. Re-generate rather than edit by hand.`,"service cloud.firestore {"," match /databases/{database}/documents {",""," // ─── Identity & roles ─────────────────────────────────────────────"," function bootstrapAdminEmail() {",` return "${t.adminEmail}";`," }",""," function signedIn() {"," return request.auth != null;"," }",""," function hasEmail() {",` return signedIn() && request.auth.token.email != null${n};`," }",""," function callerEmail() {"," return request.auth.token.email.lower();"," }",""," function isBootstrapAdmin() {"," return hasEmail() && callerEmail() == bootstrapAdminEmail();"," }",""," function selfPath() {"," return /databases/$(database)/documents/users/$(request.auth.uid);"," }",""," // admin | member | viewer | none (no record / disabled)."," function role() {"," return isBootstrapAdmin() ? 'admin'"," : !exists(selfPath()) ? 'none'"," : get(selfPath()).data.get('disabled', false) == true ? 'none'"," : get(selfPath()).data.get('role', 'none');"," }",""," function isAdmin() {"," return signedIn() && role() == 'admin';"," }",""," function isMember() {"," return signedIn() && role() in ['admin', 'member'];"," }",""," function isActive() {"," return signedIn() && role() in ['admin', 'member', 'viewer'];"," }",""," function validRole(r) {"," return r in ['admin', 'member', 'viewer'];"," }",""," // ─── invites/{email} ──────────────────────────────────────────────"," // Mirrored by the admin from the users it adds (Settings → Users)."," function invitePath() {"," return /databases/$(database)/documents/invites/$(callerEmail());"," }",""," match /invites/{email} {"," allow read: if isAdmin() || (hasEmail() && callerEmail() == email);"," allow create, update: if isAdmin() && email == email.lower()"," && validRole(request.resource.data.role);"," allow delete: if isAdmin();"," }",""," // ─── users/{uid} ──────────────────────────────────────────────────"," function signupAllowed() {",` return ${r};`," }",""," // First sign-in: the caller creates its own record."," function selfCreate(uid) {"," let d = request.resource.data;"," return hasEmail() && request.auth.uid == uid"," && d.email == callerEmail()"," && d.get('authUid', '') == uid"," && d.get('disabled', false) == false"," && ("," (isBootstrapAdmin() && d.role == 'admin')"," || (exists(invitePath()) && d.role == get(invitePath()).data.role"," && d.get('replaces', get(invitePath()).data.get('userId', '')) == get(invitePath()).data.get('userId', ''))"," || (!exists(invitePath()) && signupAllowed() && d.role == 'member' && !('replaces' in d))"," );"," }",""," match /users/{uid} {"," allow read: if isActive() || (signedIn() && request.auth.uid == uid);"," allow create: if (isAdmin() && validRole(request.resource.data.role)) || selfCreate(uid);"," // Nobody changes their own role / email / disabled flag."," allow update: if (isAdmin() && validRole(request.resource.data.role))"," || (isActive() && request.auth.uid == uid"," && request.resource.data.diff(resource.data).affectedKeys().hasOnly(['name', 'avatarUrl', 'updatedAt']));"," allow delete: if isAdmin();"," }",""," // ─── CRM data ─────────────────────────────────────────────────────"];for(const a of o$)s.push(` match /${a}/{id} {`," allow read: if isActive();"," allow create, update, delete: if isMember();"," }","");s.push(" // Views: members manage their own private views; shared views are admin-only."," match /views/{id} {"," allow read: if isActive();"," allow create: if isAdmin()"," || (isMember() && request.resource.data.get('ownerId', '') == request.auth.uid"," && request.resource.data.get('shared', false) == false);"," allow update: if isAdmin()"," || (isMember() && resource.data.get('ownerId', '') == request.auth.uid"," && request.resource.data.get('ownerId', '') == request.auth.uid"," && request.resource.data.get('shared', false) == false);"," allow delete: if isAdmin() || (isMember() && resource.data.get('ownerId', '') == request.auth.uid);"," }",""," // Automations: admins edit; members running them may stamp lastRunAt."," match /automations/{id} {"," allow read: if isActive();"," allow create, delete: if isAdmin();"," allow update: if isAdmin()"," || (isMember() && request.resource.data.diff(resource.data).affectedKeys().hasOnly(['lastRunAt', 'updatedAt']));"," }",""," match /automationRuns/{id} {"," allow read: if isActive();"," allow create, update: if isMember();"," allow delete: if isAdmin();"," }",""," // File metadata (bytes in Firebase Storage, see storage.rules): members"," // upload / attach / soft-delete; only admins purge (compact)."," match /files/{id} {"," allow read: if isActive();"," allow create, update: if isMember();"," allow delete: if isAdmin();"," }","");for(const a of a$)s.push(` match /${a}/{id} {`," allow read: if isActive();"," allow write: if isAdmin();"," }","");return s.push(" // Pieces of large extension bundles (src/data/firebase.ts)."," match /extensionChunks/{id} {"," allow read: if isActive();"," allow write: if isAdmin();"," }",""," // ─── inbox/{id}: public lead-form submissions ──────────────────────"," function validSubmission(d) {"," return d.keys().hasAll(['formId', 'data', 'createdAt'])"," && d.keys().hasOnly(['formId', 'data', 'createdAt', 'meta'])",` && d.formId is string && d.formId.matches('${ju.formIdPattern}')`," && exists(/databases/$(database)/documents/forms/$(d.formId))",` && d.data is map && d.data.size() <= ${ju.maxFields}`,` && (!('meta' in d) || (d.meta is map && d.meta.size() <= ${ju.maxMetaKeys}))`," && d.createdAt is int",` && d.createdAt > request.time.toMillis() - ${ju.clockSkewMs}`,` && d.createdAt < request.time.toMillis() + ${ju.clockSkewMs};`," }",""," match /inbox/{id} {"," // Public: anyone (the static lead form) may create, nobody else reads."," allow create: if validSubmission(request.resource.data);"," // Ingested (then deleted) by members — the admin or the CLI."," allow read, delete: if isMember();"," // Failed submissions are only marked {status, error}."," allow update: if isMember()"," && request.resource.data.diff(resource.data).affectedKeys().hasOnly(['status', 'error']);"," }",""," // Anything else: closed."," match /{document=**} {"," allow read, write: if false;"," }"," }","}",""),s.join(`
1174
+ `});const a=await s.get(ku).catch(()=>null),o=s.listPrefix?await s.listPrefix(".agentcrm-").catch(()=>null):[ku];return await s.delete(ku),a===null?{ok:!1,detail:"write succeeded but read-back failed"}:!o||!o.includes(ku)?{ok:!1,detail:"write succeeded but listing failed (ListBucket permission / CORS)"}:{ok:!0,detail:await s.publicUrl("")}}catch(s){const a=s instanceof Si?` (${s.status})`:"";return{ok:!1,detail:`${s.message}${a}`}}}const rw=[{id:"aws",settings:{endpoint:"",region:"eu-west-3",forcePathStyle:!1},endpointPlaceholder:"(derived from the region)",regionPlaceholder:"eu-west-3",consoleUrl:"https://console.aws.amazon.com/s3/"},{id:"r2",settings:{endpoint:"",region:"auto",forcePathStyle:!0},endpointPlaceholder:"https://<ACCOUNT_ID>.r2.cloudflarestorage.com",regionPlaceholder:"auto",consoleUrl:"https://dash.cloudflare.com/?to=/:account/r2"},{id:"ovh",settings:{endpoint:"https://s3.gra.io.cloud.ovh.net",region:"gra",forcePathStyle:!0},endpointPlaceholder:"https://s3.<region>.io.cloud.ovh.net",regionPlaceholder:"gra",consoleUrl:"https://www.ovh.com/manager/#/public-cloud"},{id:"scaleway",settings:{endpoint:"https://s3.fr-par.scw.cloud",region:"fr-par",forcePathStyle:!0},endpointPlaceholder:"https://s3.<region>.scw.cloud",regionPlaceholder:"fr-par",consoleUrl:"https://console.scaleway.com/object-storage/buckets"},{id:"minio",settings:{endpoint:"http://localhost:9000",region:"us-east-1",forcePathStyle:!0},endpointPlaceholder:"http://localhost:9000",regionPlaceholder:"us-east-1"},{id:"other",settings:{endpoint:"",region:"us-east-1",forcePathStyle:!0},endpointPlaceholder:"https://s3.example.com",regionPlaceholder:"us-east-1"}];function sw(e){return rw.find(t=>t.id===e)??rw[0]}const iw=[{id:"s3",connectorId:"s3",preset:{...sw("r2").settings,s3Preset:"r2"}},{id:"github",connectorId:"git-pages",preset:{provider:"github",branch:"main"}},{id:"gitlab",connectorId:"git-pages",preset:{provider:"gitlab",branch:"main"}},{id:"local-folder",connectorId:"local-folder",preset:{handleKey:"data-folder"}}];function ed(e){return iw.find(t=>t.id===e)??iw[0]}const Ff={s3:[{key:"endpoint",type:"text",help:!0,required:!0,show:e=>e.s3Preset!=="aws"},{key:"region",type:"text",required:!0},{key:"bucket",type:"text",required:!0,help:!0},{key:"accessKeyId",type:"text",required:!0},{key:"secretAccessKey",type:"password",required:!0},{key:"forcePathStyle",type:"checkbox",help:!0}],github:[{key:"owner",type:"text",placeholder:"my-company",required:!0},{key:"repo",type:"text",placeholder:"crm-data",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",required:!0,help:!0},{key:"apiBaseUrl",type:"text",placeholder:"https://api.github.com"}],gitlab:[{key:"project",type:"text",placeholder:"group/crm-data",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",required:!0,help:!0},{key:"apiBaseUrl",type:"text",placeholder:"https://gitlab.com/api/v4"}],"local-folder":[]},Tc=[{id:"none",connectorId:null,preset:{}},{id:"github-pages",connectorId:"git-pages",preset:{host:"github-pages",provider:"github",branch:"main"}},{id:"cloudflare-pages",connectorId:"git-pages",preset:{host:"cloudflare-pages",provider:"github",branch:"main"}},{id:"gitlab-pages",connectorId:"git-pages",preset:{host:"gitlab-pages",provider:"gitlab",branch:"main",dir:"public"}},{id:"s3",connectorId:"s3",preset:{region:"auto",forcePathStyle:!0}},{id:"local-folder",connectorId:"local-folder",preset:{handleKey:"publish-target"}},{id:"zip",connectorId:"browser-mirror",preset:{}}];function td(e){return Tc.find(t=>t.id===e)??Tc[0]}function G4(e,t){return e?e==="git-pages"?td(String(t.host??"github-pages")):Tc.find(n=>n.connectorId===e)??Tc[0]:Tc[0]}const J4={"github-pages":[{key:"owner",type:"text",placeholder:"my-company",required:!0},{key:"repo",type:"text",placeholder:"crm-admin",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",help:!0},{key:"siteUrl",type:"text",placeholder:"https://my-company.github.io/crm-admin",required:!0,help:!0}],"cloudflare-pages":[{key:"provider",type:"select",options:["github","gitlab"]},{key:"owner",type:"text",placeholder:"my-company",show:e=>e.provider!=="gitlab",required:!0},{key:"repo",type:"text",placeholder:"crm-admin",show:e=>e.provider!=="gitlab",required:!0},{key:"project",type:"text",placeholder:"group/crm-admin",show:e=>e.provider==="gitlab",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",help:!0},{key:"siteUrl",type:"text",placeholder:"https://crm-admin.pages.dev",required:!0,help:!0}],"gitlab-pages":[{key:"project",type:"text",placeholder:"group/crm-admin",required:!0},{key:"branch",type:"text",placeholder:"main",required:!0},{key:"token",type:"password",help:!0},{key:"siteUrl",type:"text",placeholder:"https://group.gitlab.io/crm-admin",required:!0,help:!0}],s3:[{key:"endpoint",type:"text",placeholder:"https://<ACCOUNT_ID>.r2.cloudflarestorage.com",help:!0},{key:"region",type:"text",placeholder:"auto",required:!0},{key:"bucket",type:"text",required:!0},{key:"accessKeyId",type:"text",required:!0},{key:"secretAccessKey",type:"password",required:!0},{key:"siteUrl",type:"text",placeholder:"https://crm.example.com",required:!0,help:!0},{key:"forcePathStyle",type:"checkbox"},{key:"publicRead",type:"checkbox",help:!0}],"local-folder":[{key:"siteUrl",type:"text",placeholder:"http://localhost:8080",help:!0}],zip:[]};function Oj(e,t){return e.filter(n=>n.required&&(!n.show||n.show(t))).filter(n=>typeof t[n.key]!="string"||!t[n.key].trim()).map(n=>n.key)}function Pj(e,t,n="local folder"){return e==="s3"?[t.endpoint?String(t.endpoint).replace(/^https?:\/\//,""):`s3.${t.region}`,t.bucket].filter(Boolean).join(" · "):e==="git-pages"?t.provider==="gitlab"?`gitlab · ${t.project}`:`github · ${t.owner}/${t.repo}`:e==="local-folder"?n:e==="browser-mirror"?"ZIP":e}class _n extends Error{constructor(t,n){super(n??t),this.kind=t,this.detail=n,this.name="SetupError"}}function Cse(e,t){const n=ed(e.locationId),{publicSettings:r,secrets:s}=Jg({...n.preset,...e.settings}),a=e.root.trim().replace(/^\/+|\/+$/g,"");return{runtime:{backend:"journal",...t?{name:t}:{},journal:{connectorId:n.connectorId,settings:r,root:a,encrypted:e.encrypted}},secrets:s}}function Y4(e,t){return{backend:"git-json",...t?{name:t}:{},git:{provider:e.provider,...e.provider==="github"?{owner:e.owner.trim(),repo:e.repo.trim()}:{},...e.provider==="gitlab"?{project:e.project.trim()}:{},branch:e.branch.trim()||"main",...e.apiBaseUrl.trim()?{apiBaseUrl:e.apiBaseUrl.trim()}:{},dir:e.dir.trim().replace(/^\/+|\/+$/g,"")}}}function Nse(e){return{apiKey:e.apiKey.trim(),authDomain:e.authDomain.trim(),projectId:e.projectId.trim(),...e.storageBucket.trim()?{storageBucket:e.storageBucket.trim()}:{},...e.messagingSenderId.trim()?{messagingSenderId:e.messagingSenderId.trim()}:{},appId:e.appId.trim()}}function Z4(e,t){return{backend:"firebase",...t?{name:t}:{},firebase:Nse(e),...e.signInMethods.length?{signInMethods:e.signInMethods}:{}}}function Ase(e){const t={};for(const n of["apiKey","authDomain","projectId","storageBucket","messagingSenderId","appId","measurementId"]){const r=new RegExp(`["']?${n}["']?\\s*:\\s*["']([^"']+)["']`).exec(e);r&&(t[n]=r[1])}return t}const _se=/^[^\s@]+@[^\s@]+\.[^\s@]+$/;function Ese(e){return[e.apiKey,e.authDomain,e.projectId,e.appId,e.adminPassword].every(t=>t.trim())&&_se.test(e.adminEmail.trim())}async function Tse(e){const t=ed(e.locationId),n={...t.preset,...e.settings};if(Oj(Ff[t.id],n).length)throw new _n("missingFields");let r;if(t.connectorId==="git-pages"){const d=String(n.token??""),f=Uk(n.provider==="gitlab"?{provider:"gitlab",project:String(n.project??""),branch:String(n.branch??"main"),token:d,apiBaseUrl:n.apiBaseUrl||void 0}:{provider:"github",owner:String(n.owner??""),repo:String(n.repo??""),branch:String(n.branch??"main"),token:d,apiBaseUrl:n.apiBaseUrl||void 0});try{const p=await f.permissions();if(!p.canWrite)throw new _n("readOnly",p.login);r=p.visibility==="public"}catch(p){throw p instanceof _n?p:new _n("connection",p.message)}}const s=await K4(t.connectorId,n,{ignore:["siteUrl"]});if(!s.ok)throw new _n(t.connectorId==="local-folder"?"folderRequired":"connection",s.detail);const a=ko(t.connectorId,n),o=e.root.trim().replace(/^\/+|\/+$/g,""),l=await Xk(a,o,e.passphrase||null);return{detail:s.detail,existing:{exists:l.exists,encrypted:l.encrypted},publicRepo:r}}async function Ise(e){const t=ed(e.locationId),n=ko(t.connectorId,{...t.preset,...e.settings});return(await Xk(n,e.root.trim().replace(/^\/+|\/+$/g,""),e.passphrase||null)).ok}async function Rse(e){const{openGitJsonTransport:t,inspectGitJsonFolder:n,roleFromPermissions:r}=await Sr(async()=>{const{openGitJsonTransport:o,inspectGitJsonFolder:l,roleFromPermissions:d}=await import("./gitJson-wy2Tytfd.js");return{openGitJsonTransport:o,inspectGitJsonFolder:l,roleFromPermissions:d}},[],import.meta.url),s=Y4(e);if(e.provider!=="local"&&(!e.token.trim()||(e.provider==="github"?!e.owner.trim()||!e.repo.trim():!e.project.trim())))throw new _n("missingFields");const a=await t(s.git,e.token.trim());if(!a)throw new _n(e.provider==="local"?"folderRequired":"missingFields");try{const o=await a.permissions(),l=e.provider==="local"?"admin":r(o),d=await n(a,s.git.dir);return{login:o.login,role:l,publicRepo:o.visibility==="public",existing:{exists:d.exists,name:d.name,documents:d.documents}}}catch(o){throw new _n("connection",o.message)}}function d_(e){const t=e;return[t.code,t.message].filter(Boolean).join(": ")}async function $se(e){var l,d;if(!Ese(e))throw new _n("missingFields");const{firebaseApiFor:t,createFirebaseStoreWith:n}=await Sr(async()=>{const{firebaseApiFor:f,createFirebaseStoreWith:p}=await import("./firebase-U38f5kc9.js");return{firebaseApiFor:f,createFirebaseStoreWith:p}},[],import.meta.url),r=Z4(e),s=await t(r);let a;try{a=await s.auth.signInWithPassword(e.adminEmail.trim(),e.adminPassword)}catch(f){throw new _n("firebaseAuth",d_(f))}if((a.email??"").toLowerCase()!==e.adminEmail.trim().toLowerCase())throw new _n("firebaseWrongEmail");if(!a.emailVerified){const f=await s.auth.reload().catch(()=>a);if(!(f!=null&&f.emailVerified))throw await s.auth.sendVerificationEmail().catch(()=>{}),new _n("firebaseUnverified",a.email??"")}const o=n({api:s});try{const f=await o.identity();if(!f)throw new _n("firebaseRules",(l=o.accessError())==null?void 0:l.message);let p=0;try{p=(await s.listCollection("objects")).length}catch(m){throw new _n("firebaseRules",d_(m))}if(f.role!=="admin"&&p===0)throw new _n("firebaseNotAdmin",f.role);return{identity:f,existing:{exists:p>0,documents:p}}}finally{(d=o.close)==null||d.call(o)}}function Dse(e){const t=e.workspace.name.trim()||void 0;switch(e.model){case"journal":return Cse(e.journal,t);case"git-json":return{runtime:Y4(e.git,t),secrets:{}};case"firebase":return{runtime:Z4(e.firebase,t),secrets:{}};default:return{runtime:{backend:"local",...t?{name:t}:{}},secrets:{}}}}async function Mse(e,t,n){if(t.backend==="journal"&&(Xg(t,Object.keys(n).length?n:null),cd(t,t.journal.encrypted?e.journal.passphrase:null)),t.backend==="git-json"){t.git.provider!=="local"&&Kw(t.git,e.git.token);const{setGitUserEmail:r}=await Sr(async()=>{const{setGitUserEmail:s}=await import("./gitJson-wy2Tytfd.js");return{setGitUserEmail:s}},[],import.meta.url);r(t,e.workspace.adminEmail)}}function Z0(e){const t=td(e.optionId);return t.connectorId?{connectorId:t.connectorId,settings:{...t.preset,...e.settings}}:null}function Q4(e){if(e.optionId==="none"||e.optionId==="zip")return[];const t=td(e.optionId);return Oj(J4[e.optionId],{...t.preset,...e.settings})}async function Ose(e){const t=Z0(e);if(!t||e.optionId==="zip")return"";if(Q4(e).length)throw new _n("missingFields");const n=await K4(t.connectorId,t.settings,{ignore:t.connectorId==="local-folder"?["siteUrl"]:[]});if(!n.ok)throw new _n("connection",n.detail);return n.detail}async function aw(e,t,n,r=null){const s=Z0(n);if(!s||n.optionId==="zip")return;const{publicSettings:a,secrets:o}=Jg(s.settings);Vw(t,Object.keys(o).length?o:null),await df(la(e,r),"hosting",{connectorId:s.connectorId,optionId:n.optionId,settings:a,folder:n.folder.trim().replace(/^\/+|\/+$/g,"")})}function Pse(e,t,n){return e.backend==="journal"?{secrets:n,passphrase:e.journal.encrypted?t.journal.passphrase:null}:e.backend==="git-json"?{secrets:{token:t.git.token,email:t.workspace.adminEmail}}:{}}async function X4(e){var s;const{runtime:t,secrets:n}=Dse(e);await Mse(e,t,n);const r=await NR(t,Pse(t,e,n));try{const a=await r.identity();if(!a)throw new _n("connection","no access");return await r.ready(),{runtime:t,store:r,identity:a}}catch(a){throw(s=r.close)==null||s.call(r),a}}async function Lse(e,t){var o;t.step("connect");const{runtime:n,store:r,identity:s}=await X4(e);let a=!1;try{t.done("connect");const l=r.list("objects").length===0;if(!e.join||l){t.step("seed");const m=e.workspace,h=n.backend==="firebase"||n.backend==="git-json"?s.uid:void 0;await r1(la(r,null),{name:m.name.trim()||void 0,currency:m.currency.trim().toUpperCase()||void 0,locale:m.locale,admin:{...h?{id:h}:{},name:m.adminName.trim()||s.displayName||"Admin",email:m.adminEmail.trim()||s.email},demo:m.demo}),a=!0,t.done("seed")}let d=null,f=!1;const p=Z0(e.hosting);return p&&e.hosting.optionId!=="zip"?(t.step("hostingConfig"),await aw(r,n,e.hosting),t.done("hostingConfig"),t.step("deploy"),d=(await q4(p,e.hosting.folder||vse,n,(h,b)=>t.step("deploy",`${h}/${b}`))).url,t.done("deploy")):e.hosting.optionId==="zip"&&(t.step("zip"),Mj(await V4(n,(m,h)=>t.step("zip",`${m}/${h}`)),"agentcrm-admin.zip"),f=!0,t.done("zip")),t.step("config"),ld(n),t.done("config"),{runtime:n,adminUrl:d,zipDownloaded:f,seeded:a}}finally{(o=r.close)==null||o.call(r)}}const Fse=["password","passphrase","agentcrm","123456","azerty","qwerty","letmein","admin","welcome","secret"];function e$(e){const t=e.trim();if(!t)return{score:0,bits:0};let n=0;/[a-z]/.test(t)&&(n+=26),/[A-Z]/.test(t)&&(n+=26),/[0-9]/.test(t)&&(n+=10),/[^a-zA-Z0-9]/.test(t)&&(n+=33);const r=new Set(t.toLowerCase()).size,s=Math.min(t.length,r*2.5);let a=Math.log2(Math.max(n,2))*s;const o=t.split(/[\s\-_.]+/).filter(d=>d.length>=3);return o.length>=4&&(a=Math.max(a,o.length*12)),Fse.some(d=>t.toLowerCase().includes(d))&&(a-=20),a=Math.max(0,Math.round(a)),{score:a<28?0:a<40?1:a<60?2:a<80?3:4,bits:a}}const zse=2,Use=10;function t$(e){return e.trim().length>=Use&&e$(e).score>=zse}function Mp({choices:e,value:t,onChange:n,columns:r=2}){return i.jsx("div",{className:ce("grid gap-2",r===2&&"sm:grid-cols-2",r===3&&"sm:grid-cols-3"),role:"radiogroup",children:e.map(s=>{const a=s.id===t;return i.jsxs("button",{type:"button",role:"radio","aria-checked":a,disabled:s.disabled,onClick:()=>n(s.id),className:ce("group relative flex items-start gap-3 rounded-lg border p-3 text-left transition-all disabled:cursor-not-allowed disabled:opacity-50",a?"border-accent-500 bg-accent-50/60 ring-1 ring-accent-500 dark:bg-accent-500/10":"border-surface-200 bg-white hover:border-surface-300 hover:shadow-sm dark:border-surface-800 dark:bg-surface-900 dark:hover:border-surface-700"),children:[i.jsx("span",{className:ce("mt-0.5 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md [&>svg]:h-4 [&>svg]:w-4",a?"bg-accent-600 text-white":"bg-surface-100 text-surface-600 dark:bg-surface-800 dark:text-surface-300"),children:s.icon}),i.jsxs("span",{className:"min-w-0 flex-1",children:[i.jsxs("span",{className:"flex flex-wrap items-center gap-1.5 text-sm font-medium text-surface-900 dark:text-white",children:[s.title,s.badge]}),s.description&&i.jsx("span",{className:"mt-0.5 block text-xs leading-relaxed text-surface-500",children:s.description})]}),i.jsx("span",{className:ce("absolute right-2.5 top-2.5 text-accent-600 [&>svg]:h-4 [&>svg]:w-4",!a&&"invisible"),children:i.jsx(Er,{})})]},s.id)})})}function n$(){const{t:e}=oe("setup");return i.jsx(tt,{color:"green",className:"text-[10px]",children:e("common.recommended")})}function Bse({steps:e,current:t}){const n=e.findIndex(r=>r.id===t);return i.jsx("ol",{className:"flex items-center gap-1 overflow-x-auto pb-1 text-xs","aria-label":"progress",children:e.map((r,s)=>{const a=s<n,o=s===n;return i.jsxs("li",{className:"flex shrink-0 items-center gap-1",children:[i.jsxs("span",{className:ce("inline-flex h-5 w-5 items-center justify-center rounded-full text-[10px] font-semibold [&_svg]:h-3 [&_svg]:w-3",a&&"bg-accent-600 text-white",o&&"bg-surface-900 text-white dark:bg-white dark:text-surface-900",!a&&!o&&"bg-surface-200 text-surface-500 dark:bg-surface-800"),children:[i.jsx("span",{className:ce(!a&&"hidden"),children:i.jsx(Er,{})}),i.jsx("span",{className:ce(a&&"hidden"),children:s+1})]}),i.jsx("span",{className:ce("font-medium",o?"text-surface-900 dark:text-white":"text-surface-500"),children:r.label}),s<e.length-1&&i.jsx("span",{className:"mx-1 h-px w-3 bg-surface-300 dark:bg-surface-700 sm:w-5"})]},r.id)})})}function Mt({tone:e="info",title:t,children:n,className:r}){const s={info:"border-sky-200 bg-sky-50 text-sky-900 dark:border-sky-500/30 dark:bg-sky-500/10 dark:text-sky-100",warning:"border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-100",danger:"border-red-200 bg-red-50 text-red-900 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-100",success:"border-emerald-200 bg-emerald-50 text-emerald-900 dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-100"}[e],a=e==="success"?to:e==="info"?ak:yo;return i.jsxs("div",{className:ce("flex gap-2.5 rounded-lg border px-3 py-2.5 text-xs leading-relaxed",s,r),children:[i.jsx(a,{className:"mt-0.5 h-4 w-4 shrink-0"}),i.jsxs("div",{className:"min-w-0 space-y-1",children:[t&&i.jsx("p",{className:"font-semibold",children:t}),n&&i.jsx("div",{className:"break-words",children:n})]})]})}function Q0({state:e}){return e.status==="idle"||e.status==="running"?null:i.jsxs("p",{className:ce("flex items-start gap-1.5 text-xs",e.status==="ok"?"text-emerald-700 dark:text-emerald-400":"text-red-600 dark:text-red-400"),children:[i.jsx("span",{className:"mt-0.5 shrink-0 [&>svg]:h-3.5 [&>svg]:w-3.5",children:e.status==="ok"?i.jsx(to,{}):i.jsx(C0,{})}),i.jsx("span",{className:"min-w-0 break-words",children:e.detail})]})}function ao({id:e,value:t,onChange:n,placeholder:r,invalid:s}){const{t:a}=oe("setup"),[o,l]=S.useState(!1);return i.jsxs("div",{className:"relative",children:[i.jsx(Oe,{id:e,type:o?"text":"password",autoComplete:"off",spellCheck:!1,value:t,placeholder:r,invalid:s,onChange:d=>n(d.target.value),className:"pr-9"}),i.jsxs("button",{type:"button",onClick:()=>l(d=>!d),"aria-label":a(o?"common.hide":"common.show"),className:"absolute right-1.5 top-1/2 inline-flex h-6 w-6 -translate-y-1/2 items-center justify-center rounded text-surface-400 hover:text-surface-700 [&>svg]:h-3.5 [&>svg]:w-3.5",children:[i.jsx("span",{className:ce("inline-flex",o&&"hidden"),children:i.jsx(A0,{})}),i.jsx("span",{className:ce("inline-flex",!o&&"hidden"),children:i.jsx(dp,{})})]})]})}function Lj({fields:e,value:t,onChange:n,idPrefix:r,placeholders:s={},missing:a=[]}){const{t:o}=oe("setup"),l=(f,p)=>n({...t,[f]:p}),d=e.filter(f=>!f.show||f.show(t));return i.jsx("div",{className:"grid gap-3 sm:grid-cols-2",children:d.map(f=>{const p=`${r}-${f.key}`,m=i.jsxs(i.Fragment,{children:[o(`fields.${f.key}`),f.required&&i.jsx("span",{className:"ml-0.5 text-red-500",children:"*"})]}),h=f.help?o(`fields.${f.key}Help`):void 0,b=typeof t[f.key]=="string"?t[f.key]:"";if(f.type==="checkbox")return i.jsxs("div",{className:"sm:col-span-2",children:[i.jsx(Ot,{id:p,label:o(`fields.${f.key}`),checked:t[f.key]===!0,onChange:y=>l(f.key,y.target.checked)}),h&&i.jsx("p",{className:"ml-6 mt-0.5 text-xs text-surface-500",children:h})]},f.key);const x=a.includes(f.key);return i.jsx(Te,{label:m,htmlFor:p,help:h,className:ce((f.key==="token"||f.key==="secretAccessKey"||f.key==="endpoint"||f.key==="siteUrl")&&"sm:col-span-2"),children:f.type==="password"?i.jsx(ao,{id:p,value:b,onChange:y=>l(f.key,y),invalid:x,placeholder:s[f.key]??f.placeholder}):f.type==="select"?i.jsx(Ve,{id:p,value:b,onChange:y=>l(f.key,y.target.value),options:(f.options??[]).map(y=>({value:y,label:o(`fields.options.${y}`,{defaultValue:y})}))}):i.jsx(Oe,{id:p,autoComplete:"off",spellCheck:!1,value:b,invalid:x,placeholder:s[f.key]??f.placeholder,onChange:y=>l(f.key,y.target.value)})},f.key)})})}function Fj({handleKey:e,onPicked:t,picked:n}){const{t:r}=oe("setup"),[s,a]=S.useState(!1);if(!oB())return i.jsx(Mt,{tone:"warning",children:r("location.folderUnsupported")});const o=async()=>{a(!0);try{const l=await Fk();await zk(e,l),t(l.name)}catch(l){l.name!=="AbortError"&&ge.error(l.message)}finally{a(!1)}};return i.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[i.jsx(ue,{icon:i.jsx(no,{}),onClick:()=>void o(),loading:s,children:r(n?"location.changeFolder":"location.pickFolder")}),n&&i.jsxs("span",{className:"inline-flex items-center gap-1 text-xs text-emerald-700 dark:text-emerald-400",children:[i.jsx(to,{className:"h-3.5 w-3.5"})," ",n]})]})}const Hse=["bg-red-500","bg-orange-500","bg-amber-500","bg-lime-500","bg-emerald-500"];function qse({value:e}){const{t}=oe("setup"),{score:n}=e$(e);return i.jsxs("div",{className:"space-y-1",children:[i.jsx("div",{className:"flex gap-1","aria-hidden":"true",children:[0,1,2,3].map(r=>i.jsx("span",{className:ce("h-1 flex-1 rounded-full",e&&r<Math.max(n,1)?Hse[n]:"bg-surface-200 dark:bg-surface-800")},r))}),i.jsx("p",{className:"text-[11px] text-surface-500",children:t(e?`passphrase.strength.${n}`:"passphrase.strengthHint")})]})}function r$({passphrase:e,confirm:t,onChange:n,idPrefix:r,withConfirm:s=!0}){const{t:a}=oe("setup"),o=s&&!!t&&t!==e;return i.jsxs("div",{className:"space-y-3",children:[i.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[i.jsx(Te,{label:a("passphrase.label"),htmlFor:`${r}-pass`,children:i.jsx(ao,{id:`${r}-pass`,value:e,onChange:l=>n({passphrase:l,confirm:t})})}),s&&i.jsx(Te,{label:a("passphrase.confirm"),htmlFor:`${r}-confirm`,error:o?a("passphrase.mismatch"):void 0,children:i.jsx(ao,{id:`${r}-confirm`,value:t,onChange:l=>n({passphrase:e,confirm:l}),invalid:o})})]}),i.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[i.jsx("div",{className:"min-w-[12rem] flex-1",children:i.jsx(qse,{value:e})}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(Ni,{}),onClick:()=>{var d;const l=zB();n({passphrase:l,confirm:l}),(d=navigator.clipboard)==null||d.writeText(l).then(()=>ge.success(a("passphrase.generatedCopied")),()=>{})},children:a("passphrase.generate")})]})]})}function Vse({enabled:e,onChange:t,disabled:n}){const{t:r}=oe("setup");return i.jsxs("div",{className:"flex items-start justify-between gap-4 rounded-lg border border-surface-200 p-3 dark:border-surface-800",children:[i.jsxs("div",{children:[i.jsx("p",{className:"text-sm font-medium",children:r("passphrase.encryptTitle")}),i.jsx("p",{className:"text-xs text-surface-500",children:r("passphrase.encryptHint")})]}),i.jsx(si,{checked:e,onChange:t,disabled:n})]})}function s$({text:e,label:t,maxHeight:n="16rem"}){const{t:r}=oe("setup");return i.jsxs("div",{className:"relative",children:[i.jsx("pre",{className:"overflow-auto rounded-lg border border-surface-200 bg-surface-50 p-3 pr-10 font-mono text-[11px] leading-relaxed text-surface-800 dark:border-surface-800 dark:bg-surface-950 dark:text-surface-200",style:{maxHeight:n},children:e}),i.jsx(ue,{size:"xs",variant:"outline",icon:i.jsx(cp,{}),className:"absolute right-2 top-2","aria-label":t??r("common.copy"),onClick:()=>{var s;return void((s=navigator.clipboard)==null?void 0:s.writeText(e).then(()=>ge.success(r("common.copied")),()=>ge.error(r("common.copyFailed"))))},children:r("common.copy")})]})}function X0({onClick:e,running:t,label:n}){const{t:r}=oe("setup");return i.jsx(ue,{icon:i.jsx(Vc,{}),loading:t,onClick:e,children:n??r("common.testConnection")})}function ni({children:e,hint:t}){return i.jsxs("div",{children:[i.jsx("h3",{className:"text-sm font-semibold text-surface-900 dark:text-white",children:e}),t&&i.jsx("p",{className:"mt-0.5 text-xs text-surface-500",children:t})]})}const ju={maxFields:60,maxMetaKeys:10,formIdPattern:"^[A-Za-z0-9_-]{1,64}$",clockSkewMs:864e5},Wse=/^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/,Kse=/^[a-z0-9-]+(\.[a-z0-9-]+)+$/;function i$(e){const t=e.adminEmail.trim().toLowerCase();if(!Wse.test(t))throw new Error(`"${e.adminEmail}" is not a valid admin email for the rules.`);const n=(e.allowedDomains??[]).map(s=>s.trim().toLowerCase().replace(/^@/,"")).filter(Boolean);for(const s of n)if(!Kse.test(s))throw new Error(`"${s}" is not a valid domain.`);const r=e.signup??(n.length?"domain":"invite");if(r==="domain"&&!n.length)throw new Error('Sign-up "domain" needs at least one allowed domain.');return{adminEmail:t,signup:r,allowedDomains:n,requireVerifiedEmail:e.requireVerifiedEmail!==!1}}const a$=["objects","pipelines","forms","settings","config","extensions"],o$=["records","activities"];function l$(e){const t=i$(e),n=t.requireVerifiedEmail?" && request.auth.token.email_verified == true":"",r=t.signup==="open"?"true":t.signup==="domain"?`callerEmail().matches('^[^@]+@(${t.allowedDomains.map(a=>a.replace(/\./g,"[.]")).join("|")})$')`:"false",s=["rules_version = '2';","","// Generated by AgentCRM (src/ops/firebaseRules.ts) — see docs/firebase.md.",`// Sign-up: ${t.signup}${t.signup==="domain"?` (${t.allowedDomains.join(", ")})`:""}. Re-generate rather than edit by hand.`,"service cloud.firestore {"," match /databases/{database}/documents {",""," // ─── Identity & roles ─────────────────────────────────────────────"," function bootstrapAdminEmail() {",` return "${t.adminEmail}";`," }",""," function signedIn() {"," return request.auth != null;"," }",""," function hasEmail() {",` return signedIn() && request.auth.token.email != null${n};`," }",""," function callerEmail() {"," return request.auth.token.email.lower();"," }",""," function isBootstrapAdmin() {"," return hasEmail() && callerEmail() == bootstrapAdminEmail();"," }",""," function selfPath() {"," return /databases/$(database)/documents/users/$(request.auth.uid);"," }",""," // admin | member | viewer | none (no record / disabled)."," function role() {"," return isBootstrapAdmin() ? 'admin'"," : !exists(selfPath()) ? 'none'"," : get(selfPath()).data.get('disabled', false) == true ? 'none'"," : get(selfPath()).data.get('role', 'none');"," }",""," function isAdmin() {"," return signedIn() && role() == 'admin';"," }",""," function isMember() {"," return signedIn() && role() in ['admin', 'member'];"," }",""," function isActive() {"," return signedIn() && role() in ['admin', 'member', 'viewer'];"," }",""," function validRole(r) {"," return r in ['admin', 'member', 'viewer'];"," }",""," // ─── invites/{email} ──────────────────────────────────────────────"," // Mirrored by the admin from the users it adds (Settings → Users)."," function invitePath() {"," return /databases/$(database)/documents/invites/$(callerEmail());"," }",""," match /invites/{email} {"," allow read: if isAdmin() || (hasEmail() && callerEmail() == email);"," allow create, update: if isAdmin() && email == email.lower()"," && validRole(request.resource.data.role);"," allow delete: if isAdmin();"," }",""," // ─── users/{uid} ──────────────────────────────────────────────────"," function signupAllowed() {",` return ${r};`," }",""," // First sign-in: the caller creates its own record."," function selfCreate(uid) {"," let d = request.resource.data;"," return hasEmail() && request.auth.uid == uid"," && d.email == callerEmail()"," && d.get('authUid', '') == uid"," && d.get('disabled', false) == false"," && ("," (isBootstrapAdmin() && d.role == 'admin')"," || (exists(invitePath()) && d.role == get(invitePath()).data.role"," && d.get('replaces', get(invitePath()).data.get('userId', '')) == get(invitePath()).data.get('userId', ''))"," || (!exists(invitePath()) && signupAllowed() && d.role == 'member' && !('replaces' in d))"," );"," }",""," match /users/{uid} {"," allow read: if isActive() || (signedIn() && request.auth.uid == uid);"," allow create: if (isAdmin() && validRole(request.resource.data.role)) || selfCreate(uid);"," // Nobody changes their own role / email / disabled flag."," allow update: if (isAdmin() && validRole(request.resource.data.role))"," || (isActive() && request.auth.uid == uid"," && request.resource.data.diff(resource.data).affectedKeys().hasOnly(['name', 'avatarUrl', 'updatedAt']));"," allow delete: if isAdmin();"," }",""," // ─── CRM data ─────────────────────────────────────────────────────"];for(const a of o$)s.push(` match /${a}/{id} {`," allow read: if isActive();"," allow create, update, delete: if isMember();"," }","");s.push(" // Views: members manage their own private views; shared views are admin-only."," match /views/{id} {"," allow read: if isActive();"," allow create: if isAdmin()"," || (isMember() && request.resource.data.get('ownerId', '') == request.auth.uid"," && request.resource.data.get('shared', false) == false);"," allow update: if isAdmin()"," || (isMember() && resource.data.get('ownerId', '') == request.auth.uid"," && request.resource.data.get('ownerId', '') == request.auth.uid"," && request.resource.data.get('shared', false) == false);"," allow delete: if isAdmin() || (isMember() && resource.data.get('ownerId', '') == request.auth.uid);"," }",""," // Automations: admins edit; members running them may stamp lastRunAt."," match /automations/{id} {"," allow read: if isActive();"," allow create, delete: if isAdmin();"," allow update: if isAdmin()"," || (isMember() && request.resource.data.diff(resource.data).affectedKeys().hasOnly(['lastRunAt', 'updatedAt']));"," }",""," match /automationRuns/{id} {"," allow read: if isActive();"," allow create, update: if isMember();"," allow delete: if isAdmin();"," }",""," // File metadata (bytes in Firebase Storage, see storage.rules): members"," // upload / attach / soft-delete; only admins purge (compact)."," match /files/{id} {"," allow read: if isActive();"," allow create, update: if isMember();"," allow delete: if isAdmin();"," }","");for(const a of a$)s.push(` match /${a}/{id} {`," allow read: if isActive();"," allow write: if isAdmin();"," }","");return s.push(" // Pieces of large extension bundles (src/data/firebase.ts)."," match /extensionChunks/{id} {"," allow read: if isActive();"," allow write: if isAdmin();"," }",""," // ─── inbox/{id}: public lead-form submissions ──────────────────────"," function validSubmission(d) {"," return d.keys().hasAll(['formId', 'data', 'createdAt'])"," && d.keys().hasOnly(['formId', 'data', 'createdAt', 'meta'])",` && d.formId is string && d.formId.matches('${ju.formIdPattern}')`," && exists(/databases/$(database)/documents/forms/$(d.formId))",` && d.data is map && d.data.size() <= ${ju.maxFields}`,` && (!('meta' in d) || (d.meta is map && d.meta.size() <= ${ju.maxMetaKeys}))`," && d.createdAt is int",` && d.createdAt > request.time.toMillis() - ${ju.clockSkewMs}`,` && d.createdAt < request.time.toMillis() + ${ju.clockSkewMs};`," }",""," match /inbox/{id} {"," // Public: anyone (the static lead form) may create, nobody else reads."," allow create: if validSubmission(request.resource.data);"," // Ingested (then deleted) by members — the admin or the CLI."," allow read, delete: if isMember();"," // Failed submissions are only marked {status, error}."," allow update: if isMember()"," && request.resource.data.diff(resource.data).affectedKeys().hasOnly(['status', 'error']);"," }",""," // Anything else: closed."," match /{document=**} {"," allow read, write: if false;"," }"," }","}",""),s.join(`
1175
1175
  `)}const Gse={indexes:[],fieldOverrides:[]};function Jse(){return JSON.stringify(Gse,null,2)+`
1176
1176
  `}function Yse(){return JSON.stringify({firestore:{rules:"firestore.rules",indexes:"firestore.indexes.json"},storage:{rules:"storage.rules"}},null,2)+`
1177
1177
  `}[...o$,...a$];function Zse(e){const{adminEmail:t,requireVerifiedEmail:n}=i$({adminEmail:e.adminEmail,requireVerifiedEmail:e.requireVerifiedEmail}),r=Math.max(1,Math.min(5120,Math.round(e.maxUploadMb??100)));return["rules_version = '2';","","// Generated by AgentCRM (src/ops/firebaseRules.ts) — see docs/files.md.","service firebase.storage {"," match /b/{bucket}/o {"," function signedIn() {"," return request.auth != null;"," }",""," function isBootstrapAdmin() {",` return signedIn() && request.auth.token.email != null${n?" && request.auth.token.email_verified == true":""}`,` && request.auth.token.email.lower() == "${t}";`," }",""," function userDoc() {"," return /databases/(default)/documents/users/$(request.auth.uid);"," }",""," function role() {"," return isBootstrapAdmin() ? 'admin'"," : !firestore.exists(userDoc()) ? 'none'"," : firestore.get(userDoc()).data.get('disabled', false) == true ? 'none'"," : firestore.get(userDoc()).data.get('role', 'none');"," }",""," match /files/{fileId} {"," allow read: if signedIn() && role() in ['admin', 'member', 'viewer'];"," allow create, update: if signedIn() && role() in ['admin', 'member']",` && request.resource.size < ${r} * 1024 * 1024`," && fileId.matches('^[A-Za-z0-9_-]{1,80}$');"," allow delete: if signedIn() && role() == 'admin';"," }",""," match /{allPaths=**} {"," allow read, write: if false;"," }"," }","}",""].join(`
1178
- `)}function wl(e,t){if(t instanceof _n){const n=e(`setup:errors.${t.kind}`,{detail:t.detail??""});return t.detail&&!n.includes(t.detail)?`${n} — ${t.detail}`:n}return(t==null?void 0:t.message)??String(t)}const Qse=["USD","EUR","GBP","CAD","CHF","AUD","JPY","SEK","NOK","DKK","PLN","BRL","INR","SGD"];function ow(){return{model:"journal",journal:{locationId:"s3",settings:{s3Preset:"r2",endpoint:"",region:"auto",forcePathStyle:!0},root:"agentcrm",encrypted:!0,passphrase:"",confirm:"",folderName:null},git:{provider:"github",owner:"",repo:"",project:"",branch:"main",dir:"crm",apiBaseUrl:"",token:"",folderName:null},firebase:{apiKey:"",authDomain:"",projectId:"",storageBucket:"",messagingSenderId:"",appId:"",adminEmail:"",adminPassword:"",signInMethods:["password","google"],signup:"invite",allowedDomains:""},hosting:{optionId:"none",settings:{},folder:"admin",folderName:null},workspace:{name:"",currency:cE(typeof navigator<"u"?navigator.language:void 0),adminName:"",adminEmail:"",demo:!1},join:!1,existing:null}}function jo({onBack:e,nextLabel:t,nextDisabled:n,busy:r,nextIcon:s}){const{t:a}=oe("setup");return i.jsxs("div",{className:"flex items-center justify-between gap-3 border-t border-surface-100 pt-4 dark:border-surface-800",children:[e?i.jsx(ue,{variant:"ghost",onClick:e,disabled:r,children:a("common.back")}):i.jsx("span",{}),i.jsx(ue,{type:"submit",variant:"primary",disabled:n,loading:r,icon:s,children:t??a("common.continue")})]})}function c$(e){return e.state.model==="firebase"?i.jsx(nie,{...e}):e.state.model==="git-json"?i.jsx(tie,{...e}):i.jsx(eie,{...e})}const Xse={s3:i.jsx(N0,{}),github:i.jsx(nk,{}),gitlab:i.jsx(rk,{}),"local-folder":i.jsx(no,{})};function eie({state:e,update:t,onBack:n,onNext:r}){const{t:s}=oe("setup"),a=e.journal,o=ed(a.locationId),[l,d]=S.useState({status:"idle"}),[f,p]=S.useState(!1),m=(I,T=!1)=>{t({journal:{...a,...I},...T?{}:{existing:null,join:!1}}),T||d({status:"idle"})},h={...o.preset,...a.settings},b=Oj(Ff[o.id],h),x=e.existing,y=!!(x!=null&&x.exists)&&e.join,v=y?!!(x!=null&&x.encrypted):a.encrypted,k=!v||(y?!!a.passphrase.trim():t$(a.passphrase)&&a.passphrase===a.confirm),C=l.status==="ok"&&(!(x!=null&&x.exists)||e.join)&&k&&(o.id!=="local-folder"||!!a.folderName),A=async()=>{d({status:"running"});try{const I=await Tse(a);t({existing:I.existing,join:I.existing.exists}),d({status:"ok",detail:i.jsxs(i.Fragment,{children:[s("location.testOk",{detail:I.detail}),I.publicRepo&&i.jsx("span",{className:"mt-1 block text-amber-700 dark:text-amber-400",children:s("location.publicRepoEncrypted")})]})})}catch(I){d({status:"error",detail:wl(s,I)})}},_=async()=>{if(y&&v){p(!0);try{if(!await Ise(a)){d({status:"error",detail:s("errors.wrongPassphrase")});return}}catch(I){d({status:"error",detail:wl(s,I)});return}finally{p(!1)}}y&&m({encrypted:v},!0),r()},D=sw(String(h.s3Preset??"r2"));return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:I=>{I.preventDefault(),C&&_()},children:[i.jsx(ni,{hint:s("location.journalHint"),children:s("location.journalTitle")}),i.jsx(Mp,{columns:2,value:a.locationId,onChange:I=>m({locationId:I,settings:I==="s3"?{...sw("r2").settings,s3Preset:"r2"}:{...ed(I).preset},folderName:null}),choices:iw.map(I=>({id:I.id,icon:Xse[I.id],title:s(`location.options.${I.id}.title`),description:s(`location.options.${I.id}.description`),badge:I.id==="s3"?i.jsx(n$,{}):void 0}))}),o.id==="s3"&&i.jsxs("div",{className:"space-y-2",children:[i.jsx("p",{className:"text-xs font-medium text-surface-600 dark:text-surface-300",children:s("location.provider")}),i.jsx("div",{className:"flex flex-wrap gap-1.5",children:rw.map(I=>i.jsx("button",{type:"button",onClick:()=>m({settings:{...a.settings,...I.settings,s3Preset:I.id}}),className:ce("rounded-full border px-2.5 py-1 text-xs font-medium transition-colors",D.id===I.id?"border-accent-500 bg-accent-50 text-accent-700 dark:bg-accent-500/10 dark:text-accent-300":"border-surface-200 text-surface-600 hover:border-surface-300 dark:border-surface-700 dark:text-surface-300"),children:s(`location.s3Presets.${I.id}`)},I.id))}),i.jsx("p",{className:"text-xs text-surface-500",children:s(`location.s3PresetHints.${D.id}`)})]}),o.id==="local-folder"?i.jsxs("div",{className:"space-y-2",children:[i.jsx(Fj,{handleKey:"data-folder",picked:a.folderName,onPicked:I=>m({folderName:I})}),i.jsx("p",{className:"text-xs text-surface-500",children:s("location.localFolderHint")})]}):i.jsx(Lj,{idPrefix:"loc",fields:Ff[o.id],value:h,onChange:I=>m({settings:I}),placeholders:o.id==="s3"?{endpoint:D.endpointPlaceholder,region:D.regionPlaceholder}:{}}),i.jsx(Te,{label:s("location.root"),htmlFor:"loc-root",help:s("location.rootHelp"),children:i.jsx(Oe,{id:"loc-root",value:a.root,autoComplete:"off",onChange:I=>m({root:I.target.value}),placeholder:"agentcrm"})}),i.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[i.jsx(X0,{running:l.status==="running",onClick:()=>void A()}),b.length>0&&i.jsx("span",{className:"text-xs text-surface-500",children:s("location.fillRequired")})]}),i.jsx(Q0,{state:l}),(x==null?void 0:x.exists)&&i.jsxs(Mt,{tone:"info",title:s("location.existingTitle"),children:[i.jsx("p",{children:s(x.encrypted?"location.existingEncrypted":"location.existingPlain")}),i.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[i.jsx(ue,{size:"sm",variant:e.join?"primary":"outline",onClick:()=>t({join:!0}),children:s("location.joinExisting")}),i.jsx(ue,{size:"sm",variant:"ghost",onClick:()=>m({root:`${a.root||"agentcrm"}-2`}),children:s("location.useAnotherFolder")})]})]}),i.jsxs("div",{className:"space-y-3",children:[!y&&i.jsx(Vse,{enabled:a.encrypted,onChange:I=>m({encrypted:I},!0)}),v&&i.jsxs(i.Fragment,{children:[y?i.jsx(Te,{label:s("passphrase.existingLabel"),htmlFor:"loc-pass",help:s("passphrase.existingHelp"),children:i.jsx(ao,{id:"loc-pass",value:a.passphrase,onChange:I=>m({passphrase:I},!0)})}):i.jsx(r$,{idPrefix:"loc",passphrase:a.passphrase,confirm:a.confirm,onChange:I=>m(I,!0)}),i.jsx(Mt,{tone:"danger",title:s("passphrase.lostTitle"),children:s("passphrase.lostBody")})]}),!v&&!y&&i.jsx(Mt,{tone:"warning",children:s("passphrase.plainWarning")})]}),i.jsx(jo,{onBack:n,nextDisabled:!C,busy:f})]})}function tie({state:e,update:t,onBack:n,onNext:r}){const{t:s}=oe("setup"),a=e.git,[o,l]=S.useState({status:"idle"}),d=y=>{t({git:{...a,...y},existing:null,join:!1}),l({status:"idle"})},[f,p]=S.useState(null),m=async()=>{l({status:"running"});try{const y=await Rse(a);if(y.publicRepo){l({status:"error",detail:s("errors.publicRepo")});return}if(y.role==="viewer"&&!y.existing.exists){l({status:"error",detail:s("errors.readOnly",{detail:y.login})});return}p(y.role),t({existing:y.existing,join:y.existing.exists}),l({status:"ok",detail:s("location.gitOk",{login:y.login,role:s(`roles.${y.role}`)})})}catch(y){l({status:"error",detail:wl(s,y)})}},h=e.existing,b=o.status==="ok"&&(!(h!=null&&h.exists)||e.join),x=a.provider==="github"?Ff.github:a.provider==="gitlab"?Ff.gitlab:[];return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:y=>{y.preventDefault(),b&&r()},children:[i.jsx(ni,{hint:s("location.gitHint"),children:s("location.gitTitle")}),i.jsx(Mp,{columns:3,value:a.provider,onChange:y=>d({provider:y,folderName:null}),choices:[{id:"github",icon:i.jsx(nk,{}),title:"GitHub",description:s("location.gitGithub")},{id:"gitlab",icon:i.jsx(rk,{}),title:"GitLab",description:s("location.gitGitlab")},{id:"local",icon:i.jsx(go,{}),title:s("location.gitLocal"),description:s("location.gitLocalHint")}]}),a.provider==="local"?i.jsx(Fj,{handleKey:"git-json-folder",picked:a.folderName,onPicked:y=>d({folderName:y})}):i.jsx(Lj,{idPrefix:"git",fields:x,value:a,onChange:y=>d(y)}),i.jsx(Te,{label:s("location.gitDir"),htmlFor:"git-dir",help:s("location.gitDirHelp"),children:i.jsx(Oe,{id:"git-dir",value:a.dir,autoComplete:"off",onChange:y=>d({dir:y.target.value}),placeholder:"crm"})}),i.jsx(Mt,{tone:"warning",title:s("location.gitHistoryTitle"),children:s("location.gitHistoryBody")}),i.jsx("div",{className:"flex items-center gap-3",children:i.jsx(X0,{running:o.status==="running",onClick:()=>void m()})}),i.jsx(Q0,{state:o}),f&&i.jsx("p",{className:"text-xs text-surface-500",children:s("location.gitRoles")}),(h==null?void 0:h.exists)&&i.jsx(Mt,{tone:"info",title:s("location.existingTitle"),children:s("location.existingGit",{count:h.documents??0,name:h.name??"AgentCRM"})}),i.jsx(jo,{onBack:n,nextDisabled:!b})]})}const u_=["apiKey","authDomain","projectId","storageBucket","messagingSenderId","appId"];function nie({state:e,update:t,onBack:n,onNext:r}){var x;const{t:s}=oe("setup"),a=e.firebase,[o,l]=S.useState(""),[d,f]=S.useState({status:"idle"}),p=y=>{t({firebase:{...a,...y},existing:null,join:!1}),f({status:"idle"})},m=S.useMemo(()=>{try{return a.adminEmail.includes("@")?l$({adminEmail:a.adminEmail,signup:a.signup,allowedDomains:a.allowedDomains.split(/[\s,]+/).filter(Boolean)}):null}catch{return null}},[a.adminEmail,a.signup,a.allowedDomains]),h=async()=>{f({status:"running"});try{const y=await $se(a);return t({existing:y.existing,join:y.existing.exists,workspace:{...e.workspace,adminEmail:e.workspace.adminEmail||a.adminEmail.trim().toLowerCase()}}),f({status:"ok",detail:s("location.firebaseOk",{email:y.identity.email,role:s(`roles.${y.identity.role}`)})}),!0}catch(y){return f({status:"error",detail:wl(s,y)}),!1}},b=(y,v)=>p({signInMethods:v?[...new Set([...a.signInMethods,y])]:a.signInMethods.filter(k=>k!==y)});return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:y=>{y.preventDefault(),d.status==="ok"?r():h().then(v=>v&&r())},children:[i.jsx(ni,{hint:s("location.firebaseHint"),children:s("location.firebaseTitle")}),i.jsxs("ol",{className:"list-decimal space-y-1 pl-5 text-xs text-surface-600 dark:text-surface-300",children:[i.jsx("li",{children:s("location.firebaseSteps.project")}),i.jsx("li",{children:s("location.firebaseSteps.app")}),i.jsx("li",{children:s("location.firebaseSteps.auth")}),i.jsx("li",{children:s("location.firebaseSteps.firestore")}),i.jsx("li",{children:s("location.firebaseSteps.rules")})]}),i.jsx(Te,{label:s("location.firebaseSnippet"),htmlFor:"fb-snippet",help:s("location.firebaseSnippetHelp"),children:i.jsx(Cr,{id:"fb-snippet",rows:3,value:o,spellCheck:!1,className:"font-mono text-xs",placeholder:'const firebaseConfig = { apiKey: "…", authDomain: "…", projectId: "…", appId: "…" };',onChange:y=>{l(y.target.value);const v=Ase(y.target.value);Object.keys(v).length&&p(Object.fromEntries(u_.map(k=>[k,v[k]??a[k]])))}})}),i.jsx("div",{className:"grid gap-3 sm:grid-cols-2",children:u_.map(y=>i.jsx(Te,{label:s(`fields.${y}`),htmlFor:`fb-${y}`,children:i.jsx(Oe,{id:`fb-${y}`,value:String(a[y]),autoComplete:"off",spellCheck:!1,onChange:v=>p({[y]:v.target.value})})},y))}),i.jsx(ni,{hint:s("location.firebaseAdminHint"),children:s("location.firebaseAdmin")}),i.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[i.jsx(Te,{label:s("fields.adminEmail"),htmlFor:"fb-email",children:i.jsx(Oe,{id:"fb-email",type:"email",autoComplete:"off",value:a.adminEmail,onChange:y=>p({adminEmail:y.target.value})})}),i.jsx(Te,{label:s("fields.adminPassword"),htmlFor:"fb-password",children:i.jsx(ao,{id:"fb-password",value:a.adminPassword,onChange:y=>p({adminPassword:y})})})]}),i.jsxs("div",{className:"flex flex-wrap gap-4",children:[i.jsx(Ot,{label:s("location.methodPassword"),checked:a.signInMethods.includes("password"),onChange:y=>b("password",y.target.checked)}),i.jsx(Ot,{label:s("location.methodGoogle"),checked:a.signInMethods.includes("google"),onChange:y=>b("google",y.target.checked)})]}),i.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[i.jsx(Te,{label:s("location.signup"),htmlFor:"fb-signup",help:s(`location.signupHelp.${a.signup}`),children:i.jsx(Ve,{id:"fb-signup",value:a.signup,onChange:y=>p({signup:y.target.value}),options:["invite","domain","open"].map(y=>({value:y,label:s(`location.signupModes.${y}`)}))})}),a.signup==="domain"&&i.jsx(Te,{label:s("location.allowedDomains"),htmlFor:"fb-domains",children:i.jsx(Oe,{id:"fb-domains",value:a.allowedDomains,placeholder:"acme.com, acme.io",onChange:y=>p({allowedDomains:y.target.value})})})]}),i.jsxs("div",{className:"space-y-2",children:[i.jsx(ni,{hint:s("location.rulesHint"),children:i.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[i.jsx(yl,{className:"h-4 w-4"})," ",s("location.rulesTitle")]})}),m?i.jsxs(i.Fragment,{children:[i.jsx(rie,{rules:m}),i.jsxs("div",{className:"flex flex-wrap gap-2",children:[i.jsx(ue,{size:"sm",icon:i.jsx(En,{}),onClick:()=>rl(m,"firestore.rules"),children:"firestore.rules"}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(En,{}),onClick:()=>rl(Jse(),"firestore.indexes.json","application/json"),children:"firestore.indexes.json"}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(En,{}),onClick:()=>rl(Zse({adminEmail:a.adminEmail}),"storage.rules"),children:"storage.rules"}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(En,{}),onClick:()=>rl(Yse(),"firebase.json","application/json"),children:"firebase.json"})]})]}):i.jsx("p",{className:"text-xs text-surface-500",children:s("location.rulesNeedEmail")})]}),i.jsx("div",{className:"flex items-center gap-3",children:i.jsx(X0,{running:d.status==="running",onClick:()=>void h(),label:s("location.firebaseVerify")})}),i.jsx(Q0,{state:d}),((x=e.existing)==null?void 0:x.exists)&&i.jsx(Mt,{tone:"info",title:s("location.existingTitle"),children:s("location.existingFirebase")}),i.jsx(jo,{onBack:n,busy:d.status==="running",nextIcon:i.jsx(Rs,{})})]})}function rie({rules:e}){const{t}=oe("setup"),[n,r]=S.useState(!1);return i.jsxs("div",{className:"space-y-2",children:[i.jsx(ue,{size:"xs",variant:"ghost",icon:i.jsx(Ii,{}),onClick:()=>r(s=>!s),children:t(n?"location.rulesHide":"location.rulesShow")}),i.jsx("div",{className:ce(!n&&"hidden"),children:i.jsx(s$,{text:e})})]})}const sie={none:i.jsx(up,{}),"github-pages":i.jsx(nk,{}),"cloudflare-pages":i.jsx(N0,{}),"gitlab-pages":i.jsx(rk,{}),s3:i.jsx(G8,{}),"local-folder":i.jsx(no,{}),zip:i.jsx(X1,{})};function d$({value:e,onChange:t,onTested:n,exclude:r=[]}){const{t:s}=oe("setup"),[a,o]=S.useState({status:"idle"}),l=td(e.optionId),d=m=>{t({...e,...m}),o({status:"idle"}),n==null||n(!1)},f=async()=>{o({status:"running"});try{const m=await Ose(e);o({status:"ok",detail:s("hosting.testOk",{detail:m})}),n==null||n(!0)}catch(m){o({status:"error",detail:wl(s,m)}),n==null||n(!1)}},p={...l.preset,...e.settings};return i.jsxs("div",{className:"space-y-4",children:[i.jsx(Mp,{columns:2,value:e.optionId,onChange:m=>d({optionId:m,settings:{...td(m).preset},folderName:null}),choices:Tc.filter(m=>!r.includes(m.id)).map(m=>({id:m.id,icon:sie[m.id],title:s(`hosting.options.${m.id}.title`),description:s(`hosting.options.${m.id}.description`)}))}),e.optionId!=="none"&&e.optionId!=="zip"&&i.jsxs(i.Fragment,{children:[e.optionId==="local-folder"&&i.jsx(Fj,{handleKey:"publish-target",picked:e.folderName,onPicked:m=>d({folderName:m})}),i.jsx(Lj,{idPrefix:"host",fields:J4[e.optionId],value:p,onChange:m=>d({settings:m})}),i.jsx(Te,{label:s("hosting.folder"),htmlFor:"host-folder",help:s("hosting.folderHelp"),children:i.jsx(Oe,{id:"host-folder",value:e.folder,autoComplete:"off",onChange:m=>d({folder:m.target.value}),placeholder:"admin"})}),i.jsx(Mt,{tone:"info",title:s(`hosting.howTo.${e.optionId}.title`),children:s(`hosting.howTo.${e.optionId}.body`)}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(X0,{running:a.status==="running",onClick:()=>void f()}),Q4(e).length>0&&i.jsx("span",{className:"text-xs text-surface-500",children:s("location.fillRequired")})]}),i.jsx(Q0,{state:a})]}),e.optionId==="zip"&&i.jsx(Mt,{tone:"info",children:s("hosting.zipHint")}),e.optionId==="none"&&i.jsx(Mt,{tone:"info",children:s("hosting.noneHint")})]})}function iie({state:e,update:t,onBack:n,onNext:r}){const{t:s}=oe("setup"),[a,o]=S.useState(!1),l=e.hosting,f=!(l.optionId!=="none"&&l.optionId!=="zip")||a;return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:p=>{p.preventDefault(),f&&r()},children:[i.jsx(ni,{hint:s("hosting.hint"),children:s("hosting.title")}),i.jsx(Mt,{tone:"warning",title:s("hosting.securityTitle"),children:s("hosting.securityBody")}),i.jsx(d$,{value:l,onChange:p=>t({hosting:p}),onTested:o}),i.jsx(jo,{onBack:n,nextDisabled:!f,nextLabel:l.optionId==="none"?s("hosting.skip"):void 0})]})}function aie(e){return e==="local"?["terms","data","workspace","install"]:["terms","data","location","hosting","workspace","install"]}function oie(){const{t:e,i18n:t}=oe("setup"),[n,r]=S.useState(ow),[s,a]=S.useState("terms"),o=S.useCallback(p=>r(m=>({...m,...p})),[]),l=aie(n.model),d=p=>a(m=>l[Math.max(0,Math.min(l.length-1,l.indexOf(m)+p))]),f={state:n,update:o,onBack:()=>d(-1),onNext:()=>d(1)};return i.jsx("div",{className:"min-h-screen bg-surface-50 px-4 py-8 dark:bg-surface-950 sm:py-12",children:i.jsxs("div",{className:"mx-auto w-full max-w-2xl space-y-5",children:[i.jsxs("header",{className:"flex items-center justify-between gap-4",children:[i.jsxs("div",{className:"flex items-center gap-2.5",children:[i.jsx("span",{className:"inline-flex h-9 w-9 items-center justify-center rounded-lg bg-surface-900 text-white dark:bg-white dark:text-surface-900",children:i.jsx(ba,{className:"h-4 w-4"})}),i.jsxs("div",{children:[i.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-white",children:e("wizard.title")}),i.jsx("p",{className:"text-xs text-surface-500",children:e("wizard.subtitle")})]})]}),i.jsx(Ve,{"aria-label":e("wizard.language"),className:"w-32",value:jc(t.language)?t.language:"en",onChange:p=>c1(p.target.value),options:u0.map(p=>({value:p,label:o1[p]}))})]}),i.jsx(Bse,{steps:l.map(p=>({id:p,label:e(`wizard.steps.${p}`)})),current:s}),i.jsxs(Ke,{className:"p-5 sm:p-6",children:[s==="terms"&&i.jsx(lie,{onNext:()=>d(1),onQuickStart:()=>{o({model:"local",existing:null,join:!1,workspace:{...n.workspace,demo:!0}}),a("workspace")}}),s==="data"&&i.jsx(cie,{...f}),s==="location"&&i.jsx(c$,{...f}),s==="hosting"&&i.jsx(iie,{...f}),s==="workspace"&&i.jsx(die,{...f}),s==="install"&&i.jsx(uie,{...f})]})]})})}function lie({onNext:e,onQuickStart:t}){const{t:n}=oe("setup"),[r,s]=S.useState(!1);return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:a=>{a.preventDefault(),r&&e()},children:[i.jsx(ni,{hint:n("terms.hint"),children:n("terms.title")}),i.jsx("ul",{className:"space-y-2 text-sm text-surface-700 dark:text-surface-300",children:["static","yourData","secrets","gdpr","warranty"].map(a=>i.jsxs("li",{className:"flex gap-2",children:[i.jsx(to,{className:"mt-0.5 h-4 w-4 shrink-0 text-accent-600"}),i.jsx("span",{children:n(`terms.points.${a}`)})]},a))}),i.jsx(Ot,{label:n("terms.accept"),checked:r,onChange:a=>s(a.target.checked)}),i.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 rounded-lg border border-dashed border-surface-300 p-3 dark:border-surface-700",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsxs("p",{className:"flex items-center gap-1.5 text-sm font-medium",children:[i.jsx(up,{className:"h-4 w-4 text-surface-500"})," ",n("terms.quickTitle")]}),i.jsx("p",{className:"text-xs text-surface-500",children:n("terms.quickHint")})]}),i.jsx(ue,{size:"sm",disabled:!r,onClick:t,children:n("terms.quickStart")})]}),i.jsx(jo,{nextDisabled:!r,nextLabel:n("terms.start")})]})}function cie({state:e,update:t,onBack:n,onNext:r}){const{t:s}=oe("setup");return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:a=>{a.preventDefault(),r()},children:[i.jsx(ni,{hint:s("data.hint"),children:s("data.title")}),i.jsx(Mp,{columns:1,value:e.model,onChange:a=>t({model:a,existing:null,join:!1}),choices:[{id:"journal",icon:i.jsx(Ii,{}),title:s("data.models.journal.title"),description:s("data.models.journal.description"),badge:i.jsx(n$,{})},{id:"firebase",icon:i.jsx(N0,{}),title:s("data.models.firebase.title"),description:s("data.models.firebase.description")},{id:"git-json",icon:i.jsx(go,{}),title:s("data.models.git-json.title"),description:s("data.models.git-json.description")},{id:"local",icon:i.jsx(up,{}),title:s("data.models.local.title"),description:s("data.models.local.description")}]}),i.jsx(Mt,{tone:"info",children:s(`data.models.${e.model}.details`)}),i.jsx(jo,{onBack:n})]})}function die({state:e,update:t,onBack:n,onNext:r}){var m;const{t:s}=oe("setup"),a=e.workspace,o=h=>t({workspace:{...a,...h}}),l=e.join&&!!((m=e.existing)!=null&&m.exists),d=/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(a.adminEmail.trim()),p=(!(e.model!=="local"||!!a.adminEmail.trim())||d)&&(l||!!a.adminName.trim()||e.model==="local");return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:h=>{h.preventDefault(),p&&r()},children:[i.jsx(ni,{hint:s(l?"workspace.joinHint":"workspace.hint"),children:s(l?"workspace.joinTitle":"workspace.title")}),!l&&i.jsxs("div",{className:"grid gap-3 sm:grid-cols-[1fr_9rem]",children:[i.jsx(Te,{label:s("workspace.name"),htmlFor:"ws-name",children:i.jsx(Oe,{id:"ws-name",value:a.name,placeholder:"Acme CRM",autoComplete:"off",onChange:h=>o({name:h.target.value})})}),i.jsx(Te,{label:s("workspace.currency"),htmlFor:"ws-currency",children:i.jsx(Ve,{id:"ws-currency",value:a.currency,onChange:h=>o({currency:h.target.value}),options:Qse.map(h=>({value:h,label:h}))})})]}),i.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[i.jsx(Te,{label:s("workspace.adminName"),htmlFor:"ws-admin-name",children:i.jsx(Oe,{id:"ws-admin-name",value:a.adminName,autoComplete:"off",onChange:h=>o({adminName:h.target.value})})}),i.jsx(Te,{label:s("workspace.adminEmail"),htmlFor:"ws-admin-email",help:e.model==="git-json"?s("workspace.gitEmailHelp"):void 0,children:i.jsx(Oe,{id:"ws-admin-email",type:"email",value:a.adminEmail,autoComplete:"off",onChange:h=>o({adminEmail:h.target.value})})})]}),!l&&i.jsx(Ot,{label:s("workspace.demo"),checked:a.demo,onChange:h=>o({demo:h.target.checked})}),i.jsx(jo,{onBack:n,nextDisabled:!p})]})}function uie({state:e,onBack:t}){var y;const{t:n}=oe("setup"),r=xd(),[s,a]=S.useState([]),[o,l]=S.useState(!1),[d,f]=S.useState(null),[p,m]=S.useState(null),h=e.join&&!!((y=e.existing)!=null&&y.exists),b=S.useMemo(()=>{const v=[[n("install.summary.model"),n(`data.models.${e.model}.title`)]];if(e.model==="journal"){const k=ed(e.journal.locationId);v.push([n("install.summary.location"),`${Pj(k.connectorId,{...k.preset,...e.journal.settings},n("access.journal.localFolder"))} / ${e.journal.root||"—"}`]),v.push([n("install.summary.encryption"),e.journal.encrypted?n("install.summary.encrypted"):n("install.summary.notEncrypted")])}if(e.model==="git-json"){const k=e.git;v.push([n("install.summary.location"),`${k.provider==="github"?`${k.owner}/${k.repo}`:k.provider==="gitlab"?k.project:n("location.gitLocal")} @ ${k.branch} / ${k.dir||"—"}`])}return e.model==="firebase"&&v.push([n("install.summary.location"),e.firebase.projectId]),e.model!=="local"&&v.push([n("install.summary.hosting"),n(`hosting.options.${td(e.hosting.optionId).id}.title`)]),v.push([n("install.summary.mode"),h?n("install.summary.join"):e.workspace.demo?n("install.summary.createDemo"):n("install.summary.create")]),e.workspace.adminEmail&&v.push([n("install.summary.admin"),`${e.workspace.adminName} <${e.workspace.adminEmail}>`]),v},[e,h,n]),x=async()=>{l(!0),f(null),a([]);const v={step:(k,j)=>a(C=>{const A=`${n(`install.steps.${k}`)}${j?` ${j}`:""}`,_=C.findIndex(I=>I.id===k);if(_===-1)return[...C,{id:k,label:A,status:"running"}];const D=[...C];return D[_]={...D[_],label:A,status:"running"},D}),done:k=>a(j=>j.map(C=>C.id===k?{...C,label:n(`install.steps.${k}`),status:"done"}:C))};try{const k=await Lse({model:e.model,journal:e.journal,git:e.git,firebase:e.firebase,hosting:e.hosting,workspace:{...e.workspace,locale:xt.language},join:h},v);m(k)}catch(k){a(j=>j.map(C=>C.status==="running"?{...C,status:"error"}:C)),f(wl(n,k))}finally{l(!1)}};return p?i.jsxs("div",{className:"space-y-5",children:[i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(to,{className:"h-8 w-8 text-emerald-600"}),i.jsxs("div",{children:[i.jsx("h2",{className:"text-base font-semibold",children:n("install.doneTitle")}),i.jsx("p",{className:"text-sm text-surface-500",children:n("install.doneHint")})]})]}),p.adminUrl&&i.jsx(Mt,{tone:"success",title:n("install.adminDeployed"),children:i.jsxs("a",{className:"inline-flex items-center gap-1 font-medium underline",href:p.adminUrl,target:"_blank",rel:"noreferrer",children:[p.adminUrl," ",i.jsx(ho,{className:"h-3 w-3"})]})}),p.zipDownloaded&&i.jsx(Mt,{tone:"success",children:n("install.zipDone")}),p.runtime.backend!=="local"&&!p.adminUrl&&i.jsxs(Mt,{tone:"info",title:n("install.configJsTitle"),children:[i.jsx("p",{children:n("install.configJsBody")}),i.jsx(ue,{size:"sm",className:"mt-2",icon:i.jsx(En,{}),onClick:()=>W4(p.runtime),children:"config.js"})]}),i.jsx("div",{className:"flex justify-end",children:i.jsx(ue,{variant:"primary",icon:i.jsx(pg,{}),onClick:()=>r.reconfigure(),children:n("install.open")})})]}):i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:v=>{v.preventDefault(),o||x()},children:[i.jsx(ni,{hint:n(e.model==="firebase"?"install.hintFirebase":"install.hint"),children:n("install.title")}),i.jsx("dl",{className:"divide-y divide-surface-100 rounded-lg border border-surface-200 text-sm dark:divide-surface-800 dark:border-surface-800",children:b.map(([v,k])=>i.jsxs("div",{className:"flex gap-4 px-3 py-2",children:[i.jsx("dt",{className:"w-36 shrink-0 text-surface-500",children:v}),i.jsx("dd",{className:"min-w-0 break-words font-medium text-surface-900 dark:text-surface-100",children:k})]},v))}),s.length>0&&i.jsx("ul",{className:"space-y-1.5 rounded-lg bg-surface-50 p-3 text-xs dark:bg-surface-950","aria-live":"polite",children:s.map(v=>i.jsxs("li",{className:"flex items-center gap-2",children:[i.jsxs("span",{className:ce("inline-flex [&>svg]:h-3.5 [&>svg]:w-3.5",v.status==="done"&&"text-emerald-600",v.status==="error"&&"text-red-600",v.status==="running"&&"text-surface-500"),children:[i.jsx("span",{className:ce("inline-flex",v.status!=="running"&&"hidden"),children:i.jsx(lk,{className:"animate-spin"})}),i.jsx("span",{className:ce("inline-flex",v.status!=="done"&&"hidden"),children:i.jsx(to,{})}),i.jsx("span",{className:ce("inline-flex",v.status!=="error"&&"hidden"),children:i.jsx(C0,{})})]}),i.jsx("span",{children:v.label})]},v.id))}),d&&i.jsx(Mt,{tone:"danger",title:n("install.failed"),children:d}),i.jsx(jo,{onBack:o?void 0:t,busy:o,nextLabel:n(d?"install.retry":"install.run"),nextIcon:i.jsx(pg,{})})]})}function fie({onSignedIn:e}){const t=mr();return(t==null?void 0:t.backend)==="firebase"?i.jsx(mie,{config:t,onSignedIn:e}):(t==null?void 0:t.backend)==="git-json"?i.jsx(gie,{config:t,onSignedIn:e}):(t==null?void 0:t.backend)==="journal"?i.jsx(yie,{config:t,onSignedIn:e}):i.jsx(nd,{title:"AgentCRM",icon:i.jsx(jv,{})})}function nd({title:e,hint:t,icon:n,children:r,footer:s}){return i.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-50 p-4 dark:bg-surface-950",children:i.jsxs("div",{className:"w-full max-w-sm space-y-3",children:[i.jsxs(Ke,{className:"p-5",children:[i.jsxs("div",{className:"mb-4 flex items-start gap-3",children:[i.jsx("span",{className:"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-surface-900 text-white dark:bg-white dark:text-surface-900 [&>svg]:h-4 [&>svg]:w-4",children:n}),i.jsxs("div",{className:"min-w-0",children:[i.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-white",children:e}),t&&i.jsx("p",{className:"mt-0.5 text-xs text-surface-500",children:t})]})]}),r]}),s]})})}function $g(){const{t:e}=oe("setup"),t=xd();return i.jsx("div",{className:"text-center",children:i.jsx("button",{type:"button",className:"text-xs text-surface-500 underline-offset-2 hover:underline",onClick:()=>{ld(null),t.reconfigure()},children:e("access.otherCrm")})})}function pie(e){const t=(e==null?void 0:e.code)??"";return`access.firebaseErrors.${{"auth/invalid-email":"invalidEmail","auth/invalid-credential":"invalidCredentials","auth/wrong-password":"invalidCredentials","auth/user-not-found":"invalidCredentials","auth/too-many-requests":"tooManyRequests","auth/user-disabled":"userDisabled","auth/network-request-failed":"network","auth/popup-closed-by-user":"popupClosed","auth/cancelled-popup-request":"popupClosed","auth/popup-blocked":"popupBlocked","auth/unauthorized-domain":"unauthorizedDomain","auth/operation-not-allowed":"methodDisabled"}[t]??"generic"}`}function mie({config:e,onSignedIn:t}){var k;const{t:n}=oe("setup"),[r,s]=S.useState(""),[a,o]=S.useState(""),[l,d]=S.useState(null),[f,p]=S.useState(null),[m,h]=S.useState(null),b=(k=e.signInMethods)!=null&&k.length?e.signInMethods:["password"];S.useEffect(()=>{let j=!1;return(async()=>{const{isFirebaseStore:C}=await Sr(async()=>{const{isFirebaseStore:_}=await import("./firebase-C1x_l9P9.js");return{isFirebaseStore:_}},[],import.meta.url),A=await Dv().catch(()=>null);if(!j&&A&&C(A)){const _=A.accessError();_&&h({reason:_.reason,email:_.email})}})(),()=>{j=!0}},[]);const x=async()=>(await Sr(async()=>{const{firebaseApiFor:j}=await import("./firebase-C1x_l9P9.js");return{firebaseApiFor:j}},[],import.meta.url)).firebaseApiFor(e),y=async()=>{const{isFirebaseStore:j}=await Sr(async()=>{const{isFirebaseStore:A}=await import("./firebase-C1x_l9P9.js");return{isFirebaseStore:A}},[],import.meta.url),C=await Dv().catch(()=>null);if(C&&j(C)&&(C.resetSession(),!await C.identity())){const _=C.accessError();h(_?{reason:_.reason,email:_.email}:null);return}t()},v=async(j,C)=>{d(j),p(null);try{await C()}catch(A){p(n(pie(A)))}finally{d(null)}};return m?i.jsx(nd,{title:n(`access.firebase.${m.reason}Title`),hint:m.email,icon:i.jsx(aa,{}),footer:i.jsx($g,{}),children:i.jsxs("div",{className:"space-y-3",children:[i.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:n(`access.firebase.${m.reason}Body`)}),f&&i.jsx("p",{className:"text-xs text-red-600",children:f}),i.jsxs("div",{className:"flex flex-wrap gap-2",children:[m.reason==="unverified"&&i.jsxs(i.Fragment,{children:[i.jsx(ue,{size:"sm",variant:"primary",icon:i.jsx(Vc,{}),loading:l==="verify",onClick:()=>void v("verify",async()=>{await(await x()).auth.reload(),await y()}),children:n("access.firebase.verified")}),i.jsx(ue,{size:"sm",icon:i.jsx(aa,{}),onClick:()=>void v("reset",async()=>{await(await x()).auth.sendVerificationEmail(),ge.success(n("access.firebase.verificationSent"))}),children:n("access.firebase.resend")})]}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(_0,{}),loading:l==="signOut",onClick:()=>void v("signOut",async()=>{await(await x()).auth.signOut(),h(null)}),children:n("access.signOut")})]})]})}):i.jsx(nd,{title:n("access.firebase.title",{name:e.name??"AgentCRM"}),hint:n("access.firebase.hint"),icon:i.jsx(wN,{}),footer:i.jsx($g,{}),children:i.jsxs("div",{className:"space-y-4",children:[b.includes("google")&&i.jsx(ue,{className:"w-full",icon:i.jsx(hie,{}),loading:l==="google",disabled:!!l,onClick:()=>void v("google",async()=>{await(await x()).auth.signInWithGoogle(),await y()}),children:n("access.firebase.google")}),b.includes("google")&&b.includes("password")&&i.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-wide text-surface-400",children:[i.jsx("span",{className:"h-px flex-1 bg-surface-200 dark:bg-surface-800"})," ",n("access.or")," ",i.jsx("span",{className:"h-px flex-1 bg-surface-200 dark:bg-surface-800"})]}),b.includes("password")&&i.jsxs("form",{"data-form-type":"other",className:"space-y-3",onSubmit:j=>{j.preventDefault(),v("password",async()=>{await(await x()).auth.signInWithPassword(r,a),await y()})},children:[i.jsx(Te,{label:n("access.email"),htmlFor:"fb-login-email",children:i.jsx(Oe,{id:"fb-login-email",type:"email",autoComplete:"username",value:r,onChange:j=>s(j.target.value)})}),i.jsx(Te,{label:n("access.password"),htmlFor:"fb-login-password",children:i.jsx(Oe,{id:"fb-login-password",type:"password",autoComplete:"current-password",value:a,onChange:j=>o(j.target.value)})}),f&&i.jsx("p",{className:"text-xs text-red-600 dark:text-red-400",children:f}),i.jsx(ue,{type:"submit",variant:"primary",className:"w-full",icon:i.jsx(wN,{}),loading:l==="password",disabled:!!l||!r||!a,children:n("access.signIn")}),i.jsx("button",{type:"button",className:"text-xs text-surface-500 hover:underline",disabled:!!l,onClick:()=>{if(!r.trim())return p(n("access.firebase.resetNeedsEmail"));v("reset",async()=>{await(await x()).auth.sendPasswordReset(r),ge.success(n("access.firebase.resetSent",{email:r}))})},children:n("access.firebase.forgot")})]}),!b.includes("password")&&f&&i.jsx("p",{className:"text-xs text-red-600 dark:text-red-400",children:f})]})})}function hie(){return i.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:i.jsx("path",{fill:"#EA4335",d:"M12 10.2v3.9h5.5c-.2 1.3-1.6 3.9-5.5 3.9-3.3 0-6-2.7-6-6.1s2.7-6.1 6-6.1c1.9 0 3.1.8 3.8 1.5l2.6-2.5C16.8 3.3 14.6 2.3 12 2.3 6.6 2.3 2.3 6.6 2.3 12s4.3 9.7 9.7 9.7c5.6 0 9.3-3.9 9.3-9.5 0-.6-.1-1.1-.2-1.6H12z"})})}function gie({config:e,onSignedIn:t}){const{t:n}=oe("setup"),r=e.git,[s,a]=S.useState(""),[o,l]=S.useState(""),[d,f]=S.useState(!1),[p,m]=S.useState(null),h=r.provider==="github"?`${r.owner}/${r.repo}`:r.provider==="gitlab"?r.project??"":n("location.gitLocal");S.useEffect(()=>{Sr(()=>import("./gitJson-CAUSxl8d.js"),[],import.meta.url).then(x=>l(x.getGitUserEmail(e)??""))},[e]);const b=async()=>{f(!0),m(null);try{const x=await Sr(()=>import("./gitJson-CAUSxl8d.js"),[],import.meta.url);if(r.provider==="local"){let y=await O0(x.LOCAL_GIT_HANDLE_KEY);if(y||(y=await Fk(),await zk(x.LOCAL_GIT_HANDLE_KEY,y)),!await wp(y,!0))throw new Error(n("access.folderDenied"))}else{const y=await x.openGitJsonTransport(r,s.trim());if(!y)throw new Error(n("access.git.tokenRequired"));if(!await y.permissions().catch(()=>null))throw new Error(n("access.git.invalidToken"));x.setGitToken(r,s.trim())}x.setGitUserEmail(e,o),jp(),t()}catch(x){x.name!=="AbortError"&&m(x.message)}finally{f(!1)}};return i.jsx(nd,{title:n("access.git.title"),hint:n("access.git.hint",{repo:h}),icon:i.jsx(Rs,{}),footer:i.jsx($g,{}),children:i.jsxs("form",{"data-form-type":"other",className:"space-y-3",onSubmit:x=>{x.preventDefault(),b()},children:[r.provider!=="local"&&i.jsx(Te,{label:n("access.git.token"),htmlFor:"git-token",help:n(r.provider==="github"?"access.git.githubTokenHelp":"access.git.gitlabTokenHelp"),children:i.jsx(ao,{id:"git-token",value:s,onChange:a})}),i.jsx(Te,{label:n("access.git.email"),htmlFor:"git-email",help:n("access.git.emailHelp"),children:i.jsx(Oe,{id:"git-email",type:"email",autoComplete:"off",value:o,onChange:x=>l(x.target.value)})}),p&&i.jsx("p",{className:"text-xs text-red-600 dark:text-red-400",children:p}),i.jsx(ue,{type:"submit",variant:"primary",className:"w-full",loading:d,disabled:r.provider!=="local"&&!s.trim(),icon:r.provider==="local"?i.jsx(no,{}):i.jsx(Rs,{}),children:r.provider==="local"?n("access.reconnectFolder"):n("access.git.connect")}),i.jsx("p",{className:"text-[11px] text-surface-500",children:n("access.storedHere")})]})})}function yie({config:e,onSignedIn:t}){const{t:n}=oe("setup"),r=e.journal,s=jR[r.connectorId]??[],[a,o]=S.useState(()=>{const k=pl(e);return Object.fromEntries(s.map(j=>[j,typeof k[j]=="string"?k[j]:""]))}),[l,d]=S.useState(Zf(e)??""),[f,p]=S.useState(null),[m,h]=S.useState(!1),[b,x]=S.useState(null);S.useEffect(()=>{SR(r.connectorId,{...r.settings,...pl(e)}).then(p)},[e,r]);const y=r.connectorId==="local-folder",v=async()=>{h(!0),x(null);try{if(y){const A=typeof r.settings.handleKey=="string"&&r.settings.handleKey?r.settings.handleKey:"data-folder";let _=await O0(A);if(_||(_=await Fk(),await zk(A,_)),!await wp(_,!0))throw new Error(n("access.folderDenied"))}const k=Object.fromEntries(Object.entries(a).map(([A,_])=>[A,_.trim()]).filter(([,A])=>A)),j=ko(r.connectorId,{...r.settings,...k}),C=await Xk(j,r.root,l.trim()||null);if(!C.exists)throw new Error(n("access.journal.noDataset"));if(C.encrypted&&!C.ok)throw new Error(n("access.journal.wrongPassphrase"));Xg(e,Object.keys(k).length?k:null),cd(e,C.encrypted?l.trim():null),jp(),t()}catch(k){k.name!=="AbortError"&&x(k.message)}finally{h(!1)}};return f===null?i.jsx(nd,{title:n("access.journal.title"),icon:i.jsx(jv,{}),children:i.jsx(Ds,{})}):i.jsx(nd,{title:n("access.journal.title"),hint:n(r.connectorId==="local-folder"?"access.journal.hintFolder":"access.journal.hint",{location:`${Pj(r.connectorId,r.settings,n("access.journal.localFolder"))} / ${r.root}`}),icon:i.jsx(jv,{}),footer:i.jsx($g,{}),children:i.jsxs("form",{"data-form-type":"other",className:"space-y-3",onSubmit:k=>{k.preventDefault(),v()},children:[s.map(k=>i.jsx(Te,{label:n(`fields.${k}`),htmlFor:`acc-${k}`,children:i.jsx(ao,{id:`acc-${k}`,value:a[k]??"",onChange:j=>o(C=>({...C,[k]:j}))})},k)),y&&i.jsx(Mt,{tone:"info",children:n("access.journal.folderHint")}),r.encrypted&&i.jsx(Te,{label:n("passphrase.existingLabel"),htmlFor:"acc-pass",help:n("access.journal.passphraseHelp"),children:i.jsx(ao,{id:"acc-pass",value:l,onChange:d})}),b&&i.jsx("p",{className:"text-xs text-red-600 dark:text-red-400",children:b}),i.jsx(ue,{type:"submit",variant:"primary",className:"w-full",loading:m,icon:y?i.jsx(no,{}):i.jsx(Rs,{}),disabled:s.some(k=>{var j;return!((j=a[k])!=null&&j.trim())})||r.encrypted&&!l.trim(),children:n(y?"access.reconnectFolder":"access.journal.unlock")}),i.jsx("p",{className:"text-[11px] text-surface-500",children:n("access.storedHere")})]})})}async function bie(e,t,n={}){if(await e.ready(),await t.ready(),!n.overwrite&&t.list("objects").length>0)throw new Error("The destination already holds a CRM. Pick an empty location (or confirm overwriting).");const r=Qf(la(e,n.user??null)),s=await r0(la(t,null),r,{mode:n.overwrite?"replace":"merge"}),a={};for(const[o,l]of Object.entries(r.collections??{}))a[o]=l.length;return{written:s.written,collections:a}}function xie(e,t){switch(e.backend){case"journal":return`${Pj(e.journal.connectorId,e.journal.settings,t("access.journal.localFolder"))} / ${e.journal.root||"—"}`;case"git-json":{const n=e.git;return`${n.provider==="github"?`${n.owner}/${n.repo}`:n.provider==="gitlab"?n.project:t("location.gitLocal")} @ ${n.branch} / ${n.dir||"—"}`}case"firebase":return e.firebase.projectId??"";default:return t("data.models.local.title")}}function vie(){const{t:e}=oe("setup"),{store:t,ops:n}=ps(),r=mr(),[s,a]=S.useState(null),[o,l]=S.useState(null),[d,f]=S.useState(!1),[p,m]=S.useState(!1);if(S.useEffect(()=>{const y=t;t.kind==="journal"&&y.stats&&y.stats().then(a).catch(()=>a(null))},[t,o]),!r)return null;const h=r.backend==="journal"?r.journal.encrypted:null,b=async()=>{if(await qt({title:e("settings.data.compactConfirmTitle"),description:e("settings.data.compactConfirmBody"),confirmLabel:e("settings.data.compact")})){l("compact");try{const y=await Lu(n);ge.success(e("settings.data.compactDone",{records:y.purgedRecords.length,activities:y.purgedActivities}))}catch(y){ge.error(y.message)}finally{l(null)}}},x=()=>{const y=Qf(n);rl(JSON.stringify(y,null,2)+`
1178
+ `)}function wl(e,t){if(t instanceof _n){const n=e(`setup:errors.${t.kind}`,{detail:t.detail??""});return t.detail&&!n.includes(t.detail)?`${n} — ${t.detail}`:n}return(t==null?void 0:t.message)??String(t)}const Qse=["USD","EUR","GBP","CAD","CHF","AUD","JPY","SEK","NOK","DKK","PLN","BRL","INR","SGD"];function ow(){return{model:"journal",journal:{locationId:"s3",settings:{s3Preset:"r2",endpoint:"",region:"auto",forcePathStyle:!0},root:"agentcrm",encrypted:!0,passphrase:"",confirm:"",folderName:null},git:{provider:"github",owner:"",repo:"",project:"",branch:"main",dir:"crm",apiBaseUrl:"",token:"",folderName:null},firebase:{apiKey:"",authDomain:"",projectId:"",storageBucket:"",messagingSenderId:"",appId:"",adminEmail:"",adminPassword:"",signInMethods:["password","google"],signup:"invite",allowedDomains:""},hosting:{optionId:"none",settings:{},folder:"admin",folderName:null},workspace:{name:"",currency:cE(typeof navigator<"u"?navigator.language:void 0),adminName:"",adminEmail:"",demo:!1},join:!1,existing:null}}function jo({onBack:e,nextLabel:t,nextDisabled:n,busy:r,nextIcon:s}){const{t:a}=oe("setup");return i.jsxs("div",{className:"flex items-center justify-between gap-3 border-t border-surface-100 pt-4 dark:border-surface-800",children:[e?i.jsx(ue,{variant:"ghost",onClick:e,disabled:r,children:a("common.back")}):i.jsx("span",{}),i.jsx(ue,{type:"submit",variant:"primary",disabled:n,loading:r,icon:s,children:t??a("common.continue")})]})}function c$(e){return e.state.model==="firebase"?i.jsx(nie,{...e}):e.state.model==="git-json"?i.jsx(tie,{...e}):i.jsx(eie,{...e})}const Xse={s3:i.jsx(N0,{}),github:i.jsx(nk,{}),gitlab:i.jsx(rk,{}),"local-folder":i.jsx(no,{})};function eie({state:e,update:t,onBack:n,onNext:r}){const{t:s}=oe("setup"),a=e.journal,o=ed(a.locationId),[l,d]=S.useState({status:"idle"}),[f,p]=S.useState(!1),m=(I,T=!1)=>{t({journal:{...a,...I},...T?{}:{existing:null,join:!1}}),T||d({status:"idle"})},h={...o.preset,...a.settings},b=Oj(Ff[o.id],h),x=e.existing,y=!!(x!=null&&x.exists)&&e.join,v=y?!!(x!=null&&x.encrypted):a.encrypted,k=!v||(y?!!a.passphrase.trim():t$(a.passphrase)&&a.passphrase===a.confirm),C=l.status==="ok"&&(!(x!=null&&x.exists)||e.join)&&k&&(o.id!=="local-folder"||!!a.folderName),A=async()=>{d({status:"running"});try{const I=await Tse(a);t({existing:I.existing,join:I.existing.exists}),d({status:"ok",detail:i.jsxs(i.Fragment,{children:[s("location.testOk",{detail:I.detail}),I.publicRepo&&i.jsx("span",{className:"mt-1 block text-amber-700 dark:text-amber-400",children:s("location.publicRepoEncrypted")})]})})}catch(I){d({status:"error",detail:wl(s,I)})}},_=async()=>{if(y&&v){p(!0);try{if(!await Ise(a)){d({status:"error",detail:s("errors.wrongPassphrase")});return}}catch(I){d({status:"error",detail:wl(s,I)});return}finally{p(!1)}}y&&m({encrypted:v},!0),r()},D=sw(String(h.s3Preset??"r2"));return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:I=>{I.preventDefault(),C&&_()},children:[i.jsx(ni,{hint:s("location.journalHint"),children:s("location.journalTitle")}),i.jsx(Mp,{columns:2,value:a.locationId,onChange:I=>m({locationId:I,settings:I==="s3"?{...sw("r2").settings,s3Preset:"r2"}:{...ed(I).preset},folderName:null}),choices:iw.map(I=>({id:I.id,icon:Xse[I.id],title:s(`location.options.${I.id}.title`),description:s(`location.options.${I.id}.description`),badge:I.id==="s3"?i.jsx(n$,{}):void 0}))}),o.id==="s3"&&i.jsxs("div",{className:"space-y-2",children:[i.jsx("p",{className:"text-xs font-medium text-surface-600 dark:text-surface-300",children:s("location.provider")}),i.jsx("div",{className:"flex flex-wrap gap-1.5",children:rw.map(I=>i.jsx("button",{type:"button",onClick:()=>m({settings:{...a.settings,...I.settings,s3Preset:I.id}}),className:ce("rounded-full border px-2.5 py-1 text-xs font-medium transition-colors",D.id===I.id?"border-accent-500 bg-accent-50 text-accent-700 dark:bg-accent-500/10 dark:text-accent-300":"border-surface-200 text-surface-600 hover:border-surface-300 dark:border-surface-700 dark:text-surface-300"),children:s(`location.s3Presets.${I.id}`)},I.id))}),i.jsx("p",{className:"text-xs text-surface-500",children:s(`location.s3PresetHints.${D.id}`)})]}),o.id==="local-folder"?i.jsxs("div",{className:"space-y-2",children:[i.jsx(Fj,{handleKey:"data-folder",picked:a.folderName,onPicked:I=>m({folderName:I})}),i.jsx("p",{className:"text-xs text-surface-500",children:s("location.localFolderHint")})]}):i.jsx(Lj,{idPrefix:"loc",fields:Ff[o.id],value:h,onChange:I=>m({settings:I}),placeholders:o.id==="s3"?{endpoint:D.endpointPlaceholder,region:D.regionPlaceholder}:{}}),i.jsx(Te,{label:s("location.root"),htmlFor:"loc-root",help:s("location.rootHelp"),children:i.jsx(Oe,{id:"loc-root",value:a.root,autoComplete:"off",onChange:I=>m({root:I.target.value}),placeholder:"agentcrm"})}),i.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[i.jsx(X0,{running:l.status==="running",onClick:()=>void A()}),b.length>0&&i.jsx("span",{className:"text-xs text-surface-500",children:s("location.fillRequired")})]}),i.jsx(Q0,{state:l}),(x==null?void 0:x.exists)&&i.jsxs(Mt,{tone:"info",title:s("location.existingTitle"),children:[i.jsx("p",{children:s(x.encrypted?"location.existingEncrypted":"location.existingPlain")}),i.jsxs("div",{className:"mt-2 flex flex-wrap gap-2",children:[i.jsx(ue,{size:"sm",variant:e.join?"primary":"outline",onClick:()=>t({join:!0}),children:s("location.joinExisting")}),i.jsx(ue,{size:"sm",variant:"ghost",onClick:()=>m({root:`${a.root||"agentcrm"}-2`}),children:s("location.useAnotherFolder")})]})]}),i.jsxs("div",{className:"space-y-3",children:[!y&&i.jsx(Vse,{enabled:a.encrypted,onChange:I=>m({encrypted:I},!0)}),v&&i.jsxs(i.Fragment,{children:[y?i.jsx(Te,{label:s("passphrase.existingLabel"),htmlFor:"loc-pass",help:s("passphrase.existingHelp"),children:i.jsx(ao,{id:"loc-pass",value:a.passphrase,onChange:I=>m({passphrase:I},!0)})}):i.jsx(r$,{idPrefix:"loc",passphrase:a.passphrase,confirm:a.confirm,onChange:I=>m(I,!0)}),i.jsx(Mt,{tone:"danger",title:s("passphrase.lostTitle"),children:s("passphrase.lostBody")})]}),!v&&!y&&i.jsx(Mt,{tone:"warning",children:s("passphrase.plainWarning")})]}),i.jsx(jo,{onBack:n,nextDisabled:!C,busy:f})]})}function tie({state:e,update:t,onBack:n,onNext:r}){const{t:s}=oe("setup"),a=e.git,[o,l]=S.useState({status:"idle"}),d=y=>{t({git:{...a,...y},existing:null,join:!1}),l({status:"idle"})},[f,p]=S.useState(null),m=async()=>{l({status:"running"});try{const y=await Rse(a);if(y.publicRepo){l({status:"error",detail:s("errors.publicRepo")});return}if(y.role==="viewer"&&!y.existing.exists){l({status:"error",detail:s("errors.readOnly",{detail:y.login})});return}p(y.role),t({existing:y.existing,join:y.existing.exists}),l({status:"ok",detail:s("location.gitOk",{login:y.login,role:s(`roles.${y.role}`)})})}catch(y){l({status:"error",detail:wl(s,y)})}},h=e.existing,b=o.status==="ok"&&(!(h!=null&&h.exists)||e.join),x=a.provider==="github"?Ff.github:a.provider==="gitlab"?Ff.gitlab:[];return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:y=>{y.preventDefault(),b&&r()},children:[i.jsx(ni,{hint:s("location.gitHint"),children:s("location.gitTitle")}),i.jsx(Mp,{columns:3,value:a.provider,onChange:y=>d({provider:y,folderName:null}),choices:[{id:"github",icon:i.jsx(nk,{}),title:"GitHub",description:s("location.gitGithub")},{id:"gitlab",icon:i.jsx(rk,{}),title:"GitLab",description:s("location.gitGitlab")},{id:"local",icon:i.jsx(go,{}),title:s("location.gitLocal"),description:s("location.gitLocalHint")}]}),a.provider==="local"?i.jsx(Fj,{handleKey:"git-json-folder",picked:a.folderName,onPicked:y=>d({folderName:y})}):i.jsx(Lj,{idPrefix:"git",fields:x,value:a,onChange:y=>d(y)}),i.jsx(Te,{label:s("location.gitDir"),htmlFor:"git-dir",help:s("location.gitDirHelp"),children:i.jsx(Oe,{id:"git-dir",value:a.dir,autoComplete:"off",onChange:y=>d({dir:y.target.value}),placeholder:"crm"})}),i.jsx(Mt,{tone:"warning",title:s("location.gitHistoryTitle"),children:s("location.gitHistoryBody")}),i.jsx("div",{className:"flex items-center gap-3",children:i.jsx(X0,{running:o.status==="running",onClick:()=>void m()})}),i.jsx(Q0,{state:o}),f&&i.jsx("p",{className:"text-xs text-surface-500",children:s("location.gitRoles")}),(h==null?void 0:h.exists)&&i.jsx(Mt,{tone:"info",title:s("location.existingTitle"),children:s("location.existingGit",{count:h.documents??0,name:h.name??"AgentCRM"})}),i.jsx(jo,{onBack:n,nextDisabled:!b})]})}const u_=["apiKey","authDomain","projectId","storageBucket","messagingSenderId","appId"];function nie({state:e,update:t,onBack:n,onNext:r}){var x;const{t:s}=oe("setup"),a=e.firebase,[o,l]=S.useState(""),[d,f]=S.useState({status:"idle"}),p=y=>{t({firebase:{...a,...y},existing:null,join:!1}),f({status:"idle"})},m=S.useMemo(()=>{try{return a.adminEmail.includes("@")?l$({adminEmail:a.adminEmail,signup:a.signup,allowedDomains:a.allowedDomains.split(/[\s,]+/).filter(Boolean)}):null}catch{return null}},[a.adminEmail,a.signup,a.allowedDomains]),h=async()=>{f({status:"running"});try{const y=await $se(a);return t({existing:y.existing,join:y.existing.exists,workspace:{...e.workspace,adminEmail:e.workspace.adminEmail||a.adminEmail.trim().toLowerCase()}}),f({status:"ok",detail:s("location.firebaseOk",{email:y.identity.email,role:s(`roles.${y.identity.role}`)})}),!0}catch(y){return f({status:"error",detail:wl(s,y)}),!1}},b=(y,v)=>p({signInMethods:v?[...new Set([...a.signInMethods,y])]:a.signInMethods.filter(k=>k!==y)});return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:y=>{y.preventDefault(),d.status==="ok"?r():h().then(v=>v&&r())},children:[i.jsx(ni,{hint:s("location.firebaseHint"),children:s("location.firebaseTitle")}),i.jsxs("ol",{className:"list-decimal space-y-1 pl-5 text-xs text-surface-600 dark:text-surface-300",children:[i.jsx("li",{children:s("location.firebaseSteps.project")}),i.jsx("li",{children:s("location.firebaseSteps.app")}),i.jsx("li",{children:s("location.firebaseSteps.auth")}),i.jsx("li",{children:s("location.firebaseSteps.firestore")}),i.jsx("li",{children:s("location.firebaseSteps.rules")})]}),i.jsx(Te,{label:s("location.firebaseSnippet"),htmlFor:"fb-snippet",help:s("location.firebaseSnippetHelp"),children:i.jsx(Cr,{id:"fb-snippet",rows:3,value:o,spellCheck:!1,className:"font-mono text-xs",placeholder:'const firebaseConfig = { apiKey: "…", authDomain: "…", projectId: "…", appId: "…" };',onChange:y=>{l(y.target.value);const v=Ase(y.target.value);Object.keys(v).length&&p(Object.fromEntries(u_.map(k=>[k,v[k]??a[k]])))}})}),i.jsx("div",{className:"grid gap-3 sm:grid-cols-2",children:u_.map(y=>i.jsx(Te,{label:s(`fields.${y}`),htmlFor:`fb-${y}`,children:i.jsx(Oe,{id:`fb-${y}`,value:String(a[y]),autoComplete:"off",spellCheck:!1,onChange:v=>p({[y]:v.target.value})})},y))}),i.jsx(ni,{hint:s("location.firebaseAdminHint"),children:s("location.firebaseAdmin")}),i.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[i.jsx(Te,{label:s("fields.adminEmail"),htmlFor:"fb-email",children:i.jsx(Oe,{id:"fb-email",type:"email",autoComplete:"off",value:a.adminEmail,onChange:y=>p({adminEmail:y.target.value})})}),i.jsx(Te,{label:s("fields.adminPassword"),htmlFor:"fb-password",children:i.jsx(ao,{id:"fb-password",value:a.adminPassword,onChange:y=>p({adminPassword:y})})})]}),i.jsxs("div",{className:"flex flex-wrap gap-4",children:[i.jsx(Ot,{label:s("location.methodPassword"),checked:a.signInMethods.includes("password"),onChange:y=>b("password",y.target.checked)}),i.jsx(Ot,{label:s("location.methodGoogle"),checked:a.signInMethods.includes("google"),onChange:y=>b("google",y.target.checked)})]}),i.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[i.jsx(Te,{label:s("location.signup"),htmlFor:"fb-signup",help:s(`location.signupHelp.${a.signup}`),children:i.jsx(Ve,{id:"fb-signup",value:a.signup,onChange:y=>p({signup:y.target.value}),options:["invite","domain","open"].map(y=>({value:y,label:s(`location.signupModes.${y}`)}))})}),a.signup==="domain"&&i.jsx(Te,{label:s("location.allowedDomains"),htmlFor:"fb-domains",children:i.jsx(Oe,{id:"fb-domains",value:a.allowedDomains,placeholder:"acme.com, acme.io",onChange:y=>p({allowedDomains:y.target.value})})})]}),i.jsxs("div",{className:"space-y-2",children:[i.jsx(ni,{hint:s("location.rulesHint"),children:i.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[i.jsx(yl,{className:"h-4 w-4"})," ",s("location.rulesTitle")]})}),m?i.jsxs(i.Fragment,{children:[i.jsx(rie,{rules:m}),i.jsxs("div",{className:"flex flex-wrap gap-2",children:[i.jsx(ue,{size:"sm",icon:i.jsx(En,{}),onClick:()=>rl(m,"firestore.rules"),children:"firestore.rules"}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(En,{}),onClick:()=>rl(Jse(),"firestore.indexes.json","application/json"),children:"firestore.indexes.json"}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(En,{}),onClick:()=>rl(Zse({adminEmail:a.adminEmail}),"storage.rules"),children:"storage.rules"}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(En,{}),onClick:()=>rl(Yse(),"firebase.json","application/json"),children:"firebase.json"})]})]}):i.jsx("p",{className:"text-xs text-surface-500",children:s("location.rulesNeedEmail")})]}),i.jsx("div",{className:"flex items-center gap-3",children:i.jsx(X0,{running:d.status==="running",onClick:()=>void h(),label:s("location.firebaseVerify")})}),i.jsx(Q0,{state:d}),((x=e.existing)==null?void 0:x.exists)&&i.jsx(Mt,{tone:"info",title:s("location.existingTitle"),children:s("location.existingFirebase")}),i.jsx(jo,{onBack:n,busy:d.status==="running",nextIcon:i.jsx(Rs,{})})]})}function rie({rules:e}){const{t}=oe("setup"),[n,r]=S.useState(!1);return i.jsxs("div",{className:"space-y-2",children:[i.jsx(ue,{size:"xs",variant:"ghost",icon:i.jsx(Ii,{}),onClick:()=>r(s=>!s),children:t(n?"location.rulesHide":"location.rulesShow")}),i.jsx("div",{className:ce(!n&&"hidden"),children:i.jsx(s$,{text:e})})]})}const sie={none:i.jsx(up,{}),"github-pages":i.jsx(nk,{}),"cloudflare-pages":i.jsx(N0,{}),"gitlab-pages":i.jsx(rk,{}),s3:i.jsx(G8,{}),"local-folder":i.jsx(no,{}),zip:i.jsx(X1,{})};function d$({value:e,onChange:t,onTested:n,exclude:r=[]}){const{t:s}=oe("setup"),[a,o]=S.useState({status:"idle"}),l=td(e.optionId),d=m=>{t({...e,...m}),o({status:"idle"}),n==null||n(!1)},f=async()=>{o({status:"running"});try{const m=await Ose(e);o({status:"ok",detail:s("hosting.testOk",{detail:m})}),n==null||n(!0)}catch(m){o({status:"error",detail:wl(s,m)}),n==null||n(!1)}},p={...l.preset,...e.settings};return i.jsxs("div",{className:"space-y-4",children:[i.jsx(Mp,{columns:2,value:e.optionId,onChange:m=>d({optionId:m,settings:{...td(m).preset},folderName:null}),choices:Tc.filter(m=>!r.includes(m.id)).map(m=>({id:m.id,icon:sie[m.id],title:s(`hosting.options.${m.id}.title`),description:s(`hosting.options.${m.id}.description`)}))}),e.optionId!=="none"&&e.optionId!=="zip"&&i.jsxs(i.Fragment,{children:[e.optionId==="local-folder"&&i.jsx(Fj,{handleKey:"publish-target",picked:e.folderName,onPicked:m=>d({folderName:m})}),i.jsx(Lj,{idPrefix:"host",fields:J4[e.optionId],value:p,onChange:m=>d({settings:m})}),i.jsx(Te,{label:s("hosting.folder"),htmlFor:"host-folder",help:s("hosting.folderHelp"),children:i.jsx(Oe,{id:"host-folder",value:e.folder,autoComplete:"off",onChange:m=>d({folder:m.target.value}),placeholder:"admin"})}),i.jsx(Mt,{tone:"info",title:s(`hosting.howTo.${e.optionId}.title`),children:s(`hosting.howTo.${e.optionId}.body`)}),i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(X0,{running:a.status==="running",onClick:()=>void f()}),Q4(e).length>0&&i.jsx("span",{className:"text-xs text-surface-500",children:s("location.fillRequired")})]}),i.jsx(Q0,{state:a})]}),e.optionId==="zip"&&i.jsx(Mt,{tone:"info",children:s("hosting.zipHint")}),e.optionId==="none"&&i.jsx(Mt,{tone:"info",children:s("hosting.noneHint")})]})}function iie({state:e,update:t,onBack:n,onNext:r}){const{t:s}=oe("setup"),[a,o]=S.useState(!1),l=e.hosting,f=!(l.optionId!=="none"&&l.optionId!=="zip")||a;return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:p=>{p.preventDefault(),f&&r()},children:[i.jsx(ni,{hint:s("hosting.hint"),children:s("hosting.title")}),i.jsx(Mt,{tone:"warning",title:s("hosting.securityTitle"),children:s("hosting.securityBody")}),i.jsx(d$,{value:l,onChange:p=>t({hosting:p}),onTested:o}),i.jsx(jo,{onBack:n,nextDisabled:!f,nextLabel:l.optionId==="none"?s("hosting.skip"):void 0})]})}function aie(e){return e==="local"?["terms","data","workspace","install"]:["terms","data","location","hosting","workspace","install"]}function oie(){const{t:e,i18n:t}=oe("setup"),[n,r]=S.useState(ow),[s,a]=S.useState("terms"),o=S.useCallback(p=>r(m=>({...m,...p})),[]),l=aie(n.model),d=p=>a(m=>l[Math.max(0,Math.min(l.length-1,l.indexOf(m)+p))]),f={state:n,update:o,onBack:()=>d(-1),onNext:()=>d(1)};return i.jsx("div",{className:"min-h-screen bg-surface-50 px-4 py-8 dark:bg-surface-950 sm:py-12",children:i.jsxs("div",{className:"mx-auto w-full max-w-2xl space-y-5",children:[i.jsxs("header",{className:"flex items-center justify-between gap-4",children:[i.jsxs("div",{className:"flex items-center gap-2.5",children:[i.jsx("span",{className:"inline-flex h-9 w-9 items-center justify-center rounded-lg bg-surface-900 text-white dark:bg-white dark:text-surface-900",children:i.jsx(ba,{className:"h-4 w-4"})}),i.jsxs("div",{children:[i.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-white",children:e("wizard.title")}),i.jsx("p",{className:"text-xs text-surface-500",children:e("wizard.subtitle")})]})]}),i.jsx(Ve,{"aria-label":e("wizard.language"),className:"w-32",value:jc(t.language)?t.language:"en",onChange:p=>c1(p.target.value),options:u0.map(p=>({value:p,label:o1[p]}))})]}),i.jsx(Bse,{steps:l.map(p=>({id:p,label:e(`wizard.steps.${p}`)})),current:s}),i.jsxs(Ke,{className:"p-5 sm:p-6",children:[s==="terms"&&i.jsx(lie,{onNext:()=>d(1),onQuickStart:()=>{o({model:"local",existing:null,join:!1,workspace:{...n.workspace,demo:!0}}),a("workspace")}}),s==="data"&&i.jsx(cie,{...f}),s==="location"&&i.jsx(c$,{...f}),s==="hosting"&&i.jsx(iie,{...f}),s==="workspace"&&i.jsx(die,{...f}),s==="install"&&i.jsx(uie,{...f})]})]})})}function lie({onNext:e,onQuickStart:t}){const{t:n}=oe("setup"),[r,s]=S.useState(!1);return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:a=>{a.preventDefault(),r&&e()},children:[i.jsx(ni,{hint:n("terms.hint"),children:n("terms.title")}),i.jsx("ul",{className:"space-y-2 text-sm text-surface-700 dark:text-surface-300",children:["static","yourData","secrets","gdpr","warranty"].map(a=>i.jsxs("li",{className:"flex gap-2",children:[i.jsx(to,{className:"mt-0.5 h-4 w-4 shrink-0 text-accent-600"}),i.jsx("span",{children:n(`terms.points.${a}`)})]},a))}),i.jsx(Ot,{label:n("terms.accept"),checked:r,onChange:a=>s(a.target.checked)}),i.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 rounded-lg border border-dashed border-surface-300 p-3 dark:border-surface-700",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsxs("p",{className:"flex items-center gap-1.5 text-sm font-medium",children:[i.jsx(up,{className:"h-4 w-4 text-surface-500"})," ",n("terms.quickTitle")]}),i.jsx("p",{className:"text-xs text-surface-500",children:n("terms.quickHint")})]}),i.jsx(ue,{size:"sm",disabled:!r,onClick:t,children:n("terms.quickStart")})]}),i.jsx(jo,{nextDisabled:!r,nextLabel:n("terms.start")})]})}function cie({state:e,update:t,onBack:n,onNext:r}){const{t:s}=oe("setup");return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:a=>{a.preventDefault(),r()},children:[i.jsx(ni,{hint:s("data.hint"),children:s("data.title")}),i.jsx(Mp,{columns:1,value:e.model,onChange:a=>t({model:a,existing:null,join:!1}),choices:[{id:"journal",icon:i.jsx(Ii,{}),title:s("data.models.journal.title"),description:s("data.models.journal.description"),badge:i.jsx(n$,{})},{id:"firebase",icon:i.jsx(N0,{}),title:s("data.models.firebase.title"),description:s("data.models.firebase.description")},{id:"git-json",icon:i.jsx(go,{}),title:s("data.models.git-json.title"),description:s("data.models.git-json.description")},{id:"local",icon:i.jsx(up,{}),title:s("data.models.local.title"),description:s("data.models.local.description")}]}),i.jsx(Mt,{tone:"info",children:s(`data.models.${e.model}.details`)}),i.jsx(jo,{onBack:n})]})}function die({state:e,update:t,onBack:n,onNext:r}){var m;const{t:s}=oe("setup"),a=e.workspace,o=h=>t({workspace:{...a,...h}}),l=e.join&&!!((m=e.existing)!=null&&m.exists),d=/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(a.adminEmail.trim()),p=(!(e.model!=="local"||!!a.adminEmail.trim())||d)&&(l||!!a.adminName.trim()||e.model==="local");return i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:h=>{h.preventDefault(),p&&r()},children:[i.jsx(ni,{hint:s(l?"workspace.joinHint":"workspace.hint"),children:s(l?"workspace.joinTitle":"workspace.title")}),!l&&i.jsxs("div",{className:"grid gap-3 sm:grid-cols-[1fr_9rem]",children:[i.jsx(Te,{label:s("workspace.name"),htmlFor:"ws-name",children:i.jsx(Oe,{id:"ws-name",value:a.name,placeholder:"Acme CRM",autoComplete:"off",onChange:h=>o({name:h.target.value})})}),i.jsx(Te,{label:s("workspace.currency"),htmlFor:"ws-currency",children:i.jsx(Ve,{id:"ws-currency",value:a.currency,onChange:h=>o({currency:h.target.value}),options:Qse.map(h=>({value:h,label:h}))})})]}),i.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[i.jsx(Te,{label:s("workspace.adminName"),htmlFor:"ws-admin-name",children:i.jsx(Oe,{id:"ws-admin-name",value:a.adminName,autoComplete:"off",onChange:h=>o({adminName:h.target.value})})}),i.jsx(Te,{label:s("workspace.adminEmail"),htmlFor:"ws-admin-email",help:e.model==="git-json"?s("workspace.gitEmailHelp"):void 0,children:i.jsx(Oe,{id:"ws-admin-email",type:"email",value:a.adminEmail,autoComplete:"off",onChange:h=>o({adminEmail:h.target.value})})})]}),!l&&i.jsx(Ot,{label:s("workspace.demo"),checked:a.demo,onChange:h=>o({demo:h.target.checked})}),i.jsx(jo,{onBack:n,nextDisabled:!p})]})}function uie({state:e,onBack:t}){var y;const{t:n}=oe("setup"),r=xd(),[s,a]=S.useState([]),[o,l]=S.useState(!1),[d,f]=S.useState(null),[p,m]=S.useState(null),h=e.join&&!!((y=e.existing)!=null&&y.exists),b=S.useMemo(()=>{const v=[[n("install.summary.model"),n(`data.models.${e.model}.title`)]];if(e.model==="journal"){const k=ed(e.journal.locationId);v.push([n("install.summary.location"),`${Pj(k.connectorId,{...k.preset,...e.journal.settings},n("access.journal.localFolder"))} / ${e.journal.root||"—"}`]),v.push([n("install.summary.encryption"),e.journal.encrypted?n("install.summary.encrypted"):n("install.summary.notEncrypted")])}if(e.model==="git-json"){const k=e.git;v.push([n("install.summary.location"),`${k.provider==="github"?`${k.owner}/${k.repo}`:k.provider==="gitlab"?k.project:n("location.gitLocal")} @ ${k.branch} / ${k.dir||"—"}`])}return e.model==="firebase"&&v.push([n("install.summary.location"),e.firebase.projectId]),e.model!=="local"&&v.push([n("install.summary.hosting"),n(`hosting.options.${td(e.hosting.optionId).id}.title`)]),v.push([n("install.summary.mode"),h?n("install.summary.join"):e.workspace.demo?n("install.summary.createDemo"):n("install.summary.create")]),e.workspace.adminEmail&&v.push([n("install.summary.admin"),`${e.workspace.adminName} <${e.workspace.adminEmail}>`]),v},[e,h,n]),x=async()=>{l(!0),f(null),a([]);const v={step:(k,j)=>a(C=>{const A=`${n(`install.steps.${k}`)}${j?` ${j}`:""}`,_=C.findIndex(I=>I.id===k);if(_===-1)return[...C,{id:k,label:A,status:"running"}];const D=[...C];return D[_]={...D[_],label:A,status:"running"},D}),done:k=>a(j=>j.map(C=>C.id===k?{...C,label:n(`install.steps.${k}`),status:"done"}:C))};try{const k=await Lse({model:e.model,journal:e.journal,git:e.git,firebase:e.firebase,hosting:e.hosting,workspace:{...e.workspace,locale:xt.language},join:h},v);m(k)}catch(k){a(j=>j.map(C=>C.status==="running"?{...C,status:"error"}:C)),f(wl(n,k))}finally{l(!1)}};return p?i.jsxs("div",{className:"space-y-5",children:[i.jsxs("div",{className:"flex items-center gap-3",children:[i.jsx(to,{className:"h-8 w-8 text-emerald-600"}),i.jsxs("div",{children:[i.jsx("h2",{className:"text-base font-semibold",children:n("install.doneTitle")}),i.jsx("p",{className:"text-sm text-surface-500",children:n("install.doneHint")})]})]}),p.adminUrl&&i.jsx(Mt,{tone:"success",title:n("install.adminDeployed"),children:i.jsxs("a",{className:"inline-flex items-center gap-1 font-medium underline",href:p.adminUrl,target:"_blank",rel:"noreferrer",children:[p.adminUrl," ",i.jsx(ho,{className:"h-3 w-3"})]})}),p.zipDownloaded&&i.jsx(Mt,{tone:"success",children:n("install.zipDone")}),p.runtime.backend!=="local"&&!p.adminUrl&&i.jsxs(Mt,{tone:"info",title:n("install.configJsTitle"),children:[i.jsx("p",{children:n("install.configJsBody")}),i.jsx(ue,{size:"sm",className:"mt-2",icon:i.jsx(En,{}),onClick:()=>W4(p.runtime),children:"config.js"})]}),i.jsx("div",{className:"flex justify-end",children:i.jsx(ue,{variant:"primary",icon:i.jsx(pg,{}),onClick:()=>r.reconfigure(),children:n("install.open")})})]}):i.jsxs("form",{"data-form-type":"other",className:"space-y-5",onSubmit:v=>{v.preventDefault(),o||x()},children:[i.jsx(ni,{hint:n(e.model==="firebase"?"install.hintFirebase":"install.hint"),children:n("install.title")}),i.jsx("dl",{className:"divide-y divide-surface-100 rounded-lg border border-surface-200 text-sm dark:divide-surface-800 dark:border-surface-800",children:b.map(([v,k])=>i.jsxs("div",{className:"flex gap-4 px-3 py-2",children:[i.jsx("dt",{className:"w-36 shrink-0 text-surface-500",children:v}),i.jsx("dd",{className:"min-w-0 break-words font-medium text-surface-900 dark:text-surface-100",children:k})]},v))}),s.length>0&&i.jsx("ul",{className:"space-y-1.5 rounded-lg bg-surface-50 p-3 text-xs dark:bg-surface-950","aria-live":"polite",children:s.map(v=>i.jsxs("li",{className:"flex items-center gap-2",children:[i.jsxs("span",{className:ce("inline-flex [&>svg]:h-3.5 [&>svg]:w-3.5",v.status==="done"&&"text-emerald-600",v.status==="error"&&"text-red-600",v.status==="running"&&"text-surface-500"),children:[i.jsx("span",{className:ce("inline-flex",v.status!=="running"&&"hidden"),children:i.jsx(lk,{className:"animate-spin"})}),i.jsx("span",{className:ce("inline-flex",v.status!=="done"&&"hidden"),children:i.jsx(to,{})}),i.jsx("span",{className:ce("inline-flex",v.status!=="error"&&"hidden"),children:i.jsx(C0,{})})]}),i.jsx("span",{children:v.label})]},v.id))}),d&&i.jsx(Mt,{tone:"danger",title:n("install.failed"),children:d}),i.jsx(jo,{onBack:o?void 0:t,busy:o,nextLabel:n(d?"install.retry":"install.run"),nextIcon:i.jsx(pg,{})})]})}function fie({onSignedIn:e}){const t=mr();return(t==null?void 0:t.backend)==="firebase"?i.jsx(mie,{config:t,onSignedIn:e}):(t==null?void 0:t.backend)==="git-json"?i.jsx(gie,{config:t,onSignedIn:e}):(t==null?void 0:t.backend)==="journal"?i.jsx(yie,{config:t,onSignedIn:e}):i.jsx(nd,{title:"AgentCRM",icon:i.jsx(jv,{})})}function nd({title:e,hint:t,icon:n,children:r,footer:s}){return i.jsx("div",{className:"flex min-h-screen items-center justify-center bg-surface-50 p-4 dark:bg-surface-950",children:i.jsxs("div",{className:"w-full max-w-sm space-y-3",children:[i.jsxs(Ke,{className:"p-5",children:[i.jsxs("div",{className:"mb-4 flex items-start gap-3",children:[i.jsx("span",{className:"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-surface-900 text-white dark:bg-white dark:text-surface-900 [&>svg]:h-4 [&>svg]:w-4",children:n}),i.jsxs("div",{className:"min-w-0",children:[i.jsx("h1",{className:"text-base font-semibold text-surface-900 dark:text-white",children:e}),t&&i.jsx("p",{className:"mt-0.5 text-xs text-surface-500",children:t})]})]}),r]}),s]})})}function $g(){const{t:e}=oe("setup"),t=xd();return i.jsx("div",{className:"text-center",children:i.jsx("button",{type:"button",className:"text-xs text-surface-500 underline-offset-2 hover:underline",onClick:()=>{ld(null),t.reconfigure()},children:e("access.otherCrm")})})}function pie(e){const t=(e==null?void 0:e.code)??"";return`access.firebaseErrors.${{"auth/invalid-email":"invalidEmail","auth/invalid-credential":"invalidCredentials","auth/wrong-password":"invalidCredentials","auth/user-not-found":"invalidCredentials","auth/too-many-requests":"tooManyRequests","auth/user-disabled":"userDisabled","auth/network-request-failed":"network","auth/popup-closed-by-user":"popupClosed","auth/cancelled-popup-request":"popupClosed","auth/popup-blocked":"popupBlocked","auth/unauthorized-domain":"unauthorizedDomain","auth/operation-not-allowed":"methodDisabled"}[t]??"generic"}`}function mie({config:e,onSignedIn:t}){var k;const{t:n}=oe("setup"),[r,s]=S.useState(""),[a,o]=S.useState(""),[l,d]=S.useState(null),[f,p]=S.useState(null),[m,h]=S.useState(null),b=(k=e.signInMethods)!=null&&k.length?e.signInMethods:["password"];S.useEffect(()=>{let j=!1;return(async()=>{const{isFirebaseStore:C}=await Sr(async()=>{const{isFirebaseStore:_}=await import("./firebase-U38f5kc9.js");return{isFirebaseStore:_}},[],import.meta.url),A=await Dv().catch(()=>null);if(!j&&A&&C(A)){const _=A.accessError();_&&h({reason:_.reason,email:_.email})}})(),()=>{j=!0}},[]);const x=async()=>(await Sr(async()=>{const{firebaseApiFor:j}=await import("./firebase-U38f5kc9.js");return{firebaseApiFor:j}},[],import.meta.url)).firebaseApiFor(e),y=async()=>{const{isFirebaseStore:j}=await Sr(async()=>{const{isFirebaseStore:A}=await import("./firebase-U38f5kc9.js");return{isFirebaseStore:A}},[],import.meta.url),C=await Dv().catch(()=>null);if(C&&j(C)&&(C.resetSession(),!await C.identity())){const _=C.accessError();h(_?{reason:_.reason,email:_.email}:null);return}t()},v=async(j,C)=>{d(j),p(null);try{await C()}catch(A){p(n(pie(A)))}finally{d(null)}};return m?i.jsx(nd,{title:n(`access.firebase.${m.reason}Title`),hint:m.email,icon:i.jsx(aa,{}),footer:i.jsx($g,{}),children:i.jsxs("div",{className:"space-y-3",children:[i.jsx("p",{className:"text-sm text-surface-600 dark:text-surface-300",children:n(`access.firebase.${m.reason}Body`)}),f&&i.jsx("p",{className:"text-xs text-red-600",children:f}),i.jsxs("div",{className:"flex flex-wrap gap-2",children:[m.reason==="unverified"&&i.jsxs(i.Fragment,{children:[i.jsx(ue,{size:"sm",variant:"primary",icon:i.jsx(Vc,{}),loading:l==="verify",onClick:()=>void v("verify",async()=>{await(await x()).auth.reload(),await y()}),children:n("access.firebase.verified")}),i.jsx(ue,{size:"sm",icon:i.jsx(aa,{}),onClick:()=>void v("reset",async()=>{await(await x()).auth.sendVerificationEmail(),ge.success(n("access.firebase.verificationSent"))}),children:n("access.firebase.resend")})]}),i.jsx(ue,{size:"sm",variant:"ghost",icon:i.jsx(_0,{}),loading:l==="signOut",onClick:()=>void v("signOut",async()=>{await(await x()).auth.signOut(),h(null)}),children:n("access.signOut")})]})]})}):i.jsx(nd,{title:n("access.firebase.title",{name:e.name??"AgentCRM"}),hint:n("access.firebase.hint"),icon:i.jsx(wN,{}),footer:i.jsx($g,{}),children:i.jsxs("div",{className:"space-y-4",children:[b.includes("google")&&i.jsx(ue,{className:"w-full",icon:i.jsx(hie,{}),loading:l==="google",disabled:!!l,onClick:()=>void v("google",async()=>{await(await x()).auth.signInWithGoogle(),await y()}),children:n("access.firebase.google")}),b.includes("google")&&b.includes("password")&&i.jsxs("div",{className:"flex items-center gap-2 text-[11px] uppercase tracking-wide text-surface-400",children:[i.jsx("span",{className:"h-px flex-1 bg-surface-200 dark:bg-surface-800"})," ",n("access.or")," ",i.jsx("span",{className:"h-px flex-1 bg-surface-200 dark:bg-surface-800"})]}),b.includes("password")&&i.jsxs("form",{"data-form-type":"other",className:"space-y-3",onSubmit:j=>{j.preventDefault(),v("password",async()=>{await(await x()).auth.signInWithPassword(r,a),await y()})},children:[i.jsx(Te,{label:n("access.email"),htmlFor:"fb-login-email",children:i.jsx(Oe,{id:"fb-login-email",type:"email",autoComplete:"username",value:r,onChange:j=>s(j.target.value)})}),i.jsx(Te,{label:n("access.password"),htmlFor:"fb-login-password",children:i.jsx(Oe,{id:"fb-login-password",type:"password",autoComplete:"current-password",value:a,onChange:j=>o(j.target.value)})}),f&&i.jsx("p",{className:"text-xs text-red-600 dark:text-red-400",children:f}),i.jsx(ue,{type:"submit",variant:"primary",className:"w-full",icon:i.jsx(wN,{}),loading:l==="password",disabled:!!l||!r||!a,children:n("access.signIn")}),i.jsx("button",{type:"button",className:"text-xs text-surface-500 hover:underline",disabled:!!l,onClick:()=>{if(!r.trim())return p(n("access.firebase.resetNeedsEmail"));v("reset",async()=>{await(await x()).auth.sendPasswordReset(r),ge.success(n("access.firebase.resetSent",{email:r}))})},children:n("access.firebase.forgot")})]}),!b.includes("password")&&f&&i.jsx("p",{className:"text-xs text-red-600 dark:text-red-400",children:f})]})})}function hie(){return i.jsx("svg",{viewBox:"0 0 24 24","aria-hidden":"true",children:i.jsx("path",{fill:"#EA4335",d:"M12 10.2v3.9h5.5c-.2 1.3-1.6 3.9-5.5 3.9-3.3 0-6-2.7-6-6.1s2.7-6.1 6-6.1c1.9 0 3.1.8 3.8 1.5l2.6-2.5C16.8 3.3 14.6 2.3 12 2.3 6.6 2.3 2.3 6.6 2.3 12s4.3 9.7 9.7 9.7c5.6 0 9.3-3.9 9.3-9.5 0-.6-.1-1.1-.2-1.6H12z"})})}function gie({config:e,onSignedIn:t}){const{t:n}=oe("setup"),r=e.git,[s,a]=S.useState(""),[o,l]=S.useState(""),[d,f]=S.useState(!1),[p,m]=S.useState(null),h=r.provider==="github"?`${r.owner}/${r.repo}`:r.provider==="gitlab"?r.project??"":n("location.gitLocal");S.useEffect(()=>{Sr(()=>import("./gitJson-wy2Tytfd.js"),[],import.meta.url).then(x=>l(x.getGitUserEmail(e)??""))},[e]);const b=async()=>{f(!0),m(null);try{const x=await Sr(()=>import("./gitJson-wy2Tytfd.js"),[],import.meta.url);if(r.provider==="local"){let y=await O0(x.LOCAL_GIT_HANDLE_KEY);if(y||(y=await Fk(),await zk(x.LOCAL_GIT_HANDLE_KEY,y)),!await wp(y,!0))throw new Error(n("access.folderDenied"))}else{const y=await x.openGitJsonTransport(r,s.trim());if(!y)throw new Error(n("access.git.tokenRequired"));if(!await y.permissions().catch(()=>null))throw new Error(n("access.git.invalidToken"));x.setGitToken(r,s.trim())}x.setGitUserEmail(e,o),jp(),t()}catch(x){x.name!=="AbortError"&&m(x.message)}finally{f(!1)}};return i.jsx(nd,{title:n("access.git.title"),hint:n("access.git.hint",{repo:h}),icon:i.jsx(Rs,{}),footer:i.jsx($g,{}),children:i.jsxs("form",{"data-form-type":"other",className:"space-y-3",onSubmit:x=>{x.preventDefault(),b()},children:[r.provider!=="local"&&i.jsx(Te,{label:n("access.git.token"),htmlFor:"git-token",help:n(r.provider==="github"?"access.git.githubTokenHelp":"access.git.gitlabTokenHelp"),children:i.jsx(ao,{id:"git-token",value:s,onChange:a})}),i.jsx(Te,{label:n("access.git.email"),htmlFor:"git-email",help:n("access.git.emailHelp"),children:i.jsx(Oe,{id:"git-email",type:"email",autoComplete:"off",value:o,onChange:x=>l(x.target.value)})}),p&&i.jsx("p",{className:"text-xs text-red-600 dark:text-red-400",children:p}),i.jsx(ue,{type:"submit",variant:"primary",className:"w-full",loading:d,disabled:r.provider!=="local"&&!s.trim(),icon:r.provider==="local"?i.jsx(no,{}):i.jsx(Rs,{}),children:r.provider==="local"?n("access.reconnectFolder"):n("access.git.connect")}),i.jsx("p",{className:"text-[11px] text-surface-500",children:n("access.storedHere")})]})})}function yie({config:e,onSignedIn:t}){const{t:n}=oe("setup"),r=e.journal,s=jR[r.connectorId]??[],[a,o]=S.useState(()=>{const k=pl(e);return Object.fromEntries(s.map(j=>[j,typeof k[j]=="string"?k[j]:""]))}),[l,d]=S.useState(Zf(e)??""),[f,p]=S.useState(null),[m,h]=S.useState(!1),[b,x]=S.useState(null);S.useEffect(()=>{SR(r.connectorId,{...r.settings,...pl(e)}).then(p)},[e,r]);const y=r.connectorId==="local-folder",v=async()=>{h(!0),x(null);try{if(y){const A=typeof r.settings.handleKey=="string"&&r.settings.handleKey?r.settings.handleKey:"data-folder";let _=await O0(A);if(_||(_=await Fk(),await zk(A,_)),!await wp(_,!0))throw new Error(n("access.folderDenied"))}const k=Object.fromEntries(Object.entries(a).map(([A,_])=>[A,_.trim()]).filter(([,A])=>A)),j=ko(r.connectorId,{...r.settings,...k}),C=await Xk(j,r.root,l.trim()||null);if(!C.exists)throw new Error(n("access.journal.noDataset"));if(C.encrypted&&!C.ok)throw new Error(n("access.journal.wrongPassphrase"));Xg(e,Object.keys(k).length?k:null),cd(e,C.encrypted?l.trim():null),jp(),t()}catch(k){k.name!=="AbortError"&&x(k.message)}finally{h(!1)}};return f===null?i.jsx(nd,{title:n("access.journal.title"),icon:i.jsx(jv,{}),children:i.jsx(Ds,{})}):i.jsx(nd,{title:n("access.journal.title"),hint:n(r.connectorId==="local-folder"?"access.journal.hintFolder":"access.journal.hint",{location:`${Pj(r.connectorId,r.settings,n("access.journal.localFolder"))} / ${r.root}`}),icon:i.jsx(jv,{}),footer:i.jsx($g,{}),children:i.jsxs("form",{"data-form-type":"other",className:"space-y-3",onSubmit:k=>{k.preventDefault(),v()},children:[s.map(k=>i.jsx(Te,{label:n(`fields.${k}`),htmlFor:`acc-${k}`,children:i.jsx(ao,{id:`acc-${k}`,value:a[k]??"",onChange:j=>o(C=>({...C,[k]:j}))})},k)),y&&i.jsx(Mt,{tone:"info",children:n("access.journal.folderHint")}),r.encrypted&&i.jsx(Te,{label:n("passphrase.existingLabel"),htmlFor:"acc-pass",help:n("access.journal.passphraseHelp"),children:i.jsx(ao,{id:"acc-pass",value:l,onChange:d})}),b&&i.jsx("p",{className:"text-xs text-red-600 dark:text-red-400",children:b}),i.jsx(ue,{type:"submit",variant:"primary",className:"w-full",loading:m,icon:y?i.jsx(no,{}):i.jsx(Rs,{}),disabled:s.some(k=>{var j;return!((j=a[k])!=null&&j.trim())})||r.encrypted&&!l.trim(),children:n(y?"access.reconnectFolder":"access.journal.unlock")}),i.jsx("p",{className:"text-[11px] text-surface-500",children:n("access.storedHere")})]})})}async function bie(e,t,n={}){if(await e.ready(),await t.ready(),!n.overwrite&&t.list("objects").length>0)throw new Error("The destination already holds a CRM. Pick an empty location (or confirm overwriting).");const r=Qf(la(e,n.user??null)),s=await r0(la(t,null),r,{mode:n.overwrite?"replace":"merge"}),a={};for(const[o,l]of Object.entries(r.collections??{}))a[o]=l.length;return{written:s.written,collections:a}}function xie(e,t){switch(e.backend){case"journal":return`${Pj(e.journal.connectorId,e.journal.settings,t("access.journal.localFolder"))} / ${e.journal.root||"—"}`;case"git-json":{const n=e.git;return`${n.provider==="github"?`${n.owner}/${n.repo}`:n.provider==="gitlab"?n.project:t("location.gitLocal")} @ ${n.branch} / ${n.dir||"—"}`}case"firebase":return e.firebase.projectId??"";default:return t("data.models.local.title")}}function vie(){const{t:e}=oe("setup"),{store:t,ops:n}=ps(),r=mr(),[s,a]=S.useState(null),[o,l]=S.useState(null),[d,f]=S.useState(!1),[p,m]=S.useState(!1);if(S.useEffect(()=>{const y=t;t.kind==="journal"&&y.stats&&y.stats().then(a).catch(()=>a(null))},[t,o]),!r)return null;const h=r.backend==="journal"?r.journal.encrypted:null,b=async()=>{if(await qt({title:e("settings.data.compactConfirmTitle"),description:e("settings.data.compactConfirmBody"),confirmLabel:e("settings.data.compact")})){l("compact");try{const y=await Lu(n);ge.success(e("settings.data.compactDone",{records:y.purgedRecords.length,activities:y.purgedActivities}))}catch(y){ge.error(y.message)}finally{l(null)}}},x=()=>{const y=Qf(n);rl(JSON.stringify(y,null,2)+`
1179
1179
  `,`agentcrm-export-${new Date().toISOString().slice(0,10)}.json`,"application/json")};return i.jsxs("div",{className:"max-w-3xl space-y-5",children:[i.jsxs(Ke,{title:e("settings.data.title"),children:[i.jsxs("dl",{className:"grid gap-3 text-sm sm:grid-cols-[10rem_1fr]",children:[i.jsx("dt",{className:"text-surface-500",children:e("settings.data.backend")}),i.jsxs("dd",{className:"flex items-center gap-2 font-medium",children:[i.jsx(ba,{className:"h-4 w-4 text-surface-500"})," ",e(`data.models.${r.backend}.title`)]}),i.jsx("dt",{className:"text-surface-500",children:e("settings.data.location")}),i.jsx("dd",{className:"break-all font-mono text-xs",children:xie(r,e)}),h!==null&&i.jsxs(i.Fragment,{children:[i.jsx("dt",{className:"text-surface-500",children:e("settings.data.encryption")}),i.jsx("dd",{children:i.jsx(tt,{color:h?"green":"orange",dot:!0,children:e(h?"install.summary.encrypted":"install.summary.notEncrypted")})})]}),s&&i.jsxs(i.Fragment,{children:[i.jsx("dt",{className:"text-surface-500",children:e("settings.data.storage")}),i.jsx("dd",{className:"text-xs text-surface-600 dark:text-surface-300",children:e("settings.data.stats",{...s})})]})]}),r.backend==="git-json"&&i.jsx(Mt,{tone:"warning",className:"mt-4",children:e("location.gitHistoryBody")})]}),r.backend==="journal"&&i.jsxs(Ke,{title:e("settings.data.encryptionTitle"),children:[i.jsx("p",{className:"mb-3 text-sm text-surface-500",children:e(h?"settings.data.encryptionOnHint":"settings.data.encryptionOffHint")}),i.jsx(ue,{icon:h?i.jsx(Rs,{}):i.jsx(Ii,{}),onClick:()=>f(!0),children:e(h?"settings.data.changePassphrase":"settings.data.enableEncryption")}),i.jsx(wie,{open:d,onClose:()=>f(!1),config:r})]}),i.jsxs(Ke,{title:e("settings.data.maintenanceTitle"),children:[i.jsxs("div",{className:"space-y-4",children:[i.jsx(Dx,{title:e("settings.data.compact"),hint:e(r.backend==="journal"?"settings.data.compactHintJournal":"settings.data.compactHint"),children:i.jsx(ue,{icon:i.jsx(wv,{}),loading:o==="compact",onClick:()=>void b(),children:e("settings.data.compactNow")})}),i.jsx(Dx,{title:e("settings.data.export"),hint:e("settings.data.exportHint"),children:i.jsx(ue,{icon:i.jsx(En,{}),onClick:x,children:e("settings.data.exportJson")})}),i.jsx(Dx,{title:e("settings.data.transfer"),hint:e("settings.data.transferHint"),children:i.jsx(ue,{icon:i.jsx(vv,{}),onClick:()=>m(!0),children:e("settings.data.transferStart")})})]}),i.jsx(kie,{open:p,onClose:()=>m(!1)})]}),r.backend==="firebase"&&i.jsx(jie,{})]})}function Dx({title:e,hint:t,children:n}){return i.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[i.jsxs("div",{className:"min-w-0 max-w-lg",children:[i.jsx("p",{className:"text-sm font-medium",children:e}),i.jsx("p",{className:"text-xs text-surface-500",children:t})]}),n]})}function wie({open:e,onClose:t,config:n}){const{t:r}=oe("setup"),s=xd(),a=n.backend==="journal"&&n.journal.encrypted,[o,l]=S.useState(Zf(n)??""),[d,f]=S.useState({passphrase:"",confirm:""}),[p,m]=S.useState(!1),[h,b]=S.useState(!1),[x,y]=S.useState(null);if(n.backend!=="journal")return null;const v=(!a||!!o.trim())&&(p||t$(d.passphrase)&&d.passphrase===d.confirm),k=async()=>{b(!0),y(null);try{const j=n.journal,C=ko(j.connectorId,{...j.settings,...pl(n)}),A=p?null:d.passphrase;await aH({connector:C,root:j.root,oldPassphrase:a?o:null,newPassphrase:A});const _={...n,journal:{...j,encrypted:!!A}};cd(_,A),_.journal.encrypted!==j.encrypted&&ld(_),ge.success(r(A?"settings.data.rekeyDone":"settings.data.decryptDone")),t(),s.reconfigure()}catch(j){y(j.name==="PassphraseError"?r("errors.wrongPassphrase"):j.message)}finally{b(!1)}};return i.jsx(on,{open:e,onClose:t,dismissible:!h,title:r(a?"settings.data.changePassphrase":"settings.data.enableEncryption"),footer:i.jsxs(i.Fragment,{children:[i.jsx(ue,{variant:"ghost",onClick:t,disabled:h,children:r("common.cancel")}),i.jsx(ue,{variant:p?"danger":"primary",icon:p?i.jsx(z8,{}):i.jsx(Rs,{}),loading:h,disabled:!v,onClick:()=>void k(),children:r(p?"settings.data.disableEncryption":"settings.data.applyPassphrase")})]}),children:i.jsxs("form",{"data-form-type":"other",className:"space-y-4",onSubmit:j=>{j.preventDefault(),v&&!h&&k()},children:[i.jsx(Mt,{tone:"warning",children:r("settings.data.rekeyWarning")}),a&&i.jsx(Te,{label:r("settings.data.currentPassphrase"),htmlFor:"rk-current",children:i.jsx(Oe,{id:"rk-current",type:"password",autoComplete:"off",value:o,onChange:j=>l(j.target.value)})}),!p&&i.jsx(r$,{idPrefix:"rk",passphrase:d.passphrase,confirm:d.confirm,onChange:f}),a&&i.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[i.jsx("input",{type:"checkbox",checked:p,onChange:j=>m(j.target.checked)}),r("settings.data.disableEncryptionCheck")]}),p&&i.jsx(Mt,{tone:"danger",children:r("passphrase.plainWarning")}),!p&&i.jsx(Mt,{tone:"danger",title:r("passphrase.lostTitle"),children:r("passphrase.lostBody")}),x&&i.jsx("p",{className:"text-xs text-red-600",children:x})]})})}function kie({open:e,onClose:t}){var I,T;const{t:n}=oe("setup"),{store:r,user:s}=ps(),a=xd(),[o,l]=S.useState(()=>({...ow(),workspace:{...ow().workspace,adminEmail:s.email,adminName:s.name}})),[d,f]=S.useState("model"),[p,m]=S.useState(!1),[h,b]=S.useState(null),[x,y]=S.useState(null),[v,k]=S.useState(null),j=E=>l(P=>({...P,...E})),C=()=>{f("model"),b(null),k(null),y(null)},A=async()=>{var E,P;m(!0),b(null);try{const U={model:o.model,journal:o.journal,git:o.git,firebase:o.firebase,hosting:{optionId:"none",settings:{},folder:""},workspace:o.workspace,join:!1},{runtime:O,store:z}=await X4(U);try{const R=await bie(r,z,{user:s});k(R),y({...O,...(E=mr())!=null&&E.name?{name:mr().name}:{}}),f("done")}finally{(P=z.close)==null||P.call(z)}}catch(U){b(wl(n,U))}finally{m(!1)}},_=async()=>{if(!x)return;ld(x);const E=r.get("config","hosting");if(E!=null&&E.connectorId&&G4(E.connectorId,E.settings??{}).id!=="zip")try{const{getHostingSecrets:P}=await Sr(async()=>{const{getHostingSecrets:O}=await Promise.resolve().then(()=>WP);return{getHostingSecrets:O}},void 0,import.meta.url),U=mr();await jse({connectorId:E.connectorId,settings:{...E.settings??{},...U?P(U):{}}},E.folder??"admin",x),ge.success(n("settings.data.configJsUpdated"))}catch(P){ge.error(n("settings.data.configJsFailed",{detail:P.message}))}t(),a.reconfigure()},D=[{id:"journal",icon:i.jsx(Ii,{})},{id:"firebase",icon:i.jsx(N0,{})},{id:"git-json",icon:i.jsx(go,{})},{id:"local",icon:i.jsx(up,{})}];return i.jsxs(on,{open:e,onClose:()=>!p&&(t(),C()),dismissible:!1,size:"lg",title:n("settings.data.transfer"),description:n("settings.data.transferHint"),children:[d==="model"&&i.jsxs("form",{"data-form-type":"other",className:"space-y-4",onSubmit:E=>{E.preventDefault(),f(o.model==="local"?"confirm":"location")},children:[i.jsx(Mp,{value:o.model,onChange:E=>j({model:E,existing:null,join:!1}),choices:D.map(E=>({id:E.id,icon:E.icon,title:n(`data.models.${E.id}.title`),description:n(`data.models.${E.id}.description`)}))}),i.jsx("div",{className:"flex justify-end",children:i.jsx(ue,{type:"submit",variant:"primary",children:n("common.continue")})})]}),d==="location"&&i.jsx(c$,{state:o,update:j,onBack:()=>f("model"),onNext:()=>f("confirm")}),d==="confirm"&&i.jsxs("form",{"data-form-type":"other",className:"space-y-4",onSubmit:E=>{E.preventDefault(),p||A()},children:[((I=o.existing)==null?void 0:I.exists)&&i.jsx(Mt,{tone:"danger",children:n("settings.data.transferNotEmpty")}),i.jsx(Mt,{tone:"info",children:n("settings.data.transferExplain")}),o.model==="firebase"&&i.jsx(Mt,{tone:"warning",children:n("settings.data.transferFirebaseUsers")}),h&&i.jsx(Mt,{tone:"danger",children:h}),i.jsxs("div",{className:"flex justify-between",children:[i.jsx(ue,{variant:"ghost",onClick:()=>f(o.model==="local"?"model":"location"),disabled:p,children:n("common.back")}),i.jsx(ue,{type:"submit",variant:"primary",icon:i.jsx(vv,{}),loading:p,disabled:!!((T=o.existing)!=null&&T.exists),children:n("settings.data.transferRun")})]})]}),d==="done"&&v&&i.jsxs("div",{className:"space-y-4",children:[i.jsx(Mt,{tone:"success",title:n("settings.data.transferDone",{count:v.written}),children:n("settings.data.transferDoneHint")}),i.jsxs("div",{className:"flex justify-end gap-2",children:[i.jsx(ue,{variant:"ghost",onClick:()=>(t(),C()),children:n("settings.data.stayHere")}),i.jsx(ue,{variant:"primary",icon:i.jsx(vv,{}),onClick:()=>void _(),children:n("settings.data.switchNow")})]})]})]})}function jie(){const{t:e}=oe("setup"),{identity:t}=Oi(),[n,r]=S.useState(t.email),[s,a]=S.useState("invite"),[o,l]=S.useState("");let d=null;try{d=l$({adminEmail:n,signup:s,allowedDomains:o.split(/[\s,]+/).filter(Boolean)})}catch{d=null}return i.jsx(Ke,{title:e("settings.data.rulesTitle"),children:i.jsxs("div",{className:"space-y-3",children:[i.jsx(ni,{hint:e("settings.data.rulesHint"),children:i.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[i.jsx(yl,{className:"h-4 w-4"})," firestore.rules"]})}),i.jsxs("div",{className:"grid gap-3 sm:grid-cols-3",children:[i.jsx(Te,{label:e("fields.adminEmail"),htmlFor:"rules-email",children:i.jsx(Oe,{id:"rules-email",value:n,onChange:f=>r(f.target.value)})}),i.jsx(Te,{label:e("location.signup"),htmlFor:"rules-signup",children:i.jsx("select",{id:"rules-signup",className:"h-8 w-full rounded-md border border-surface-200 bg-white px-2 text-sm dark:border-surface-700 dark:bg-surface-900",value:s,onChange:f=>a(f.target.value),children:["invite","domain","open"].map(f=>i.jsx("option",{value:f,children:e(`location.signupModes.${f}`)},f))})}),s==="domain"&&i.jsx(Te,{label:e("location.allowedDomains"),htmlFor:"rules-domains",children:i.jsx(Oe,{id:"rules-domains",value:o,onChange:f=>l(f.target.value)})})]}),d?i.jsxs(i.Fragment,{children:[i.jsx(s$,{text:d}),i.jsx(ue,{size:"sm",icon:i.jsx(En,{}),onClick:()=>rl(d,"firestore.rules"),children:"firestore.rules"})]}):i.jsx("p",{className:"text-xs text-surface-500",children:e("location.rulesNeedEmail")})]})})}function Sie(){const{t:e}=oe("setup"),{store:t,user:n}=ps(),r=mr(),s=lp("hosting"),[a,o]=S.useState(()=>({optionId:s!=null&&s.connectorId?G4(s.connectorId,s.settings??{}).id:"none",settings:{...(s==null?void 0:s.settings)??{},...r?e0(r):{}},folder:(s==null?void 0:s.folder)??"admin",folderName:null})),[l,d]=S.useState(null),[f,p]=S.useState(null),[m,h]=S.useState(s!=null&&s.settings?B4(s.settings,s.folder??"admin"):null);if(!r)return null;const b=async()=>{d("save");try{a.optionId==="none"||a.optionId==="zip"?await df(la(t,n),"hosting",null):await aw(t,r,a,n),ge.success(e("settings.hosting.saved"))}catch(k){ge.error(k.message)}finally{d(null)}},x=async()=>{const k=Z0(a);if(k){d("deploy");try{await aw(t,r,a,n);const j=await q4(k,a.folder||"admin",r,(C,A)=>p(`${C}/${A}`));h(j.url),ge.success(e("settings.hosting.deployed",{count:j.files,version:j.version}))}catch(j){ge.error(j.message)}finally{d(null),p(null)}}},y=async()=>{d("zip");try{Mj(await V4(r,(k,j)=>p(`${k}/${j}`)),"agentcrm-admin.zip")}catch(k){ge.error(k.message)}finally{d(null),p(null)}},v=a.optionId!=="none"&&a.optionId!=="zip";return i.jsx("div",{className:"max-w-3xl space-y-5",children:i.jsx(Ke,{title:e("settings.hosting.title"),children:i.jsxs("div",{className:"space-y-4",children:[i.jsx("p",{className:"text-sm text-surface-500",children:e("hosting.hint")}),i.jsx(Mt,{tone:"warning",title:e("hosting.securityTitle"),children:e("hosting.securityBody")}),i.jsx(d$,{value:a,onChange:o}),m&&i.jsx(Mt,{tone:"success",title:e("settings.hosting.currentUrl"),children:i.jsxs("a",{href:m,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1 font-medium underline",children:[m," ",i.jsx(ho,{className:"h-3 w-3"})]})}),i.jsxs("div",{className:"flex flex-wrap items-center gap-2 border-t border-surface-100 pt-4 dark:border-surface-800",children:[i.jsx(ue,{icon:i.jsx(Ri,{}),loading:l==="save",disabled:!!l,onClick:()=>void b(),children:e("common.save")}),v&&i.jsxs(ue,{variant:"primary",icon:i.jsx(pg,{}),loading:l==="deploy",disabled:!!l,onClick:()=>void x(),children:[e("settings.hosting.deploy"),l==="deploy"&&f?` ${f}`:""]}),i.jsx(ue,{variant:"ghost",icon:i.jsx(En,{}),onClick:()=>W4(r),children:"config.js"}),i.jsxs(ue,{variant:"ghost",icon:i.jsx(X1,{}),loading:l==="zip",disabled:!!l,onClick:()=>void y(),children:[e("settings.hosting.zip"),l==="zip"&&f?` ${f}`:""]})]}),i.jsx("p",{className:"text-xs text-surface-500",children:e("settings.hosting.devNote")})]})})})}function Cie(){const{t:e}=oe("setup"),{role:t,backend:n,canSignOut:r,signOut:s,identity:a}=Oi(),o=xd(),l=mr(),d=S.useMemo(()=>{if(!l)return[];const p=[];return l.backend==="journal"&&(p.push({id:"connector",present:Object.keys(pl(l)).length>0}),l.journal.encrypted&&p.push({id:"passphrase",present:!!Zf(l)})),l.backend==="git-json"&&l.git.provider!=="local"&&p.push({id:"gitToken",present:!!Ww(l.git)}),l.backend==="firebase"&&p.push({id:"firebaseSession",present:!0}),p.push({id:"hosting",present:Object.keys(e0(l)).length>0}),p},[l]);if(!l)return null;const f=async()=>{if(!await qt({title:e("settings.security.forgetConfirmTitle"),description:e("settings.security.forgetConfirmBody"),confirmLabel:e("settings.security.forget"),danger:!0}))return;Gw(l);const p=uo(l);Qg(`gitSecrets:${p}`,null),Yf(`gitEmail:${p}`,null),n==="firebase"&&await s().catch(()=>{}),jp(),o.reconfigure()};return i.jsxs("div",{className:"max-w-3xl space-y-5",children:[i.jsx(Ke,{title:e("settings.security.roleTitle"),children:i.jsxs("div",{className:"space-y-3",children:[i.jsxs("p",{className:"flex flex-wrap items-center gap-2 text-sm",children:[i.jsx(yl,{className:"h-4 w-4 text-surface-500"}),e("settings.security.signedInAs",{email:a.email||a.displayName}),i.jsx(tt,{color:t==="admin"?"purple":t==="member"?"blue":"gray",children:e(`roles.${t}`)})]}),i.jsx("ul",{className:"grid gap-2 sm:grid-cols-3",children:["admin","member","viewer"].map(p=>i.jsxs("li",{className:ce("rounded-lg border p-3 text-xs",p===t?"border-accent-500 bg-accent-50/50 dark:bg-accent-500/10":"border-surface-200 dark:border-surface-800"),children:[i.jsx("p",{className:"mb-1 font-semibold",children:e(`roles.${p}`)}),i.jsx("p",{className:"text-surface-500",children:e(`roles.${p}Hint`)})]},p))}),i.jsx("p",{className:"text-xs text-surface-500",children:e(`settings.security.enforcement.${l.backend}`)})]})}),i.jsx(Ke,{title:e("settings.security.secretsTitle"),children:i.jsxs("div",{className:"space-y-3",children:[i.jsx("p",{className:"text-sm text-surface-500",children:e("settings.security.secretsHint")}),i.jsx("ul",{className:"space-y-1.5 text-sm",children:d.map(p=>i.jsxs("li",{className:"flex items-center gap-2",children:[i.jsxs("span",{className:ce("[&>svg]:h-4 [&>svg]:w-4",p.present?"text-emerald-600":"text-surface-300"),children:[i.jsx("span",{className:ce("inline-flex",!p.present&&"hidden"),children:i.jsx(to,{})}),i.jsx("span",{className:ce("inline-flex",p.present&&"hidden"),children:i.jsx(a8,{})})]}),e(`settings.security.secrets.${p.id}`)]},p.id))}),i.jsx(Mt,{tone:"info",children:e("settings.security.neverShared")}),i.jsxs("div",{className:"flex flex-wrap gap-2",children:[i.jsx(ue,{variant:"danger",icon:i.jsx(Rt,{}),onClick:()=>void f(),children:e("settings.security.forget")}),r&&i.jsx(ue,{icon:n==="journal"?i.jsx(Rs,{}):i.jsx(_0,{}),onClick:()=>void s(),children:e(n==="journal"?"settings.security.lock":"access.signOut")})]})]})})]})}const Nie={id:"setup",module:fs("setup"),routes:[],unconfiguredRoutes:[{path:"*",element:S.createElement(oie)}],i18n:{en:sse,fr:xse},slots:{loginScreen:fie,settingsSections:[{id:"data-backend",label:"setup:settings.sections.data",icon:ba,order:80,roles:["admin"],component:vie},{id:"admin-hosting",label:"setup:settings.sections.hosting",icon:sk,order:85,roles:["admin"],component:Sie},{id:"security",label:"setup:settings.sections.security",icon:yl,order:90,component:Cie}]}},Aie={title:"Reports"},_ie={nav:Aie},Eie={title:"Rapports"},Tie={nav:Eie};function f_(e){const t=new Date(e);return`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`}function p_(e,t=!1){const n=/^(\d{4})-(\d{2})-(\d{2})$/.exec(e);return n?new Date(Number(n[1]),Number(n[2])-1,Number(n[3])+(t?1:0)).getTime()-(t?1:0):null}function Iie(e,t,n,r){const s=new Date(t);switch(e){case"30d":return{since:t-30*Hu,until:null};case"90d":return{since:t-90*Hu,until:null};case"ytd":return{since:new Date(s.getFullYear(),0,1).getTime(),until:null};case"12m":return{since:new Date(s.getFullYear(),s.getMonth()-11,1).getTime(),until:null};case"custom":{const a=p_(n)??t-90*Hu,o=p_(r,!0);return{since:a,until:o!==null&&o<t?o:null}}}}function Rie(e,t){const n=new Date(e),r=new Date(t);return Math.max(1,Math.min(36,(r.getFullYear()-n.getFullYear())*12+r.getMonth()-n.getMonth()+1))}function Go(e,t){$0(`agentcrm-${e}-${Sc()}.csv`,kU(t))}function Jo({id:e,title:t,subtitle:n,onExport:r,children:s,className:a}){const{t:o}=oe("dashboard");return i.jsx(Ke,{"data-report":e,className:a,title:t,actions:i.jsxs(i.Fragment,{children:[n&&i.jsx("span",{className:"mr-2 hidden text-xs text-surface-500 sm:inline",children:n}),r&&i.jsx(ue,{size:"xs",variant:"ghost",icon:i.jsx(En,{}),onClick:r,"data-export":e,children:o("exportCsv")})]}),children:i.jsx("div",{className:"space-y-4",children:s})})}function $ie(){const{t:e}=oe("dashboard"),t=Xe(),n=Ge("reports.read"),r=di(),s=mt("records"),a=Ti(),o=Cf("deals"),l=ms(),d=S.useMemo(()=>o?l:[],[o,l]),f=sr({includeDisabled:!0}),p=mt("objects"),m=S.useMemo(()=>Pv(r.defaultCurrency),[r.defaultCurrency]),h=S.useMemo(()=>Pv(r.defaultCurrency,!1),[r.defaultCurrency]),[b,x]=S.useState("90d"),[y,v]=S.useState(()=>f_(t.now()-90*Hu)),[k,j]=S.useState(()=>f_(t.now())),[C,A]=S.useState(""),_=d.find(q=>q.object==="deals")??d[0],D=d.find(q=>q.id===C)??_,I=D==null?void 0:D.id,T=S.useMemo(()=>{var Ne,Le;if(!n)return null;const q=t.now(),ne=Iie(b,q,y,k),me=yA(ne.since),Se=yA(ne.until??q),Y=I?fr(()=>s0(t,{pipelineId:I})):null,ve=I?fr(()=>Cl(t,{pipelineId:I,from:ne.since,...ne.until!==null?{to:ne.until}:{}})):null,Fe=I?fr(()=>pf(t,{pipelineId:I,months:Rie(ne.since,q)})):null,Ue=(Fe==null?void 0:Fe.months.filter(Be=>Be.month>=me&&Be.month<=Se))??[],L=Ue.reduce((Be,He)=>({wonCount:Be.wonCount+He.wonCount,wonAmount:Be.wonAmount+He.wonAmount,lostCount:Be.lostCount+He.lostCount,lostAmount:Be.lostAmount+He.lostAmount}),{wonCount:0,wonAmount:0,lostCount:0,lostAmount:0}),be=L.wonCount+L.lostCount?Math.round(L.wonCount/(L.wonCount+L.lostCount)*1e3)/10:null,ie=Math.max(1,Math.ceil((q-ne.since)/Hu)),K=fr(()=>i0(t,{days:ie})),H=p.find(Be=>Be.id==="people"),ae=H==null?void 0:H.fields.find(Be=>Be.id==="leadSource"),ke=H==null?void 0:H.fields.find(Be=>Be.id==="lifecycleStage"),Ae=(((Ne=fr(()=>a0(t,{since:ne.since})))==null?void 0:Ne.sources)??[]).map(Be=>{var He,at;return{...Be,label:Be.id?Be.label:e("unknown"),color:(at=(He=ae==null?void 0:ae.options)==null?void 0:He.find(Ft=>Ft.id===Be.id))==null?void 0:at.color}}),G=((Le=fr(()=>Xw(t,{since:ne.since})))==null?void 0:Le.stages)??[],Ce=Object.fromEntries(((ke==null?void 0:ke.options)??[]).map(Be=>[Be.id,Be.color])),_e=o?fr(()=>o0(t,I?{pipelineId:I}:{})):null;return{range:ne,byStage:Y,fc:ve,wlMonths:Ue,wlTotals:L,winRate:be,activity:K,days:ie,sources:Ae,funnel:G,lifecycleColors:Ce,stale:_e}},[t,n,b,y,k,I,s,a,d,f,p,r,e,o]),E=S.useMemo(()=>new Map(f.map(q=>[q.id,q])),[f]),P=S.useMemo(()=>{const q=new Map(s.map(ne=>[ne.id,ne.object]));return ne=>q.get(ne)??"deals"},[s]);if(!T)return i.jsxs("div",{children:[i.jsx(Kr,{title:e("reportsTitle"),icon:i.jsx(bc,{})}),i.jsx(ut,{className:"py-24",icon:i.jsx(bc,{}),title:e("noAccess")})]});const{byStage:U,fc:O,wlMonths:z,wlTotals:R,winRate:V,activity:X,sources:Q,funnel:ee,stale:J}=T,se=(X==null?void 0:X.users.filter(q=>q.total>0||q.tasksOpen>0))??[],M=[{value:"30d",label:e("range.30d")},{value:"90d",label:e("range.90d")},{value:"ytd",label:e("range.ytd")},{value:"12m",label:e("range.12m")},{value:"custom",label:e("range.custom")}],F=q=>q===null?"—":`${q}%`,Z=(q,ne)=>q?ne:e("unassigned"),de=q=>{var ne;return q?((ne=E.get(q))==null?void 0:ne.name)??q:""},re=q=>q==="none"?e("noCloseDate"):bA(q);return i.jsxs("div",{children:[i.jsx(Kr,{title:e("reportsTitle"),icon:i.jsx(bc,{}),children:i.jsxs("div",{className:"mt-3 flex flex-wrap items-end gap-2","data-testid":"report-filters",children:[i.jsxs("label",{className:"flex flex-col gap-1 text-xs text-surface-500",children:[e("filters.period"),i.jsx(Ve,{className:"w-44",value:b,onChange:q=>x(q.target.value),options:M,"aria-label":e("filters.period")})]}),b==="custom"&&i.jsxs(i.Fragment,{children:[i.jsxs("label",{className:"flex flex-col gap-1 text-xs text-surface-500",children:[e("filters.from"),i.jsx(Oe,{type:"date",className:"w-40",value:y,max:k||void 0,onChange:q=>v(q.target.value),"aria-label":e("filters.from")})]}),i.jsxs("label",{className:"flex flex-col gap-1 text-xs text-surface-500",children:[e("filters.to"),i.jsx(Oe,{type:"date",className:"w-40",value:k,min:y||void 0,onChange:q=>j(q.target.value),"aria-label":e("filters.to")})]})]}),d.length>0&&i.jsxs("label",{className:"flex flex-col gap-1 text-xs text-surface-500",children:[e("filters.pipeline"),i.jsx(Ve,{className:"w-48",value:I??"",onChange:q=>A(q.target.value),options:d.map(q=>({value:q.id,label:q.name})),"aria-label":e("filters.pipeline")})]})]})}),i.jsxs("div",{className:"grid grid-cols-1 gap-4 p-4 sm:p-6 lg:grid-cols-2",children:[!D&&o&&i.jsx(Ke,{className:"lg:col-span-2",children:i.jsx(ut,{icon:i.jsx(bc,{}),title:e("noPipeline"),description:e("noPipelineHint")})}),U&&i.jsxs(Jo,{id:"pipelineByStage",title:e("byStage"),subtitle:D==null?void 0:D.name,onExport:()=>Go("pipeline-by-stage",[[e("col.stage"),e("col.kind"),e("col.count"),e("col.amount"),e("col.weighted")],...U.stages.map(q=>[q.label,q.kind,q.count,q.amount,q.weighted])]),children:[i.jsx(zR,{stages:U.stages,money:m}),i.jsx(fc,{head:[e("col.stage"),e("col.count"),e("col.amount"),e("col.weighted")],align:["left","right","right","right"],rows:U.stages.map(q=>[q.label,Nn(q.count),h(q.amount),h(Math.round(q.weighted))]),foot:[e("col.total"),Nn(U.stages.reduce((q,ne)=>q+ne.count,0)),h(U.stages.reduce((q,ne)=>q+ne.amount,0)),h(Math.round(U.stages.reduce((q,ne)=>q+ne.weighted,0)))]})]}),O&&i.jsxs(Jo,{id:"forecast",title:e("forecastByMonth"),subtitle:e("forecastHint"),onExport:()=>Go("forecast",[[e("col.month"),e("col.count"),e("col.amount"),e("col.weighted")],...O.byMonth.map(q=>[q.month,q.count,q.amount,q.weighted])]),children:[O.byMonth.length?i.jsx(NW,{months:O.byMonth,money:m}):i.jsx(na,{children:e("noData")}),i.jsx(fc,{head:[e("col.month"),e("col.count"),e("col.amount"),e("col.weighted")],align:["left","right","right","right"],rows:O.byMonth.map(q=>[re(q.month),Nn(q.count),h(q.amount),h(Math.round(q.weighted))]),foot:[e("col.total"),Nn(O.byMonth.reduce((q,ne)=>q+ne.count,0)),h(O.byMonth.reduce((q,ne)=>q+ne.amount,0)),h(Math.round(O.byMonth.reduce((q,ne)=>q+ne.weighted,0)))]})]}),D&&i.jsxs(Jo,{id:"wonLost",title:e("wonLost"),subtitle:V===null?void 0:e("winRateValue",{pct:V}),onExport:()=>Go("won-lost",[[e("col.month"),e("col.wonCount"),e("col.wonAmount"),e("col.lostCount"),e("col.lostAmount"),e("col.winRate")],...z.map(q=>[q.month,q.wonCount,q.wonAmount,q.lostCount,q.lostAmount,q.winRate??""])]),children:[i.jsx(UR,{months:z,money:m}),i.jsx(fc,{head:[e("col.month"),e("col.wonCount"),e("col.wonAmount"),e("col.lostCount"),e("col.lostAmount"),e("col.winRate")],align:["left","right","right","right","right","right"],rows:z.map(q=>[bA(q.month),Nn(q.wonCount),h(q.wonAmount),Nn(q.lostCount),h(q.lostAmount),F(q.winRate)]),foot:[e("col.total"),Nn(R.wonCount),h(R.wonAmount),Nn(R.lostCount),h(R.lostAmount),F(V)]})]}),i.jsxs(Jo,{id:"activityByUser",title:e("activityByUser"),subtitle:e("lastDays",{count:T.days}),onExport:()=>Go("activity-by-user",[[e("col.user"),...Xs.map(q=>e(`activityTypes.${q}`)),e("col.total"),e("col.tasksDone"),e("col.tasksOpen")],...se.map(q=>[Z(q.userId,q.name),...Xs.map(ne=>q.byType[ne]),q.total,q.tasksDone,q.tasksOpen])]),children:[se.length?i.jsx(HR,{users:se}):i.jsx(na,{children:e("noData")}),i.jsx(fc,{head:[e("col.user"),...Xs.map(q=>e(`activityTypes.${q}`)),e("col.total"),e("col.tasksDone"),e("col.tasksOpen")],align:["left",...Xs.map(()=>"right"),"right","right","right"],rows:se.map(q=>[Z(q.userId,q.name),...Xs.map(ne=>Nn(q.byType[ne])),Nn(q.total),Nn(q.tasksDone),Nn(q.tasksOpen)])})]}),i.jsxs(Jo,{id:"leadSources",title:e("leadSources"),onExport:()=>Go("lead-sources",[[e("col.source"),e("col.people"),e("col.customers"),e("col.customerRate")],...Q.map(q=>[q.label,q.count,q.customers,q.count?Math.round(q.customers/q.count*1e3)/10:""])]),children:[Q.length?i.jsx(BR,{sources:Q}):i.jsx(na,{children:e("noData")}),i.jsx(fc,{head:[e("col.source"),e("col.people"),e("col.customers"),e("col.customerRate")],align:["left","right","right","right"],rows:Q.map(q=>[q.label,Nn(q.count),Nn(q.customers),F(q.count?Math.round(q.customers/q.count*1e3)/10:null)])})]}),i.jsxs(Jo,{id:"conversion",title:e("conversion"),onExport:()=>Go("conversion",[[e("col.stage"),e("col.count"),e("col.reached"),e("col.conversion")],...ee.map(q=>[q.label,q.count,q.reached,q.conversionFromPrevious??""])]),children:[ee.some(q=>q.reached>0)?i.jsx(wW,{stages:ee,colors:T.lifecycleColors}):i.jsx(na,{children:e("noData")}),i.jsx(fc,{head:[e("col.stage"),e("col.count"),e("col.reached"),e("col.conversion")],align:["left","right","right","right"],rows:ee.map(q=>[q.label,Nn(q.count),Nn(q.reached),F(q.conversionFromPrevious)])})]}),J&&i.jsxs(Jo,{id:"staleDeals",title:e("staleDeals"),subtitle:e("idleFor",{count:J.days}),onExport:()=>Go("stale-deals",[[e("col.deal"),e("col.stage"),e("col.amount"),e("col.owner"),e("col.idleDays"),e("col.lastActivity")],...J.deals.map(q=>[q.label,q.stage,q.amount,de(q.ownerId),q.idleDays,q.lastActivityAt?new Date(q.lastActivityAt).toISOString():""])]),children:[J.deals.length?i.jsx(qR,{deals:J.deals.slice(0,50),users:E,objectOf:P,money:m}):i.jsx(na,{children:e("noStaleDeals")}),J.deals.length>50&&i.jsx("div",{className:"text-xs text-surface-500",children:e("moreRows",{count:J.deals.length-50})})]})]})]})}const Die={id:"reports",module:fs("reports"),routes:[{path:"/reports",element:S.createElement($ie)}],navItems:[{id:"reports",label:"reports:nav.title",icon:bc,to:"/reports",section:"workspace",order:30}],i18n:{en:_ie,fr:Tie}},Mie="Deals & pipelines",Oie={title:Mie},Pie="Affaires et pipelines",Lie={title:Pie},Fie={id:"deals",module:fs("deals"),routes:[],i18n:{en:Oie,fr:Lie}},zie={modules:"Modules",appearance:"Appearance"},Uie="Only admins can change this. You see the current workspace settings.",Bie={title:"Modules",description:"Switch features on or off for the whole workspace. Disabling a module hides its pages, navigation and widgets — its data is kept.",tabs:{modules:"Modules",extensions:"Installed extensions"},categories:{core:"Core",sales:"Sales",productivity:"Productivity",automation:"Automation",integrations:"Integrations",ai:"AI",customisation:"Customisation"},required:"Required",extension:"Extension",requires:"Requires {{list}}",usedBy:"Used by {{list}}",missing:"Needs {{list}} — enable it first.",settings:"Settings",enable:"Enable {{name}}",disable:"Disable {{name}}",enabled:"“{{name}}” enabled.",disabled:"“{{name}}” disabled — its data is kept.",cascadeDisableTitle:"Disable dependent modules too?",cascadeDisableBody:"{{list}} depend on “{{name}}”. They will be disabled as well.",cascadeEnableTitle:"Enable required modules too?",cascadeEnableBody:"“{{name}}” needs {{list}}. They will be enabled as well.",cascadeConfirm:"Continue",incompatible:"This version targets an unsupported API — install an update.",docs:"Create your own module",docsHint:"Modules are ZIP packages built with the AgentCRM runtime API — see the guide.",back:"All modules",noSettings:"This module has no settings page.",notLoaded:"This module isn't loaded (disabled, safe mode or failed to load).",catalog:{records:{name:"Records",description:"Objects, records, table & kanban views and record pages."},search:{name:"Search",description:"⌘K command palette over records and navigation."},settings:{name:"Settings",description:"Workspace settings, data model, users, import and export."},setup:{name:"Setup & access",description:"Setup wizard, sign-in, data backend, admin hosting and security."},dashboard:{name:"Dashboard",description:"Home dashboard with KPIs, charts and widgets."},deals:{name:"Deals & pipelines",description:"The deals object, pipelines, kanban board, pipeline reports and dashboard widgets."},reports:{name:"Reports",description:"Pipeline, forecast, won / lost, activity and lead source reports with CSV export."},forms:{name:"Lead forms",description:"Static lead capture forms and inbox ingestion."},tasks:{name:"Tasks",description:"The tasks page and task overlays."},automations:{name:"Automations",description:"Trigger → conditions → actions workflows and their run log."},integrations:{name:"Email & calendar",description:"Gmail, Google Calendar and Outlook sync through browser OAuth."},assistant:{name:"AI assistant",description:"Chat panel driving the CRM with your own Claude API key."},customize:{name:"Customisation",description:"Modules, extensions and appearance."}}},Hie={title:"Installed extensions",description:"External modules and themes, stored in your workspace data (encrypted with it) and loaded in every admin.",drop:"Drop an extension ZIP here, or click to choose a file",dropHint:"manifest.json + bundle.js (+ style.css) · up to 4 MB",reading:"Reading the package…",empty:"No extension installed yet.",kind:{module:"Module",theme:"Theme"},status:{loaded:"Running",error:"Failed to load",disabled:"Disabled",skipped:"Skipped (safe mode)",incompatible:"Incompatible",pending:"Not loaded yet"},by:"by {{author}}",installedOn:"Installed {{date}}",upgradedFrom:"Upgraded from {{version}}",export:"Export ZIP",uninstall:"Uninstall",uninstallTitle:"Uninstall “{{name}}”?",uninstallBody:"Its code is removed from the workspace for everyone. Data it created and its settings are kept.",uninstalled:"“{{name}}” uninstalled.",enabledToast:"“{{name}}” enabled.",disabledToast:"“{{name}}” disabled.",safeMode:"Safe mode is on: extensions are not loaded in this tab.",install:{title:"Install an extension",upgradeTitle:"Upgrade an extension",id:"Id",version:"Version",kind:"Type",author:"Author",homepage:"Homepage",api:"API version",size:"Size",dependsOn:"Requires",upgrade:"Upgrade {{from}} → {{to}}",reinstall:"Reinstall {{version}}",warningTitle:"This code will run with your rights",warning:"An extension can read and change every record of this workspace, for every user who opens the admin. Only install packages from people you trust.",trust:"I trust the author of “{{name}}”",confirm:"Install",confirmUpgrade:"Upgrade",done:"“{{name}}” {{version}} installed.",upgraded:"“{{name}}” upgraded to {{version}}.",invalid:"This package can't be installed"}},qie={title:"Appearance",description:"Colors, shape and branding of the workspace. Changes apply live for everyone.",presets:"Presets",themes:"Themes from extensions",themeNotLoaded:"Not loaded",custom:"Custom",accent:"Accent color",accentHint:"A full color scale is generated from it.",hex:"Hex",neutral:"Neutral tone",neutrals:{zinc:"Zinc",slate:"Slate",stone:"Stone",gray:"Gray",neutral:"Neutral"},radius:"Corner radius",radii:{none:"None",sm:"Small",md:"Medium",lg:"Large",xl:"Extra large"},density:"Density",densities:{compact:"Compact",comfortable:"Comfortable"},font:"Font",fontHint:"Google fonts are loaded from fonts.googleapis.com when selected.",sidebar:"Sidebar",sidebars:{default:"Light",dark:"Dark",accent:"Accent"},buttons:"Primary buttons",buttonStyles:{neutral:"Neutral",accent:"Accent"},mode:"Default mode",modeHint:"For users who never switched light / dark themselves.",modes:{system:"System",light:"Light",dark:"Dark"},contrast:"High contrast",contrastHint:"Stronger borders and secondary text.",branding:"Branding",logo:"Logo",favicon:"Favicon",upload:"Upload",remove:"Remove",imageHint:"PNG, SVG, JPEG, WebP or ICO · up to 200 KB",imageTooLarge:"The image is larger than 200 KB.",customCss:"Custom CSS",customCssHint:"Appended after every other style, for every user. Prefer CSS variables (--acc-500, --srf-100…).",save:"Save",saved:"Appearance updated.",reset:"Reset to default",resetTitle:"Reset the appearance?",resetBody:"Colors, shape, font and custom CSS go back to the defaults. The logo and favicon are kept.",preview:"Preview",previewSample:{title:"Acme Corp",search:"Search…",primary:"New deal",secondary:"Filter",row1:"Globex",row2:"Initech",row3:"Umbrella",badge:"Qualified",link:"View all"}},Vie={sections:zie,readOnly:Uie,modules:Bie,extensions:Hie,appearance:qie},Wie={modules:"Modules",appearance:"Apparence"},Kie="Seuls les administrateurs peuvent modifier ceci. Vous voyez les réglages actuels de l'espace.",Gie={title:"Modules",description:"Activez ou désactivez des fonctionnalités pour tout l'espace. Désactiver un module masque ses pages, sa navigation et ses widgets — ses données sont conservées.",tabs:{modules:"Modules",extensions:"Extensions installées"},categories:{core:"Socle",sales:"Ventes",productivity:"Productivité",automation:"Automatisation",integrations:"Intégrations",ai:"IA",customisation:"Personnalisation"},required:"Obligatoire",extension:"Extension",requires:"Nécessite {{list}}",usedBy:"Utilisé par {{list}}",missing:"Nécessite {{list}} — activez-le d'abord.",settings:"Réglages",enable:"Activer {{name}}",disable:"Désactiver {{name}}",enabled:"« {{name}} » activé.",disabled:"« {{name}} » désactivé — ses données sont conservées.",cascadeDisableTitle:"Désactiver aussi les modules dépendants ?",cascadeDisableBody:"{{list}} dépendent de « {{name}} ». Ils seront aussi désactivés.",cascadeEnableTitle:"Activer aussi les modules requis ?",cascadeEnableBody:"« {{name}} » nécessite {{list}}. Ils seront aussi activés.",cascadeConfirm:"Continuer",incompatible:"Cette version cible une API non prise en charge — installez une mise à jour.",docs:"Créer votre propre module",docsHint:"Les modules sont des paquets ZIP construits avec l'API runtime d'AgentCRM — voir le guide.",back:"Tous les modules",noSettings:"Ce module n'a pas de page de réglages.",notLoaded:"Ce module n'est pas chargé (désactivé, mode sans échec ou échec du chargement).",catalog:{records:{name:"Fiches",description:"Objets, fiches, vues tableau et kanban, pages de fiche."},search:{name:"Recherche",description:"Palette de commandes ⌘K sur les fiches et la navigation."},settings:{name:"Paramètres",description:"Réglages de l'espace, modèle de données, utilisateurs, import et export."},setup:{name:"Installation et accès",description:"Assistant d'installation, connexion, stockage des données, hébergement de l'admin et sécurité."},dashboard:{name:"Tableau de bord",description:"Accueil avec indicateurs, graphiques et widgets."},deals:{name:"Affaires et pipelines",description:"L'objet affaires, les pipelines, le kanban, les rapports de pipeline et les widgets du tableau de bord."},reports:{name:"Rapports",description:"Rapports pipeline, prévisions, gagnées / perdues, activité et sources de leads, avec export CSV."},forms:{name:"Formulaires de leads",description:"Formulaires statiques de capture de leads et ingestion de la boîte de réception."},tasks:{name:"Tâches",description:"La page des tâches et les fenêtres de tâche."},automations:{name:"Automatisations",description:"Workflows déclencheur → conditions → actions et leur historique."},integrations:{name:"E-mail et agenda",description:"Synchronisation Gmail, Google Agenda et Outlook via OAuth dans le navigateur."},assistant:{name:"Assistant IA",description:"Panneau de discussion qui pilote le CRM avec votre propre clé API Claude."},customize:{name:"Personnalisation",description:"Modules, extensions et apparence."}}},Jie={title:"Extensions installées",description:"Modules et thèmes externes, stockés dans les données de votre espace (chiffrés avec elles) et chargés dans chaque admin.",drop:"Déposez le ZIP d'une extension ici, ou cliquez pour choisir un fichier",dropHint:"manifest.json + bundle.js (+ style.css) · 4 Mo maximum",reading:"Lecture du paquet…",empty:"Aucune extension installée.",kind:{module:"Module",theme:"Thème"},status:{loaded:"Actif",error:"Échec du chargement",disabled:"Désactivé",skipped:"Ignoré (mode sans échec)",incompatible:"Incompatible",pending:"Pas encore chargé"},by:"par {{author}}",installedOn:"Installé le {{date}}",upgradedFrom:"Mis à jour depuis {{version}}",export:"Exporter le ZIP",uninstall:"Désinstaller",uninstallTitle:"Désinstaller « {{name}} » ?",uninstallBody:"Son code est retiré de l'espace pour tout le monde. Les données qu'il a créées et ses réglages sont conservés.",uninstalled:"« {{name}} » désinstallé.",enabledToast:"« {{name}} » activé.",disabledToast:"« {{name}} » désactivé.",safeMode:"Le mode sans échec est actif : les extensions ne sont pas chargées dans cet onglet.",install:{title:"Installer une extension",upgradeTitle:"Mettre à jour une extension",id:"Identifiant",version:"Version",kind:"Type",author:"Auteur",homepage:"Site",api:"Version de l'API",size:"Taille",dependsOn:"Nécessite",upgrade:"Mise à jour {{from}} → {{to}}",reinstall:"Réinstaller {{version}}",warningTitle:"Ce code s'exécutera avec vos droits",warning:"Une extension peut lire et modifier toutes les fiches de cet espace, pour chaque utilisateur qui ouvre l'admin. N'installez que des paquets de personnes de confiance.",trust:"Je fais confiance à l'auteur de « {{name}} »",confirm:"Installer",confirmUpgrade:"Mettre à jour",done:"« {{name}} » {{version}} installé.",upgraded:"« {{name}} » mis à jour en {{version}}.",invalid:"Ce paquet ne peut pas être installé"}},Yie={title:"Apparence",description:"Couleurs, formes et identité visuelle de l'espace. Les changements s'appliquent en direct pour tout le monde.",presets:"Préréglages",themes:"Thèmes des extensions",themeNotLoaded:"Non chargé",custom:"Personnalisé",accent:"Couleur d'accent",accentHint:"Une gamme complète de teintes en est générée.",hex:"Hexa",neutral:"Ton neutre",neutrals:{zinc:"Zinc",slate:"Ardoise",stone:"Pierre",gray:"Gris",neutral:"Neutre"},radius:"Arrondi des angles",radii:{none:"Aucun",sm:"Petit",md:"Moyen",lg:"Grand",xl:"Très grand"},density:"Densité",densities:{compact:"Compacte",comfortable:"Confortable"},font:"Police",fontHint:"Les polices Google sont chargées depuis fonts.googleapis.com lorsqu'elles sont choisies.",sidebar:"Barre latérale",sidebars:{default:"Claire",dark:"Sombre",accent:"Accent"},buttons:"Boutons principaux",buttonStyles:{neutral:"Neutres",accent:"Accent"},mode:"Mode par défaut",modeHint:"Pour les utilisateurs qui n'ont jamais choisi clair / sombre eux-mêmes.",modes:{system:"Système",light:"Clair",dark:"Sombre"},contrast:"Contraste élevé",contrastHint:"Bordures et textes secondaires plus marqués.",branding:"Identité visuelle",logo:"Logo",favicon:"Favicon",upload:"Importer",remove:"Retirer",imageHint:"PNG, SVG, JPEG, WebP ou ICO · 200 Ko maximum",imageTooLarge:"L'image dépasse 200 Ko.",customCss:"CSS personnalisé",customCssHint:"Ajouté après tous les autres styles, pour tout le monde. Préférez les variables CSS (--acc-500, --srf-100…).",save:"Enregistrer",saved:"Apparence mise à jour.",reset:"Réinitialiser",resetTitle:"Réinitialiser l'apparence ?",resetBody:"Couleurs, formes, police et CSS personnalisé reviennent aux valeurs par défaut. Le logo et le favicon sont conservés.",preview:"Aperçu",previewSample:{title:"Acme Corp",search:"Rechercher…",primary:"Nouvelle affaire",secondary:"Filtrer",row1:"Globex",row2:"Initech",row3:"Umbrella",badge:"Qualifiée",link:"Tout voir"}},Zie={sections:Wie,readOnly:Kie,modules:Gie,extensions:Jie,appearance:Yie};function zj({title:e,description:t,actions:n}){return i.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsx("h2",{className:"text-[15px] font-semibold text-surface-900 dark:text-white",children:e}),t&&i.jsx("p",{className:"mt-0.5 max-w-2xl text-[13px] text-surface-500",children:t})]}),n&&i.jsx("div",{className:"flex shrink-0 flex-wrap items-center gap-2",children:n})]})}function Uj(){const{t:e}=oe("customize");return i.jsxs("div",{className:"flex items-center gap-2 rounded-md border border-surface-200 bg-surface-50 px-3 py-2 text-xs text-surface-600 dark:border-surface-800 dark:bg-surface-900 dark:text-surface-300",children:[i.jsx(Ii,{className:"h-3.5 w-3.5 shrink-0"}),e("readOnly")]})}function Su({value:e,options:t,onChange:n,disabled:r,label:s}){return i.jsx("div",{role:"radiogroup","aria-label":s,className:"inline-flex flex-wrap rounded-md border border-surface-200 bg-surface-50 p-0.5 dark:border-surface-700 dark:bg-surface-900",children:t.map(a=>{const o=a.value===e;return i.jsxs("button",{type:"button",role:"radio","aria-checked":o,disabled:r,onClick:()=>n(a.value),className:ce("inline-flex h-7 items-center gap-1.5 rounded px-2.5 text-xs font-medium transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500/50 disabled:cursor-not-allowed disabled:opacity-60",o?"bg-white text-surface-900 shadow-sm dark:bg-surface-700 dark:text-white":"text-surface-500 hover:text-surface-900 dark:hover:text-white"),children:[a.icon&&i.jsx("span",{className:"inline-flex [&>svg]:h-3.5 [&>svg]:w-3.5",children:a.icon}),a.label]},a.value)})})}function Ua({label:e,hint:t,children:n}){return i.jsxs("div",{className:"flex flex-col gap-2 border-b border-surface-100 py-3 last:border-b-0 sm:flex-row sm:items-center sm:justify-between dark:border-surface-800",children:[i.jsxs("div",{className:"min-w-0",children:[i.jsx("div",{className:"text-[13px] font-medium text-surface-900 dark:text-white",children:e}),t&&i.jsx("div",{className:"text-xs text-surface-500",children:t})]}),i.jsx("div",{className:"shrink-0",children:n})]})}function ey(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/1024/1024).toFixed(2)} MB`}const Qie={BarChart3:bc,CheckSquare:$i,Database:ba,FileInput:gl,LayoutDashboard:Fu,Palette:E0,Plug:fk,Puzzle:I0,Search:Wr,Settings:mk,ShieldCheck:yl,Sparkles:Ni,Zap:pa};function u$(e){return e&&(Qie[e]??Nk[e])||I0}function Xie(){const e=S.useSyncExternalStore(EH,Ov,Ov);return S.useMemo(()=>new Map(e.map(t=>[t.id,t])),[e])}function eae(e,t){const n=URL.createObjectURL(new Blob([t],{type:"application/zip"})),r=document.createElement("a");r.href=n,r.download=e,document.body.appendChild(r),r.click(),r.remove(),setTimeout(()=>URL.revokeObjectURL(n),1e3)}const tae={loaded:"green",error:"red",disabled:"gray",skipped:"yellow",incompatible:"red",pending:"gray"};function nae(){const{t:e}=oe("customize"),t=Ge("extensions.write"),n=mt("extensions"),r=S.useMemo(()=>n.map(tp).sort((d,f)=>d.name.localeCompare(f.name)),[n]),s=Xie(),[a,o]=S.useState(null),l=PR();return i.jsxs("div",{className:"space-y-4","data-testid":"extensions-panel",children:[i.jsx("p",{className:"text-[13px] text-surface-500",children:e("extensions.description")}),!t&&i.jsx(Uj,{}),l&&i.jsxs("div",{className:"flex items-center gap-2 rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-200",children:[i.jsx(hk,{className:"h-3.5 w-3.5 shrink-0"}),e("extensions.safeMode")]}),t&&i.jsx(rae,{onPackage:d=>o({pkg:d}),onError:d=>o({error:d})}),r.length===0?i.jsx(ut,{className:"py-10",icon:i.jsx(hI,{}),title:e("extensions.empty")}):i.jsx(Ke,{padded:!1,children:i.jsx("ul",{className:"divide-y divide-surface-100 dark:divide-surface-800",children:r.map(d=>i.jsx(iae,{ext:d,state:s.get(d.id),canEdit:t},d.id))})}),a&&i.jsx(sae,{pending:a,installed:r,onClose:()=>o(null)})]})}function rae({onPackage:e,onError:t}){const{t:n}=oe("customize"),r=S.useRef(null),[s,a]=S.useState(!1),[o,l]=S.useState(!1),d=async p=>{if(p){l(!0);try{e(await U6(new Uint8Array(await p.arrayBuffer())))}catch(m){t(m instanceof pr||m instanceof Error?m.message:String(m))}finally{l(!1),r.current&&(r.current.value="")}}},f=p=>{p.preventDefault(),a(!1),d(p.dataTransfer.files[0])};return i.jsxs("div",{role:"button",tabIndex:0,onClick:()=>{var p;return(p=r.current)==null?void 0:p.click()},onKeyDown:p=>{var m;return(p.key==="Enter"||p.key===" ")&&((m=r.current)==null?void 0:m.click())},onDragOver:p=>{p.preventDefault(),a(!0)},onDragLeave:()=>a(!1),onDrop:f,className:ce("flex cursor-pointer flex-col items-center justify-center gap-1.5 rounded-lg border-2 border-dashed px-4 py-7 text-center transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500/50",s?"border-accent-500 bg-accent-50/60 dark:bg-accent-500/10":"border-surface-200 hover:border-surface-300 dark:border-surface-700 dark:hover:border-surface-600"),"data-testid":"extension-dropzone",children:[i.jsx("span",{className:"text-surface-400 [&>svg]:h-5 [&>svg]:w-5",children:o?i.jsx(Ds,{size:"sm"}):i.jsx(ro,{})}),i.jsx("span",{className:"text-[13px] font-medium text-surface-700 dark:text-surface-200",children:n(o?"extensions.reading":"extensions.drop")}),i.jsx("span",{className:"text-xs text-surface-400",children:n("extensions.dropHint")}),i.jsx("input",{ref:r,type:"file",accept:".zip,application/zip",className:"hidden","data-testid":"extension-file",onChange:p=>{var m;return void d((m=p.target.files)==null?void 0:m[0])}})]})}function sae({pending:e,installed:t,onClose:n}){var v;const{t:r}=oe("customize"),{t:s}=oe(),a=Xe(),[o,l]=S.useState(!1),[d,f]=S.useState(!1);if("error"in e)return i.jsx(on,{open:!0,onClose:n,title:r("extensions.install.invalid"),size:"md",footer:i.jsx(ue,{onClick:n,children:s("common.close")}),children:i.jsxs("div",{className:"flex gap-2 rounded-md border border-red-200 bg-red-50 p-3 text-[13px] text-red-800 dark:border-red-500/30 dark:bg-red-500/10 dark:text-red-200",children:[i.jsx(yo,{className:"mt-0.5 h-4 w-4 shrink-0"}),i.jsx("span",{className:"break-words",children:e.error})]})});const{manifest:p,files:m}=e.pkg,h=t.find(k=>k.id===p.id),b=new TextEncoder().encode(m["bundle.js"]).length+(m["style.css"]?new TextEncoder().encode(m["style.css"]).length:0),x=async()=>{f(!0);try{const k=await hT(a,e.pkg);ge.success(k.mode==="upgrade"?r("extensions.install.upgraded",{name:p.name,version:p.version}):r("extensions.install.done",{name:p.name,version:p.version}));for(const j of k.warnings)ge.warn(j);n()}catch(k){ge.error(k instanceof Error?k.message:String(k))}finally{f(!1)}},y=[[r("extensions.install.id"),p.id],[r("extensions.install.kind"),r(`extensions.kind.${p.kind}`)],[r("extensions.install.version"),h?h.version===p.version?r("extensions.install.reinstall",{version:p.version}):r("extensions.install.upgrade",{from:h.version,to:p.version}):p.version],[r("extensions.install.author"),p.author],[r("extensions.install.homepage"),p.homepage],[r("extensions.install.api"),p.apiVersion],[r("extensions.install.size"),ey(b)],[r("extensions.install.dependsOn"),(v=p.dependsOn)==null?void 0:v.join(", ")]];return i.jsx(on,{open:!0,onClose:n,dismissible:!d,title:r(h?"extensions.install.upgradeTitle":"extensions.install.title"),size:"md",footer:i.jsxs(i.Fragment,{children:[i.jsx(ue,{variant:"ghost",onClick:n,disabled:d,children:s("common.cancel")}),i.jsx(ue,{variant:"primary",icon:i.jsx(ro,{}),loading:d,disabled:!o,onClick:()=>void x(),"data-testid":"confirm-install",children:r(h?"extensions.install.confirmUpgrade":"extensions.install.confirm")})]}),children:i.jsxs("form",{"data-form-type":"other",onSubmit:k=>k.preventDefault(),className:"space-y-4",children:[i.jsxs("div",{className:"flex items-start gap-3",children:[i.jsx("span",{className:"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-accent-50 text-accent-700 dark:bg-accent-500/15 dark:text-accent-300 [&>svg]:h-5 [&>svg]:w-5",children:p.kind==="theme"?i.jsx(E0,{}):i.jsx(I0,{})}),i.jsxs("div",{className:"min-w-0",children:[i.jsx("div",{className:"text-sm font-semibold text-surface-900 dark:text-white",children:p.name}),p.description&&i.jsx("p",{className:"text-[13px] text-surface-500",children:p.description})]})]}),i.jsx("dl",{className:"grid grid-cols-[8rem_1fr] gap-x-3 gap-y-1.5 text-[13px]",children:y.filter(([,k])=>k).map(([k,j])=>i.jsxs("div",{className:"contents",children:[i.jsx("dt",{className:"text-surface-500",children:k}),i.jsx("dd",{className:"min-w-0 break-words font-medium text-surface-900 dark:text-surface-100",children:j})]},k))}),i.jsxs("div",{className:"rounded-md border border-amber-200 bg-amber-50 p-3 text-[13px] text-amber-900 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-200",children:[i.jsxs("div",{className:"flex items-center gap-1.5 font-semibold",children:[i.jsx(hk,{className:"h-4 w-4"}),r("extensions.install.warningTitle")]}),i.jsx("p",{className:"mt-1",children:r("extensions.install.warning")})]}),i.jsx(Ot,{checked:o,onChange:k=>l(k.target.checked),label:r("extensions.install.trust",{name:p.name}),"data-testid":"trust-extension"})]})})}function iae({ext:e,state:t,canEdit:n}){const{t:r}=oe("customize"),s=Xe(),[a,o]=S.useState(!1),l=e.kind==="theme"?E0:u$(e.icon),d=e.compatible?(t==null?void 0:t.status)??(e.enabled?"pending":"disabled"):"incompatible",f=async(h,b)=>{o(!0);try{await h(),b&&ge.success(b)}catch(x){ge.error(x instanceof Error?x.message:String(x))}finally{o(!1)}},p=async()=>{await qt({title:r("extensions.uninstallTitle",{name:e.name}),description:r("extensions.uninstallBody"),confirmLabel:r("extensions.uninstall"),danger:!0})&&await f(()=>yT(s,e.id),r("extensions.uninstalled",{name:e.name}))},m=()=>f(async()=>{const h=await B6(mT(s,e.id));eae(`${e.id}-${e.version}.zip`,h)});return i.jsxs("li",{className:"flex items-start gap-3 px-card py-3","data-extension":e.id,children:[i.jsx("span",{className:"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-surface-100 text-surface-600 dark:bg-surface-800 dark:text-surface-300",children:i.jsx(l,{className:"h-4 w-4"})}),i.jsxs("div",{className:"min-w-0 flex-1",children:[i.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[i.jsx("span",{className:"truncate text-sm font-semibold text-surface-900 dark:text-white",children:e.name}),i.jsxs("span",{className:"text-xs tabular-nums text-surface-500",children:["v",e.version]}),i.jsx(tt,{color:e.kind==="theme"?"pink":"purple",children:r(`extensions.kind.${e.kind}`)}),i.jsx(tt,{color:tae[d],dot:!0,children:r(`extensions.status.${d}`)})]}),e.description&&i.jsx("p",{className:"mt-0.5 text-xs text-surface-500",children:e.description}),i.jsx("p",{className:"mt-1 text-2xs text-surface-400",children:[e.author?r("extensions.by",{author:e.author}):null,r("extensions.installedOn",{date:Pw(e.installedAt,_r())}),e.previousVersion?r("extensions.upgradedFrom",{version:e.previousVersion}):null,ey(e.size.bundle+e.size.style)].filter(Boolean).join(" · ")}),d==="error"&&(t==null?void 0:t.error)&&i.jsx("p",{className:"mt-1 break-words font-mono text-2xs text-red-600 dark:text-red-400",children:t.error})]}),i.jsxs("div",{className:"flex shrink-0 items-center gap-1",children:[i.jsx(si,{checked:e.enabled,disabled:!n||a||!e.enabled&&!e.compatible,label:i.jsx("span",{className:"sr-only",children:e.name}),onChange:h=>void f(()=>L1(s,e.id,h),h?r("extensions.enabledToast",{name:e.name}):r("extensions.disabledToast",{name:e.name}))}),i.jsx(Tr,{align:"end",trigger:({ref:h,onClick:b})=>i.jsx(dt,{ref:h,size:"sm",label:e.name,icon:i.jsx(mo,{}),onClick:b,disabled:a}),items:[{id:"export",label:r("extensions.export"),icon:i.jsx(En,{}),onSelect:()=>void m()},...n?[{id:"uninstall",label:r("extensions.uninstall"),icon:i.jsx(Rt,{}),danger:!0,separator:!0,onSelect:()=>void p()}]:[]]})]})]})}const aae="https://github.com/fleox/agentcrm/blob/master/docs/extensions.md";function f$(){const{t:e}=oe();return t=>t.nameKey?e(t.nameKey):t.name}function oae(){const{sub:e}=lo(),{t}=oe("customize"),[n,r]=S.useState(e==="extensions"?"extensions":"modules");return e&&e!=="extensions"?i.jsx(dae,{moduleId:e}):i.jsxs("div",{className:"max-w-4xl space-y-5",children:[i.jsx(zj,{title:t("modules.title"),description:t("modules.description")}),i.jsx(bo,{tabs:[{id:"modules",label:t("modules.tabs.modules")},{id:"extensions",label:t("modules.tabs.extensions")}],value:n,onChange:s=>r(s)}),n==="modules"?i.jsx(lae,{}):i.jsx(nae,{}),i.jsxs("a",{href:aae,target:"_blank",rel:"noreferrer",className:"flex items-start gap-3 rounded-lg border border-dashed border-surface-300 p-3 text-sm hover:border-surface-400 dark:border-surface-700",children:[i.jsx("span",{className:"mt-0.5 text-surface-500 [&>svg]:h-4 [&>svg]:w-4",children:i.jsx(Yz,{})}),i.jsxs("span",{children:[i.jsx("span",{className:"font-medium text-surface-900 dark:text-white",children:t("modules.docs")}),i.jsx("span",{className:"block text-xs text-surface-500",children:t("modules.docsHint")})]})]})]})}function lae(){const{t:e}=oe("customize"),t=ap(),n=Ge("modules.write"),r=S.useMemo(()=>lv.map(s=>({id:s,items:t.filter(a=>a.category===s)})).filter(s=>s.items.length),[t]);return i.jsxs("div",{className:"space-y-5","data-testid":"modules-list",children:[!n&&i.jsx(Uj,{}),r.map(s=>i.jsxs("section",{children:[i.jsx("h3",{className:"mb-2 text-2xs font-medium uppercase tracking-wide text-surface-400",children:e(`modules.categories.${s.id}`)}),i.jsx("div",{className:"grid gap-3 sm:grid-cols-2",children:s.items.map(a=>i.jsx(cae,{module:a,modules:t,canEdit:n},a.id))})]},s.id))]})}function cae({module:e,modules:t,canEdit:n}){var v;const{t:r}=oe("customize"),s=Xe(),a=dn(),o=f$(),[l,d]=S.useState(!1);hd();const f=u$(e.icon),p=new Map(t.map(k=>[k.id,k])),m=k=>k.map(j=>p.get(j)?o(p.get(j)):j).join(", "),h=o(e),b=e.descriptionKey?r(e.descriptionKey):e.description,x=e.settingsSection?pt.settings(e.settingsSection):(v=k0().find(k=>k.id===e.id))!=null&&v.settingsPage?pt.settings(`modules/${e.id}`):null,y=async k=>{var j;d(!0);try{try{await vf(s,e.id,k)}catch(C){if(!(C instanceof he)||C.code!=="conflict")throw C;const A=((j=C.details)==null?void 0:j.blockers)??[];if(!await qt({title:r(k?"modules.cascadeEnableTitle":"modules.cascadeDisableTitle"),description:k?r("modules.cascadeEnableBody",{name:h,list:m(A)}):r("modules.cascadeDisableBody",{name:h,list:m(A)}),confirmLabel:r("modules.cascadeConfirm"),danger:!k}))return;await vf(s,e.id,k,{cascade:!0})}ge.success(k?r("modules.enabled",{name:h}):r("modules.disabled",{name:h}))}catch(C){ge.error(C instanceof Error?C.message:String(C))}finally{d(!1)}};return i.jsx(Ke,{padded:!1,className:ce("flex flex-col",!e.enabled&&"bg-surface-50/70 dark:bg-surface-900/60"),"data-module":e.id,children:i.jsxs("div",{className:"flex items-start gap-3 p-card",children:[i.jsx("span",{className:ce("flex h-9 w-9 shrink-0 items-center justify-center rounded-lg [&>svg]:h-4.5 [&>svg]:w-4.5",e.enabled?"bg-accent-50 text-accent-700 dark:bg-accent-500/15 dark:text-accent-300":"bg-surface-100 text-surface-400 dark:bg-surface-800"),children:i.jsx(f,{className:"h-[18px] w-[18px]"})}),i.jsxs("div",{className:"min-w-0 flex-1",children:[i.jsxs("div",{className:"flex flex-wrap items-center gap-1.5",children:[i.jsx("span",{className:ce("truncate text-sm font-semibold",e.enabled?"text-surface-900 dark:text-white":"text-surface-500"),children:h}),e.required&&i.jsx(tt,{color:"gray",children:r("modules.required")}),e.source==="extension"&&i.jsx(tt,{color:"purple",children:e.version?`${r("modules.extension")} · v${e.version}`:r("modules.extension")})]}),i.jsx("p",{className:"mt-0.5 text-xs leading-relaxed text-surface-500",children:b}),e.dependsOn.length>0&&i.jsx("p",{className:"mt-1.5 text-2xs text-surface-500",children:r("modules.requires",{list:m(e.dependsOn)})}),e.dependents.length>0&&i.jsx("p",{className:"mt-0.5 text-2xs text-surface-500",children:r("modules.usedBy",{list:m(e.dependents)})}),!e.enabled&&e.missingDependencies.length>0&&i.jsx("p",{className:"mt-1.5 text-2xs font-medium text-amber-700 dark:text-amber-400",children:r("modules.missing",{list:m(e.missingDependencies)})}),e.incompatible&&i.jsx("p",{className:"mt-1.5 text-2xs font-medium text-red-600 dark:text-red-400",children:r("modules.incompatible")})]}),i.jsxs("div",{className:"flex shrink-0 items-center gap-1",children:[x&&e.enabled&&i.jsx(dt,{size:"sm",label:r("modules.settings"),icon:i.jsx(Nf,{}),onClick:()=>a(x)}),i.jsx(si,{checked:e.enabled,disabled:!n||e.required||l||!e.enabled&&!!e.incompatible,label:i.jsx("span",{className:"sr-only",children:e.enabled?r("modules.disable",{name:h}):r("modules.enable",{name:h})}),onChange:k=>void y(k)})]})]})})}function dae({moduleId:e}){const{t}=oe("customize"),n=dn(),r=f$();hd();const a=ap().find(d=>d.id===e),o=k0().find(d=>d.id===e),l=o==null?void 0:o.settingsPage;return i.jsxs("div",{className:"max-w-4xl space-y-4",children:[i.jsxs("button",{type:"button",onClick:()=>n(pt.settings("modules")),className:"inline-flex items-center gap-1 text-xs text-surface-500 hover:text-surface-900 dark:hover:text-white",children:[i.jsx(po,{className:"h-3.5 w-3.5"}),t("modules.back")]}),i.jsx(zj,{title:a?r(a):e,description:a?a.descriptionKey?t(a.descriptionKey):a.description:void 0}),l&&(a!=null&&a.enabled)?i.jsx(l,{}):i.jsx(ut,{className:"py-16",icon:i.jsx(Nf,{}),title:(a==null?void 0:a.enabled)===!1||!o?t("modules.notLoaded"):t("modules.noSettings")})]})}const uae=["#3366ff","#0891b2","#16a34a","#ea580c","#e11d48","#7c3aed","#db2777","#ca8a04","#52525b","#0f766e"];function fae(){const e=lp("appearance"),t=mt("extensions"),n=S.useSyncExternalStore(FT,tg,tg);return S.useMemo(()=>{const r=t.filter(a=>a.kind==="theme").map(a=>{const o=rp(a.id);return{id:a.id,name:(o==null?void 0:o.name)??a.manifest.name,enabled:!!a.enabled,loaded:!!o,values:(o==null?void 0:o.appearance)??{}}}),s=e!=null&&e.themeId?r.find(a=>a.id===e.themeId&&a.enabled):void 0;return{doc:e,appearance:q1(e,s?{appearance:s.values}:null),themes:r}},[e,t,n])}function Ic(e){return e instanceof Error?e.message:String(e)}function pae(){const{t:e}=oe("customize"),t=Xe(),n=Ge("appearance.write"),{doc:r,appearance:s,themes:a}=fae(),[o,l]=S.useState(s);S.useEffect(()=>l(s),[s]);const d=async y=>{try{await sp(t,y)}catch(v){ge.error(Ic(v)),l(s)}},f=y=>{l(v=>({...v,...y})),d(y)},p=S.useRef(IP(y=>void d({accent:y}),350)).current;S.useEffect(()=>()=>p.cancel(),[p]);const m=y=>{const v={...o,accent:y,preset:"custom"};l(v),UT(v,{persist:!1,theme:r!=null&&r.themeId?rp(r.themeId):null}),p(y)},h=async y=>{try{await W1(t,y)}catch(v){ge.error(Ic(v))}},b=async()=>{if(await qt({title:e("appearance.resetTitle"),description:e("appearance.resetBody"),confirmLabel:e("appearance.reset"),danger:!0}))try{await qT(t),ge.success(e("appearance.saved"))}catch(v){ge.error(Ic(v))}},x=!n;return i.jsxs("div",{className:"space-y-5","data-testid":"appearance-section",children:[i.jsx(zj,{title:e("appearance.title"),description:e("appearance.description"),actions:n?i.jsx(ue,{size:"sm",variant:"outline",icon:i.jsx(fa,{}),onClick:()=>void b(),children:e("appearance.reset")}):void 0}),!n&&i.jsx(Uj,{}),i.jsxs("div",{className:"grid gap-5 xl:grid-cols-[minmax(0,1fr)_340px]",children:[i.jsxs("div",{className:"min-w-0 space-y-5",children:[i.jsx(gae,{current:o,themes:a,disabled:x,onPick:y=>void h(y)}),i.jsx(Ke,{title:e("appearance.accent"),children:i.jsxs("div",{className:"space-y-3",children:[i.jsx(hae,{value:o.accent,disabled:x,onChange:m}),i.jsx("p",{className:"text-xs text-surface-500",children:e("appearance.accentHint")})]})}),i.jsx(Ke,{padded:!1,children:i.jsxs("div",{className:"px-card",children:[i.jsx(Ua,{label:e("appearance.neutral"),children:i.jsx("div",{role:"radiogroup","aria-label":e("appearance.neutral"),className:"flex flex-wrap gap-1.5",children:F1.map(y=>i.jsxs("button",{type:"button",role:"radio","aria-checked":o.neutral===y,disabled:x,onClick:()=>f({neutral:y}),className:ce("inline-flex h-7 items-center gap-1.5 rounded-md border px-2 text-xs font-medium disabled:opacity-60",o.neutral===y?"border-accent-500 ring-2 ring-accent-500/20":"border-surface-200 hover:border-surface-300 dark:border-surface-700"),children:[i.jsx("span",{className:"flex",children:[200,500,800].map(v=>i.jsx("span",{className:"-ml-0.5 h-3 w-3 rounded-full border border-white first:ml-0 dark:border-surface-900",style:{background:jf[y][v]}},v))}),e(`appearance.neutrals.${y}`)]},y))})}),i.jsx(Ua,{label:e("appearance.radius"),children:i.jsx(Su,{label:e("appearance.radius"),value:o.radius,disabled:x,onChange:y=>f({radius:y}),options:z1.map(y=>({value:y,label:e(`appearance.radii.${y}`),icon:i.jsx(mae,{radius:y})}))})}),i.jsx(Ua,{label:e("appearance.density"),children:i.jsx(Su,{label:e("appearance.density"),value:o.density,disabled:x,onChange:y=>f({density:y}),options:["comfortable","compact"].map(y=>({value:y,label:e(`appearance.densities.${y}`)}))})}),i.jsx(Ua,{label:e("appearance.font"),hint:e("appearance.fontHint"),children:i.jsx(Ve,{className:"w-56","aria-label":e("appearance.font"),value:o.font,disabled:x,options:Uc.map(y=>({value:y.id,label:y.label})),onChange:y=>f({font:y.target.value})})}),i.jsx(Ua,{label:e("appearance.sidebar"),children:i.jsx(Su,{label:e("appearance.sidebar"),value:o.sidebar,disabled:x,onChange:y=>f({sidebar:y}),options:["default","dark","accent"].map(y=>({value:y,label:e(`appearance.sidebars.${y}`)}))})}),i.jsx(Ua,{label:e("appearance.buttons"),children:i.jsx(Su,{label:e("appearance.buttons"),value:o.buttons,disabled:x,onChange:y=>f({buttons:y}),options:["neutral","accent"].map(y=>({value:y,label:e(`appearance.buttonStyles.${y}`)}))})}),i.jsx(Ua,{label:e("appearance.mode"),hint:e("appearance.modeHint"),children:i.jsx(Su,{label:e("appearance.mode"),value:o.defaultMode,disabled:x,onChange:y=>f({defaultMode:y}),options:[{value:"system",label:e("appearance.modes.system"),icon:i.jsx(up,{})},{value:"light",label:e("appearance.modes.light"),icon:i.jsx(yk,{})},{value:"dark",label:e("appearance.modes.dark"),icon:i.jsx(ck,{})}]})}),i.jsx(Ua,{label:e("appearance.contrast"),hint:e("appearance.contrastHint"),children:i.jsx(si,{checked:o.contrast==="high",disabled:x,onChange:y=>f({contrast:y?"high":"normal"}),label:i.jsx("span",{className:"sr-only",children:e("appearance.contrast")})})})]})}),i.jsx(Ke,{title:e("appearance.branding"),children:i.jsxs("div",{className:"grid gap-4 sm:grid-cols-2",children:[i.jsx(m_,{label:e("appearance.logo"),value:o.logo,disabled:x,kind:"logo"}),i.jsx(m_,{label:e("appearance.favicon"),value:o.favicon,disabled:x,kind:"favicon"})]})}),i.jsx(xae,{value:(r==null?void 0:r.customCss)??"",disabled:x})]}),i.jsx("div",{className:"xl:sticky xl:top-4 xl:self-start",children:i.jsx(Ke,{title:e("appearance.preview"),children:i.jsx(bae,{appearance:o})})})]})]})}function mae({radius:e}){const t={none:0,sm:2,md:4,lg:6,xl:9}[e];return i.jsx("svg",{viewBox:"0 0 14 14",fill:"none","aria-hidden":"true",children:i.jsx("path",{d:`M2 12 V${2+t} ${t?`Q2 2 ${2+t} 2`:""} H12`,stroke:"currentColor",strokeWidth:"1.6"})})}function hae({value:e,onChange:t,disabled:n}){const{t:r}=oe("customize"),[s,a]=S.useState(e);return S.useEffect(()=>a(e),[e]),i.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[i.jsx("label",{className:"relative inline-flex h-9 w-9 shrink-0 cursor-pointer overflow-hidden rounded-lg border border-surface-200 shadow-sm dark:border-surface-700",style:{background:e},children:i.jsx("input",{type:"color","aria-label":r("appearance.accent"),className:"absolute inset-0 cursor-pointer opacity-0",value:e,disabled:n,onChange:o=>t(o.target.value)})}),i.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-surface-500",children:[r("appearance.hex"),i.jsx("input",{"aria-label":r("appearance.hex"),className:"h-8 w-24 rounded-md border border-surface-200 bg-white px-2 font-mono text-[13px] text-surface-900 focus:border-accent-500 focus:outline-none focus:ring-2 focus:ring-accent-500/20 dark:border-surface-700 dark:bg-surface-900 dark:text-surface-100",value:s,disabled:n,maxLength:7,onChange:o=>{a(o.target.value),CT(o.target.value)&&o.target.value.replace("#","").length===6&&t(v0(o.target.value))},onBlur:()=>a(e)})]}),i.jsx("div",{className:"flex flex-wrap gap-1.5",children:uae.map(o=>i.jsx("button",{type:"button",disabled:n,"aria-label":o,onClick:()=>t(o),className:ce("flex h-6 w-6 items-center justify-center rounded-full border border-black/10 text-white disabled:opacity-60",e.toLowerCase()===o&&"ring-2 ring-offset-1 ring-surface-400 dark:ring-offset-surface-900"),style:{background:o},children:e.toLowerCase()===o&&i.jsx(Er,{className:"h-3 w-3"})},o))})]})}function gae({current:e,themes:t,onPick:n,disabled:r}){const{t:s}=oe("customize"),a=(o,l,d,f,p)=>{const m=e.preset===o;return i.jsxs("button",{type:"button",disabled:r||p,onClick:()=>n(o),"aria-pressed":m,"data-preset":o,className:ce("group rounded-lg border p-1.5 text-left transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent-500/50 disabled:cursor-not-allowed",m?"border-accent-500 ring-2 ring-accent-500/20":"border-surface-200 hover:border-surface-300 dark:border-surface-700 dark:hover:border-surface-600",p&&"opacity-50"),children:[i.jsx(yae,{appearance:d}),i.jsxs("div",{className:"flex items-center gap-1 px-0.5 pt-1.5 text-xs font-medium text-surface-800 dark:text-surface-100",children:[i.jsx("span",{className:"truncate",children:l}),m&&i.jsx(Er,{className:"ml-auto h-3.5 w-3.5 shrink-0 text-accent-600"}),f]})]},o)};return i.jsxs(Ke,{title:s("appearance.presets"),actions:e.preset==="custom"?i.jsx(tt,{color:"blue",children:s("appearance.custom")}):void 0,children:[i.jsx("div",{className:"grid grid-cols-2 gap-2.5 sm:grid-cols-3 lg:grid-cols-4",children:np.map(o=>a(o.id,o.name,{...Bc,...o.values,preset:o.id}))}),t.length>0&&i.jsxs(i.Fragment,{children:[i.jsx("div",{className:"mb-2 mt-4 text-2xs font-medium uppercase tracking-wide text-surface-400",children:s("appearance.themes")}),i.jsx("div",{className:"grid grid-cols-2 gap-2.5 sm:grid-cols-3 lg:grid-cols-4",children:t.map(o=>a(o.id,o.name,{...Bc,...o.values,preset:o.id},o.loaded?void 0:i.jsx("span",{className:"ml-auto text-2xs text-surface-400",children:s("appearance.themeNotLoaded")}),!o.enabled))})]})]})}function p$(e){return{...dz(e),fontFamily:"var(--font-sans)"}}function yae({appearance:e}){const t=e.sidebar;return i.jsxs("div",{style:p$(e),className:"flex h-[68px] overflow-hidden rounded-md border border-surface-200 bg-white","aria-hidden":"true",children:[i.jsxs("div",{className:ce("flex w-[30%] flex-col gap-1 p-1.5",t==="default"?"bg-surface-50":t==="dark"?"bg-surface-900":"bg-accent-700"),children:[i.jsx("div",{className:ce("h-1.5 w-3/4 rounded-sm",t==="default"?"bg-surface-300":"bg-white/40")}),i.jsx("div",{className:ce("h-1.5 w-full rounded-sm",t==="default"?"bg-surface-200":"bg-white/20")}),i.jsx("div",{className:ce("h-1.5 w-2/3 rounded-sm",t==="default"?"bg-surface-200":"bg-white/20")})]}),i.jsxs("div",{className:"flex flex-1 flex-col gap-1.5 p-1.5",children:[i.jsxs("div",{className:"flex items-center gap-1",children:[i.jsx("div",{className:"h-2 flex-1 rounded-sm bg-surface-100"}),i.jsx("div",{className:"h-2.5 w-6 rounded bg-primary"})]}),i.jsx("div",{className:"h-1.5 w-full rounded-sm bg-surface-100"}),i.jsxs("div",{className:"flex items-center gap-1",children:[i.jsx("div",{className:"h-1.5 w-1/2 rounded-sm bg-surface-200"}),i.jsx("div",{className:"h-2 w-5 rounded-full bg-accent-100"})]}),i.jsx("div",{className:"h-1.5 w-3/4 rounded-sm bg-accent-500"})]})]})}function bae({appearance:e}){const{t}=oe("customize"),n=s=>t(`appearance.previewSample.${s}`),r=e.sidebar;return i.jsx("div",{style:p$(e),className:"overflow-hidden rounded-lg border border-surface-200 bg-white text-surface-900 dark:border-surface-800 dark:bg-surface-950 dark:text-surface-100","data-testid":"appearance-preview",children:i.jsxs("div",{className:"flex",children:[i.jsxs("div",{className:ce("w-24 shrink-0 space-y-1 border-r p-2",r==="default"?"border-surface-200 bg-surface-50 dark:border-surface-800 dark:bg-surface-900":"dark border-surface-800 bg-surface-900",r==="accent"&&"acrm-sidebar-accent"),children:[i.jsxs("div",{className:"mb-2 flex items-center gap-1.5",children:[e.logo?i.jsx("img",{src:e.logo,alt:"",className:"h-4 w-4 rounded object-contain"}):i.jsx("span",{className:"h-4 w-4 rounded bg-surface-900 dark:bg-white"}),i.jsx("span",{className:"h-2 w-10 rounded-sm bg-surface-300 dark:bg-surface-600"})]}),[0,1,2,3].map(s=>i.jsx("div",{className:ce("h-5 rounded-md px-1.5 py-1.5",s===1?"bg-surface-200/70 dark:bg-surface-800":""),children:i.jsx("div",{className:ce("h-2 rounded-sm",s===1?"w-10 bg-surface-500 dark:bg-surface-300":"w-12 bg-surface-300 dark:bg-surface-600")})},s))]}),i.jsxs("div",{className:"min-w-0 flex-1",children:[i.jsxs("div",{className:"flex items-center gap-2 border-b border-surface-200 px-3 py-page dark:border-surface-800",children:[i.jsx("span",{className:"truncate text-[13px] font-semibold",children:n("title")}),i.jsxs("span",{className:"ml-auto flex h-6 items-center gap-1 rounded-md border border-surface-200 px-1.5 text-2xs text-surface-400 dark:border-surface-700",children:[i.jsx(Wr,{className:"h-3 w-3"}),n("search")]})]}),i.jsxs("div",{className:"space-y-2 p-3",children:[i.jsxs("div",{className:"flex gap-1.5",children:[i.jsx(ue,{size:"xs",variant:"primary",children:n("primary")}),i.jsx(ue,{size:"xs",variant:"outline",children:n("secondary")})]}),i.jsx("div",{className:"overflow-hidden rounded-md border border-surface-200 dark:border-surface-800",children:["row1","row2","row3"].map((s,a)=>i.jsxs("div",{className:ce("flex h-row items-center gap-2 border-b border-surface-100 px-2 text-xs last:border-b-0 dark:border-surface-800",a===0&&"bg-accent-50/60 dark:bg-accent-500/10"),children:[i.jsx("span",{className:"flex-1 truncate",children:n(s)}),a===0&&i.jsx(tt,{color:"blue",children:n("badge")})]},s))}),i.jsxs("div",{className:"flex items-center justify-between",children:[i.jsx("span",{className:"text-xs font-medium text-accent-600 dark:text-accent-400",children:n("link")}),i.jsx("span",{className:"h-4 w-7 rounded-full bg-accent-600 p-0.5",children:i.jsx("span",{className:"block h-3 w-3 translate-x-3 rounded-full bg-white"})})]})]})]})]})})}function m_({label:e,value:t,kind:n,disabled:r}){const{t:s}=oe("customize"),a=Xe(),o=S.useRef(null),[l,d]=S.useState(!1),f=async m=>{if(m){if(m.size>fv){ge.error(s("appearance.imageTooLarge"));return}d(!0);try{const h=await new Promise((b,x)=>{const y=new FileReader;y.onload=()=>b(String(y.result)),y.onerror=()=>x(y.error),y.readAsDataURL(m)});await yv(a,h,{kind:n}),ge.success(s("appearance.saved"))}catch(h){ge.error(Ic(h))}finally{d(!1),o.current&&(o.current.value="")}}},p=async()=>{d(!0);try{await yv(a,null,{kind:n})}catch(m){ge.error(Ic(m))}finally{d(!1)}};return i.jsxs("div",{className:"flex items-center gap-3","data-image":n,children:[i.jsx("span",{className:"flex h-12 w-12 shrink-0 items-center justify-center overflow-hidden rounded-lg border border-dashed border-surface-300 bg-surface-50 dark:border-surface-700 dark:bg-surface-900",children:t?i.jsx("img",{src:t,alt:"",className:"max-h-full max-w-full object-contain"}):i.jsx(vN,{className:"h-4 w-4 text-surface-400"})}),i.jsxs("div",{className:"min-w-0 space-y-1",children:[i.jsx("div",{className:"text-[13px] font-medium text-surface-900 dark:text-white",children:e}),i.jsx("div",{className:"text-2xs text-surface-500",children:t?ey(TT(t)):s("appearance.imageHint")}),!r&&i.jsxs("div",{className:"flex gap-1",children:[i.jsx(ue,{size:"xs",variant:"outline",icon:i.jsx(vN,{}),loading:l,onClick:()=>{var m;return(m=o.current)==null?void 0:m.click()},children:s("appearance.upload")}),t&&i.jsx(ue,{size:"xs",variant:"ghost",icon:i.jsx(Rt,{}),disabled:l,onClick:()=>void p(),children:s("appearance.remove")})]})]}),i.jsx("input",{ref:o,type:"file",accept:"image/png,image/jpeg,image/gif,image/webp,image/svg+xml,image/x-icon,.ico",className:"hidden",onChange:m=>{var h;return void f((h=m.target.files)==null?void 0:h[0])}})]})}function xae({value:e,disabled:t}){const{t:n}=oe("customize"),r=Xe(),[s,a]=S.useState(e),[o,l]=S.useState(!1);S.useEffect(()=>a(e),[e]);const d=new TextEncoder().encode(s).length,f=d>zc,p=async()=>{l(!0);try{await sp(r,{customCss:s.trim()?s:null}),ge.success(n("appearance.saved"))}catch(m){ge.error(Ic(m))}finally{l(!1)}};return i.jsx(Ke,{title:n("appearance.customCss"),actions:i.jsx("span",{className:ce("text-2xs tabular-nums",f?"font-medium text-red-600":"text-surface-400"),children:`${ey(d)} / ${zc/1024} KB`}),children:i.jsxs("form",{"data-form-type":"other",className:"space-y-2",onSubmit:m=>{m.preventDefault(),p()},children:[i.jsx("p",{className:"text-xs text-surface-500",children:n("appearance.customCssHint")}),i.jsx(Cr,{"aria-label":n("appearance.customCss"),rows:8,spellCheck:!1,className:"font-mono text-xs",value:s,disabled:t,invalid:f,placeholder:`:root {
1180
1180
  --acc-500: 51 102 255;
1181
1181
  }`,onChange:m=>a(m.target.value)}),!t&&i.jsx("div",{className:"flex justify-end",children:i.jsx(ue,{type:"submit",size:"sm",variant:"primary",icon:i.jsx(Er,{}),loading:o,disabled:f||s===e,children:n("appearance.save")})})]})})}const vae={id:"customize",module:fs("customize"),routes:[],i18n:{en:Vie,fr:Zie},slots:{settingsSections:[{id:"modules",label:"customize:sections.modules",icon:Jz,order:20,group:"workspace",component:oae},{id:"appearance",label:"customize:sections.appearance",icon:E0,order:21,group:"workspace",component:pae}]}},wae=[RW,EK,mZ,Fie,Die,JZ,eX,HX,mte,Une,vae,Hre,Nie];LH();Ez(wae);cw.createRoot(document.getElementById("root")).render(i.jsx(S.StrictMode,{children:i.jsx(BH,{})}));export{qw as A,Kw as B,In as C,jae as D,S as E,bE as F,nl as G,TP as H,qa as I,oe as J,i as K,Xs as L,Nae as M,Nn as N,bA as O,Xo as P,h_ as R,Hw as S,Sr as _,sl as a,lw as b,Zk as c,Sae as d,$f as e,Yk as f,kl as g,qB as h,tL as i,uB as j,Ns as k,eR as l,O0 as m,Zc as n,wp as o,BB as p,cB as q,Cae as r,L0 as s,Ww as t,Uk as u,Yf as v,i1 as w,uo as x,Zg as y,Qg as z};