{"context":{"domain":"natura-pay-crm"},"layers":{"ApplicationLayer":{"reference":"ApplicationLayer","availableInstances":[{"reference":"ComponentsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"SystemsDataSet","params":{"filter":{"domain":"data2"},"pagination":{"size":1},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSource"}}}},{"reference":"ExternalComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"SystemsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"5e3b796d6228227ca637d0f4","name":"data2","domain":"data2","organization":"62292184611f480b3191c37c","visibility":"public","updatedAt":"2026-07-27T14:19:36.810Z"}]}},{"reference":"OrganizationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"DataComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"OneFileComponentInstancesDataSet","params":{"pagination":{"size":1},"master":{"dataset":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSet"}},"localField":"system","masterField":"_id"},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"FileComponentInstancesDataSource"}}}},{"reference":"ApplicationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ServiceComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@Data2TableDataSource","reference":"FileComponentInstancesDataSource","params":{"table":"fileComponentInstances","schema":[{"component":"data2-core-types@Field","params":{"key":"component","title":"Component","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"system","title":"System","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"displayName","title":"Display Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"params","title":"Params","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"reference","title":"Reference","component":"data2-core-primitives@String"}}]}},{"component":"data2-core@MemoryDataSource","reference":"EmptyDataSource","params":{"initialData":[]}},{"reference":"ComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"UserComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"DataComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ServiceComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ExternalComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ApplicationsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}}],"processesParams":{}},"HostApplicationLayer":{"reference":"HostApplicationLayer","availableInstances":[{"_id":"5f15ff190528b92601890f71","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"SystemsTableDataSource"}},"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"domain"}}},"pk":"_id","fields":[{"component":"data2-core-types@FieldReference","params":{"key":"_id"}},{"component":"data2-core-types@FieldReference","params":{"key":"name"}},{"component":"data2-core-types@FieldReference","params":{"key":"domain"}},{"component":"data2-core-types@FieldReference","params":{"key":"visibility"}},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization._id"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.name"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.billingStatus"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.publicTrial.active"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"settings.defaultAccessPolicy"}}},"break":true}],"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"staticPagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"policies":[{"component":"data2-core-auth@Policy","params":{"allow":{"params":{"actions":[{"params":{"components":[{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"_id"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"domain"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"}]},"component":"data2-core-logical-operators@Or"}]},"component":"data2-core-flow@Series"}}}]},"reference":"SystemsDataSet","updatedAt":"2026-08-07T21:51:24.037Z","createdAt":"2020-07-20T20:31:21.838Z"},{"_id":"5f1601ce0528b92601890f7c","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":1000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"sort":{"params.package":1,"params.component":1},"pk":"_id","autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"staticFilter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}},"filter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}}},"reference":"ComponentsDataSet","updatedAt":"2025-11-05T19:37:01.935Z","createdAt":"2020-07-20T20:42:54.898Z"},{"_id":"5f9041dbc8da12be8b94aea4","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":2000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"UserComponentsDataSet","updatedAt":"2025-11-06T21:06:58.095Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"65d8c4fabc9dbb8f94de8d53","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ExternalComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ExternalComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:23.742Z","createdAt":"2024-02-23T16:17:01.816Z"},{"reference":"SystemsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"69bd2cbc4c2708c13a0b572b","name":"natura pay crm","domain":"natura-pay-crm","visibility":"public","settings":{"defaultAccessPolicy":"private"},"updatedAt":"2026-10-02T19:18:20.475Z","createdAt":"2026-03-20T11:17:16.160Z"}]}},{"reference":"ComponentsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"5f52a278a575399a45d239b4","component":"data2-core-types@Component","params":{"package":"data2-core-primitives","component":"Router","interactions":{"component":"data2-core-types@FieldSet","params":{"fields":{"goBack":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.goBack","args":[]}}}},"icon":{"component":"data2-core-primitives@String","params":{"content":"arrow-left"}},"visibility":"public"}},"goTo":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.push","args":[{"component":"data2-core-types@Reference","params":{"reference":"url"}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"preserveQuery"}}}}]}},"parameters":[{"component":"data2-core-primitives@String","params":{"content":"url"}},{"component":"data2-core-primitives@String","params":{"content":"preserveQuery"}}]},"break":true},"icon":{"component":"data2-core-primitives@String","params":{"content":"share"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Path to route"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Path to redirect user"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Boolean"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Preserve Query"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Preserve query string parameters  preserve query parameters on navigating."}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"}]}},"open":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.push","args":[{"pathname":{"component":"data2-core-types@Reference","params":{"reference":"value"}}}]}},"parameters":["value"]}},"icon":{"component":"data2-core-primitives@String","params":{"content":"share"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Link to open"}},"description":{"component":"data2-core-primitives@String","params":{"content":""}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Target"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Where to open the link"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"oneOf":[{"params":{"content":"_blank"},"component":"data2-core-primitives@String"},{"params":{"content":"_self"},"component":"data2-core-primitives@String"},{"params":{"content":"_parent"},"component":"data2-core-primitives@String"},{"params":{"content":"_top"},"component":"data2-core-primitives@String"}]},"component":"data2-core-types@ComponentParameter"}]}},"close":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":"close"}},"parameters":["value"]}},"icon":{"component":"data2-core-primitives@String","params":{"content":"times"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Link to open"}},"description":{"component":"data2-core-primitives@String","params":{"content":""}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Target"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Where to open the link"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"oneOf":[{"params":{"content":"_blank"},"component":"data2-core-primitives@String"},{"params":{"content":"_self"},"component":"data2-core-primitives@String"},{"params":{"content":"_parent"},"component":"data2-core-primitives@String"},{"params":{"content":"_top"},"component":"data2-core-primitives@String"}]},"component":"data2-core-types@ComponentParameter"}],"description":{"component":"data2-core-primitives@String","params":{"content":"Closes a window that was opened via router.open."}}}}}}}}},{"_id":"620d28658271aa4129919d89","component":"data2-core-types@Component","params":{"package":"data2-interface-services","component":"DeviceController","interactions":{"params":{"fields":{"postMessage":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@String","title":{"component":"data2-core-primitives@String","params":{"content":"data"}}}}]},"component":"data2-core-types@ComponentParameter"},"print":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"parameters":{"zoom":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Number"}},"title":{"component":"data2-core-primitives@String","params":{"content":"zoom"}},"visibility":"public"}}},"visibility":"public"},"component":"data2-core-types@ComponentParameter"}],"visibility":"public"},"component":"data2-core-types@ComponentParameter"},"share":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}}},"component":"data2-core-types@ComponentParameter"},"clipboard.copy":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}}}}]},"component":"data2-core-types@ComponentParameter"},"clipboard.paste":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}}}}]},"component":"data2-core-types@ComponentParameter"},"download":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Content"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Options"}},"parameters":{"params":{"fields":{"type":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Mimetype"}}}}}},"component":"data2-core-types@FieldSet"}}}]},"component":"data2-core-types@ComponentParameter"},"downloadUrl":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Url"}}}}]},"component":"data2-core-types@ComponentParameter"},"promptFiles":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@Object","flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"parameters":{"params":{"fields":{"multiple":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Multiple"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Whether or not to allow selecting multiple files"}},"component":"data2-core-primitives@Boolean"}},"acceptedFormats":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Accepted Formats"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Accepted file formats"}},"component":"data2-core-primitives@String","list":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}},"timeout":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Timeout"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Max milliseconds to wait for file upload"}},"component":"data2-core-primitives@Number"}}}},"component":"data2-core-types@FieldSet"}}}],"visibility":"public"},"component":"data2-core-types@ComponentParameter"},"meetingRecord":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","definition":{"params":{"actions":[{"params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"meeting"}},"script":{"component":"data2-core-primitives@String","params":{"content":"(function() {\n  let mediaRecorder;\n  let audioChunks = [];\n  let combinedStream;\n  let audioContext;\n  \n  window.meetingCapture = async function() {\n    try {\n      // Solicitar acesso ao áudio da guia (e vídeo, que será ignorado depois)\n      const tabStream = await navigator.mediaDevices.getDisplayMedia({ \n        video: true, // Necessário para alguns navegadores\n        audio: true\n      });\n      \n      // Remover a trilha de vídeo\n      const tabAudioTrack = tabStream.getAudioTracks()[0];\n      \n      // Solicitar acesso ao microfone\n      const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });\n      const micAudioTrack = micStream.getAudioTracks()[0];\n      \n      // Criar um novo MediaStream com ambas as trilhas de áudio\n      combinedStream = new MediaStream([tabAudioTrack, micAudioTrack]);\n      \n      // Criar um contexto de áudio para misturar os streams\n      audioContext = new AudioContext();\n      const destination = audioContext.createMediaStreamDestination();\n      \n      // Conectar a trilha de áudio da guia\n      const tabSource = audioContext.createMediaStreamSource(new MediaStream([tabAudioTrack]));\n      tabSource.connect(destination);\n      \n      // Conectar a trilha de áudio do microfone\n      const micSource = audioContext.createMediaStreamSource(new MediaStream([micAudioTrack]));\n      micSource.connect(destination);\n      \n      // Iniciar gravação com o stream misturado\n      mediaRecorder = new MediaRecorder(destination.stream);\n      audioChunks = [];\n      mediaRecorder.ondataavailable = (e) => audioChunks.push(e.data);\n      mediaRecorder.start();\n      \n      console.log('Gravação iniciada. Chame meetingCaptureStop() para finalizar.');\n    } catch (error) {\n      console.error('Erro ao iniciar a captura:', error);\n    }\n  };\n  \n  window.meetingCaptureStop = function() {\n    return new Promise((resolve, reject) => {\n      if (!mediaRecorder) {\n        reject('Nenhuma gravação em andamento.');\n        return;\n      }\n      \n      mediaRecorder.onstop = () => {\n        const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });\n        combinedStream.getTracks().forEach(track => track.stop());\n        audioContext.close();\n        \n        resolve(audioBlob);\n        console.log('Gravação finalizada. O arquivo de áudio está pronto para upload.');\n      };\n      \n      mediaRecorder.stop();\n    });\n  };\n})();"}}},"component":"data2-core-web@Script"},{"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":{"component":"data2-core-primitives@String","params":{"content":"meetingCapture"}}}}]},"component":"data2-core-flow@Series"}},"component":"data2-core-types@ComponentParameter"},"meetingRecordStop":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Content"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Options"}},"parameters":{"params":{"fields":{"type":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Mimetype"}}}}}},"component":"data2-core-types@FieldSet"}}}],"definition":{"params":{"actions":[{"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":{"component":"data2-core-primitives@String","params":{"content":"meetingCaptureStop"}}}}]},"component":"data2-core-flow@Series"}},"component":"data2-core-types@ComponentParameter"},"notify":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"private","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@Object","parameters":{"title":{"params":{"component":"data2-core-primitives@String","index":{"component":"data2-core-primitives@Number","params":{"content":0}},"title":{"component":"data2-core-primitives@String","params":{"content":"title"}}},"component":"data2-core-types@ComponentParameter"},"sound":{"params":{"component":"data2-core-types@FileComponentUrlReference","index":{"component":"data2-core-primitives@Number","params":{"content":1}},"title":{"component":"data2-core-primitives@String","params":{"content":"sound"}}},"component":"data2-core-types@ComponentParameter"}},"flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}}]},"component":"data2-core-types@ComponentParameter"}}},"component":"data2-core-types@FieldSet"}}},{"_id":"6a3db1250a33ea1e6b2a50c4","component":"data2-core-types@Component","system":"69bd2cbc4c2708c13a0b572b","params":{"extends":"data2-core-primitives@Block","component":"icHGMidS2T0qnSVa5bstW","package":"natura-pay-crm","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    select {\n      width: 100%;\n      height: 100%;\n      border: 1px solid #D1D5DB;\n      border-radius: 8px;\n      padding: 0 8px;\n      font-size: 13px;\n      background: #fff;\n      color: #374151;\n      cursor: pointer;\n      outline: none;\n    }\n    select:focus {\n      border-color: #7C3AED;\n      box-shadow: 0 0 0 2px rgba(124,58,237,0.15);\n    }\n  `,\n  render(d2) {\n    const opts = (d2.params.options || [\n      { label: 'Abertura de conta Emana Pay', value: 'abertura_de_conta_emana_pay' },\n      { label: 'Abertura de conta reduzida', value: 'abertura_de_conta_reduzida' }\n    ]).map(o => `<option value=\"${o.value}\">${o.label}</option>`).join('');\n    const placeholder = d2.params.placeholder || 'Todas as campanhas';\n    return `<select id=\"campaign-select\">\n      <option value=\"\">${placeholder}</option>\n      ${opts}\n    </select>`;\n  },\n  mounted(d2, root) {\n    d2.on(root.querySelector('#campaign-select'), 'change', e => {\n      d2.state.campanha = e.target.value;\n    });\n  }\n}"}},"options":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"options"}}}},"placeholder":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"placeholder"}}}}}}}}}},{"_id":"6aace4904ef0bfdfc9a51e20","component":"data2-core-types@Component","system":"69bd2cbc4c2708c13a0b572b","params":{"extends":"data2-core-primitives@Block","component":"qaSimulador","package":"natura-pay-crm","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    :host { display:block; }\n    * { box-sizing:border-box; }\n    .wrap {\n      display:grid; grid-template-columns: 300px 1fr 320px;\n      height:100%; font-family: ui-sans-serif, system-ui, -apple-system, sans-serif;\n      background:#F7F5F0; color:#1F2A24;\n    }\n    .col { overflow-y:auto; padding:22px; }\n    .left { background:#1E2B24; color:#EDEFEE; }\n    .right { background:#FDFCF9; border-left:1px solid #E3E0D6; }\n    .mid { display:flex; flex-direction:column; padding:0; }\n\n    h2 { font-size:13px; letter-spacing:.09em; text-transform:uppercase; margin:0 0 14px; opacity:.72; font-weight:700; }\n    .left h2 { color:#9FC4AE; }\n\n    .persona {\n      border:1px solid rgba(255,255,255,.14); border-radius:10px; padding:11px 13px;\n      margin-bottom:8px; cursor:pointer; background:transparent;\n    }\n    .persona:hover { background:rgba(255,255,255,.06); }\n    .persona.on { background:#2F6F4E; border-color:#2F6F4E; }\n    .persona .nm { font-weight:700; font-size:13.5px; }\n    .persona .tr { font-size:11.5px; opacity:.78; line-height:1.45; margin-top:3px; }\n    .persona .cn { font-size:10px; opacity:.6; margin-top:5px; font-family:ui-monospace,monospace; }\n\n    .head {\n      padding:18px 26px; border-bottom:1px solid #E3E0D6; background:#FDFCF9;\n      display:flex; align-items:center; gap:14px;\n    }\n    .head .who { font-weight:700; font-size:15px; }\n    .head .sub { font-size:11.5px; color:#5B6660; font-family:ui-monospace,monospace; }\n    .btn {\n      all:unset; cursor:pointer; font-size:12px; padding:6px 13px; border-radius:999px;\n      border:1px solid #D8D4C8; color:#5B6660; background:#fff;\n    }\n    .btn:hover { background:#F0EEE7; color:#1F2A24; }\n    .btn.pri { background:#2F6F4E; color:#fff; border-color:#2F6F4E; }\n    .btn.pri:hover { background:#255C40; color:#fff; }\n    .btn[disabled] { opacity:.4; cursor:default; }\n\n    .chat { flex:1; overflow-y:auto; padding:24px 26px; display:flex; flex-direction:column; gap:14px; }\n    .msg { display:flex; }\n    .msg.u { justify-content:flex-end; }\n    .bub {\n      max-width:74%; padding:11px 15px; border-radius:14px; font-size:13.5px; line-height:1.6;\n      white-space:pre-wrap; word-break:break-word;\n    }\n    .msg.b .bub { background:#fff; border:1px solid #E3E0D6; }\n    .msg.u .bub { background:#2F6F4E; color:#fff; }\n    .meta { font-size:10.5px; color:#93A0A6; font-family:ui-monospace,monospace; margin-top:7px; display:flex; gap:7px; flex-wrap:wrap; align-items:center; }\n    .tag { background:#F0EEE7; color:#5B6660; padding:1px 7px; border-radius:999px; }\n    .tag.bad { background:#F3DEDA; color:#7A2F26; font-weight:700; }\n    .acts { display:flex; gap:6px; margin-top:8px; }\n    .ico { all:unset; cursor:pointer; font-size:15px; padding:3px 8px; border-radius:7px; border:1px solid #E3E0D6; background:#fff; }\n    .ico:hover { background:#F0EEE7; }\n    .ico.on { background:#2F6F4E; border-color:#2F6F4E; }\n\n    .fb { margin-top:9px; background:#F7F5F0; border:1px solid #E3E0D6; border-radius:10px; padding:12px; }\n    .fb label { display:block; font-size:10.5px; text-transform:uppercase; letter-spacing:.06em; color:#5B6660; margin-bottom:4px; font-weight:700; }\n    .fb textarea, .fb input {\n      width:100%; font-family:inherit; font-size:12.5px; padding:7px 9px; border:1px solid #D8D4C8;\n      border-radius:7px; background:#fff; color:#1F2A24; resize:vertical; margin-bottom:9px;\n    }\n    .fb .row { display:flex; gap:7px; }\n\n    .composer { border-top:1px solid #E3E0D6; padding:14px 26px; background:#FDFCF9; display:flex; gap:10px; }\n    .composer textarea {\n      flex:1; font-family:inherit; font-size:13.5px; padding:10px 13px; border:1px solid #D8D4C8;\n      border-radius:10px; resize:none; height:46px; background:#fff; color:#1F2A24;\n    }\n\n    .kv { font-size:12px; line-height:1.65; margin-bottom:13px; }\n    .kv b { display:block; font-size:10px; text-transform:uppercase; letter-spacing:.06em; color:#93A0A6; margin-bottom:2px; }\n    .empty { color:#93A0A6; font-size:12.5px; line-height:1.7; padding:36px 26px; text-align:center; }\n    .warnbox { background:#F3DEDA; border-left:3px solid #B23A2E; padding:11px 13px; border-radius:8px; font-size:12px; line-height:1.6; margin-bottom:13px; }\n    .spin { font-size:12.5px; color:#5B6660; font-style:italic; }\n  `,\n\n  render(d2) {\n    const esc = (s) => String(s == null ? '' : s)\n      .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n\n    const personas = (d2.data('personasDs')?.records() || []).filter(p => p.ativo !== false);\n    const st = d2.state;\n    const msgs = st.msgs || [];\n    const sel = st.personaKey;\n    const pers = personas.find(p => p.persona_key === sel);\n\n    const left = `\n      <div class=\"col left\">\n        <h2>Persona</h2>\n        ${personas.map(p => `\n          <div class=\"persona ${p.persona_key === sel ? 'on' : ''}\" data-key=\"${esc(p.persona_key)}\" data-persona=\"${esc(p.persona_key)}\">\n            <div class=\"nm\">${esc(p.nome)}</div>\n            <div class=\"tr\">${esc(p.descricao)}</div>\n            <div class=\"cn\">cenário ${esc(p.cenario_origem)} · ${esc(p.nivel)}</div>\n          </div>`).join('')}\n      </div>`;\n\n    const chat = msgs.length ? msgs.map((m, i) => {\n      if (m.role === 'user') {\n        return `<div class=\"msg u\" data-key=\"m${i}\"><div><div class=\"bub\">${esc(m.text)}</div></div></div>`;\n      }\n      const falhas = (m.checks_falhados || []).map(c => `<span class=\"tag bad\">${esc(c)}</span>`).join('');\n      const aberto = st.fbIdx === i;\n      return `\n        <div class=\"msg b\" data-key=\"m${i}\">\n          <div style=\"max-width:74%\">\n            <div class=\"bub\">${esc(m.text)}</div>\n            <div class=\"meta\">\n              ${m.faq ? `<span class=\"tag\">FAQ ${esc(m.faq)}</span>` : ''}\n              ${m.estado ? `<span class=\"tag\">${esc(m.estado)}</span>` : ''}\n              ${falhas || (m.checks_rodados ? '<span class=\"tag\">checks ok</span>' : '')}\n            </div>\n            <div class=\"acts\">\n              <button class=\"ico ${m.fb === 'positivo' ? 'on' : ''}\" data-fb=\"positivo\" data-i=\"${i}\" title=\"Boa resposta — vira teste de regressão\">👍</button>\n              <button class=\"ico ${m.fb === 'negativo' ? 'on' : ''}\" data-fb=\"negativo\" data-i=\"${i}\" title=\"Resposta ruim — vira teste de progressão\">👎</button>\n            </div>\n            ${aberto ? `\n              <div class=\"fb\">\n                <label>Por que ${st.fbTipo === 'positivo' ? 'está boa' : 'está errada'}?</label>\n                <textarea class=\"f-motivo\" rows=\"2\" placeholder=\"${st.fbTipo === 'positivo' ? 'o que essa resposta acertou' : 'o que o bot deveria ter feito em vez disso'}\"></textarea>\n                ${st.fbTipo === 'negativo' ? `<label>Resposta ideal acordada</label><textarea class=\"f-ideal\" rows=\"3\" placeholder=\"escreva aqui a resposta que o bot deveria ter dado\"></textarea>` : ''}\n                <div class=\"row\">\n                  <button class=\"btn pri\" data-save=\"1\">Salvar feedback</button>\n                  <button class=\"btn\" data-cancel=\"1\">Cancelar</button>\n                </div>\n              </div>` : ''}\n          </div>\n        </div>`;\n    }).join('') : `<div class=\"empty\">Escolha uma persona à esquerda e escreva a primeira mensagem<br>como se você fosse ela.</div>`;\n\n    const ultima = [...msgs].reverse().find(m => m.role !== 'user');\n    const sm = ultima && ultima.state_machine ? ultima.state_machine : null;\n\n    const right = `\n      <div class=\"col right\">\n        <h2>O que o bot entendeu</h2>\n        ${st.erro ? `<div class=\"warnbox\">${esc(st.erro)}</div>` : ''}\n        ${sm ? `\n          <div class=\"kv\"><b>Estado</b>${esc(sm.estado || '—')}</div>\n          <div class=\"kv\"><b>Sub-estado</b>${esc(sm.sub_estado || '—')}</div>\n          <div class=\"kv\"><b>É recusa?</b>${sm.is_recusa ? 'sim' : 'não'}${sm.reason ? ' · ' + esc(sm.reason) : ''}</div>\n          <div class=\"kv\"><b>Instrução dada ao redator</b>${esc(sm.instrucao || '—')}</div>\n          <div class=\"kv\"><b>Resumo do histórico</b>${esc(sm.resumo || '—')}</div>\n        ` : `<div class=\"empty\" style=\"padding:20px 0\">Aparece aqui depois da primeira resposta.</div>`}\n      </div>`;\n\n    return `\n      <div class=\"wrap\">\n        ${left}\n        <div class=\"col mid\">\n          <div class=\"head\">\n            <div style=\"flex:1\">\n              <div class=\"who\">${pers ? esc(pers.nome) : 'Nenhuma persona escolhida'}</div>\n              <div class=\"sub\">${pers ? esc(pers.nivel) + ' · cenário ' + esc(pers.cenario_origem) : 'escolha à esquerda'}</div>\n            </div>\n            <button class=\"btn\" data-reset=\"1\">Recomeçar</button>\n          </div>\n          <div class=\"chat\">${chat}${st.carregando ? '<div class=\"spin\">o bot está respondendo…</div>' : ''}</div>\n          <div class=\"composer\">\n            <textarea class=\"entrada\" placeholder=\"${pers ? 'escreva como ' + esc(pers.nome.split(' ')[0]) + '…' : 'escolha uma persona primeiro'}\" ${pers ? '' : 'disabled'}></textarea>\n            <button class=\"btn pri\" data-send=\"1\" ${pers && !st.carregando ? '' : 'disabled'}>Enviar</button>\n          </div>\n        </div>\n        ${right}\n      </div>`;\n  },\n\n  mounted(d2) {\n    const ABERTURA = 'Olá, {{Nome}}! Tudo bem?\\nVi que você já utiliza o Pag Emana Pay para ter mais prazo e flexibilidade nos seus pedidos Natura e Avon. Isso já ajuda muito, mas sabia que sua rotina pode simplificar ainda mais, ao abrir sua conta Emana Pay? 🚀\\n\\nTopa abrir a sua conta agora para aproveitar essas vantagens ou prefere que eu te explique melhor como funcionam essas ferramentas?';\n\n    if (!d2.state.msgs) d2.state.msgs = [];\n\n    const perfilDe = (p) => ({\n      phone: p.telefone_ficticio || '5511900000000',\n      first_name: (p.nome || '').split(' ')[0],\n      name: p.nome,\n      nivel_consultora: p.nivel,\n      segmentacao_1: p.segmentacao,\n      hab_pep: p.ja_usou_pep === true,\n      hab_aproximaae: p.ja_usou_aproximaae === true,\n      ja_usou_superlink: p.ja_usou_superlink === true,\n      contratou_seg_estoque: p.contratou_seg_estoque === true,\n      campaign_id: '6a0328b953f0fae2fbc989e5'\n    });\n\n    d2.on('[data-persona]', 'click', (e) => {\n      const key = e.target.closest('[data-persona]').dataset.persona;\n      d2.setState({ personaKey: key, msgs: [{ role: 'agent', text: ABERTURA }], fbIdx: null, erro: null });\n    });\n\n    d2.on('[data-reset]', 'click', () => {\n      d2.setState({ msgs: d2.state.personaKey ? [{ role: 'agent', text: ABERTURA }] : [], fbIdx: null, erro: null });\n    });\n\n    const enviar = async () => {\n      const ta = d2.$('.entrada');\n      const texto = (ta?.value || '').trim();\n      const personas = d2.data('personasDs')?.records() || [];\n      const p = personas.find(x => x.persona_key === d2.state.personaKey);\n      if (!texto || !p || d2.state.carregando) return;\n\n      const anteriores = (d2.state.msgs || []).map(m => ({\n        role: m.role === 'user' ? 'user' : 'agent',\n        message: { text: m.text }\n      }));\n      const historico = anteriores.concat([{ role: 'user', message: { text: texto } }]);\n\n      d2.setState({\n        msgs: (d2.state.msgs || []).concat([{ role: 'user', text: texto }]),\n        carregando: true, erro: null, fbIdx: null\n      });\n      if (ta) ta.value = '';\n\n      try {\n        const r = await d2.rush('brainRush').invoke({\n          message: texto,\n          all_messages: historico,\n          user_data: perfilDe(p),\n          started_by_user: false,\n          chat_state_inicial: d2.state.chatState || 'ESTADO_1',\n          sub_state_inicial: d2.state.subState || '',\n          resumo_inicial: d2.state.resumo || ''\n        });\n        const dados = (r && r.data) ? r.data : r;\n        d2.setState({\n          carregando: false,\n          chatState: dados.state_machine?.estado || d2.state.chatState,\n          subState: dados.state_machine?.sub_estado || '',\n          resumo: dados.state_machine?.resumo || '',\n          msgs: (d2.state.msgs || []).concat([{\n            role: 'agent',\n            text: dados.resposta,\n            faq: dados.faq,\n            estado: dados.state_machine?.estado,\n            state_machine: dados.state_machine,\n            checks_rodados: dados.checks_rodados,\n            checks_falhados: dados.checks_falhados,\n            entrada: texto\n          }])\n        });\n      } catch (err) {\n        d2.setState({ carregando: false, erro: 'Falha ao chamar o bot: ' + (err?.message || err) });\n      }\n    };\n\n    d2.on('[data-send]', 'click', enviar);\n    d2.on('.entrada', 'keydown', (e) => {\n      if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); enviar(); }\n    });\n\n    d2.on('[data-fb]', 'click', (e) => {\n      const b = e.target.closest('[data-fb]');\n      d2.setState({ fbIdx: Number(b.dataset.i), fbTipo: b.dataset.fb });\n    });\n    d2.on('[data-cancel]', 'click', () => d2.setState({ fbIdx: null }));\n\n    d2.on('[data-save]', 'click', async () => {\n      const i = d2.state.fbIdx;\n      const m = (d2.state.msgs || [])[i];\n      if (m == null) return;\n      const motivo = d2.$('.f-motivo')?.value || '';\n      const ideal = d2.$('.f-ideal')?.value || '';\n      const personas = d2.data('personasDs')?.records() || [];\n      const p = personas.find(x => x.persona_key === d2.state.personaKey);\n      try {\n        await d2.data('feedbacksDs').create({\n          feedback_id: 'fb-' + Date.now(),\n          origem: 'simulador',\n          consultora: p ? p.nome : '',\n          seq: i,\n          mensagem_usuario: m.entrada || '',\n          mensagem_bot: m.text || '',\n          veredito: d2.state.fbTipo,\n          motivo: motivo,\n          resposta_ideal: ideal,\n          cenario: p ? p.cenario_origem : '',\n          criado_em: new Date().toISOString(),\n          virou_teste: false\n        });\n        const novas = (d2.state.msgs || []).slice();\n        novas[i] = Object.assign({}, novas[i], { fb: d2.state.fbTipo });\n        d2.setState({ msgs: novas, fbIdx: null });\n      } catch (err) {\n        d2.setState({ erro: 'Não consegui salvar o feedback: ' + (err?.message || err) });\n      }\n    });\n  }\n}"}},"personasDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"personasDs"}}}},"feedbacksDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"feedbacksDs"}}}},"brainRush":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brainRush"}}}}}}}}}},{"_id":"6aace781263c3723046fe391","component":"data2-core-types@Component","system":"69bd2cbc4c2708c13a0b572b","params":{"extends":"data2-core-primitives@Block","component":"qaApp","package":"natura-pay-crm","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"export default {\n  css: `\n    :host { display:block; }\n    * { box-sizing:border-box; }\n    .app { display:grid; grid-template-columns:236px 1fr; height:100%;\n      font-family:ui-sans-serif,system-ui,-apple-system,sans-serif; background:#F7F5F0; color:#1F2A24; }\n\n    .nav { background:#1E2B24; color:#EDEFEE; padding:24px 16px; display:flex; flex-direction:column; gap:26px; overflow-y:auto; }\n    .brand { font-family:Georgia,serif; font-size:19px; line-height:1.25; font-weight:600; }\n    .brand small { display:block; font-family:ui-monospace,monospace; font-size:9.5px; letter-spacing:.11em;\n      text-transform:uppercase; color:#8FB39E; margin-top:7px; }\n    .nv { all:unset; cursor:pointer; display:flex; align-items:center; gap:9px; padding:9px 12px;\n      border-radius:9px; font-size:13.5px; color:#C3D2C9; }\n    .nv:hover { background:rgba(255,255,255,.07); color:#fff; }\n    .nv.on { background:#2F6F4E; color:#fff; font-weight:700; }\n    .nv .n { margin-left:auto; font-family:ui-monospace,monospace; font-size:10.5px; opacity:.7; }\n\n    main { overflow-y:auto; padding:34px 40px 70px; }\n    h1 { font-family:Georgia,serif; font-size:31px; font-weight:600; margin:0 0 8px; line-height:1.15; }\n    .eyebrow { font-size:10.5px; letter-spacing:.13em; text-transform:uppercase; color:#2F6F4E; font-weight:700; margin:0 0 9px; }\n    .lede { font-size:14.5px; color:#5B6660; line-height:1.65; max-width:78ch; margin:0 0 26px; }\n    h2 { font-family:Georgia,serif; font-size:21px; font-weight:600; margin:34px 0 5px; }\n    .sub { font-size:13px; color:#5B6660; line-height:1.6; margin:0 0 15px; max-width:80ch; }\n\n    .kpis { display:grid; grid-template-columns:repeat(auto-fit,minmax(178px,1fr)); gap:13px; margin-bottom:8px; }\n    .kpi { background:#FDFCF9; border:1px solid #E3E0D6; border-radius:13px; padding:17px 19px; }\n    .kpi .n { font-family:Georgia,serif; font-size:29px; font-weight:700; color:#2F6F4E; line-height:1.1; }\n    .kpi.w .n { color:#B23A2E; }\n    .kpi .c { font-size:12px; color:#5B6660; line-height:1.4; margin-top:5px; }\n\n    .card { background:#FDFCF9; border:1px solid #E3E0D6; border-radius:14px; padding:22px; }\n    .card + .card { margin-top:13px; }\n    .warncard { border-left:3px solid #B23A2E; }\n    .warncard p { margin:0 0 9px; font-size:14px; line-height:1.65; max-width:86ch; }\n    .warncard p:last-child { margin:0; }\n    code { font-family:ui-monospace,monospace; font-size:12px; background:#F0EEE7; padding:1px 5px; border-radius:4px; }\n\n    table { width:100%; border-collapse:collapse; font-size:13px; }\n    th { text-align:left; font-size:10px; text-transform:uppercase; letter-spacing:.07em; color:#93A0A6;\n      padding:9px 11px; border-bottom:1px solid #E3E0D6; font-weight:700; }\n    td { padding:10px 11px; border-bottom:1px solid #EFEDE5; vertical-align:top; line-height:1.55; }\n    tr.clk { cursor:pointer; }\n    tr.clk:hover { background:#F7F5F0; }\n    .nm { font-weight:700; }\n    .mono { font-family:ui-monospace,monospace; font-size:11.5px; }\n\n    .bar { display:flex; align-items:center; gap:11px; margin-bottom:7px; }\n    .bar .lb { width:250px; flex-shrink:0; font-family:ui-monospace,monospace; font-size:11.5px; color:#5B6660; }\n    .bar .tk { flex:1; background:#F0EEE7; border-radius:6px; height:25px; position:relative; }\n    .bar .fl { position:absolute; left:0; top:0; height:25px; border-radius:6px; background:#2F6F4E;\n      display:flex; align-items:center; justify-content:flex-end; padding-right:8px; min-width:26px; }\n    .bar .fl.w { background:#B23A2E; }\n    .bar .fl b { font-family:ui-monospace,monospace; font-size:11.5px; color:#fff; }\n\n    .pill { display:inline-block; padding:2px 8px; border-radius:999px; font-size:10px; font-weight:700;\n      background:#F0EEE7; color:#5B6660; font-family:ui-monospace,monospace; }\n    .pill.bad { background:#F3DEDA; color:#7A2F26; }\n    .pill.ok { background:#DCE9E1; color:#1F4A34; }\n\n    .btn { all:unset; cursor:pointer; font-size:12.5px; padding:7px 15px; border-radius:999px;\n      border:1px solid #D8D4C8; color:#5B6660; background:#fff; }\n    .btn:hover { background:#F0EEE7; color:#1F2A24; }\n    .btn.pri { background:#2F6F4E; color:#fff; border-color:#2F6F4E; }\n    .btn.pri:hover { background:#255C40; }\n    .btn[disabled] { opacity:.4; cursor:default; }\n    .row { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }\n\n    .chat { background:#F7F5F0; border-radius:11px; padding:15px; max-height:440px; overflow-y:auto;\n      display:flex; flex-direction:column; gap:11px; }\n    .msg { display:flex; }\n    .msg.u { justify-content:flex-end; }\n    .bub { max-width:76%; min-width:0; width:fit-content; padding:10px 14px; border-radius:13px;\n      font-size:13px; line-height:1.6; white-space:pre-wrap; overflow-wrap:break-word; flex:0 1 auto; }\n    .msg.b .bub { background:#fff; border:1px solid #E3E0D6; }\n    .msg.u .bub { background:#2F6F4E; color:#fff; }\n    .meta { font-size:10px; color:#93A0A6; font-family:ui-monospace,monospace; margin-top:6px; display:flex; gap:6px; flex-wrap:wrap; }\n    .acts { display:flex; gap:6px; margin-top:7px; }\n    .ico { all:unset; cursor:pointer; font-size:14px; padding:3px 9px; border-radius:7px; border:1px solid #E3E0D6; background:#fff; }\n    .ico:hover { background:#F0EEE7; }\n    .ico.on { background:#2F6F4E; border-color:#2F6F4E; }\n\n    .fb { margin-top:9px; background:#FDFCF9; border:1px solid #E3E0D6; border-radius:10px; padding:13px; }\n    .fb label { display:block; font-size:10px; text-transform:uppercase; letter-spacing:.06em; color:#5B6660; margin-bottom:4px; font-weight:700; }\n    .fb textarea, .fb input, .fb select { width:100%; font-family:inherit; font-size:12.5px; padding:8px 10px;\n      border:1px solid #D8D4C8; border-radius:7px; background:#fff; color:#1F2A24; resize:vertical; margin-bottom:10px; }\n\n    .composer { display:flex; gap:9px; margin-top:13px; }\n    .composer textarea { flex:1; font-family:inherit; font-size:13px; padding:10px 13px; border:1px solid #D8D4C8;\n      border-radius:10px; resize:none; height:44px; background:#fff; }\n\n    .split { display:grid; grid-template-columns:1fr 330px; gap:15px; align-items:start; }\n    .kv { font-size:12.5px; line-height:1.6; margin-bottom:12px; }\n    .kv b { display:block; font-size:9.5px; text-transform:uppercase; letter-spacing:.06em; color:#93A0A6; margin-bottom:2px; }\n    .empty { color:#93A0A6; font-size:13px; line-height:1.7; padding:40px 20px; text-align:center; }\n    .note { font-size:11.5px; color:#5B6660; line-height:1.6; margin-top:11px; }\n    .persona { border:1px solid #E3E0D6; border-radius:10px; padding:11px 13px; margin-bottom:7px; cursor:pointer; background:#FDFCF9; }\n    .persona:hover { background:#F0EEE7; }\n    .persona.on { background:#2F6F4E; border-color:#2F6F4E; color:#fff; }\n    .persona .t { font-weight:700; font-size:13px; }\n    .persona .d { font-size:11.5px; opacity:.8; line-height:1.45; margin-top:3px; }\n\n    .navcap { font-family:ui-monospace,monospace; font-size:9px; letter-spacing:.12em; text-transform:uppercase;\n      color:#6E8B7B; padding:0 12px; margin-bottom:5px; }\n\n    .tabs { display:flex; gap:7px; flex-wrap:wrap; margin-bottom:18px; }\n    .tab { all:unset; cursor:pointer; padding:8px 15px; border-radius:999px; font-size:12.5px;\n      border:1px solid #D8D4C8; background:#fff; color:#5B6660; }\n    .tab:hover { background:#F0EEE7; }\n    .tab.on { background:#1E2B24; border-color:#1E2B24; color:#fff; font-weight:700; }\n\n    .sec { border:1px solid #E3E0D6; border-radius:11px; background:#FDFCF9; margin-bottom:8px; overflow:hidden; }\n    .sec > .hd { all:unset; cursor:pointer; display:flex; align-items:baseline; gap:11px; width:100%;\n      padding:13px 17px; box-sizing:border-box; }\n    .sec > .hd:hover { background:#F7F5F0; }\n    .sec .ix { font-family:ui-monospace,monospace; font-size:10.5px; color:#93A0A6; flex-shrink:0; width:20px; }\n    .sec .ti { font-weight:700; font-size:13.5px; flex:1; }\n    .sec .cv { font-family:ui-monospace,monospace; font-size:10px; color:#93A0A6; }\n    .sec .bd { padding:0 17px 16px 48px; }\n    .pre { font-family:ui-monospace,monospace; font-size:11.5px; line-height:1.65; white-space:pre-wrap;\n      background:#F4F2EC; border:1px solid #E3E0D6; border-radius:8px; padding:14px 15px;\n      max-height:460px; overflow:auto; margin:0; }\n    .pre .vr { background:#DCE9E1; color:#1F4A34; border-radius:3px; padding:0 3px; font-weight:700; }\n    .obs { margin-top:10px; font-size:12.5px; line-height:1.6; color:#5B6660;\n      border-left:2px solid #C8A227; padding-left:11px; }\n    .obs b { color:#1F2A24; }\n\n    .sm { display:flex; flex-direction:column; gap:9px; }\n    .st { border:1px solid #E3E0D6; border-radius:12px; background:#FDFCF9; padding:16px 19px; }\n    .st.warn { border-left:3px solid #B23A2E; }\n    .st .hd2 { display:flex; align-items:baseline; gap:10px; flex-wrap:wrap; margin-bottom:7px; }\n    .st .cd { font-family:ui-monospace,monospace; font-size:12px; font-weight:700; color:#2F6F4E; }\n    .st .nm2 { font-size:13.5px; font-weight:700; }\n    .st p { margin:0 0 7px; font-size:13px; line-height:1.65; max-width:84ch; }\n    .st p:last-child { margin:0; }\n    .st ul { margin:5px 0 7px; padding-left:19px; font-size:12.5px; line-height:1.6; color:#5B6660; }\n    .arw { text-align:center; font-size:15px; color:#B5BEB8; line-height:1; }\n\n    td.acts { white-space:nowrap; width:1%; text-align:right; }\n    .mini { all:unset; cursor:pointer; font-size:12px; padding:4px 9px; border-radius:7px;\n      border:1px solid #E3E0D6; background:#fff; color:#5B6660; margin-left:4px; }\n    .mini:hover { background:#F0EEE7; color:#1F2A24; }\n    .mini.danger:hover { background:#F3DEDA; color:#7A2F26; border-color:#E0BDB6; }\n    .confirmar { background:#FBF3F1; padding:13px 15px; }\n    .confirmar b { font-size:13px; }\n    .confirmar p { margin:4px 0 10px; font-size:12.5px; color:#5B6660; line-height:1.6; }\n    .editar { background:#F7F5F0; padding:15px; }\n    .editar .lin { display:grid; grid-template-columns:150px 1fr; gap:11px; align-items:start; margin-bottom:10px; }\n    .editar label { font-size:10px; text-transform:uppercase; letter-spacing:.06em; color:#5B6660;\n      font-weight:700; padding-top:8px; }\n    .editar input, .editar textarea, .editar select { width:100%; font-family:inherit; font-size:12.5px;\n      padding:7px 10px; border:1px solid #D8D4C8; border-radius:7px; background:#fff; color:#1F2A24;\n      resize:vertical; box-sizing:border-box; }\n    .editar textarea { min-height:58px; line-height:1.55; }\n    .editar .curta { max-width:110px; }\n  `,\n\n  render(d2) {\n    const esc = (s) => String(s == null ? '' : s)\n      .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/\"/g,'&quot;');\n    const st = d2.state;\n    const view = st.view || 'geral';\n\n    const convs = d2.data('conversasDs')?.records() || [];\n    const msgs  = d2.data('mensagensDs')?.records() || [];\n    const fbs   = d2.data('feedbacksDs')?.records() || [];\n    const tests = d2.data('testsDs')?.records() || [];\n    const checks= d2.data('checksDs')?.records() || [];\n    const pers  = (d2.data('personasDs')?.records() || []).filter(p => p.ativo !== false);\n    const res   = d2.data('resultadosDs')?.records() || [];\n\n    const nav = [\n      ['geral','Visão geral',''],\n      ['conversas','Conversas reais', convs.length || ''],\n      ['simulador','Simulador',''],\n      ['feedbacks','Feedbacks', fbs.length || ''],\n      ['testes','Testes', tests.length || ''],\n    ].map(([k,l,n]) => `<button class=\"nv ${view===k?'on':''}\" data-view=\"${k}\">${l}<span class=\"n\">${n}</span></button>`).join('');\n\n    const nav2 = [\n      ['prompts','Prompts base',''],\n      ['estados','Máquina de estados',''],\n    ].map(([k,l,n]) => `<button class=\"nv ${view===k?'on':''}\" data-view=\"${k}\">${l}<span class=\"n\">${n}</span></button>`).join('');\n\n    return `<div class=\"app\">\n      <nav class=\"nav\">\n        <div class=\"brand\">Dinâmica<br>CRM Abertura de Contas<small>Emana Pay</small></div>\n        <div style=\"display:flex;flex-direction:column;gap:3px\">${nav}</div>\n        <div>\n          <div class=\"navcap\">Como o bot funciona</div>\n          <div style=\"display:flex;flex-direction:column;gap:3px\">${nav2}</div>\n        </div>\n      </nav>\n      <main>${this.view(d2, view, {convs,msgs,fbs,tests,checks,pers,res,esc})}</main>\n    </div>`;\n  },\n\n  view(d2, v, x) {\n    if (v === 'conversas')  return this.vConversas(d2, x);\n    if (v === 'simulador')  return this.vSimulador(d2, x);\n    if (v === 'feedbacks')  return this.vFeedbacks(d2, x);\n    if (v === 'testes')     return this.vTestes(d2, x);\n    if (v === 'prompts')    return this.vPrompts(d2, x);\n    if (v === 'estados')    return this.vEstados(d2, x);\n    return this.vGeral(d2, x);\n  },\n\n  carregaPrompt(d2, key, url) {\n    const t = (d2.state.ptxt || {})[key];\n    if (t !== undefined) return t;\n    this._ld = this._ld || {};\n    if (!this._ld[key]) {\n      this._ld[key] = true;\n      fetch(url)\n        .then(r => { if (!r.ok) throw new Error('HTTP ' + r.status); return r.text(); })\n        .then(txt => d2.setState({ ptxt: Object.assign({}, d2.state.ptxt, { [key]: txt }) }))\n        .catch(e => d2.setState({ ptxt: Object.assign({}, d2.state.ptxt, { [key]: '__ERRO__' + ((e && e.message) || e) }) }));\n    }\n    return null;\n  },\n\n  fatiaPrompt(txt) {\n    const secs = []; let atual = null;\n    txt.split('\\n').forEach(l => {\n      const m = /^##\\s+(.*)$/.exec(l);\n      if (m) { atual = { titulo: m[1].trim(), corpo: [] }; secs.push(atual); }\n      else if (atual) atual.corpo.push(l);\n    });\n    return secs.map(s => ({ titulo: s.titulo, texto: s.corpo.join('\\n').replace(/^\\s+|\\s+$/g, '') }));\n  },\n\n  vPrompts(d2, x) {\n    const esc = x.esc;\n    const sel = d2.state.promptSel || 'bot2';\n\n    const NOTAS = {\n      bot2: {\n        '2. Contexto da Conversa': 'Aqui ele recebe a ordem de obedecer o Bot 1. Logo adiante, na seção 7, recebe o manual completo para classificar sozinho. As duas instruções se contradizem, e é parte do motivo de a mesma mensagem receber respostas diferentes a cada vez.',\n        '3. Estrutura Obrigatória de Resposta': 'Define a receita de toda mensagem: gancho, argumento e CTA. O checklist final manda remover qualquer coisa que soe como linguagem de suporte — inclusive quando a consultora está pedindo suporte.',\n        '6. Serviços Habilitados para a Consultora': 'Montado com condicionais sobre o cadastro dela. Se o perfil chegar como texto em vez de objeto, todas as condicionais caem no ramo negativo em silêncio: a consultora elegível passa a ser tratada como não elegível, sem erro nenhum aparecer.',\n        '7. Máquina de Estados da Conversa': 'Traz a definição dos estados e os critérios de avanço. Não existe seção para ESTADO_REATIVACAO: quando o Bot 1 classifica assim, o comportamento chega só pela instrução, não pelo prompt.',\n        '9. Regras de Comportamento Conversacional': 'A maior seção do prompt. Nela também estão embutidos, dentro de condicionais de elegibilidade, o catálogo fechado de produtos, as especificações vindas da tabela e os argumentos por objeção. Três regras aqui não cabem juntas: combinar pelo menos duas FAQs, tratar uma coisa de cada vez, e caber em 150 palavras.',\n        '14. Segurança': 'Proíbe repetir CPF, dados bancários e senha. Não há nenhuma regra sobre pedir selfie, documento ou foto — e essas palavras não aparecem em lugar nenhum do prompt, apesar de serem etapas do onboarding.',\n        '18. Base de Conhecimento (FAQ)': 'Obriga combinar pelo menos duas FAQs e manda ignorar qualquer menção a Cartão de Crédito e cashback. Nos logs, a busca frequentemente devolve justamente a FAQ de cartão de crédito como primeiro resultado.',\n        '19. Formato de Resposta': 'Diz \"as quatro tags abaixo\" e lista cinco. Nos logs, o modelo emite as tags sem fechar, e o extrator acaba gravando a resposta inteira dentro do campo de FAQ — por isso a atribuição de qual FAQ foi usada está contaminada.',\n      },\n      bot1: {\n        'Input Recebido': 'O catálogo inteiro de motivos de recusa entra no prompt a cada turno. Quanto mais motivos cadastrados, maior o prompt.',\n        'Definição de Estados': 'Aqui está o buraco do cenário E: a lista de fora de escopo cobre problema no app da Natura, mas não cobre problema no próprio Emana Pay. \"Tentei abrir e deu erro\" não é ESTADO_3 nem objeção — cai no ESTADO_1 e vira argumento de venda.',\n        'Análise de Motivo de Recusa': 'O bot cria linha nova na tabela de motivos sozinho, sem ninguém aprovar. Vale conferir na dinâmica que motivos ele já inventou.',\n        'Como Construir o Resumo': 'A seção mais importante do sistema inteiro. O Bot 2 não vê as mensagens originais: vê este resumo. O que não for escrito aqui deixa de existir para quem redige.',\n        'Como Gerar a Instrução para o Bot 2': 'A instrução é o único canal de controle sobre o redator. Se sair vaga, o Bot 2 volta ao comportamento padrão do prompt dele, que é vender.',\n        'Formato de Saída': 'O pedido para não usar bloco de markdown existe porque o modelo escapa com cercas de código. Quando escapa, o JSON não parseia e o turno inteiro falha.',\n      },\n    };\n\n    const INTENCAO = 'you need to break-down user questions/intentions/topics,\\nanswering one or more intention objects:\\n\\n[{\\n\"intention\" : \"\",\\n\"user_message_chunk\" : \"\",\\n}]\\n\\navailable_intents : \"faq\"';\n\n    const JUIZ = [\n      { titulo: 'Papel', texto: 'Você é o juiz de uma suíte de testes de comportamento de um agente de atendimento por WhatsApp. O agente avaliado vende a conta digital Emana Pay para consultoras Natura/Avon.\\n\\nSeu trabalho é decidir, com rigor e sem simpatia pelo agente, se uma resposta produzida por ele ATENDE o critério de aceite que um time humano definiu numa dinâmica de trabalho. Você não é o autor do agente e não tem interesse em que ele passe.\\n\\nVocê recebe sempre:\\n- CONTEXTO: o histórico da conversa até ali e o perfil da consultora\\n- ENTRADA: a última coisa que a consultora disse\\n- RESPOSTA OBTIDA: o que o agente respondeu agora\\n- CRITÉRIO DE ACEITE: a regra de comportamento, escrita por gente, que decide o veredito\\n- TIPO DE TESTE: \"regressao\" ou \"progressao\"\\n- RESPOSTA DE REFERÊNCIA (opcional): em regressão, a resposta que já foi considerada boa; em progressão, a resposta ideal acordada pelo time' },\n      { titulo: 'Regras de julgamento', texto: 'REGRAS DE JULGAMENTO — siga na ordem:\\n\\n1. JULGUE O COMPORTAMENTO, NUNCA A REDAÇÃO. A resposta de referência é um exemplo do que se espera, não um gabarito literal. Uma resposta escrita de forma completamente diferente PASSA se cumpre o critério. Uma resposta parecidíssima com a referência FALHA se não cumpre.\\n\\n2. O CRITÉRIO DE ACEITE MANDA. Se o critério exige uma ação (reconhecer uma reclamação, parar de pedir o motivo, encaminhar para suporte, não emitir CTA), verifique literalmente se aquilo aconteceu no texto. Não dê crédito por intenção, tom simpático ou proximidade temática.\\n\\n3. DIFERENÇA ENTRE OS TIPOS:\\n   - \"regressao\": a resposta antiga era boa. Pergunte \"a resposta de agora continua cumprindo o critério?\". Pequenas variações de forma são aceitáveis.\\n   - \"progressao\": a resposta antiga era RUIM e o time definiu o comportamento correto. Pergunte \"a resposta de agora passou a cumprir o critério?\". Seja mais exigente: o teste nasceu vermelho justamente porque o comportamento não existia.\\n\\n4. FALHAS AUTOMÁTICAS, independentemente do critério. Se a RESPOSTA OBTIDA contiver qualquer uma destas, o veredito é \"falhou\":\\n   - placeholder não substituído\\n   - pedido de CPF, documento ou selfie dentro da conversa\\n   - afirmação de ter executado uma ação que o agente não executa (por exemplo \"já enviei o link\", \"acionei o suporte\")\\n   - dado de contato incompleto, como um telefone com \"xxxx\"\\n   - tratamento da consultora por um nome diferente do que consta no perfil\\n\\n5. QUANDO NÃO DER PARA DECIDIR, use \"inconclusivo\". É melhor devolver para revisão humana do que aprovar por dúvida. Nunca invente uma justificativa para fechar o caso.\\n\\n6. JUSTIFIQUE CITANDO. A justificativa precisa conter o trecho exato da resposta obtida que sustenta o veredito, entre aspas. Máximo 2 frases.' },\n      { titulo: 'Formato de saída', texto: 'Responda SOMENTE com um objeto JSON válido, sem markdown, sem cercas de código, sem texto antes ou depois.\\n\\nFormato exato:\\n{\"veredito\":\"passou|falhou|inconclusivo\",\"confianca\":0.0,\"justificativa\":\"...\",\"trecho_citado\":\"...\",\"criterio_atendido\":true,\"falhas_automaticas\":[\"...\"]}\\n\\n- \"veredito\": exatamente uma das três palavras\\n- \"confianca\": número entre 0 e 1 com uma casa decimal\\n- \"justificativa\": no máximo 2 frases, em português do Brasil\\n- \"trecho_citado\": o trecho literal da resposta obtida que sustenta o veredito\\n- \"criterio_atendido\": true ou false\\n- \"falhas_automaticas\": lista das falhas da regra 4 encontradas' },\n    ];\n\n    const P = {\n      bot2: { nome: 'Bot 2 — redator', papel: 'Escreve a mensagem que a consultora lê. Recebe a instrução do Bot 1 e obedece.',\n        onde: 'sales-assistant-prompt · assistant write-final-answer · modelo cerebras',\n        url: 'https://natura-pay-crm.data2.media/file/TQHokX_nl-WrHDRkAm2w1' },\n      bot1: { nome: 'Bot 1 — classificador', papel: 'Lê a conversa e decide o estado. Não fala com a consultora: devolve estado, resumo e instrução.',\n        onde: 'state-machine-prompt · assistant assistant-state-machine · modelo cerebras',\n        url: 'https://natura-pay-crm.data2.media/file/9fIZWM5P9BjLImCGgE1hq' },\n      intencao: { nome: 'Quebra de intenção', papel: 'Primeiro passo do turno: parte a fala da consultora em intenções antes da busca de FAQ.',\n        onde: 'assistant break-down-user-intentions · modelo cerebras · saída em JSON',\n        secs: [{ titulo: 'Prompt completo', texto: INTENCAO }] },\n      juiz: { nome: 'Juiz dos testes', papel: 'Não faz parte do bot. É quem avalia se uma resposta cumpre o critério de aceite escrito pelo time.',\n        onde: 'assistant qa-juiz · modelo cerebras · usado só nesta ferramenta',\n        secs: JUIZ },\n    };\n\n    const ordem = ['bot1','bot2','intencao','juiz'];\n    const tabs = ordem.map(k =>\n      `<button class=\"tab ${sel===k?'on':''}\" data-prompt=\"${k}\">${esc(P[k].nome)}</button>`).join('');\n\n    const p = P[sel];\n    let secs = p.secs || null;\n    let aviso = '';\n    if (!secs) {\n      const txt = this.carregaPrompt(d2, sel, p.url);\n      if (txt === null) {\n        aviso = '<div class=\"empty\">Carregando o prompt…</div>';\n      } else if (txt.indexOf('__ERRO__') === 0) {\n        aviso = `<div class=\"card warncard\"><p><b>Não consegui carregar o prompt.</b> ${esc(txt.slice(9))}</p></div>`;\n      } else {\n        secs = this.fatiaPrompt(txt);\n      }\n    }\n\n    const notas = NOTAS[sel] || {};\n    const destaca = (s) => esc(s).replace(/\\$\\{[^}]*\\}/g, m => '<span class=\"vr\">' + m + '</span>');\n\n    const corpo = secs ? secs.map((s, i) => {\n      const k = sel + '-' + i;\n      const aberta = d2.state.secAberta === k;\n      const nota = notas[s.titulo];\n      return `<div class=\"sec\">\n        <button class=\"hd\" data-sec=\"${k}\">\n          <span class=\"ix\">${aberta ? '&#9662;' : '&#9656;'}</span>\n          <span class=\"ti\">${esc(s.titulo)}</span>\n          <span class=\"cv\">${nota ? 'tem observação · ' : ''}${s.texto.length} car.</span>\n        </button>\n        ${aberta ? `<div class=\"bd\">\n          <pre class=\"pre\">${destaca(s.texto)}</pre>\n          ${nota ? `<div class=\"obs\"><b>Observação:</b> ${esc(nota)}</div>` : ''}\n        </div>` : ''}\n      </div>`;\n    }).join('') : '';\n\n    const comNota = secs ? secs.filter(s => notas[s.titulo]).length : 0;\n\n    return `\n      <p class=\"eyebrow\">Como o bot funciona</p>\n      <h1>Prompts base</h1>\n      <p class=\"lede\">O texto integral das instruções que governam o bot, como estão hoje no ar.\n      Nada aqui é resumo: é o que cada modelo recebe antes de responder. Clique numa seção para abrir.</p>\n\n      <div class=\"tabs\">${tabs}</div>\n\n      <div class=\"card\">\n        <div class=\"kv\"><b>O que faz</b>${esc(p.papel)}</div>\n        <div class=\"kv\" style=\"margin-bottom:0\"><b>Onde está</b><span class=\"mono\">${esc(p.onde)}</span></div>\n      </div>\n\n      ${secs ? `<p class=\"sub\" style=\"margin-top:18px\">${secs.length} seções${comNota ? ` · ${comNota} com observação nossa` : ''}. Os trechos destacados em verde são os campos preenchidos em tempo real, a cada mensagem.</p>` : ''}\n      ${aviso}\n      ${corpo}\n\n      ${sel === 'bot2' ? `<div class=\"card warncard\" style=\"margin-top:16px\">\n        <p><b>Por que os números das seções pulam de 9 para 14.</b> As seções 10 a 13 — catálogo de produtos,\n        especificações, argumentos por objeção e parte dos guardrails — não são texto solto: estão dentro de\n        condicionais de elegibilidade e aparecem embutidas na seção 9. Elas mudam de acordo com o cadastro da\n        consultora, então duas pessoas diferentes recebem prompts diferentes.</p>\n        <p><b>Metade do registro é lixo.</b> Junto do prompt ativo existe uma cópia de uma versão antiga,\n        guardada num campo de backup. São 37 mil caracteres que não fazem nada — mas quem editar a cópia por\n        engano não vê efeito nenhum.</p>\n      </div>` : ''}`;\n  },\n\n  vEstados(d2, x) {\n    const ESTADOS = [\n      { cd:'ESTADO_1', nm:'Exploração e superação de barreiras', warn:false,\n        quando:['É a primeira mensagem da conversa',\n          'Ela demonstrou dúvida, receio ou objeção ainda não respondida',\n          'Ela não deu sinal claro nem de abertura nem de recusa'],\n        fica:['A frase tem conectivo de contraste: \"mas\", \"porém\", \"só que\", \"mesmo assim\", \"ainda assim\"',\n          'O tom carrega ceticismo, mesmo sem objeção explícita',\n          'Apareceu objeção nova ainda não respondida'],\n        faz:'Responde a objeção com empatia e um benefício concreto, e fecha com uma pergunta leve. Não tenta fechar a venda de forma direta.',\n        obs:'\"Agora não\", \"depois\", \"vou pensar\", \"tô ocupada\" caem aqui, não em recusa. Na prática isso dá ao bot licença para insistir mais uma vez antes de aceitar o não.' },\n\n      { cd:'ESTADO_2', nm:'Tentativa de conversão', warn:false,\n        quando:['Ela pediu o passo a passo',\n          'Ela usou \"parece bom\", \"faz sentido\", \"vou abrir\", \"quero saber mais\", \"me manda\"',\n          'Ela confirmou um benefício sem ressalva',\n          'Ela demonstrou abertura e só fez perguntas práticas sobre como abrir'],\n        fica:['Ou: levantou objeção, a objeção foi respondida, a última mensagem não trouxe objeção nova e não tem conectivo de contraste'],\n        faz:'Fica direta. Reforça o resultado concreto e usa CTA de ação, alternando o CTA a cada mensagem.',\n        obs:'Pergunta prática (\"demora muito?\", \"precisa de documento?\") conta como intenção de abrir, não como objeção.' },\n\n      { cd:'ESTADO_3', nm:'Fora de escopo', warn:false,\n        quando:['Pedido Natura/Avon: rastreio, prazo, entrega, troca, devolução, produto errado',\n          'Catálogo, preço, comissão, pontuação, Plano de Crescimento',\n          'Cadastro da consultoria, app ou site Natura/Avon',\n          'Outro banco, assunto pessoal'],\n        fica:['Dura uma única mensagem e nunca se repete em sequência',\n          'Se ela insistir no mesmo assunto externo, volta para ESTADO_1 sem repetir o direcionamento'],\n        faz:'Reconhece em uma frase, diz que cuida só do Emana Pay, direciona para o 0800 011 55 66 uma única vez e retoma o assunto de onde parou. Sem CTA de venda, máximo 80 palavras.',\n        obs:'A lista cobre problema no app da Natura, mas não cobre problema no próprio Emana Pay. \"Tentei abrir a conta e deu erro\" não é ESTADO_3, não é objeção de venda — cai no ESTADO_1 e o bot responde com argumento comercial em cima de uma falha técnica. É o cenário E.' },\n\n      { cd:'FLUXO_ACEITACAO', nm:'Ela aceitou', warn:false,\n        quando:['Concordou em abrir a conta',\n          'Perguntou como ou onde abrir',\n          'Pediu o passo a passo depois de um CTA direto'],\n        fica:[],\n        faz:'Confirma o aceite, envia o passo a passo de abertura, pergunta se ficou dúvida e encerra encorajando.',\n        obs:'É o único estado que dispara o passo a passo. O texto do passo a passo não está no prompt: vem da tabela de FAQ com o rótulo OPEN_ACCOUNT.' },\n\n      { cd:'FLUXO_RECUSA', nm:'Ela recusou de verdade', warn:true,\n        quando:['Usou \"não tenho interesse\", \"não quero\", \"pode encerrar\", \"não vou abrir\", \"para de mandar\"',\n          'Repetiu a mesma objeção depois de já ter sido respondida',\n          'Recusou CTA direto mais de uma vez',\n          'Repetiu uma recusa branda mesmo depois de uma tentativa de reversão',\n          'O tom indica desconforto claro em continuar'],\n        fica:['Sub-estado aguardando_motivo: a recusa foi identificada mas a pergunta de encerramento ainda não foi feita',\n          'Sub-estado recusa_completa: a pergunta de encerramento já foi feita, tendo ela respondido o motivo ou não'],\n        faz:'Respeita sem insistir, faz uma única pergunta de encerramento sondando o motivo, agradece e encerra. Não tenta mais nenhuma conversão.',\n        obs:'Recusa branda na PRIMEIRA vez não entra aqui — é ESTADO_1. É por isso que um \"agora não\" costuma receber mais uma investida antes de o bot aceitar.' },\n\n      { cd:'ESTADO_REATIVACAO', nm:'Ela voltou depois de recusar', warn:true,\n        quando:['O resumo anterior indica sub-estado recusa_completa',\n          'E ela mandou qualquer mensagem nova, seja qual for o conteúdo'],\n        fica:[],\n        faz:'Retoma com acolhimento, sem mencionar a recusa anterior, tratando como ESTADO_1 com tom leve.',\n        obs:'Conversa encerrada por recusa reabre por desenho, em qualquer mensagem nova. Vale a pergunta na dinâmica: uma pessoa que pediu para parar e escreveu de novo deve voltar para o funil de venda?' },\n    ];\n\n    const blocos = ESTADOS.map((e, i) => `\n      <div class=\"st ${e.warn ? 'warn' : ''}\">\n        <div class=\"hd2\"><span class=\"cd\">${e.cd}</span><span class=\"nm2\">${x.esc(e.nm)}</span></div>\n        <p><b>Quando entra:</b></p>\n        <ul>${e.quando.map(q => `<li>${x.esc(q)}</li>`).join('')}</ul>\n        ${e.fica.length ? `<p><b>Regras de permanência:</b></p><ul>${e.fica.map(q => `<li>${x.esc(q)}</li>`).join('')}</ul>` : ''}\n        <p><b>O que o bot faz:</b> ${x.esc(e.faz)}</p>\n        <div class=\"obs\">${x.esc(e.obs)}</div>\n      </div>\n      ${i < ESTADOS.length - 1 ? '<div class=\"arw\">&#9662;</div>' : ''}`).join('');\n\n    return `\n      <p class=\"eyebrow\">Como o bot funciona</p>\n      <h1>A máquina de estados</h1>\n      <p class=\"lede\">Toda mensagem que chega passa por uma classificação antes de virar resposta.\n      O estado escolhido define o que o bot pode e não pode fazer naquele turno. Quem classifica não é\n      quem escreve.</p>\n\n      <h2>Dois bots, não um</h2>\n      <div class=\"card\">\n        <table>\n          <tr><th>Quem</th><th>O que faz</th><th>O que entrega</th></tr>\n          <tr><td class=\"nm\">Bot 1 — analisador</td>\n            <td>Lê a conversa inteira e classifica em que ponto do funil ela está. Não fala com a consultora.</td>\n            <td class=\"mono\">estado, sub_estado, resumo, instrução</td></tr>\n          <tr><td class=\"nm\">Bot 2 — redator</td>\n            <td>Recebe a instrução do Bot 1 e escreve a mensagem que a consultora lê.</td>\n            <td class=\"mono\">a resposta final</td></tr>\n        </table>\n      </div>\n\n      <div class=\"card warncard\" style=\"margin-top:13px\">\n        <p><b>O Bot 2 não vê a conversa original.</b> Ele vê um resumo em prosa que o Bot 1 reescreve a cada\n        mensagem. O que o Bot 1 esquecer de colocar no resumo deixa de existir para quem redige a resposta.\n        Se a consultora contou no começo que já tentou abrir e deu erro, e isso não entrou no resumo, o\n        redator responde como se nunca tivesse ouvido.</p>\n        <p><b>E o Bot 2 tem instrução conflitante.</b> Ele recebe \"siga obrigatoriamente o estado, não\n        reclassifique por conta própria\" e, algumas linhas depois, o manual completo de como classificar\n        o estado sozinho. Isso é parte do motivo de a mesma mensagem receber respostas diferentes a cada vez.</p>\n      </div>\n\n      <h2>Os seis estados</h2>\n      <p class=\"sub\">Na ordem em que costumam aparecer numa conversa. Em destaque vermelho, os dois que\n      valem discussão na dinâmica.</p>\n      <div class=\"sm\">${blocos}</div>\n\n      <h2>O que isso quer dizer para a dinâmica</h2>\n      <div class=\"card\">\n        <p style=\"margin:0 0 9px;font-size:14px;line-height:1.65;max-width:86ch\">Quando a gente discordar de\n        uma resposta do bot, a pergunta útil não é \"o texto ficou ruim\". É <b>em qual estado essa mensagem\n        deveria ter caído</b>. Quase toda falha que a gente catalogou é um erro de classificação, não de\n        redação — e erro de classificação se conserta mudando as regras de entrada de um estado, que é um\n        texto curto e legível.</p>\n        <p style=\"margin:0;font-size:14px;line-height:1.65;max-width:86ch\">Por isso cada caso de teste\n        guarda o estado em que a conversa começou: sem isso, o mesmo texto de entrada pode passar ou\n        falhar dependendo de onde o bot achava que estava.</p>\n      </div>`;\n  },\n\n  vGeral(d2, x) {\n    const { convs, checks, esc } = x;\n    const humano = convs.filter(c => c.resposta_tipo === 'humano').length;\n    const robo   = convs.filter(c => c.resposta_tipo === 'robo').length;\n    const conv   = convs.filter(c => c.status === 'CONVERTED').length;\n    const DISPARADAS = 632, SILENCIO = 601;\n    if (!convs.length) return `\n      <p class=\"eyebrow\">Visão geral</p>\n      <h1>O que os dados reais dizem antes da gente decidir qualquer coisa</h1>\n      <div class=\"card warncard\"><p><b>Carregando os dados…</b> Se esta mensagem continuar aqui, atualize a página.</p></div>`;\n\n    const porCenario = {};\n    convs.forEach(c => { porCenario[c.cenario] = (porCenario[c.cenario]||0)+1; });\n    porCenario['A'] = SILENCIO;\n    const nomes = {A:'Silêncio / não-resposta',R:'Resposta automática (robô da consultora)',B:'Aceitação direta',\n      C:'Recusa branda / adiamento',D:'Recusa firme com motivo',E:'Reclamação operacional camuflada',\n      F:'Erro de premissa',G:'Engajou, não decidiu'};\n    const maxC = Math.max(...Object.values(porCenario));\n    const barras = Object.entries(porCenario).sort((a,b)=>b[1]-a[1]).map(([k,n]) => `\n      <div class=\"bar\"><div class=\"lb\">${k} · ${esc(nomes[k]||k)}</div>\n        <div class=\"tk\"><div class=\"fl ${['D','E','R'].includes(k)?'w':''}\" style=\"width:${Math.max(3,100*n/maxC)}%\"><b>${n}</b></div></div>\n      </div>`).join('');\n\n    const alcance = {};\n    convs.forEach(c => (c.falhas||[]).forEach(f => { alcance[f] = (alcance[f]||0)+1; }));\n    alcance['F1'] = 161;\n    const sev = {}; checks.forEach(c => sev[c.code] = c);\n    const ordem = ['crítica','alta','média','a validar'];\n    const linhasFalha = Object.entries(alcance)\n      .sort((a,b) => (ordem.indexOf(sev[a[0]]?.severidade) - ordem.indexOf(sev[b[0]]?.severidade)) || b[1]-a[1])\n      .map(([code,n]) => {\n        const c = sev[code] || {};\n        return `<tr><td class=\"mono\"><span class=\"pill ${['crítica','alta'].includes(c.severidade)?'bad':''}\">${esc(code)}</span></td>\n          <td class=\"nm\">${esc(c.nome||code)}</td><td>${esc(c.severidade||'—')}</td>\n          <td class=\"mono\">${n}</td><td>${esc(c.implicacao||'')}</td></tr>`;\n      }).join('');\n\n    const porLote = {};\n    convs.forEach(c => { const l=c.lote||'—'; porLote[l]=porLote[l]||{r:0}; porLote[l].r++; });\n    const LOTES = [['09/06',25],['11/06',26],['18/06',91],['19/06',98],['30/07',194],['19/08',198]];\n    const barLote = LOTES.map(([l,n]) => {\n      const r = (porLote[l]?.r)||0, taxa = 100*r/n;\n      return `<div class=\"bar\"><div class=\"lb\">${l} (${n} disparos)</div>\n        <div class=\"tk\"><div class=\"fl\" style=\"width:${Math.max(4,taxa*8)}%\"><b>${taxa.toFixed(1)}%</b></div></div></div>`;\n    }).join('');\n\n    return `\n      <p class=\"eyebrow\">Visão geral</p>\n      <h1>O que os dados reais dizem antes da gente decidir qualquer coisa</h1>\n      <p class=\"lede\">Leitura das conversas que o bot teve no WhatsApp com as consultoras.</p>\n\n      <div class=\"kpis\">\n        <div class=\"kpi\"><div class=\"n\">${DISPARADAS}</div><div class=\"c\">sessões reais disparadas</div></div>\n        <div class=\"kpi w\"><div class=\"n\">${humano} (${(100*humano/DISPARADAS).toFixed(1)}%)</div><div class=\"c\">pessoas responderam</div></div>\n        <div class=\"kpi w\"><div class=\"n\">${robo}</div><div class=\"c\">\"respostas\" que eram robô da própria consultora</div></div>\n        <div class=\"kpi\"><div class=\"n\">${SILENCIO}</div><div class=\"c\">nunca responderam</div></div>\n        <div class=\"kpi\"><div class=\"n\">${conv}</div><div class=\"c\">converteram</div></div>\n      </div>\n\n      <h2>Três achados que mudam a pauta</h2>\n      <div class=\"card warncard\">\n        <p><b>1. A maior categoria não é objeção, é silêncio.</b> ${SILENCIO} de ${DISPARADAS} sessões (95%) nunca tiveram resposta.\n        Mexer no fluxo de objeção afeta um punhado de conversas; mexer na <b>mensagem de abertura</b> afeta todas.\n        E a abertura saiu com o placeholder <code>{{Nome}}</code> literal para <b>161 consultoras</b>.</p>\n        <p><b>2. ${robo} das ${humano+robo} \"respostas\" eram máquina.</b> Auto-resposta do WhatsApp Business da própria consultora —\n        saudação em 3ª pessoa, aviso de ausência, catálogo da loja. O bot não detecta e responde como se fosse conversa,\n        chegando a adotar o nome errado que aparece no texto automático.</p>\n        <p><b>3. A mesma mensagem recebe respostas diferentes a cada vez.</b> Repetindo o caso da Gessy três vezes,\n        em uma delas o bot emendou a oferta de venda e nas outras duas respeitou a recusa. Por isso cada caso\n        de teste roda várias vezes: o resultado é a taxa de acerto, não uma tentativa.</p>\n      </div>\n\n      <h2>Distribuição por cenário</h2>\n      <p class=\"sub\">A situação de cada conversa vem do que a consultora escreveu.</p>\n      <div class=\"card\">${barras}</div>\n\n      <h2>Falhas de comportamento catalogadas</h2>\n      <p class=\"sub\">As de severidade crítica e alta são a pauta de correção.</p>\n      <div class=\"card\" style=\"padding:6px 10px\">\n        <table><tr><th>Cód</th><th>Falha</th><th>Severidade</th><th>Consultoras</th><th>O que fazer</th></tr>${linhasFalha}</table>\n      </div>\n\n      <h2>O que estes dados não respondem</h2>\n      <div class=\"card\">\n        <table>\n          <tr><th>Pergunta</th><th>Por quê</th></tr>\n          <tr><td class=\"nm\">Quem responde mais: segmentação A, B ou C?</td><td>O campo <code>segmentacao_1</code> está com <code>0</code> em 643 das 652 consultoras. Só 5 têm valor real — não dá pra cruzar.</td></tr>\n          <tr><td class=\"nm\">O nível da consultora explica quem responde?</td><td>Não. Ouro 4,4% e Diamante 4,2% — praticamente iguais.</td></tr>\n          <tr><td class=\"nm\">Por que as ${SILENCIO} caladas não responderam?</td><td>Em 471 delas não há nenhuma mensagem armazenada, nem a que o bot mandou. Não há pista do motivo.</td></tr>\n          <tr><td class=\"nm\">A consultora leu a mensagem?</td><td>Não há status de leitura/entrega em nenhuma tabela. \"Não respondeu\" não é o mesmo que \"não viu\".</td></tr>\n        </table>\n      </div>`;\n  },\n\n  vConversas(d2, x) {\n    const { convs, msgs, esc } = x;\n    const st = d2.state;\n    const aberta = st.conv;\n    if (!aberta) {\n      const linhas = convs.map(c => `\n        <tr class=\"clk\" data-conv=\"${esc(c.phone)}\" data-key=\"${esc(c.phone)}\">\n          <td class=\"nm\">${esc(c.nome)}</td>\n          <td><span class=\"pill\">${esc(c.cenario)}</span></td>\n          <td>${c.resposta_tipo==='robo'?'<span class=\"pill bad\">robô</span>':'pessoa'}</td>\n          <td class=\"mono\">${esc(c.lote)}</td>\n          <td class=\"mono\">${esc(c.status)}</td>\n          <td>${(c.falhas||[]).map(f=>`<span class=\"pill bad\">${esc(f)}</span>`).join(' ')}</td>\n          <td style=\"max-width:400px\">${esc(c.resumo||'').slice(0,150)}…</td>\n        </tr>`).join('');\n      return `\n        <p class=\"eyebrow\">Conversas reais</p>\n        <h1>Ler o que aconteceu e transformar em caso de teste</h1>\n        <p class=\"lede\">Abra uma conversa, leia na íntegra, e marque 👍 ou 👎 em qualquer resposta do bot.\n        Cada marcação vira um caso de teste.</p>\n        <div class=\"card\" style=\"padding:6px 10px\">\n          <table><tr><th>Consultora</th><th>Cenário</th><th>Quem respondeu</th><th>Lote</th><th>Status</th><th>Falhas</th><th>Resumo</th></tr>${linhas}</table>\n        </div>`;\n    }\n    const c = convs.find(z => z.phone === aberta) || {};\n    const linha = msgs.filter(m => m.phone === aberta).sort((a,b) => (a.seq||0)-(b.seq||0));\n    const bolhas = linha.length ? linha.map((m,i) => {\n      if (m.role === 'consultora') {\n        return `<div class=\"msg u\" data-key=\"c${i}\"><div><div class=\"bub\">${esc(m.text)}</div>\n          ${m.eh_autoresposta?`<div class=\"meta\" style=\"justify-content:flex-end\"><span class=\"pill bad\">auto-resposta</span>${(m.sinais_autoresposta||[]).map(s=>`<span class=\"pill\">${esc(s)}</span>`).join('')}</div>`:''}</div></div>`;\n      }\n      const ab = st.fbKey === aberta+'#'+m.seq;\n      return `<div class=\"msg b\" data-key=\"b${i}\"><div style=\"max-width:76%\">\n        <div class=\"bub\">${esc(m.text)}</div>\n        <div class=\"meta\">${m.faq?`<span class=\"pill\">FAQ ${esc(m.faq)}</span>`:''}</div>\n        <div class=\"acts\">\n          <button class=\"ico\" data-fbc=\"positivo\" data-phone=\"${esc(aberta)}\" data-seq=\"${m.seq}\" title=\"Boa — vira teste de regressão\">👍</button>\n          <button class=\"ico\" data-fbc=\"negativo\" data-phone=\"${esc(aberta)}\" data-seq=\"${m.seq}\" title=\"Ruim — vira teste de progressão\">👎</button>\n        </div>\n        ${ab?`<div class=\"fb\">\n          <label>Por que ${st.fbTipo==='positivo'?'está boa':'está errada'}?</label>\n          <textarea class=\"f-motivo\" rows=\"2\"></textarea>\n          ${st.fbTipo==='negativo'?`<label>Resposta ideal acordada pelo time</label><textarea class=\"f-ideal\" rows=\"3\"></textarea>`:''}\n          <label>Critério de aceite (o que o teste vai cobrar)</label>\n          <textarea class=\"f-criterio\" rows=\"2\" placeholder=\"ex: deve reconhecer a reclamação e encaminhar para suporte antes de qualquer CTA de venda\"></textarea>\n          <div class=\"row\"><button class=\"btn pri\" data-savec=\"1\">Salvar e criar teste</button><button class=\"btn\" data-cancel=\"1\">Cancelar</button></div>\n        </div>`:''}\n      </div></div>`;\n    }).join('') : `<div class=\"empty\">Esta conversa não tem mensagens replicadas.</div>`;\n\n    return `\n      <div class=\"row\" style=\"margin-bottom:14px\"><button class=\"btn\" data-back=\"1\">← todas as conversas</button></div>\n      <p class=\"eyebrow\">${esc(c.lote)} · cenário ${esc(c.cenario)} · ${esc(c.status)}</p>\n      <h1>${esc(c.nome)}</h1>\n      <p class=\"lede\">${esc(c.resumo||'')}</p>\n      ${(c.falhas||[]).length?`<div class=\"card warncard\" style=\"margin-bottom:15px\"><p><b>Falhas nesta conversa:</b> ${(c.falhas||[]).join(', ')}</p></div>`:''}\n      <div class=\"card\"><div class=\"chat\">${bolhas}</div></div>`;\n  },\n\n  vSimulador(d2, x) {\n    const { esc } = x;\n    const st = d2.state;\n    const ms = st.msgs || [];\n    const nome = st.nome || 'Maria';\n\n    const bolhas = ms.length ? ms.map((m,i) => {\n      if (m.role === 'user') return `<div class=\"msg u\" data-key=\"s${i}\"><div class=\"bub\">${esc(m.text)}</div></div>`;\n      const ab = st.fbIdx === i;\n      return `<div class=\"msg b\" data-key=\"s${i}\"><div style=\"max-width:76%\">\n        <div class=\"bub\">${esc(m.text)}</div>\n        <div class=\"meta\">${m.faq?`<span class=\"pill\">FAQ ${esc(m.faq)}</span>`:''}${m.estado?`<span class=\"pill\">${esc(m.estado)}</span>`:''}\n          ${(m.checks_falhados||[]).map(f=>`<span class=\"pill bad\">${esc(f)}</span>`).join('')}\n          ${(m.checks_falhados||[]).length===0&&m.checks_rodados?'<span class=\"pill ok\">checks ok</span>':''}</div>\n        ${i>0?`<div class=\"acts\">\n          <button class=\"ico\" data-fb=\"positivo\" data-i=\"${i}\">👍</button>\n          <button class=\"ico\" data-fb=\"negativo\" data-i=\"${i}\">👎</button>\n        </div>`:''}\n        ${ab?`<div class=\"fb\">\n          <label>Por que ${st.fbTipo==='positivo'?'está boa':'está errada'}?</label>\n          <textarea class=\"f-motivo\" rows=\"2\"></textarea>\n          ${st.fbTipo==='negativo'?`<label>Resposta ideal acordada</label><textarea class=\"f-ideal\" rows=\"3\"></textarea>`:''}\n          <label>Critério de aceite</label><textarea class=\"f-criterio\" rows=\"2\"></textarea>\n          <div class=\"row\"><button class=\"btn pri\" data-saves=\"1\">Salvar e criar teste</button><button class=\"btn\" data-cancel=\"1\">Cancelar</button></div>\n        </div>`:''}\n      </div></div>`;\n    }).join('') : '';\n\n    const ult = [...ms].reverse().find(m => m.role !== 'user');\n    const sm = ult && ult.state_machine;\n\n    return `\n      <p class=\"eyebrow\">Simulador</p>\n      <h1>Conversar com o bot no papel de uma consultora</h1>\n      <p class=\"lede\">Escreva como uma consultora escreveria e veja como o bot responde. Nada é enviado para ninguém.</p>\n      ${st.erro?`<div class=\"card warncard\" style=\"margin-bottom:13px\"><p>${esc(st.erro)}</p></div>`:''}\n      <div class=\"split\">\n        <div>\n          <div class=\"card\">\n            <div class=\"row\" style=\"margin-bottom:12px;gap:12px\">\n              <label style=\"font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:#5B6660;font-weight:700\">Nome da consultora</label>\n              <input class=\"nome-consultora\" value=\"${esc(nome)}\" style=\"font-family:inherit;font-size:13px;padding:6px 10px;border:1px solid #D8D4C8;border-radius:7px;width:180px\">\n              <span class=\"note\" style=\"margin:0\">nível Ouro · já usa o Pag Emana Pay</span>\n              <button class=\"btn\" data-reset=\"1\" style=\"margin-left:auto\">Recomeçar</button>\n            </div>\n            <div class=\"chat\">${bolhas}${st.carregando?'<div class=\"empty\">o bot está respondendo…</div>':''}</div>\n            <div class=\"composer\">\n              <textarea class=\"entrada\" placeholder=\"escreva como ${esc(nome)} escreveria…\"></textarea>\n              <button class=\"btn pri\" data-send=\"1\" ${st.carregando?'disabled':''}>Enviar</button>\n            </div>\n          </div>\n        </div>\n        <div>\n          <div class=\"card\">\n            <b style=\"font-size:12px\">O que o bot entendeu</b>\n            <div style=\"margin-top:11px\">\n            ${sm?`<div class=\"kv\"><b>Estado</b>${esc(sm.estado||'—')}</div>\n              <div class=\"kv\"><b>Sub-estado</b>${esc(sm.sub_estado||'—')}</div>\n              <div class=\"kv\"><b>É recusa?</b>${sm.is_recusa?'sim':'não'}${sm.reason?' · '+esc(sm.reason):''}</div>\n              <div class=\"kv\"><b>Instrução ao redator</b>${esc(sm.instrucao||'—')}</div>`\n            :'<div class=\"note\">Aparece após a primeira resposta.</div>'}\n            </div>\n          </div>\n        </div>\n      </div>`;\n  },\n\n  vFeedbacks(d2, x) {\n    const { fbs, esc } = x;\n    const pos = fbs.filter(f => f.veredito === 'positivo').length;\n    const neg = fbs.filter(f => f.veredito === 'negativo').length;\n    const linhas = fbs.length ? fbs.map(f => `<tr data-key=\"${esc(f.feedback_id)}\">\n      <td>${f.veredito==='positivo'?'<span class=\"pill ok\">👍 regressão</span>':'<span class=\"pill bad\">👎 progressão</span>'}</td>\n      <td class=\"nm\">${esc(f.consultora||'—')}</td>\n      <td class=\"mono\">${esc(f.origem)}</td>\n      <td style=\"max-width:280px\">${esc(f.mensagem_bot||'').slice(0,160)}…</td>\n      <td style=\"max-width:240px\">${esc(f.motivo||'')}</td>\n      <td>${f.virou_teste?'<span class=\"pill ok\">virou teste</span>':'<span class=\"pill\">pendente</span>'}</td>\n    </tr>`).join('') : `<tr><td colspan=\"6\" class=\"empty\">Nenhum feedback ainda. Marque 👍 ou 👎 numa conversa real ou no simulador.</td></tr>`;\n    return `\n      <p class=\"eyebrow\">Feedbacks</p>\n      <h1>O que o time marcou</h1>\n      <p class=\"lede\">Cada 👍 vira um teste de regressão (isto tem que continuar funcionando) e cada 👎 vira um teste\n      de progressão (isto precisa passar a funcionar).</p>\n      <div class=\"kpis\">\n        <div class=\"kpi\"><div class=\"n\">${fbs.length}</div><div class=\"c\">feedbacks coletados</div></div>\n        <div class=\"kpi\"><div class=\"n\">${pos}</div><div class=\"c\">👍 viram regressão</div></div>\n        <div class=\"kpi w\"><div class=\"n\">${neg}</div><div class=\"c\">👎 viram progressão</div></div>\n      </div>\n      <div class=\"card\" style=\"padding:6px 10px\"><table>\n        <tr><th>Tipo</th><th>Consultora</th><th>Origem</th><th>Resposta do bot</th><th>Motivo</th><th>Estado</th></tr>${linhas}\n      </table></div>`;\n  },\n\n  vTestes(d2, x) {\n    const { tests, res, esc } = x;\n    const st = d2.state;\n\n    const ultimos = {};\n    res.forEach(r => { if (!ultimos[r.test_key] || r.criado_em > ultimos[r.test_key].criado_em) ultimos[r.test_key] = r; });\n    const comResultado = Object.values(ultimos);\n    const passou = comResultado.filter(r => r.veredito === 'passou').length;\n    const prog = tests.filter(t => t.tipo === 'progressao').length;\n    const pct = (v) => (v == null ? '—' : Math.round(v * 100) + '%');\n\n    const ordem = { falhou: 0, passou: 1 };\n    const linhas = tests.length ? tests.slice().sort((a,b) => {\n        const ra = ultimos[a.test_key], rb = ultimos[b.test_key];\n        return (ordem[ra?.veredito] ?? -1) - (ordem[rb?.veredito] ?? -1);\n      }).map(t => {\n      const u = ultimos[t.test_key];\n      const aberto = st.detalhe === t.test_key;\n      const status = !u ? '<span class=\"pill\">sem resultado</span>'\n        : u.veredito === 'passou'\n          ? `<span class=\"pill ok\">✓ ${u.passou_n} de ${u.execucoes}</span>`\n          : `<span class=\"pill bad\">✕ ${u.passou_n} de ${u.execucoes}</span>`;\n      const editando = st.editKey === t.test_key;\n      const apagando = st.delKey === t.test_key;\n      return `<tr class=\"clk\" data-detalhe=\"${esc(t.test_key)}\" data-key=\"${esc(t.test_key)}\">\n        <td>${t.tipo==='progressao'?'<span class=\"pill bad\">progressão</span>':'<span class=\"pill ok\">regressão</span>'}</td>\n        <td class=\"nm\">${esc(t.titulo)}</td>\n        <td style=\"max-width:300px\">${esc(t.criterio_aceite||'')}</td>\n        <td>${status}</td>\n        <td class=\"mono\">${u ? pct(u.taxa) : '—'}</td>\n        <td class=\"acts\">\n          <button class=\"mini\" data-edit=\"${esc(t.test_key)}\">Editar</button>\n          <button class=\"mini danger\" data-del=\"${esc(t.test_key)}\">Apagar</button>\n        </td>\n      </tr>\n      ${apagando ? `<tr data-key=\"${esc(t.test_key)}-c\"><td colspan=\"6\" class=\"confirmar\">\n        <b>Apagar o caso “${esc(t.titulo)}”?</b>\n        <p>O caso sai da suíte e não volta. O feedback que deu origem a ele continua na tela de Feedbacks.</p>\n        <div class=\"row\">\n          <button class=\"btn pri\" data-delok=\"${esc(t._id)}\" ${st.salvando?'disabled':''}>${st.salvando?'apagando…':'Apagar'}</button>\n          <button class=\"btn\" data-delno=\"1\">Cancelar</button>\n        </div></td></tr>` : ''}\n      ${editando ? `<tr data-key=\"${esc(t.test_key)}-e\"><td colspan=\"6\" class=\"editar\">\n        <div class=\"lin\"><label>Título</label><input class=\"e-titulo\" value=\"${esc(t.titulo||'')}\"></div>\n        <div class=\"lin\"><label>Origem do caso</label><select class=\"e-tipo\">\n          <option value=\"regressao\" ${t.tipo!=='progressao'?'selected':''}>Regressão — já funcionava, tem que continuar</option>\n          <option value=\"progressao\" ${t.tipo==='progressao'?'selected':''}>Progressão — não funcionava, precisa passar a funcionar</option>\n        </select></div>\n        <div class=\"lin\"><label>Mensagem de entrada</label><textarea class=\"e-entrada\">${esc(t.entrada||'')}</textarea></div>\n        <div class=\"lin\"><label>Critério de aceite</label><textarea class=\"e-criterio\" placeholder=\"a regra que decide se passou — escreva o comportamento, não o texto\">${esc(t.criterio_aceite||'')}</textarea></div>\n        <div class=\"lin\"><label>Resposta ideal</label><textarea class=\"e-ideal\" placeholder=\"exemplo do que se espera; serve de referência, não de gabarito\">${esc(t.resposta_ideal||'')}</textarea></div>\n        <div class=\"lin\"><label>Rodadas por execução</label><input class=\"e-rep curta\" type=\"number\" min=\"1\" max=\"10\" value=\"${t.repeticoes||3}\"></div>\n        <div class=\"lin\"><label>Mínimo para passar</label><input class=\"e-taxa curta\" type=\"number\" min=\"0\" max=\"100\" value=\"${Math.round((t.taxa_minima==null?0.9:t.taxa_minima)*100)}\"><span class=\"note\" style=\"margin:0;grid-column:2\">em % das rodadas</span></div>\n        <div class=\"row\" style=\"margin-top:4px\">\n          <button class=\"btn pri\" data-editsave=\"${esc(t._id)}\" ${st.salvando?'disabled':''}>${st.salvando?'salvando…':'Salvar'}</button>\n          <button class=\"btn\" data-editcancel=\"1\">Cancelar</button>\n        </div></td></tr>` : ''}\n      ${aberto && u && !editando && !apagando ? `<tr data-key=\"${esc(t.test_key)}-d\"><td colspan=\"6\" style=\"background:#F7F5F0\">\n        <div style=\"padding:6px 2px 10px\">\n          <div class=\"kv\"><b>O que a consultora disse</b>${esc(u.entrada||'')}</div>\n          <div class=\"kv\"><b>O que o bot respondeu</b><span style=\"white-space:pre-wrap\">${esc(u.resposta_obtida||'')}</span></div>\n          <div class=\"kv\"><b>Avaliação</b>${esc(u.juiz_justificativa||'')}</div>\n          ${(u.checks_resultado||[]).length?`<div class=\"kv\"><b>Verificações automáticas reprovadas</b>${(u.checks_resultado||[]).map(c=>`<span class=\"pill bad\">${esc(c)}</span>`).join(' ')}</div>`:''}\n        </div></td></tr>` : ''}`;\n    }).join('') : `<tr><td colspan=\"6\" class=\"empty\">Nenhum caso registrado ainda.<br>Os casos nascem quando alguém aprova ou reprova uma resposta do bot,<br>em Conversas reais ou no Simulador.</td></tr>`;\n\n    const r = st.ultimaRodada;\n    const painel = st.rodando\n      ? `<div class=\"card\" style=\"margin-bottom:15px\"><b>Executando…</b>\n           <p class=\"note\" style=\"margin-top:5px\">Cada caso roda ${tests.length?(tests[0].repeticoes||3):3} vezes. Leva cerca de ${Math.max(10, tests.length*8)} segundos.</p></div>`\n      : r\n        ? `<div class=\"card ${r.falhou?'warncard':''}\" style=\"margin-bottom:15px\">\n             <div class=\"row\" style=\"gap:26px;align-items:flex-end\">\n               <div><div style=\"font-family:Georgia,serif;font-size:30px;font-weight:700;line-height:1;color:${r.falhou?'#B23A2E':'#2F6F4E'}\">${r.passou} de ${r.total}</div>\n                 <div class=\"note\" style=\"margin-top:4px\">casos atenderam o critério</div></div>\n               <div class=\"note\" style=\"margin:0\">execução de ${esc((r.run_key||'').replace('run-',''))}</div>\n             </div>\n             ${r.falhou?`<p class=\"note\" style=\"margin-top:11px\">Abra um caso reprovado abaixo para ver a resposta e a avaliação.</p>`:''}\n           </div>`\n        : '';\n\n    return `\n      <p class=\"eyebrow\">Testes</p>\n      <h1>Casos registrados e o resultado da última execução</h1>\n      <p class=\"lede\">Cada caso é executado várias vezes, porque a mesma mensagem recebe respostas diferentes\n      a cada tentativa. O resultado é a proporção de execuções que atenderam o critério.</p>\n      <div class=\"kpis\">\n        <div class=\"kpi\"><div class=\"n\">${tests.length}</div><div class=\"c\">casos registrados</div></div>\n        <div class=\"kpi\"><div class=\"n\">${passou}</div><div class=\"c\">atendendo o critério</div></div>\n        <div class=\"kpi w\"><div class=\"n\">${comResultado.length - passou}</div><div class=\"c\">pendentes de correção</div></div>\n        <div class=\"kpi\"><div class=\"n\">${prog}</div><div class=\"c\">abertos a partir de um erro</div></div>\n      </div>\n      <div class=\"row\" style=\"margin:18px 0\">\n        <button class=\"btn pri\" data-run=\"1\" ${st.rodando||!tests.length?'disabled':''}>${st.rodando?'executando…':'Executar todos os casos'}</button>\n      </div>\n      ${st.erroRun?`<div class=\"card warncard\" style=\"margin-bottom:13px\"><p>${esc(st.erroRun)}</p></div>`:''}\n      ${st.erroTeste?`<div class=\"card warncard\" style=\"margin-bottom:13px\"><p>${esc(st.erroTeste)}</p></div>`:''}\n      ${painel}\n      <div class=\"card\" style=\"padding:6px 10px\"><table>\n        <tr><th>Origem</th><th>Caso</th><th>Critério de aceite</th><th>Último resultado</th><th>Proporção</th><th></th></tr>${linhas}\n      </table></div>\n      ${tests.length?`<p class=\"note\">Clique na linha para ver a resposta do bot e a avaliação. Editar muda o critério e o texto de referência; apagar tira o caso da suíte.</p>`:''}`;\n  },\n\n  mounted(d2) {\n    const ABERTURA = 'Olá, {{Nome}}! Tudo bem?\\nVi que você já utiliza o Pag Emana Pay para ter mais prazo e flexibilidade nos seus pedidos Natura e Avon. Isso já ajuda muito, mas sabia que sua rotina pode simplificar ainda mais, ao abrir sua conta Emana Pay? 🚀\\n\\nTopa abrir a sua conta agora para aproveitar essas vantagens ou prefere que eu te explique melhor como funcionam essas ferramentas?';\n    if (!d2.state.view) d2.state.view = 'geral';\n    const abertura = (nome) => ABERTURA.replace('{{Nome}}', nome || 'Maria');\n    if (!d2.state.msgs || !d2.state.msgs.length) d2.state.msgs = [{ role:'agent', text: abertura(d2.state.nome) }];\n\n    d2.on('[data-view]', 'click', e => {\n      d2.setState({ view: e.target.closest('[data-view]').dataset.view, conv: null, fbKey: null, fbIdx: null });\n    });\n    d2.on('[data-conv]', 'click', e => d2.setState({ conv: e.target.closest('[data-conv]').dataset.conv, fbKey: null }));\n    d2.on('[data-back]', 'click', () => d2.setState({ conv: null, fbKey: null }));\n    d2.on('[data-cancel]', 'click', () => d2.setState({ fbKey: null, fbIdx: null }));\n    d2.on('.nome-consultora', 'change', e => d2.setState({ nome: (e.target.value || '').trim() || 'Maria' }));\n    d2.on('[data-reset]', 'click', () => d2.setState({\n      msgs: [{ role:'agent', text: abertura(d2.state.nome) }], fbIdx: null, erro: null,\n      chatState: 'ESTADO_1', subState: '', resumo: ''\n    }));\n    d2.on('[data-fb]', 'click', e => {\n      const b = e.target.closest('[data-fb]');\n      d2.setState({ fbIdx: Number(b.dataset.i), fbTipo: b.dataset.fb });\n    });\n    d2.on('[data-fbc]', 'click', e => {\n      const b = e.target.closest('[data-fbc]');\n      d2.setState({ fbKey: b.dataset.phone + '#' + b.dataset.seq, fbTipo: b.dataset.fbc, fbSeq: Number(b.dataset.seq) });\n    });\n\n    const perfil = () => ({\n      phone: '5511900000000',\n      first_name: (d2.state.nome || 'Maria').split(' ')[0], name: d2.state.nome || 'Maria',\n      nivel_consultora: 'Ouro', hab_pep: true, hab_aproximaae: false,\n      campaign_id: '6a0328b953f0fae2fbc989e5'\n    });\n\n    const enviar = async () => {\n      const ta = d2.$('.entrada');\n      const texto = (ta?.value || '').trim();\n      if (!texto || d2.state.carregando) return;\n      const hist = (d2.state.msgs||[]).map(m => ({ role: m.role === 'user' ? 'user' : 'agent', message:{ text: m.text }}))\n        .concat([{ role:'user', message:{ text: texto }}]);\n      d2.setState({ msgs: (d2.state.msgs||[]).concat([{ role:'user', text: texto }]), carregando:true, erro:null, fbIdx:null });\n      if (ta) ta.value = '';\n      try {\n        const r = await d2.rush('brainRush').invoke({\n          message: texto, all_messages: hist, user_data: perfil(), started_by_user:false,\n          chat_state_inicial: d2.state.chatState || 'ESTADO_1',\n          sub_state_inicial: d2.state.subState || '', resumo_inicial: d2.state.resumo || ''\n        });\n        const o = (r && r.data) ? r.data : r;\n        d2.setState({\n          carregando:false,\n          chatState: o.state_machine?.estado || d2.state.chatState,\n          subState: o.state_machine?.sub_estado || '', resumo: o.state_machine?.resumo || '',\n          msgs: (d2.state.msgs||[]).concat([{ role:'agent', text:o.resposta, faq:o.faq,\n            estado:o.state_machine?.estado, state_machine:o.state_machine,\n            checks_rodados:o.checks_rodados, checks_falhados:o.checks_falhados, entrada:texto }])\n        });\n      } catch (err) { d2.setState({ carregando:false, erro:'Falha ao chamar o bot: ' + (err?.message||err) }); }\n    };\n    d2.on('[data-send]', 'click', enviar);\n    d2.on('.entrada', 'keydown', e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); enviar(); } });\n\n    const gravar = async (payload, idealTexto, criterioTexto) => {\n      const fid = 'fb-' + Date.now();\n      await d2.data('feedbacksDs').create(Object.assign({ feedback_id: fid, criado_em: new Date().toISOString() }, payload));\n      const tipo = payload.veredito === 'positivo' ? 'regressao' : 'progressao';\n      await d2.data('testsDs').create({\n        test_key: 'tc-' + Date.now(),\n        titulo: (payload.consultora ? payload.consultora + ' — ' : '') + (payload.mensagem_usuario || '').slice(0, 60),\n        tipo, persona_key: d2.state.personaKey || '',\n        user_data: payload.user_data || {},\n        historico: payload.historico || [],\n        entrada: payload.mensagem_usuario || '',\n        resposta_referencia: payload.mensagem_bot || '',\n        resposta_ideal: idealTexto || payload.mensagem_bot || '',\n        criterio_aceite: criterioTexto || '',\n        cenario: payload.cenario || '', origem_feedback: fid,\n        status: tipo === 'progressao' ? 'falhando' : 'novo',\n        repeticoes: 3, taxa_minima: 0.9, chat_state_inicial: 'ESTADO_1',\n        criado_em: new Date().toISOString(), ativo: true\n      });\n    };\n\n    d2.on('[data-saves]', 'click', async () => {\n      const i = d2.state.fbIdx, m = (d2.state.msgs||[])[i];\n      if (m == null) return;\n      const hist = (d2.state.msgs||[]).slice(0, i).map(z => ({ role: z.role==='user'?'user':'agent', message:{ text:z.text }}));\n      try {\n        await gravar({\n          origem:'simulador', consultora: d2.state.nome || 'Maria', seq:i,\n          mensagem_usuario: m.entrada||'', mensagem_bot: m.text||'',\n          veredito: d2.state.fbTipo, motivo: d2.$('.f-motivo')?.value||'',\n          resposta_ideal: d2.$('.f-ideal')?.value||'', cenario: '',\n          virou_teste:true, user_data: perfil(), historico: hist\n        }, d2.$('.f-ideal')?.value, d2.$('.f-criterio')?.value);\n        const nv = (d2.state.msgs||[]).slice(); nv[i] = Object.assign({}, nv[i], { fb: d2.state.fbTipo });\n        d2.setState({ msgs:nv, fbIdx:null });\n      } catch (err) { d2.setState({ erro:'Não consegui salvar: ' + (err?.message||err) }); }\n    });\n\n    d2.on('[data-savec]', 'click', async () => {\n      const phone = d2.state.conv, seq = d2.state.fbSeq;\n      const todas = (d2.data('mensagensDs')?.records()||[]).filter(z => z.phone === phone).sort((a,b)=>(a.seq||0)-(b.seq||0));\n      const m = todas.find(z => z.seq === seq);\n      const antes = todas.filter(z => (z.seq||0) < seq);\n      const ultimaUser = [...antes].reverse().find(z => z.role === 'consultora');\n      const c = (d2.data('conversasDs')?.records()||[]).find(z => z.phone === phone) || {};\n      if (!m) return;\n      try {\n        await gravar({\n          origem:'conversa-real', phone, consultora: c.nome||'', seq,\n          mensagem_usuario: ultimaUser?ultimaUser.text:'', mensagem_bot: m.text||'',\n          veredito: d2.state.fbTipo, motivo: d2.$('.f-motivo')?.value||'',\n          resposta_ideal: d2.$('.f-ideal')?.value||'', cenario: c.cenario||'',\n          virou_teste:true,\n          user_data:{ phone, first_name:(c.nome||'').split(' ')[0], name:c.nome, nivel_consultora:c.nivel,\n            hab_pep:true, hab_aproximaae:false, campaign_id:'6a0328b953f0fae2fbc989e5' },\n          historico: antes.map(z => ({ role: z.role==='consultora'?'user':'agent', message:{ text:z.text }}))\n        }, d2.$('.f-ideal')?.value, d2.$('.f-criterio')?.value);\n        d2.setState({ fbKey:null });\n      } catch (err) { d2.setState({ erro:'Não consegui salvar: ' + (err?.message||err) }); }\n    });\n\n    d2.on('[data-prompt]', 'click', e => {\n      d2.setState({ promptSel: e.target.closest('[data-prompt]').dataset.prompt, secAberta: null });\n    });\n\n    d2.on('[data-sec]', 'click', e => {\n      const k = e.target.closest('[data-sec]').dataset.sec;\n      d2.setState({ secAberta: d2.state.secAberta === k ? null : k });\n    });\n\n    d2.on('[data-detalhe]', 'click', e => {\n      if (e.target.closest('[data-edit],[data-del],[data-delok],[data-delno],[data-editsave],[data-editcancel],.editar,.confirmar')) return;\n      const k = e.target.closest('[data-detalhe]').dataset.detalhe;\n      d2.setState({ detalhe: d2.state.detalhe === k ? null : k });\n    });\n\n    d2.on('[data-edit]', 'click', e => {\n      e.stopPropagation();\n      d2.setState({ editKey: e.target.closest('[data-edit]').dataset.edit, delKey: null, detalhe: null, erroTeste: null });\n    });\n    d2.on('[data-editcancel]', 'click', e => { e.stopPropagation(); d2.setState({ editKey: null, erroTeste: null }); });\n    d2.on('[data-del]', 'click', e => {\n      e.stopPropagation();\n      d2.setState({ delKey: e.target.closest('[data-del]').dataset.del, editKey: null, detalhe: null, erroTeste: null });\n    });\n    d2.on('[data-delno]', 'click', e => { e.stopPropagation(); d2.setState({ delKey: null, erroTeste: null }); });\n\n    d2.on('[data-delok]', 'click', async e => {\n      e.stopPropagation();\n      const id = e.target.closest('[data-delok]').dataset.delok;\n      d2.setState({ salvando: true, erroTeste: null });\n      try {\n        await d2.data('testsDs').remove(id);\n        await d2.data('testsDs').refresh();\n        d2.setState({ delKey: null, salvando: false, detalhe: null });\n      } catch (err) {\n        d2.setState({ salvando: false, erroTeste: 'Não consegui apagar o caso: ' + ((err && err.message) || err) });\n      }\n    });\n\n    d2.on('[data-editsave]', 'click', async e => {\n      e.stopPropagation();\n      const id = e.target.closest('[data-editsave]').dataset.editsave;\n      const val = (s) => ((d2.$(s) || {}).value || '').trim();\n      const rep = Math.min(10, Math.max(1, Number((d2.$('.e-rep') || {}).value) || 3));\n      const tx = Number((d2.$('.e-taxa') || {}).value);\n      const titulo = val('.e-titulo');\n      if (!titulo) { d2.setState({ erroTeste: 'O caso precisa de um título.' }); return; }\n      d2.setState({ salvando: true, erroTeste: null });\n      try {\n        await d2.data('testsDs').update({\n          _id: id,\n          titulo,\n          tipo: (d2.$('.e-tipo') || {}).value || 'regressao',\n          entrada: val('.e-entrada'),\n          criterio_aceite: val('.e-criterio'),\n          resposta_ideal: val('.e-ideal'),\n          repeticoes: rep,\n          taxa_minima: isNaN(tx) ? 0.9 : Math.min(1, Math.max(0, tx / 100)),\n        });\n        await d2.data('testsDs').refresh();\n        d2.setState({ editKey: null, salvando: false });\n      } catch (err) {\n        d2.setState({ salvando: false, erroTeste: 'Não consegui salvar: ' + ((err && err.message) || err) });\n      }\n    });\n\n    d2.on('[data-run]', 'click', async () => {\n      if (d2.state.rodando) return;\n      d2.setState({ rodando:true, erroRun:null, ultimaRodada:null, detalhe:null });\n      try {\n        const r = await d2.rush('runnerRush').invoke({});\n        const o = (r && r.data) ? r.data : r;\n        await d2.data('resultadosDs').refresh();\n        await d2.data('runsDs').refresh();\n        d2.setState({ rodando:false, ultimaRodada: o?.run || null });\n      } catch (err) { d2.setState({ rodando:false, erroRun:'Não foi possível concluir a execução: ' + (err?.message||err) }); }\n    });\n  }\n}"}},"personasDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"personasDs"}}}},"conversasDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"conversasDs"}}}},"mensagensDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"mensagensDs"}}}},"feedbacksDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"feedbacksDs"}}}},"checksDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"checksDs"}}}},"testsDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"testsDs"}}}},"runsDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"runsDs"}}}},"resultadosDs":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"resultadosDs"}}}},"brainRush":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brainRush"}}}},"runnerRush":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"runnerRush"}}}}}}}}}},{"_id":"6ac6c48e862cb6202e1cb674","component":"data2-core-types@Component","system":"69bd2cbc4c2708c13a0b572b","params":{"extends":"data2-core-primitives@Block","component":"kNpProposta","package":"natura-pay-crm","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// Deck Natura Pay · Proposta de valor + CRM (35 slides, v2: conceito pra continuidade).\n// O módulo completo (CSS + slides + ilustração) vive no drive deck-media e é carregado em runtime.\n// Para editar: natura-pay-crm/deck-proposta-valor/ → python3 build.py → subir kNpProposta.js no\n// drive deck-media e trocar o SRC abaixo → publicar.\nconst SRC='https://natura-pay-crm.data2.media/file/7PIcYzeq8HEHWyS5ydy8n'\nlet MOD=null, LOADING=null, BOOTED=false\n\nfunction load(){\n  if(!LOADING){\n    LOADING=fetch(SRC,{cache:'no-cache'})\n      .then(r=>r.text())\n      .then(code=>import(URL.createObjectURL(new Blob([code],{type:'text/javascript'}))))\n      .then(m=>{ MOD=m.default; return MOD })\n  }\n  return LOADING\n}\n\nexport default {\n  css:`:host{display:block}\n  .ld{height:100vh;height:100svh;background:#F6EFE5;display:flex;align-items:center;justify-content:center;\n    font-family:-apple-system,BlinkMacSystemFont,sans-serif;font-size:11px;letter-spacing:.24em;text-transform:uppercase;color:#6B5B4E}`,\n  render(d2){\n    if(!d2.state.ready||!MOD) return '<div class=\"ld\">carregando</div>'\n    return '<style>'+MOD.css+'</style>'+MOD.render(d2)\n  },\n  mounted(d2){\n    load().then(()=>{\n      d2.state.ready=1\n      // preview do builder (data2.qa) já exige login de builder: pula o gate\n      try{ if(/\\.data2\\.qa$/.test(location.hostname)) d2.state.unlocked=true }catch(e){}\n      setTimeout(()=>{ if(!BOOTED){ BOOTED=true; MOD.mounted(d2) } },0)\n    }).catch(()=>{})\n  },\n  updated(d2){\n    if(BOOTED&&MOD&&MOD.updated) MOD.updated(d2)\n  }\n}\n"}}}}}}}}]}},{"reference":"ExternalComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f060d9b1ca96def42f3c40a","displayName":"Builder AuthStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"credentials":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"UsersDataSet"}},"sessionShared":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},"email":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"nR6Q9d7qdaPtZhJ28Q8Dy"},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"yPCJBTKo8q1Mw0B_3Kpwl"},"component":"data2-core-types@ArtboardReference"}}},"session":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"name"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"sessionMetadata":{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},{"params":{"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"active"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.status"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is active user"}]},"component":"data2-core-logical-operators@And","displayName":"is active and has _id"}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $user"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-primitives@String","params":{"content":"@data2.app"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.email"}}}}},"component":"data2-core-functions@Includes","displayName":"isData2User"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}},"component":"data2-core-flow@Step"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.d2_app"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"management"}}]},"component":"data2-core-functions@Includes","displayName":"isData2App Exception"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}},"component":"data2-core-flow@Step"},{"params":{"resultName":{"component":"data2-core-primitives@String","params":{"content":"has_access"}},"action":{"params":{"compare":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}]},"component":"data2-core-logical-operators@Or"},"else":{"params":{"actions":[{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $metadata.system"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":"filter","args":[{"_id":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records.length"}}}}},"component":"data2-core-logical-operators@Not","displayName":"systems not found"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check system found"},{"params":{"actions":[{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"organization":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"cursor.current.organization._id"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"}]},"component":"data2-core-flow@Parallel"}]},"component":"data2-core-flow@Series","displayName":"common setup"},{"params":{"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"else":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"compare":{"params":{"components":{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"mapper":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"system"}}],"body":{"params":{"expression":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.visibility"}}}},"defaultCase":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"public"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"billing-owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}},{"component":"data2-core-primitives@String","params":{"content":"member"}}]},"component":"data2-core-functions@Includes","displayName":"has role with access"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"collaborator"}}},"component":"data2-core-comparison-operators@Equal","displayName":"is collaborator"}]},"component":"data2-core-logical-operators@And","displayName":"is org member and collaborator"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is collaborator"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is collaborator and has system access"}]},"component":"data2-core-logical-operators@Or"}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"private"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}}]},"component":"data2-core-functions@Includes","displayName":"is owner/admin"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is owner/admin"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is member and has system access"}]},"component":"data2-core-logical-operators@Or","displayName":"is owner/admin or has system access"}}}]},"component":"data2-core-flow@Switch"}}}},"component":"data2-core-functions@ArrayMap"}},"component":"data2-core-logical-operators@And","displayName":"has org member for all systems in request"}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}},"component":"data2-core-flow@If"}},"component":"data2-core-flow@Step"},{"params":{"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"},"compare":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"has_access"}}}}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"sessionExpiresIn":{"component":"data2-core-primitives@Number","params":{"content":604800}},"sessionRenewal":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"identityProviders":[{"provider":{"component":"data2-core-primitives@String","params":{"content":"GOOGLE"}},"clientId":{"component":"data2-core-primitives@String","params":{"content":"55470861603-22pvfc1t49lp8cjnbfk71s5ct9hp1q1v.apps.googleusercontent.com"}}}]},"reference":"Data2BuilderAuthentication","updatedAt":"2026-08-06T19:31:23.557Z"},{"_id":"5f060ee51ca96def42f3fbd1","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"UsersTableDataSource"}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}}},"reference":"UsersDataSet","updatedAt":"2026-03-04T21:16:40.291Z"},{"_id":"68f938cf5fb002e33752a43d","displayName":"InternalApplicationsAuthenticationStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}}},"verifier":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{"reference":"InternalApplicationsVerifierDataSet"}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"secret"}},"credentials":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}],"session":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}]},"reference":"InternalApplicationsAuthenticationStrategy","updatedAt":"2025-10-22T20:08:54.442Z","createdAt":"2025-10-22T20:04:31.198Z"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"_id":"5f16172a0528b92601890f85","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":10000}}},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"DataComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"DataComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:12.831Z","createdAt":"2020-07-20T22:14:02.097Z"},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f1600b70528b92601890f75","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ServiceComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ServiceComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:20.208Z","createdAt":"2020-07-20T20:38:15.436Z"},{"_id":"5f1602190528b92601890f7d","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":40000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentInstancesTableDataSource"}},"sort":{"_id":1},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:07.089Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"5f16017f0528b92601890f7a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"FileComponentInstancesDataSet","updatedAt":"2023-08-03T16:08:18.193Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"5f1601990528b92601890f7b","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ApplicationsTableDataSource"}},"pk":"_id","autoEdit":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"params":{"column":"_id"},"component":"data2-core-types@DataSetColumnReference"}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"ApplicationsDataSet","updatedAt":"2022-12-13T21:51:13.995Z","createdAt":"2020-07-20T20:42:01.657Z"},{"_id":"60ddc1bbda3861ca65407c5a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"pagination":{"size":1},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"}},"reference":"OneFileComponentInstancesDataSet","updatedAt":"2022-02-09T19:44:38.036Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"63ee3d38b8c9838c62fb05fb","displayName":"DriveFileComponentInstancesDataSet","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core@Drive"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"DriveFileComponentInstancesDataSet","updatedAt":"2025-12-04T21:58:32.367Z","createdAt":"2023-02-16T14:27:07.797Z"},{"reference":"ServiceComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6ac6c48fd0e6a463e3571944","component":"data2-core-primitives@Artboard","system":"69bd2cbc4c2708c13a0b572b","displayName":"Deck Proposta de Valor","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Deck Proposta de Valor"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"pr_BWrtU5zGN-d4xraBVA"},{"_id":"0d26ebd6842a4a4d8c865f4a","parent":"6ac6c48fd0e6a463e3571944","component":"natura-pay-crm@kNpProposta","system":"69bd2cbc4c2708c13a0b572b","displayName":"Deck Proposta de Valor","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}}},"reference":"Xw58Fb1K248zMFR1jOXCz"}]}},{"_id":"5fc4faeec8da12be8bf3d08a","component":"data2-core@Data2TableDataSource","system":"5e3b796d6228227ca637d0f4","params":{"paginate":{"default":1000},"super":{},"table":"fileComponentInstances","schema":[{"component":"data2-core-types@Field","params":{"key":"component","title":"Component","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"system","title":"System","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"displayName","title":"Display Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"params","title":"Params","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"reference","title":"Reference","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"fileId"}},"title":"File ID","component":"data2-core-primitives@ObjectId"},"break":true}],"hooks":{"before":{"all":[{"hook":"softDelete"}],"find":[{"hook":"useCache","options":{"additionalGroupKeys":["$and.0.system","$and.1.system"],"skipCache":true}}],"create":[{"hook":"timestamp","options":{"fields":["createdAt","updatedAt"]}}],"update":[{"hook":"timestamp","options":{"fields":["updatedAt"]}}],"patch":[{"hook":"timestamp","options":{"fields":["updatedAt"]}}]},"after":{"all":[{"hook":"fileUrl","options":{"downloadField":"params.fileUrl","uploadField":"params.uploadFileUrl","enhanceSchema":false}}],"find":[{"hook":"useCache","options":{"additionalGroupKeys":["$and.0.system","$and.1.system"],"skipCache":true}}],"create":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}],"update":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}],"patch":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}],"remove":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}]}},"multi":["create"],"useEstimatedDocumentCount":true},"reference":"FileComponentInstancesTableDataSource","updatedAt":"2022-12-19T20:42:51.837Z","createdAt":"2020-11-30T13:59:52.294Z"},{"reference":"ApplicationsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6ac6c4999cddc83ab29f50b1","displayName":"Proposta de Valor","reference":"8Cugjjxz9xXN2WBsFKkay","params":{"domain":{"component":"data2-core-primitives@String","params":{"content":"proposta-valor"}},"entryPoint":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"pr_BWrtU5zGN-d4xraBVA"}}},"system":"69bd2cbc4c2708c13a0b572b","component":"data2-core-primitives@Application"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}