{"context":{"domain":"babi-hera"},"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":"2022-03-09T02:01:26.213Z"}]}},{"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}],"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":"2025-11-05T19:23:47.135Z","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":"65901b6eeafc5e0931497047","name":"Hera Build","domain":"babi-hera","visibility":"public","updatedAt":"2024-01-19T14:00:37.645Z","createdAt":"2023-12-30T13:30:22.456Z"}]}},{"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":"6a5fec3e3bba43b237376def","component":"data2-core-types@Component","system":"65901b6eeafc5e0931497047","params":{"extends":"data2-core-primitives@Block","component":"justos-reveal-shell","package":"babi-hera","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"/* ===== JUSTOS \"HERA REVEAL\" — SHARED KIT (concatenated) ===== */\nconst esc = s => s == null ? '' : String(s).replace(/[&<>\"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]));\nconst num = n => (n==null||isNaN(n)) ? '—' : new Intl.NumberFormat('pt-BR').format(Math.round(n));\nconst pct = (n,d=0) => (n==null||isNaN(n)) ? '—' : (n*100).toFixed(d).replace('.',',')+'%';\nconst money = n => new Intl.NumberFormat('pt-BR',{style:'currency',currency:'BRL',maximumFractionDigits:0}).format(Math.round(n||0));\nconst moneyK = n => { const v=n||0, a=Math.abs(v); if(a>=1e6) return 'R$ '+(v/1e6).toFixed(1).replace('.',',')+'M'; if(a>=1e3) return 'R$ '+(v/1e3).toFixed(0)+'k'; return money(v); };\nconst fmtDate = iso => { if(!iso) return '—'; const d=new Date(iso); if(isNaN(d)) return String(iso).slice(0,10); return d.toLocaleDateString('pt-BR',{day:'2-digit',month:'2-digit',year:'2-digit'}); };\nconst cxColor = (c, fb) => !c ? fb : (typeof c==='string' ? c : (c.rgba || (c.color && c.color.rgba) || fb));\nconst kwOf  = r => Array.isArray(r && r.keywords) ? r.keywords : [];\nconst trOf  = r => (r && r.traits   && typeof r.traits==='object'   && !Array.isArray(r.traits))   ? r.traits   : {};\nconst cxOf  = r => (r && r.cx_tags  && typeof r.cx_tags==='object'  && !Array.isArray(r.cx_tags))  ? r.cx_tags  : {};\nconst botOf = r => (r && r.bot_tags && typeof r.bot_tags==='object' && !Array.isArray(r.bot_tags)) ? r.bot_tags : {};\nconst shortVal = v => v==null ? null : (Array.isArray(v) ? (v[0]==null?null:String(v[0]).split(':')[0].trim()) : String(v).split(':')[0].trim());\nconst trait = (r,k) => shortVal(trOf(r)[k]);\nconst bot   = (r,k) => shortVal(botOf(r)[k]);\nconst CX_ALIASES = [['Empatia do bot','Empatia do bot (Justina)']];\nconst cxTag = (r,k) => { const o=cxOf(r); if(o[k]!=null) return shortVal(o[k]); for(const [a,b] of CX_ALIASES){ if(k===a&&o[b]!=null) return shortVal(o[b]); if(k===b&&o[a]!=null) return shortVal(o[a]); } return null; };\nconst asArray = v => v==null ? [] : (Array.isArray(v) ? v.filter(x=>x!=null) : [v]);\nconst botArr = (r,k) => asArray(botOf(r)[k]).map(x=>String(x));\nconst timeToMin = t => { if(t==null) return 0; if(typeof t==='number') return t; const p=String(t).trim().split(':').map(Number); if(!p.length||p.some(isNaN)) return 0; let h=0,m=0,s=0; if(p.length===3)[h,m,s]=p; else if(p.length===2)[m,s]=p; else s=p[0]; return h*60+m+s/60; };\nconst riskLevel = r => { const s=trait(r,'Risco de churn'); if(!s) return null; if(s.startsWith('Churn em andamento')) return 'Saindo'; if(s.startsWith('Risco declarado')) return 'Declarou'; if(s.startsWith('Risco latente')) return 'Sinalizou'; if(s.startsWith('Sem risco')) return 'Estável'; return null; };\nconst RISK_CANCEL = { Saindo:0.90, Declarou:0.50, Sinalizou:0.15, 'Estável':0 };\nconst satBucket = r => { const s=trait(r,'Satisfação'); if(!s) return null; if(s.startsWith('Promotor')) return 'Promotor'; if(s.startsWith('Satisfeito')) return 'Satisfeito'; if(s.startsWith('Neutro')) return 'Neutro'; if(s.startsWith('Detrator')) return 'Detrator'; if(s.startsWith('Insatisf')) return 'Insatisfeito'; return null; };\nconst transbordou = r => bot(r,'Transbordo')==='Sim' || cxTag(r,'Transbordo')==='Sim' || kwOf(r).includes('Justina transferiu para o atendimento humano') || bot(r,'Desfecho da Justina')==='Resolvida após transbordo';\nconst desfecho = r => { const d=bot(r,'Desfecho da Justina'); if(d==='Resolvida pela Justina') return 'justina'; if(d==='Resolvida após transbordo') return 'transbordo_ok'; if(d==='Não resolvida') return 'nao_resolvida'; const nr=kwOf(r).includes('Não resolvido'), ok=kwOf(r).includes('Resolvido com sucesso'), tb=transbordou(r); if(nr) return 'nao_resolvida'; if(tb) return 'transbordo_ok'; if(ok) return 'justina'; return 'sem_evidencia'; };\nconst isRetrabalho = r => { if(!transbordou(r)) return false; const adeq=bot(r,'Adequação da Resposta da Justina')||''; return desfecho(r)==='nao_resolvida' || cxTag(r,'Loop do Bot')==='Sim' || cxTag(r,'Beco sem saída')==='Sim' || /tema diferente/i.test(adeq) || /contestad/i.test(adeq) || bot(r,'Reincidência Declarada')==='Sim'; };\nconst commSignal = r => { const sigs=[]; const tsol=botArr(r,'Transação Solicitada').join(' ').toLowerCase(); const obj=(bot(r,'Objeto da Demanda Principal')||'').toLowerCase(); const kw=kwOf(r).join(' ').toLowerCase(); const opp=trait(r,'Oportunidade comercial'); if(opp) sigs.push(opp); if(/assist|vidro|carro reserva|guincho|buraco/.test(tsol+' '+obj+' '+kw)) sigs.push('Upsell de cobertura'); if(/novo ve[ií]culo|segundo carro|troca de ve[ií]culo|multive/.test(kw+' '+obj+' '+String(trait(r,'Perfil')||'').toLowerCase())) sigs.push('Novo veículo'); if(/indica|mgm/.test(kw+' '+tsol)) sigs.push('Indicação (MGM)'); return Array.from(new Set(sigs)); };\nconst buildAccounts = rows => { const acc={}; for(const r of rows){ const k=r.phone||r.contact||r._id; if(!k) continue; (acc[k]=acc[k]||{key:k,phone:r.phone,contact:r.contact,contact_type:r.contact_type,sessions:[]}).sessions.push(r); } const out=[]; for(const k in acc){ const a=acc[k]; a.sessions.sort((x,y)=>String(y.ticket_date||'').localeCompare(String(x.ticket_date||''))); const latest=a.sessions[0]||{}; a.latest=latest; a.sessionCount=a.sessions.length; a.lastDate=latest.ticket_date; a.risk=riskLevel(latest); a.sat=satBucket(latest); out.push(a); } return out; };\nconst gatilhosOf = r => asArray(trOf(r)['Gatilhos de churn']).map(x=>String(x).split(':')[0].trim()).filter(Boolean);\nconst RX_PUBLIC = /(procon|reclame aqui|jur[ií]dic|ju[íi]zad|advogad|processo)/i;\nconst RX_LEAK = /(dado sens[íi]vel|exposi[çc][ãa]o de info|info interna|captura de ferramenta|vazamento)/i;\n\n/* ---- perfis (Aba 3) helpers — MUST match tab-perfis source ---- */\nconst pfDimValue = (r, dim) => { switch(dim){ case 'SAT': return satBucket(r); case 'RISCO': return riskLevel(r); case 'TRANSB': return transbordou(r)?'Transbordou':'Contida'; case 'ASSUNTO': return r&&r.contact_reason?r.contact_reason:null; case 'PRECO': return trait(r,'Sensibilidade a preço'); case 'MATUR': return trait(r,'Maturidade digital e autoatendimento'); case 'ENGAJ': return trait(r,'Engajamento com o produto'); case 'ESTILO': return trait(r,'Estilo de comunicação'); case 'CICLO': return trait(r,'Momento no ciclo de vida'); case 'PAGTO': return trait(r,'Comportamento de pagamento'); case 'PERFIL': { const v=trait(r,'Perfil'); return v?String(v).split(';')[0].trim():null; } default: return null; } };\nconst pfExcl = r => { const kw=kwOf(r).join(' '); const hay=((r&&r.summary)||'')+' '+kw; const L=hay.toLowerCase(); if(/sem resposta|sem retorno|n[aã]o respondeu|sem manifesta[çc][aã]o do cliente/.test(kw.toLowerCase())) return 'sem_resposta'; if(/por engano|n[uú]mero errado|pessoa errada|n[aã]o reconhe[çc]|n[aã]o sou cliente|engano\\b/.test(L)) return 'engano'; if(/desatualiz|n[uú]mero n[aã]o pertence|dono anterior|antigo dono|n[aã]o [eé] mais (o|a) (dono|cliente)/.test(L)) return 'desatualizado'; if(/\\bspam\\b|propaganda|divulga[çc][aã]o|marketing n[aã]o solicitado/.test(L)) return 'spam'; if(/assistente virtual do cliente|bot do cliente|respondid[oa] por (ia|bot|assistente)|agente de ia|resposta autom[aá]tica|mensagem autom[aá]tica/.test(L)) return 'agente_ia'; return null; };\nconst pfPersona = r => { const perfil=trait(r,'Perfil')||''; if(/Corretor/i.test(perfil)||(r&&r.contact_type==='Corretor')) return 'corretor'; const rk=riskLevel(r), ciclo=trait(r,'Momento no ciclo de vida'); if(rk==='Saindo'||rk==='Declarou'||ciclo==='Em cancelamento') return 'saida'; const eng=trait(r,'Engajamento com o produto')||''; if(/telemetria|privacidade/i.test(eng)) return 'telemetria'; const preco=trait(r,'Sensibilidade a preço'); if(preco==='Alta sensibilidade'||preco==='Busca ativa por desconto') return 'preco'; if(/Sinistralidade/i.test(perfil)) return 'sinistro'; const mat=trait(r,'Maturidade digital e autoatendimento'), sb=satBucket(r); if((mat==='Alta autonomia digital'||mat==='Adepto ao autoatendimento')&&(sb==='Promotor'||sb==='Satisfeito')) return 'autonomo'; return 'padrao'; };\nconst PF_LABELS = {SAT:'Satisfação',PRECO:'Sensibilidade a preço',MATUR:'Maturidade digital',ENGAJ:'Engajamento c/ app',ESTILO:'Estilo de comunicação',CICLO:'Momento no ciclo',PAGTO:'Comportamento de pagamento',PERFIL:'Perfil de uso',RISCO:'Risco de churn',TRANSB:'Transbordo',ASSUNTO:'Assunto'};\nconst PF_PERSONA_LBL = {corretor:'Corretor / canal B2B',saida:'Em cancelamento / saída',telemetria:'Resistente à telemetria',preco:'Sensível a preço',sinistro:'Sinistralidade recente',autonomo:'Autônomo digital',padrao:'Cliente ativo padrão'};\nconst PF_EXCL_LBL = {sem_resposta:'Sem resposta',engano:'Contato por engano',desatualizado:'Número desatualizado',spam:'Spam / propaganda',agente_ia:'Agente de IA do cliente'};\n\n/* ---- atrito (Aba 4) helpers — MUST match tab-atrito source ---- */\nconst REFORM_KEYS = ['Reformulação do pedido ou pergunta','Reformulação'];\nconst effortSig = r => ({ rep:cxTag(r,'Repetição de Informação')==='Sim', ref:REFORM_KEYS.some(k=>cxTag(r,k)==='Sim'), loop:cxTag(r,'Loop do Bot')==='Sim', beco:cxTag(r,'Beco sem saída')==='Sim', tb:transbordou(r), duv:cxTag(r,'Dúvidas pendentes no encerramento')==='Dúvida não respondida', reinc:bot(r,'Reincidência Declarada')==='Sim', fric:kwOf(r).includes('Resolvido com alta fricção') });\nconst effortCount = r => { const s=effortSig(r); let n=0; for(const k in s) if(s[k]) n++; return n; };\nconst hasAtrito = r => { const s=effortSig(r); return s.loop||s.rep||s.ref||s.beco; };\nconst fcrResolved = r => { const d=desfecho(r); return (d==='justina'||d==='transbordo_ok')&&bot(r,'Reincidência Declarada')!=='Sim'; };\nconst isBeco = r => !transbordou(r)&&bot(r,'Redirecionamento ao Autosserviço')==='Não houve direcionamento'&&(desfecho(r)==='nao_resolvida'||cxTag(r,'Beco sem saída')==='Sim');\nconst AUTOMATIZAVEL_RX = /(acesso a dado|capacidade de execu)/i;\nconst transbordoEvitavel = r => transbordou(r)&&(isRetrabalho(r)||AUTOMATIZAVEL_RX.test(bot(r,'Origem da Limitação da Justina')||''));\nconst pendBucket = r => { const pend=desfecho(r)==='nao_resolvida'||cxTag(r,'Dúvidas pendentes no encerramento')==='Dúvida não respondida'; if(!pend) return null; const redir=bot(r,'Redirecionamento ao Autosserviço'); if(!transbordou(r)&&redir==='Não houve direcionamento') return 'semresp'; if(transbordou(r)||cxTag(r,'Protocolo informado')==='Sim'||cxTag(r,'Prazo definido')==='Sim') return 'justos'; return 'cliente'; };\nconst canonReason = s => ({ 'Assistência':'Assistência','Sinistro':'Sinistro','Geral':'Outro','Cancelamento':'Cancelamento','Pagamento':'Pagamento','Aquisição':'Cotação','Aplicativo':'Aplicativo','Rewards':'Clube','Endosso':'Endosso','Apólice':'Apólice','Profile':'Cadastro','Portal':'Aplicativo','Driving Test':'Telemetria','Erro Justina':'Outro','Proposta':'Cotação' }[s] || (s?'Outro':null));\nconst canonObjeto = s => ({ 'Sinistro':'Sinistro','Assistência 24h':'Assistência','Pagamento e Cobrança':'Pagamento','Cancelamento':'Cancelamento','Cotação e Contratação':'Cotação','Outro':'Outro','Vistoria':'Vistoria','Apólice e Documentos':'Apólice','Aplicativo e Permissões':'Aplicativo','Clube Justos e Pontos':'Clube','Endosso':'Endosso','Dados Cadastrais':'Cadastro','Telemetria e Perfil de Direção':'Telemetria','Renovação Anual':'Renovação','Rastreador':'Telemetria','Alteração de Plano':'Endosso' }[s] || (s?'Outro':null));\nconst ATR_SIGKEY = {rep:'rep',ref:'ref',loop:'loop',beco:'beco',tb:'tb',duv:'duv',reinc:'reinc',fric:'fric'};\n\n/* ---- receita (Aba 2) helpers — MUST match tab-receita source ---- */\nconst COMM_SIGS = ['Upsell de cobertura','Novo veículo','Engajado com indicação','Receptivo a campanhas','Cliente referenciável','Mensal→Anual'];\nconst commSignalX = r => { const out={}; const opp=trait(r,'Oportunidade comercial'); if(opp){ const n=COMM_SIGS.find(s=>opp.toLowerCase().startsWith(s.toLowerCase().split('→')[0]))||opp; out[n]='trait'; } const tsol=botArr(r,'Transação Solicitada').join(' ').toLowerCase(); const objP=(bot(r,'Objeto da Demanda Principal')||'').toLowerCase(); const objS=botArr(r,'Objeto da Demanda Secundário').join(' ').toLowerCase(); const kw=kwOf(r).join(' ').toLowerCase(); const perfil=String(trait(r,'Perfil')||'').toLowerCase(); const sens=String(trait(r,'Sensibilidade a preço')||'').toLowerCase(); const hay=[tsol,objP,objS,kw].join(' '); const add=n=>{ if(!out[n]) out[n]='derivado'; }; if(/assist|vidro|carro reserva|guincho|buraco|reboque|p[aá]ra-choque|dano/.test(hay)||objP==='assistência 24h') add('Upsell de cobertura'); if(/novo ve[ií]culo|segundo carro|troca de ve[ií]culo|multive/.test(hay+' '+perfil)||objP==='endosso'||objP==='cotação e contratação') add('Novo veículo'); if(/indica|mgm|clube justos|pontos/.test(hay)||objP==='clube justos e pontos') add('Engajado com indicação'); if(/desconto/.test(sens)) add('Mensal→Anual'); if(satBucket(r)==='Promotor'&&Number(r.avr_sentiment)>=75) add('Cliente referenciável'); return Object.keys(out).map(n=>({name:n,src:out[n]})); };\nconst OPP_REV = { 'Upsell de cobertura':{factor:0.15,prob:0.30}, 'Novo veículo':{factor:1.00,prob:0.20}, 'Engajado com indicação':{factor:0.15,prob:0.35}, 'Receptivo a campanhas':{factor:0.10,prob:0.25}, 'Cliente referenciável':{factor:0.05,prob:0.20}, 'Mensal→Anual':{factor:0.08,prob:0.30} };\nconst oppApproach = (nSig, cond, atRisk) => { if(atRisk) return 'BLOCK'; if(nSig>=2) return cond>=2?'A1':'NAO'; if(nSig===1) return cond===3?'A1':(cond===2?'A2':'NAO'); if(nSig===0) return cond===3?'A3':'NONE'; return 'NONE'; };\nconst buildOpps = (rows, premio) => { const pr=premio==null?2250:premio; const accs=buildAccounts(rows); return accs.map(a=>{ const smap={}; for(const s of a.sessions){ for(const g of commSignalX(s)){ if(smap[g.name]!=='trait') smap[g.name]=g.src; } } const signals=Object.keys(smap).map(n=>({name:n,src:smap[n]})); const nSig=signals.length; const satisfeito=a.sat==='Promotor'||a.sat==='Satisfeito'; const semRisco=a.risk==='Estável'; const ciclo=trait(a.latest,'Momento no ciclo de vida'); const janela=(ciclo&&ciclo.startsWith('Em renovação'))||a.sessions.some(s=>desfecho(s)==='justina'||desfecho(s)==='transbordo_ok'||kwOf(s).includes('Resolvido com sucesso')); const cond=(satisfeito?1:0)+(semRisco?1:0)+(janela?1:0); const atRisk=a.risk==='Saindo'||a.risk==='Declarou'||a.sat==='Detrator'||a.sat==='Insatisfeito'; const approach=oppApproach(nSig,cond,atRisk); let revenue=0; for(const g of signals){ const m=OPP_REV[g.name]; if(m) revenue+=pr*m.factor*m.prob; } return { key:a.key, sessions:a.sessions, signals, nSig, approach, atRisk, revenue }; }); };\n\n/* ---- justina (Aba 5) helpers — verbatim from tab-justina ---- */\nconst J5_ASSUNTO = r => bot(r,'Objeto da Demanda Principal') || r.contact_reason || 'Sem assunto';\nconst j5adeq = r => { const a=bot(r,'Adequação da Resposta da Justina'); if(!a) return null; if(/tema diferente/i.test(a)) return 'tema_diferente'; if(/contestada/i.test(a)) return 'contestada'; if(/parcial/i.test(a)) return 'parcial'; if(/resolveu/i.test(a)) return 'resolveu'; return null; };\nconst j5origem = r => { const o=bot(r,'Origem da Limitação da Justina'); if(!o) return null; if(/sem limita/i.test(o)) return null; if(/tema ausente/i.test(o)) return {k:'conteudo',sub:'Tema ausente na base'}; if(/informa[çc][ãa]o.*(aplicad|caso)/i.test(o)) return {k:'conteudo',sub:'Info não aplicada ao caso'}; if(/incorret|contradit/i.test(o)) return {k:'conteudo',sub:'Info incorreta/contraditória'}; if(/capacidade de execu/i.test(o)) return {k:'capacidade',sub:'Falta de capacidade de execução'}; if(/acesso a dado/i.test(o)) return {k:'capacidade',sub:'Falta de acesso a dado'}; if(/formato/i.test(o)) return {k:'capacidade',sub:'Limitação de formato'}; return {k:'outro',sub:o}; };\nconst j5motivo = r => { const m=bot(r,'Motivo do Transbordo'); if(!m) return null; if(/capacidade de execu/i.test(m)) return 'Falta de capacidade de execução'; if(/acesso a dado/i.test(m)) return 'Falta de acesso a dado'; if(/solicitado pelo cliente/i.test(m)) return 'Solicitado pelo cliente'; if(/informa/i.test(m)) return 'Ausência de informação'; if(/regra de encaminh/i.test(m)) return 'Regra de encaminhamento'; return m; };\nconst j5kbgap = r => { const g=bot(r,'Lacuna de Base de Conhecimento'); if(g && !/^sem/i.test(g)) return g; const o=j5origem(r); if(o && o.k==='conteudo') return o.sub; return null; };\nconst j5loop = r => cxTag(r,'Loop do Bot')==='Sim';\nconst j5beco = r => cxTag(r,'Beco sem saída')==='Sim';\nconst j5empatia = r => cxTag(r,'Empatia do bot')==='Empatia Demonstrada';\n\n/* ---- humano (Aba 6) helpers — verbatim from tab-humano ---- */\nconst CHK = [\n  {key:'apres',label:'Apresentou-se com nome',get:r=>{const v=cxTag(r,'Apresentação do analista');return v==null?null:(v==='Apresentou-se com nome'?1:0);}},\n  {key:'contexto',label:'Recebeu transbordo com contexto',get:r=>{const v=cxTag(r,'Transbordo para humano com contexto');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'seg',label:'Validação de dados de segurança',get:r=>{const v=cxTag(r,'Validação de dados de segurança');if(v==null) return null;if(/completa/i.test(v)) return 1;if(/parcial/i.test(v)) return 0.5;return 0;}},\n  {key:'prazo',label:'Informou prazo concreto',get:r=>{const v=cxTag(r,'Prazo definido');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'proto',label:'Informou protocolo quando devido',get:r=>{const v=cxTag(r,'Protocolo informado');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'retomada',label:'Retomou após pausa com posição',get:r=>{const v=cxTag(r,'Retomada após pausa declarada');if(v==null) return null;return /retomou com posicionamento/i.test(v)?1:0;}},\n  {key:'abertura',label:'Abriu espaço p/ novas dúvidas',get:r=>{const v=cxTag(r,'Abertura para novas dúvidas');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'pesquisa',label:'Convidou p/ pesquisa de satisfação',get:r=>{const v=cxTag(r,'Convite à pesquisa de satisfação');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'empatia',label:'Empatia do atendente humano',get:r=>{const v=cxTag(r,'Empatia do Atendente Humano');if(v==null) return null;return /demonstrada/i.test(v)?1:0;}}\n];\nconst CHK_W = {apres:1,contexto:3,seg:3,prazo:1.5,proto:1.5,retomada:1.5,abertura:1,pesquisa:0.5,empatia:2};\nconst qIndex = r => { let sw=0,ss=0; for(const c of CHK){ const s=c.get(r); if(s==null) continue; const w=CHK_W[c.key]||1; sw+=w; ss+=w*s; } return sw>0?ss/sw:null; };\nconst RX_LEAK2 = /(dado sens[íi]vel|captura de (tela|ferramenta)|print (do|da) (sistema|tela)|vazamento|informa[çc][ãa]o interna|dado de terceiro|expos(i[çc][ãa]o|to) de (info|dado))/i;\nconst cSegAusente = r => cxTag(r,'Validação de dados de segurança')==='Validação ausente';\nconst cExposicao = r => cxTag(r,'Exposição de info interna')==='Sim' || RX_LEAK2.test(String(r&&r.summary||''));\nconst cTom = r => cxTag(r,'Tom inadequado')==='Sim' || (cxTag(r,'Empatia do Atendente Humano')==='Empatia Ausente' && Number(r&&r.avr_sentiment)<35);\nconst cCorrecao = r => cxTag(r,'Correção da informação')==='Não corrigida' || cxTag(r,'Correção de informação')==='Não corrigida';\nconst humBand = q => q==null?null:(q>=0.85?'alto':q>=0.70?'bom':q>=0.50?'medio':'baixo');\n\n/* ---- app (Aba 8) helpers — verbatim from tab-app ---- */\nconst SYMPTOM_DEFS = [{key:'viagens',rx:/viagen/i},{key:'permissoes',rx:/permiss|localiza/i},{key:'bateria',rx:/bateria/i},{key:'naoabre',rx:/n[ãa]o abre|trava|instalar|baixar/i},{key:'login',rx:/login|acesso/i},{key:'fotos',rx:/foto|documento/i},{key:'pontuacao',rx:/pontua/i},{key:'notificacao',rx:/notifica/i},{key:'versao',rx:/vers[ãa]o/i}];\nconst symptomKeyOf = v => { const s=String(v||'').toLowerCase(); for(const d of SYMPTOM_DEFS){ if(d.rx.test(s)) return d.key; } return 'outros'; };\nconst symptomsOf = r => { const out=[]; for(const v of botArr(r,'Sintoma Técnico Relatado')){ const k=symptomKeyOf(v); if(k!=='outros'&&out.indexOf(k)<0) out.push(k); } return out; };\nconst hasSymptom = r => botArr(r,'Sintoma Técnico Relatado').length>0;\nconst APP_RX = /\\bapp\\b|aplicativo|telemetr|rastread|driving test|registro de viagens|permiss|vistoria|inspe[çc]|pontua[çc]/i;\nconst appHay = r => (kwOf(r).join(' ')+' '+(bot(r,'Objeto da Demanda Principal')||'')+' '+String(r&&r.summary||'').slice(0,400));\nconst isAppContext = r => hasSymptom(r) || APP_RX.test(appHay(r));\nconst isAppComplaint = r => isAppContext(r) && (bot(r,'Natureza da Demanda')==='Reclamação' || /reclama[çc][ãa]o sobre o app|reclama[çc][ãa]o sobre permiss/i.test(kwOf(r).join(' ')));\nconst isRiskyA = r => { const lv=riskLevel(r); return lv==='Saindo'||lv==='Declarou'||lv==='Sinalizou'; };\nconst isGap = r => bot(r,'Tentativa Prévia no App')==='Sim' && transbordou(r);\nconst redirOf = r => bot(r,'Redirecionamento ao Autosserviço');\nconst isRedirApp = r => redirOf(r)==='Direcionado ao app';\nconst isRedirReincid = r => isRedirApp(r) && (bot(r,'Reincidência Declarada')==='Sim' || desfecho(r)==='nao_resolvida');\nconst PRIV_RX = /telemetr|privacidad|rastread|monitorament|dados pessoais|invas[ãa]o|n[ãa]o quero ser (rastrea|monitor)/i;\nconst isPrivacy = r => PRIV_RX.test(appHay(r));\nconst FLOW_DEFS = [{key:'inspecao',label:'Inspeção / Fotos',rx:/inspe[çc]|vistoria|foto|documento/i},{key:'permissoes',label:'Permissões',rx:/permiss|localiza/i},{key:'login',label:'Login / Acesso',rx:/login|acesso|baixar|instalar/i},{key:'viagens',label:'Validação de viagens',rx:/viagen|telemetr|registro de viagens/i},{key:'driving',label:'Driving Test',rx:/driving test|pontua|score/i},{key:'pagamento',label:'Pagamento',rx:/pagamento|cobran[çc]a|fatura|boleto|cart[ãa]o/i}];\nconst flowHay = r => (botArr(r,'Sintoma Técnico Relatado').join(' ')+' '+kwOf(r).join(' ')+' '+(bot(r,'Objeto da Demanda Principal')||'')+' '+String(r&&r.summary||'').slice(0,300)).toLowerCase();\nconst inFlow = (r,def) => def.rx.test(flowHay(r));\n\n/* ---- automacao (Aba 7) helpers — verbatim from tab-automacao ---- */\nconst normOrig = r => { const o=(bot(r,'Origem da Limitação da Justina')||'').toLowerCase(); if(/acesso a dado/.test(o)) return 'dado'; if(/capacidade de execu/.test(o)) return 'exec'; return null; };\nconst splitVals = arr => arr.map(x=>String(x).trim()).filter(Boolean);\nconst autoClassify = r => { if(!transbordou(r)) return null; const og=normOrig(r); if(og==='dado'){ const c=splitVals(botArr(r,'Dado Consultado')); return {tipo:'consulta',caps:c.length?c:['Consulta não especificada']}; } if(og==='exec'){ const c=splitVals(botArr(r,'Transação Solicitada')); return {tipo:'transacao',caps:c.length?c:['Transação não especificada']}; } if(bot(r,'Ação do Atendente Humano')==='Apenas repassou informação'){ return {tipo:'conteudo',caps:['Conteúdo — '+(bot(r,'Objeto da Demanda Principal')||'Assunto geral')]}; } return null; };\nconst hasV = (r,k,rx)=> botArr(r,k).some(v=>rx.test(String(v)));\nconst NOTIF=[\n  {key:'pagamento',title:'Vencimento / falha de pagamento',m:r=> /pagamento|cobran|fatura/i.test(r.contact_reason||'')||hasV(r,'Dado Consultado',/vencimento|fatura/i)||hasV(r,'Transação Solicitada',/segunda via de cobran|forma ou cart[ãa]o de pagamento/i)},\n  {key:'sinistro',title:'Mudança de status de sinistro',m:r=> hasV(r,'Dado Consultado',/status de sinistro/i)||(/sinistro/i.test(r.contact_reason||'')&&/acompanh/i.test(kwOf(r).join(' ')))},\n  {key:'vistoria',title:'Pendência de documento / vistoria',m:r=> hasV(r,'Transação Solicitada',/enviar documentos|agendar vistoria/i)||hasV(r,'Dado Consultado',/status de vistoria/i)},\n  {key:'assistencia',title:'Conclusão / status de assistência',m:r=> hasV(r,'Dado Consultado',/assist[êe]ncia acionada/i)||hasV(r,'Transação Solicitada',/acionar assist[êe]ncia/i)},\n  {key:'renovacao',title:'Prazo de renovação',m:r=> hasV(r,'Transação Solicitada',/renova/i)||/renova/i.test(r.contact_reason||'')||trait(r,'Momento no ciclo de vida')==='Em renovação'},\n  {key:'voucher',title:'Voucher / pontos expirando',m:r=> hasV(r,'Dado Consultado',/voucher|pontos/i)||hasV(r,'Transação Solicitada',/resgatar pontos|voucher/i)},\n  {key:'permissao',title:'Permissão do app desativada',m:r=> hasV(r,'Sintoma Técnico Relatado',/permiss/i)}\n];\n/* ===== END KIT + drill helpers ===== */\n\nconst TABS = [['exec','Visão Executiva','0'],['churn','Risco de Churn','1'],['receita','Oportunidades de Receita','2'],['perfis','Perfis de Cliente','3'],['atrito','Experiência e Atrito','4'],['justina','Qualidade Justina','5'],['humano','Qualidade do Atendimento','6'],['automacao','Automação da Justina','7'],['app','Melhorias do App','8'],['ficha','Ficha / Conversa','9'],['premissas','Premissas e Cobertura','10']];\nconst TAB_META = {exec:['CEO','Onde está o dinheiro e o risco neste mês?'],churn:['CS/CX','Quem eu ligo amanhã?'],receita:['CS/Comercial','Quem eu abordo e com qual oferta?'],perfis:['Todos','Quem são meus clientes, de verdade?'],atrito:['CX','Onde o cliente sofre?'],justina:['Produto','A IA está entregando?'],humano:['CS/CX','O time está entregando?'],automacao:['Produto/COO','O que integrar primeiro, e quanto economiza?'],app:['Produto','O que o app está causando de atendimento?'],ficha:['Todos','Drill-down universal — destino de todo clique'],premissas:['CFO','Em que eu posso confiar aqui?']};\nconst TAB_GUIDE = {\n  exec:{ what:\"Resumo do mês em dinheiro e risco: quanto o atendimento custa, quanto a Justina economiza, onde há receita a capturar e quais clientes são os mais caros de servir.\", method:[\"Valores em R$ são estimativas, calculadas a partir das premissas da Aba 10 (ticket médio, custo por transbordo, taxas). Contagens e tags são fato.\",\"O custo de servir de um cliente soma o custo das conversas dele: Justina mais os transbordos humanos.\",\"O ranking mostra os 15 clientes de maior custo, coloridos por risco e satisfação.\"], terms:[[\"Transbordo\",\"Quando a Justina (IA) passa a conversa para um atendente humano.\"],[\"Contenção\",\"Percentual de conversas que a Justina resolve sozinha, sem transbordo.\"],[\"Sinal comercial\",\"Indício, dentro da conversa, de oportunidade de venda (upsell, novo veículo, indicação).\"]] },\n  churn:{ what:\"Lista de clientes com risco de sair, priorizada por gravidade, para a ação de retenção: a resposta de quem ligar primeiro.\", method:[\"O risco vem da extração de IA Risco de churn na conversa mais recente de cada cliente.\",\"É agregado por cliente (telefone/contato), não por conversa: cada linha é uma pessoa.\",\"Os gatilhos são os motivos declarados do risco (preço, sinistro, atendimento).\"], terms:[[\"Saindo\",\"Churn em andamento: o cliente já está cancelando.\"],[\"Declarou\",\"Risco declarado: o cliente disse que pensa em sair.\"],[\"Sinalizou\",\"Risco latente: sinais indiretos de insatisfação, sem declaração.\"],[\"Estável\",\"Sem risco aparente na conversa.\"]] },\n  receita:{ what:\"Clientes com oportunidade de venda e qual abordagem faz sentido para cada um, para o time comercial e de CS priorizar.\", method:[\"Sinais comerciais são detectados na conversa (pedido de assistência, menção a novo veículo, indicação).\",\"A abordagem cruza o número de sinais com as condições do cliente: satisfeito, sem risco e em janela de renovação.\",\"A receita potencial é estimativa: aplica fatores e probabilidades de conversão (Aba 10) sobre o ticket médio.\"], terms:[[\"Upsell de cobertura\",\"Ampliar a cobertura atual do cliente (por exemplo vidros ou carro reserva).\"],[\"Regra de ouro\",\"Cliente em risco que também tem sinal comercial: retenção antes de oferta.\"],[\"Abordagem A1/A2/A3\",\"Prontidão para oferta: A1 aborda já, A3 apenas nutre, BLOCK não oferta (cliente em risco).\"]] },\n  perfis:{ what:\"Retrato dos clientes por dimensões de comportamento e atitude (satisfação, sensibilidade a preço, maturidade digital) e o agrupamento em personas.\", method:[\"Cada dimensão vem de uma extração de IA sobre a conversa (traits).\",\"Personas são regras que combinam essas dimensões (por exemplo resistente à telemetria ou sensível a preço).\",\"Conversas que não são de um cliente real (engano, spam, número desatualizado, agente de IA do cliente) ficam separadas como exclusões.\"], terms:[[\"Persona\",\"Grupo de clientes com perfil semelhante, derivado das traits.\"],[\"Maturidade digital\",\"O quanto o cliente resolve sozinho no app e no autoatendimento.\"],[\"Exclusão\",\"Conversa que não representa um cliente real e sai das análises de perfil.\"]] },\n  atrito:{ what:\"Onde o cliente teve esforço ou fricção: repetir informação, entrar em loop, ficar sem resposta. Aponta os assuntos que mais geram sofrimento.\", method:[\"Cada sinal de esforço é uma tag de IA (repetição, reformulação, loop do bot, beco sem saída).\",\"O FCR mede quantas conversas foram resolvidas já no primeiro contato.\",\"O custo do atrito estima o gasto com transbordos que poderiam ter sido evitados.\"], terms:[[\"Loop do bot\",\"A Justina repete respostas sem fazer a conversa avançar.\"],[\"Beco sem saída\",\"Conversa que trava sem solução e sem transbordo.\"],[\"FCR\",\"Resolução no primeiro contato, sem reincidência.\"],[\"Transbordo evitável\",\"Transbordo que uma automação ou base melhor teria evitado.\"]] },\n  justina:{ what:\"Qualidade da IA (Justina): quando resolve, quando erra e por quê. Separa falhas de conteúdo (base de conhecimento) de falhas de capacidade (integração).\", method:[\"A adequação da resposta classifica cada resposta da Justina (resolveu, parcial, contestada, fora do tema).\",\"A origem da limitação diz se faltou conteúdo (informação) ou capacidade (acesso a dado ou execução).\",\"As lacunas de base apontam assuntos em que falta conteúdo para a IA responder.\"], terms:[[\"Conteúdo\",\"Limitação por falta ou erro de informação na base de conhecimento.\"],[\"Capacidade\",\"Limitação por falta de acesso a dado ou de executar uma ação (integração).\"],[\"Lacuna de base\",\"Tema recorrente que a base de conhecimento não cobre.\"],[\"Empatia do bot\",\"A Justina demonstrou acolhimento na conversa.\"]] },\n  humano:{ what:\"Qualidade do atendimento humano após o transbordo: aderência a um checklist de conduta e riscos de compliance (segurança, exposição de dados, tom).\", method:[\"O índice de qualidade é uma média ponderada de um checklist de conduta: os itens mais críticos pesam mais.\",\"Cada item vem de uma tag de IA sobre a conversa (apresentou-se, validou segurança, informou prazo e protocolo).\",\"Considera apenas conversas que passaram para o atendente humano (transbordo).\"], terms:[[\"Índice de qualidade\",\"Nota de 0 a 100% do atendimento, ponderada pela criticidade de cada item.\"],[\"Validação de segurança\",\"Confirmar a identidade do cliente antes de tratar dados sensíveis.\"],[\"Exposição de info interna\",\"Vazamento de dado interno ou de terceiro na conversa: risco de compliance.\"]] },\n  automacao:{ what:\"O que vale integrar ou automatizar primeiro: agrupa os transbordos pela capacidade que falta à Justina e estima a economia de cada uma.\", method:[\"Cada transbordo automatizável é classificado por tipo: consulta (falta acesso a dado), transação (falta executar ação) ou conteúdo.\",\"As capacidades são agrupadas e ranqueadas por economia líquida estimada por mês.\",\"As notificações proativas listam gatilhos que a Justina poderia avisar antes de o cliente perguntar.\"], terms:[[\"Consulta\",\"A Justina precisaria acessar um dado que hoje não tem (por exemplo status de sinistro).\"],[\"Transação\",\"A Justina precisaria executar uma ação (por exemplo segunda via ou agendar vistoria).\"],[\"Notificação proativa\",\"Aviso automático antes de o cliente precisar perguntar (por exemplo vencimento de pagamento).\"]] },\n  app:{ what:\"O que o app Justos está gerando de atendimento: sintomas técnicos relatados, fluxos com mais fricção e reclamações. Insumo para o time de Produto.\", method:[\"Sintomas técnicos são problemas de app citados na conversa (viagens, permissões, login, fotos).\",\"As conversas são marcadas como contexto de app por palavras-chave e pelo objeto da demanda.\",\"App falhou e virou contato humano mostra onde o autoatendimento não resolveu e gerou atendimento.\"], terms:[[\"Sintoma técnico\",\"Problema de app relatado pelo cliente na conversa.\"],[\"Gap do app\",\"O cliente tentou resolver no app, não conseguiu e precisou de humano.\"],[\"Telemetria\",\"Rastreamento de direção (Driving Test): fonte comum de dúvida e de privacidade.\"]] },\n  ficha:{ what:\"O destino de todo clique. Qualquer número ou barra do dashboard abre aqui, já filtrado: a conversa completa, as extrações de IA e o link do ticket no Zendesk. É o que torna cada número auditável.\", method:[\"Mostra a conversa transcrita e as quatro extrações de IA: resumo, traits, cx_tags e bot_tags.\",\"Quando aberta por um clique, já vem filtrada pelo recorte que você clicou.\",\"O link leva ao ticket original no Zendesk para conferência.\"], terms:[[\"Extração\",\"Análise de IA sobre a conversa: resumo, perfil e tags de experiência e de bot.\"],[\"Auditabilidade\",\"Poder rastrear qualquer número até as conversas reais que o formam.\"]] },\n  premissas:{ what:\"Onde ficam as premissas e cenários que alimentam TODAS as estimativas em R$, e a cobertura da análise (quantas conversas foram efetivamente processadas). Responde em que confiar.\", method:[\"Separa o que é fato (contagens, tags) do que é estimativa (todo valor em R$).\",\"O cenário (conservador, base ou otimista) multiplica as taxas e reprecifica o dashboard inteiro.\",\"Você pode editar aqui as taxas de cancelamento e de conversão: as demais abas recalculam.\"], terms:[[\"Fato\",\"Número contado direto das conversas, não depende de premissa.\"],[\"Estimativa\",\"Valor em R$ derivado de premissas: muda com o cenário.\"],[\"Cenário\",\"Ajuste global otimista, base ou conservador aplicado às taxas.\"]] }\n};\nconst TAB_UC = {\n  exec:'babi-hera@justos-tab-exec',\n  churn:'babi-hera@justos-tab-churn',\n  receita:'babi-hera@justos-tab-receita',\n  perfis:'babi-hera@justos-tab-perfis',\n  atrito:'babi-hera@justos-tab-atrito',\n  justina:'babi-hera@justos-tab-justina',\n  humano:'babi-hera@justos-tab-humano',\n  automacao:'babi-hera@justos-tab-automacao',\n  app:'babi-hera@justos-tab-app',\n  ficha:'babi-hera@justos-tab-ficha',\n  premissas:'babi-hera@justos-tab-premissas'\n};\nconst SCEN_F = { conservador:0.7, base:1.0, otimista:1.3 };\nconst DEF_PREM = { cancelRates:{Saindo:0.90,Declarou:0.50,Sinalizou:0.15}, convRates:{upsell:0.25,mensalAnual:0.30,novoVeiculo:0.15,indicacao:0.20,campanha:0.10,referenciavel:0.05}, scenario:'base' };\nconst PREM_STORE = 'poc-justus-premises';\nconst DESF_LBL = {justina:'Resolvida pela Justina',transbordo_ok:'Resolvida após transbordo',nao_resolvida:'Não resolvida',sem_evidencia:'Sem evidência'};\nconst desfChip = r => { const st=desfecho(r); const tone=st==='justina'?'ok':st==='nao_resolvida'?'bad':st==='transbordo_ok'?'warn':''; return '<span class=\"jr-chip '+tone+'\">'+esc(DESF_LBL[st]||st)+'</span>'; };\nconst byDateDesc = (a,b) => String(b.ticket_date||'').localeCompare(String(a.ticket_date||''));\nconst nparse = (a,b) => { const v=(a==null||a==='')?b:a; const n=Number(v); return isNaN(n)?Number(b):n; };\nconst acctKey = r => r.phone||r.contact||r._id;\n\n/* ---- account-level drill: sessions of matching accounts ---- */\nconst acctDrill = (rows, title, matchAcc) => { const accs=buildAccounts(rows); const keys=new Set(accs.filter(matchAcc).map(a=>a.key)); return { title, list: rows.filter(r=>keys.has(acctKey(r))).sort(byDateDesc) }; };\n\n/* ================= drillFor: token -> {title, list of sessions} ================= */\nconst pf3_perfilToks = r => { const raw = trOf(r)['Perfil']; if(raw==null) return []; const s = Array.isArray(raw)?raw.join('; '):String(raw); return s.split(';').map(x=>x.split(':')[0].trim()).filter(Boolean); };\nconst pf3_dim = (r,key)=>{ switch(key){ case 'sat': return satBucket(r); case 'risco': return riskLevel(r); case 'transb': return transbordou(r)?'Sim':'Não'; case 'reason': return r.contact_reason||'Sem motivo'; case 'matdig': return trait(r,'Maturidade digital e autoatendimento'); case 'sens': return trait(r,'Sensibilidade a preço'); case 'engaj': return trait(r,'Engajamento com o produto'); case 'estilo': return trait(r,'Estilo de comunicação'); case 'momento': return trait(r,'Momento no ciclo de vida'); case 'pgto': return trait(r,'Comportamento de pagamento'); case 'perfil': { const t=pf3_perfilToks(r); return t.length?t[0]:null; } default: return null; } };\nconst pf3_persona = acc => { const r = acc.latest||{}; const mom = trait(r,'Momento no ciclo de vida'); if (acc.risk==='Saindo' || acc.risk==='Declarou' || mom==='Em cancelamento') return 'cancelamento'; const perfilT = pf3_perfilToks(r); if (acc.contact_type==='Corretor' || perfilT.includes('Corretor')) return 'corretor'; if (perfilT.includes('Sinistralidade recente') || r.contact_reason==='Sinistro') return 'sinistro'; const sens = trait(r,'Sensibilidade a preço'); const gat = trait(r,'Gatilhos de churn'); if (sens==='Alta sensibilidade' || sens==='Busca ativa por desconto' || gat==='Preço') return 'preco'; const eng = trait(r,'Engajamento com o produto'); const mat = trait(r,'Maturidade digital e autoatendimento'); if (eng==='Resistente à telemetria' || eng==='Preocupado com privacidade de dados' || mat==='Prefere atendimento humano') return 'telemetria'; if (mat==='Alta autonomia digital' || mat==='Adepto ao autoatendimento') return 'autonomo'; return 'outros'; };\nconst PF3_ENGANO=/engano|n[uú]mero errado|pessoa errada|n[aã]o sou (o |a )?(cliente|segurad)|n[aã]o [eé] comigo|contato errado|foi sem querer/i;\nconst PF3_DESAT=/desatualiz|vendeu o (carro|ve[ií]culo)|outro dono|n[aã]o [eé] mais (cliente|segurad)|n[uú]mero antigo|troquei de n[uú]mero/i;\nconst PF3_SPAM=/\\bspam\\b|propaganda|divulga[çc][aã]o|marketing n[aã]o solicitad/i;\nconst PF3_IA=/assistente virtual|resposta autom[aá]tica|mensagem autom[aá]tica|chatbot do cliente|agente de ia/i;\nconst pf3_exclusion = r => { const hay=(r.summary||'')+' '+kwOf(r).join(' '); if (kwOf(r).some(k=>/^contato sem resposta/i.test(k)) || /\\bcontato sem resposta\\b/i.test(hay)) return 'semresposta'; if (PF3_ENGANO.test(hay)) return 'engano'; if (PF3_DESAT.test(hay)) return 'desatualizado'; if (PF3_SPAM.test(hay)) return 'spam'; if (PF3_IA.test(hay)) return 'ia'; return null; };\nconst drillFor = (rows, token) => {\n  if(!token) return null;\n  const R = (title, f) => ({ title, list: rows.filter(f).sort(byDateDesc) });\n  if(token==='all') return R('Todas as conversas analisadas', ()=>true);\n  const ci = token.indexOf(':'); const kind = ci<0?token:token.slice(0,ci); const val = ci<0?'':token.slice(ci+1);\n\n  if(kind==='desf'){ if(val==='transb') return R('Conversas transbordadas', transbordou); if(val==='retrab') return R('Retrabalho — Justina + humano que falharam', isRetrabalho); return R(DESF_LBL[val]||'Conversas', r=>desfecho(r)===val); }\n  if(kind==='sat') return R('Satisfação: '+val, r=>satBucket(r)===val);\n  if(kind==='reason') return R('Assunto: '+val, r=>(r.contact_reason||'Sem motivo')===val);\n  if(kind==='risk') return R('Nível de risco: '+val, r=>riskLevel(r)===val);\n  if(kind==='alert'){ if(val==='churn') return R('Churn em andamento', r=>riskLevel(r)==='Saindo'); if(val==='publica') return R('Ameaça de exposição pública', r=>RX_PUBLIC.test((r.summary||'')+' '+kwOf(r).join(' ')+' '+botArr(r,'Sinal de Risco').join(' '))); if(val==='exposicao') return R('Exposição indevida de info', r=>RX_LEAK.test((r.summary||'')+' '+kwOf(r).join(' '))||cxTag(r,'Exposição de info interna')==='Sim'); }\n\n  if(kind==='churn'){\n    if(val==='risco') return acctDrill(rows,'Clientes em risco', a=>{const l=a.risk;return l&&l!=='Estável';});\n    if(val.indexOf('nivel:')===0){ const lv=val.slice(6); return acctDrill(rows,'Nível: '+lv, a=>a.risk===lv); }\n    if(val.indexOf('gatilho:')===0){ const g=val.slice(8).toLowerCase(); return R('Gatilho: '+val.slice(8), r=>gatilhosOf(r).some(x=>x.toLowerCase().startsWith(g))); }\n  }\n\n  if(kind==='abord'){ const opps=buildOpps(rows,2250); const keys=new Set(opps.filter(o=>o.approach===val).map(o=>o.key)); return { title:'Abordagem '+val, list: rows.filter(r=>keys.has(acctKey(r))).sort(byDateDesc) }; }\n  if(token==='abordrisco'){ const opps=buildOpps(rows,2250); const keys=new Set(opps.filter(o=>o.atRisk&&o.nSig>0).map(o=>o.key)); return { title:'Em risco com sinal comercial (regra de ouro)', list: rows.filter(r=>keys.has(acctKey(r))).sort(byDateDesc) }; }\n  if(token==='sinalcom') return R('Contas com sinal comercial', r=>commSignalX(r).length>0);\n  if(kind==='sinal'){ return R('Sinal comercial: '+val, r=>commSignalX(r).some(g=>g.name===val)); }\n\n  if(kind==='ptrait'){ const p=val.split('~'); const code=p[0], v=p.slice(1).join('~'); return R((PF_LABELS[code]||code)+': '+v, r=>pfDimValue(r,code)===v); }\n  if(kind==='pcross'){ const parts=val.split('__'); const a=(parts[0]||'').split('~'), b=(parts[1]||'').split('~'); const px=a[0], cv=a.slice(1).join('~'), py=b[0], rv=b.slice(1).join('~'); return R((PF_LABELS[px]||px)+' '+cv+' × '+(PF_LABELS[py]||py)+' '+rv, r=>pfDimValue(r,px)===cv&&pfDimValue(r,py)===rv); }\n  if(kind==='ppersona'){ return acctDrill(rows,'Persona: '+(PF_PERSONA_LBL[val]||val), a=>pfPersona(a.latest)===val); }\n  if(kind==='pexcl'){ return R('Exclusão: '+(PF_EXCL_LBL[val]||val), r=>pfExcl(r)===val); }\n\n  if(kind==='perfis'){\n    const ci2=val.indexOf(':'); const sub=ci2<0?val:val.slice(0,ci2); const arg=ci2<0?'':val.slice(ci2+1);\n    if(sub==='persona'){ return acctDrill(rows, 'Persona: '+arg, a=>pf3_persona(a)===arg); }\n    if(sub==='exc'){ if(arg==='naosegurado') return R('Não é o segurado', r=>!!(r.contact_type && r.contact_type!=='Cliente')); return R('Exclusão: '+arg, r=>pf3_exclusion(r)===arg); }\n    if(sub==='f'){\n      const PFL={sat:'Satisfação',risco:'Risco',transb:'Transbordo',reason:'Assunto',matdig:'Maturidade digital',sens:'Sensibilidade a preço',engaj:'Engajamento',estilo:'Estilo',momento:'Momento no ciclo',pgto:'Pagamento',perfil:'Perfil de uso'};\n      const parts=arg.split(';').filter(Boolean).map(p=>{ const eq=p.indexOf('='); if(eq>=0) return {key:p.slice(0,eq), val:p.slice(eq+1)}; const tl=p.indexOf('~'); if(tl>=0) return {key:p.slice(0,tl), val:p.slice(tl+1)}; return {key:p, val:''}; });\n      const single=parts.length===1;\n      const title=parts.map(p=>(PFL[p.key]||p.key)+': '+p.val).join(' × ');\n      return R(title, r=> parts.every(p=> p.key==='perfil' ? (single ? pf3_perfilToks(r).indexOf(p.val)>=0 : pf3_dim(r,'perfil')===p.val) : pf3_dim(r,p.key)===p.val ));\n    }\n    return { title:'Perfis ('+token+')', list: rows.slice().sort(byDateDesc) };\n  }\n\n  if(kind==='atrito'){\n    if(val==='fcr') return R('Resolvidas no 1º contato', fcrResolved);\n    if(val==='effort') return R('Maior esforço (3+ sinais)', r=>effortCount(r)>=3);\n    if(val==='custo') return R('Custo do atrito (transbordo evitável)', transbordoEvitavel);\n    if(val.indexOf('signal:')===0){ const s=val.slice(7); if(s==='atrito') return R('Conversas com atrito', hasAtrito); return R('Sinal de esforço: '+s, r=>!!effortSig(r)[ATR_SIGKEY[s]]); }\n    if(val.indexOf('assunto:')===0){ const o=val.slice(8); return R('Assunto (objeto): '+o, r=>(bot(r,'Objeto da Demanda Principal')||'Sem objeto')===o); }\n    if(val.indexOf('naoresolv:')===0){ const o=val.slice(10); return R('Não resolvido — '+o, r=>(bot(r,'Objeto da Demanda Principal')||'Sem objeto')===o&&desfecho(r)==='nao_resolvida'); }\n    if(val.indexOf('pend:')===0){ const b=val.slice(5); return R('Pendência: '+b, r=>pendBucket(r)===b); }\n    if(val.indexOf('cell:')===0){ const cv=val.slice(5); const bar=cv.lastIndexOf('|'); const obj=cv.slice(0,bar), sig=cv.slice(bar+1); return R(obj+' · '+sig, r=>(bot(r,'Objeto da Demanda Principal')||'Sem objeto')===obj&&!!effortSig(r)[ATR_SIGKEY[sig]]); }\n    if(val.indexOf('conf:')===0){ const cv=val.slice(5); const bar=cv.lastIndexOf('|'); const decl=cv.slice(0,bar), real=cv.slice(bar+1); return R('Declarado '+decl+' → real '+real, r=>canonReason(r.contact_reason)===decl&&canonObjeto(bot(r,'Objeto da Demanda Principal'))===real); }\n  }\n\n  if(kind==='j5'){\n    if(val==='loop') return R('Loop do bot', j5loop);\n    if(val==='beco') return R('Beco sem saída', j5beco);\n    if(val==='empatia') return R('Empatia do bot demonstrada', j5empatia);\n    if(val==='adeq:falha') return R('Falhas de conteúdo (tema diferente / contestada)', r=>{const a=j5adeq(r);return a==='tema_diferente'||a==='contestada';});\n    if(val.indexOf('adeq:')===0){ const k=val.slice(5); return R('Adequação da resposta: '+k, r=>j5adeq(r)===k); }\n    if(val.indexOf('assunto:')===0){ const a=val.slice(8); return R('Assunto: '+a, r=>J5_ASSUNTO(r)===a); }\n    if(val==='origem:conteudo') return R('Limitação de conteúdo (base de conhecimento)', r=>{const o=j5origem(r);return o&&o.k==='conteudo';});\n    if(val==='origem:capacidade') return R('Limitação de capacidade (integração)', r=>{const o=j5origem(r);return o&&o.k==='capacidade';});\n    if(val.indexOf('origemsub:')===0){ const s=val.slice(10); return R('Origem: '+s, r=>{const o=j5origem(r);return o&&o.sub===s;}); }\n    if(val.indexOf('kbgap:')===0){ const a=val.slice(6); return R('Lacuna de base — '+a, r=>J5_ASSUNTO(r)===a&&!!j5kbgap(r)); }\n    if(val.indexOf('motivo:')===0){ const m=val.slice(7); return R('Motivo do transbordo: '+m, r=>j5motivo(r)===m); }\n    if(val.indexOf('loopbeco:')===0){ const a=val.slice(9); return R('Loop/beco — '+a, r=>J5_ASSUNTO(r)===a&&(j5loop(r)||j5beco(r))); }\n    if(val.indexOf('retrab:')===0){ const a=val.slice(7); return R('Retrabalho — '+a, r=>J5_ASSUNTO(r)===a&&isRetrabalho(r)); }\n    return R('Qualidade da Justina', transbordou);\n  }\n\n  if(kind==='hum'){\n    const H = (title,f)=>({title, list: rows.filter(r=>transbordou(r)&&f(r)).sort(byDateDesc)});\n    if(val==='all') return H('Atendimentos humanos', ()=>true);\n    if(val==='sem_contexto') return H('Transbordo sem contexto', r=>cxTag(r,'Transbordo para humano com contexto')==='Não');\n    if(val==='repassou') return H('Apenas repassou informação', r=>bot(r,'Ação do Atendente Humano')==='Apenas repassou informação');\n    if(val==='seg_ausente') return H('Validação de segurança ausente', cSegAusente);\n    if(val==='exposicao') return H('Exposição de info interna', cExposicao);\n    if(val==='tom') return H('Tom inadequado', cTom);\n    if(val==='correcao') return H('Correção de info não corrigida', cCorrecao);\n    if(val==='index') return H('Índice de qualidade do atendimento', ()=>true);\n    if(val.indexOf('index:')===0){ const k=val.slice(6); return H('Qualidade: '+k, r=>humBand(qIndex(r))===k); }\n    if(val.indexOf('check:')===0){ const key=val.slice(6); const c=CHK.find(x=>x.key===key); if(c) return H(c.label, r=>c.get(r)===1); return H('Checklist de conduta', ()=>true); }\n    if(val.indexOf('acao:')===0){ const a=val.slice(5); return H('Ação do atendente: '+a, r=>bot(r,'Ação do Atendente Humano')===a); }\n    if(val.indexOf('team:')===0){ const t=val.slice(5); return H('Time: '+t, r=>r.team===t); }\n    if(val.indexOf('analyst:')===0){ const a=val.slice(8); return H('Atendente: '+a, r=>r.analyst===a); }\n    return H('Atendimento humano', ()=>true);\n  }\n\n  if(kind==='auto'){\n    if(val==='all') return R('Transbordos automatizáveis', r=>!!autoClassify(r));\n    if(val.indexOf('cap:')===0){ const cap=val.slice(4); return R('Capacidade: '+cap, r=>{const c=autoClassify(r);return c&&c.caps&&c.caps[0]===cap;}); }\n    if(val.indexOf('notif:')===0){ const key=val.slice(6); const n=NOTIF.find(x=>x.key===key); if(n) return R('Notificação proativa: '+(n.title||key), n.m); return R('Notificação proativa', transbordou); }\n    return R('Automação da Justina', r=>!!autoClassify(r));\n  }\n\n  if(kind==='app'){\n    if(val==='ctx') return R('Conversas com contexto de app', isAppContext);\n    if(val==='gap') return R('App falhou → contato humano', isGap);\n    if(val==='tentativa') return R('Tentativa prévia no app', r=>bot(r,'Tentativa Prévia no App')==='Sim');\n    if(val==='reclama') return R('Reclamações sobre o app', isAppComplaint);\n    if(val==='reclama:risco') return R('Reclamações de app com risco de churn', r=>isAppComplaint(r)&&isRiskyA(r));\n    if(val==='neutro') return R('Dúvidas neutras sobre o app', r=>isAppContext(r)&&!isAppComplaint(r));\n    if(val==='privacidade') return R('Privacidade / telemetria', isPrivacy);\n    if(val.indexOf('sintoma:')===0){ const k=val.slice(8); return R('Sintoma técnico: '+k, r=>symptomsOf(r).indexOf(k)>=0); }\n    if(val.indexOf('redir:')===0){ const k=val.slice(6); if(k==='app') return R('Direcionado ao app', isRedirApp); if(k==='reincid') return R('Redirecionado ao app e reincidiu', isRedirReincid); if(k==='none') return R('Sem direcionamento', r=>redirOf(r)==='Não houve direcionamento'); if(k==='outro') return R('Outro direcionamento', r=>{const x=redirOf(r);return x&&x!=='Direcionado ao app'&&x!=='Não houve direcionamento';}); return R('Redirecionamento ao autosserviço', r=>!!redirOf(r)); }\n    if(val.indexOf('fluxo:')===0){ const k=val.slice(6); const f=FLOW_DEFS.find(x=>x.key===k); if(f) return R('Fricção por fluxo: '+f.label, r=>inFlow(r,f)); return R('Fricção por fluxo', isAppContext); }\n    return R('Sinais do app', isAppContext);\n  }\n\n  if(kind==='fieldv'){ const parts=val.split('~'); const obj=parts[0], field=parts[1], value=parts.slice(2).join('~'); const LBL={traits:'Trait',cx:'Qualidade',bot:'Automação',class:'Classificação'}[obj]||obj; return R(LBL+' · '+field+': '+value, r=>fieldValues(r,obj,field).indexOf(value)>=0); }\n  if(kind==='extr'){\n    if(val==='e1') return R('E1 · Classificação — conversas classificadas', r=>!!(r.summarized||r.contact_analyzed||r.summary));\n    if(val==='e2') return R('E2 · Traits do cliente — conversas com traits', r=>Object.keys(trOf(r)).length>0);\n    if(val==='e3') return R('E3 · Qualidade — conversas com cx_tags', r=>!!r.cx_analyzed||Object.keys(cxOf(r)).length>0);\n    if(val==='e4') return R('E4 · Automação e produto — conversas com bot_tags', r=>!!r.bot_analyzed||Object.keys(botOf(r)).length>0);\n  }\n  if(kind==='extrf'){ const ci2=val.indexOf(':'); const obj=ci2<0?val:val.slice(0,ci2); const field=ci2<0?'':val.slice(ci2+1); const OBJ={traits:trOf,cx:cxOf,bot:botOf}[obj]; const LBL={traits:'Trait',cx:'Qualidade',bot:'Automação',class:'Classificação'}[obj]||obj; if(obj==='class'){ const has=field==='keywords'?(r=>kwOf(r).length>0):(r=>r[field]!=null&&String(r[field]).trim()!==''); return R(LBL+': '+field, has); } if(OBJ) return R(LBL+': '+field, r=>{ const o=OBJ(r); return o&&o[field]!=null&&String(o[field]).trim()!==''; }); }\n  return { title: 'Conversas ('+token+')', list: rows.slice().sort(byDateDesc) };\n};\n\nconst listRowHtml = r => '<div class=\"dw-row\" data-drill=\"ticket:'+esc(r.ticket_id)+'\">'+\n  '<div class=\"dw-row-main\"><div class=\"dw-row-t\">#'+esc(r.ticket_id)+' · '+esc(r.contact||'—')+'</div>'+\n  '<div class=\"dw-row-s\">'+esc(fmtDate(r.ticket_date))+' · '+esc(r.contact_reason||'—')+' · '+esc(r.analyst||'Justina')+'</div></div>'+\n  '<div class=\"dw-row-tags\">'+desfChip(r)+(satBucket(r)?'<span class=\"jr-chip\">'+esc(satBucket(r))+'</span>':'')+(riskLevel(r)?'<span class=\"jr-chip bad\">'+esc(riskLevel(r))+'</span>':'')+'</div>'+\n'</div>';\nconst LIST_PAGE = 100;\nconst renderList = (drill, page) => {\n  const total = drill.list.length;\n  const pages = Math.max(1, Math.ceil(total/LIST_PAGE));\n  const p = Math.min(Math.max(0, page||0), pages-1);\n  const start = p*LIST_PAGE, end = Math.min(total, start+LIST_PAGE);\n  const slice = drill.list.slice(start, end);\n  const head = '<div class=\"dw-list-head\"><div class=\"dw-title\">'+esc(drill.title)+'</div><div class=\"dw-count\">'+num(total)+' conversa'+(total===1?'':'s')+'</div></div>';\n  const body = '<div class=\"dw-list\">'+(total?slice.map(listRowHtml).join(''):'<div class=\"jr-empty\">Nenhuma conversa neste recorte.</div>')+'</div>';\n  const pager = pages>1 ? '<div class=\"dw-pager\"><button class=\"dw-pg\" data-dir=\"prev\"'+(p===0?' disabled':'')+'>‹ Anterior</button><span class=\"dw-pg-info\">'+num(start+1)+'–'+num(end)+' de '+num(total)+' · pág. '+(p+1)+'/'+num(pages)+'</span><button class=\"dw-pg\" data-dir=\"next\"'+(p>=pages-1?' disabled':'')+'>Próxima ›</button></div>' : '';\n  return head + body + pager;\n};\n\nconst placeholder = (id) => { const m=TAB_META[id]||['','']; const t=(TABS.find(x=>x[0]===id)||[])[1]||id, n=(TABS.find(x=>x[0]===id)||[])[2]||''; return '<div class=\"ph-wrap\"><div class=\"ph-card\"><div class=\"ph-n\">Aba '+esc(n)+'</div><div class=\"ph-title\">'+esc(t)+'</div><div class=\"ph-meta\">Dono: <b>'+esc(m[0])+'</b></div><div class=\"ph-q\">“'+esc(m[1])+'”</div><div class=\"ph-tag\">Aba ainda não integrada.</div></div></div>'; };\nconst renderGuide = (id) => {\n  const g=TAB_GUIDE[id]; if(!g) return '<div class=\"jr-empty\">Sem guia para esta aba.</div>';\n  const meta=TAB_META[id]||['','']; const tb=TABS.find(x=>x[0]===id)||[];\n  const method=(g.method||[]).map(m=>'<li>'+esc(m)+'</li>').join('');\n  const terms=(g.terms||[]).map(t=>'<div class=\"gd-term\"><div class=\"gd-term-t\">'+esc(t[0])+'</div><div class=\"gd-term-d\">'+esc(t[1])+'</div></div>').join('');\n  return '<div class=\"gd\">'+\n    '<div class=\"gd-head\"><span class=\"gd-n\">Aba '+esc(tb[2]||'')+'</span><span class=\"gd-title\">'+esc(tb[1]||id)+'</span></div>'+\n    '<div class=\"gd-q\">'+esc(meta[1])+'</div>'+\n    '<div class=\"gd-sec\"><div class=\"gd-lab\">O que você vê aqui</div><p class=\"gd-p\">'+esc(g.what)+'</p></div>'+\n    (method?'<div class=\"gd-sec\"><div class=\"gd-lab\">Como os números são construídos</div><ul class=\"gd-ul\">'+method+'</ul></div>':'')+\n    (terms?'<div class=\"gd-sec\"><div class=\"gd-lab\">Termos desta aba</div><div class=\"gd-terms\">'+terms+'</div></div>':'')+\n    '<div class=\"gd-foot\">Contagens e tags são <b>fato</b>. Todo valor em <b>R$</b> é estimativa, ajustável na Aba 10. Clique em qualquer número do dashboard para abrir as conversas por trás dele.</div>'+\n  '</div>';\n};\n\nconst effPrem = d2 => { const prem=d2.state.prem||DEF_PREM; const f=SCEN_F[prem.scenario]||1; const ec={}; const cr=prem.cancelRates||DEF_PREM.cancelRates; for(const k in cr) ec[k]=Math.min(1,cr[k]*f); const cvs=Object.keys(prem.convRates||{}).map(k=>prem.convRates[k]); const blended=cvs.length?cvs.reduce((a,b)=>a+b,0)/cvs.length:0.25; return { raw:prem, effCancel:ec, effConv:Math.min(1,blended*f), scenario:prem.scenario }; };\nconst analyzedRows = d2 => { const all=(d2.state.allRows&&d2.state.allRows.length)?d2.state.allRows:[]; const az=all.filter(r=>r&&(r.summarized||r.contact_analyzed||r.bot_analyzed)); return az.length?az:all; };\nconst FIELD_FREETEXT = new Set(['summary']);\nconst EXTR_LBL = {class:'E1 · Classificação', traits:'E2 · Traits do cliente', cx:'E3 · Qualidade', bot:'E4 · Automação e produto'};\nconst FIELD_DESC = {\n  'summary':'Resumo em texto do que aconteceu na conversa.',\n  'contact_reason':'Assunto principal do contato, na taxonomia da Justos (ex.: Aquisição, Sinistro, Cancelamento).',\n  'contact_reason_detail':'Detalhamento do assunto do contato.',\n  'keywords':'Etiquetas livres que resumem temas e desfechos da conversa.',\n  'avr_sentiment':'Sentimento médio do cliente na conversa, de 0 (muito negativo) a 100 (muito positivo).',\n  'Risco de churn':'Nível de risco de o cliente cancelar, inferido da conversa.',\n  'Satisfação':'Grau de satisfação percebido, de detrator a promotor.',\n  'Gatilhos de churn':'O que está por trás do risco (preço, fricção, sinistro…).',\n  'Oportunidade comercial':'Sinal de oportunidade de venda percebido na conversa.',\n  'Perfil':'Perfil do cliente ou de uso inferido (ex.: multiveículo, corretor).',\n  'Estilo de comunicação':'Como o cliente se comunica (objetivo, detalhista…).',\n  'Momento no ciclo de vida':'Fase do cliente com a Justos (onboarding, renovação, cancelamento…).',\n  'Sensibilidade a preço':'O quanto o cliente reage a preço e desconto.',\n  'Maturidade digital e autoatendimento':'Autonomia do cliente para resolver sozinho no digital.',\n  'Engajamento com o produto':'Nível de uso e engajamento com o produto e o app.',\n  'Comportamento de pagamento':'Padrão de pagamento do cliente.',\n  'Natureza do contato':'Se o contato foi proativo do cliente, reativo, etc.',\n  'Sinistralidade recente':'Se o cliente teve sinistro recente.',\n  'Repetição de Informação':'Se o cliente teve de repetir informação já fornecida.',\n  'Reformulação':'Se o cliente teve de reformular o pedido para ser entendido.',\n  'Reformulação do pedido ou pergunta':'Se o cliente teve de reformular o pedido para ser entendido.',\n  'Loop do Bot':'Se a Justina ficou repetindo respostas sem avançar.',\n  'Beco sem saída':'Se a conversa travou sem solução e sem transbordo.',\n  'Transbordo':'Se a conversa passou da Justina para um atendente humano.',\n  'Modo de Transbordo':'Como o transbordo aconteceu (decidido pelo bot, pedido pelo cliente…).',\n  'Transbordo para humano com contexto':'Se o humano recebeu o histórico e o contexto ao assumir.',\n  'Prazo definido':'Se o atendente informou um prazo concreto.',\n  'Protocolo informado':'Se foi informado número de protocolo quando devido.',\n  'Jargão não explicado':'Se houve termo técnico usado sem explicação ao cliente.',\n  'Empatia do Atendente Humano':'Se o atendente humano demonstrou empatia.',\n  'Empatia do bot':'Se a Justina demonstrou empatia e acolhimento.',\n  'Empatia do bot (Justina)':'Se a Justina demonstrou empatia e acolhimento.',\n  'Dúvidas pendentes no encerramento':'Se sobraram dúvidas sem resposta no encerramento.',\n  'Apresentação do analista':'Se o atendente se apresentou com nome.',\n  'Validação de dados de segurança':'Se houve confirmação de identidade antes de tratar dados sensíveis.',\n  'Retomada após pausa declarada':'Se o atendente retomou a conversa com posicionamento após uma pausa.',\n  'Abertura para novas dúvidas':'Se o atendente abriu espaço para novas perguntas.',\n  'Convite à pesquisa de satisfação':'Se o cliente foi convidado à pesquisa de satisfação.',\n  'Tom inadequado':'Se houve tom inadequado no atendimento.',\n  'Exposição de info interna':'Se houve exposição de informação interna ou de terceiros (risco de compliance).',\n  'Exposição de informação interna':'Se houve exposição de informação interna ou de terceiros (risco de compliance).',\n  'Correção da informação':'Se uma informação incorreta foi corrigida durante a conversa.',\n  'Correção de informação':'Se uma informação incorreta foi corrigida durante a conversa.',\n  'Ameaça do Cliente':'Se o cliente ameaçou tomar alguma ação (reclamação pública, jurídica…).',\n  'Ameaça do Cliente Procon':'Se o cliente ameaçou acionar o Procon.',\n  'Ameaça do Cliente Reclame Aqui':'Se o cliente ameaçou reclamar no Reclame Aqui.',\n  'Ameaça do Cliente Jurídica':'Se o cliente ameaçou acionar via jurídica.',\n  'Ameaça do Cliente - Cancelamento':'Se o cliente ameaçou cancelar.',\n  'Jurídica':'Sinal de teor jurídico na conversa.',\n  'Mudança para concorrência':'Se o cliente mencionou ir para a concorrência.',\n  'Perfil do Solicitante':'Quem falou com a Justos na conversa (segurado, corretor, terceiro…).',\n  'Objeto da Demanda Principal':'Sobre o que era a demanda principal (sinistro, pagamento, cotação…).',\n  'Objeto da Demanda Secundário':'Demanda secundária tratada na mesma conversa.',\n  'Natureza da Demanda':'Tipo de demanda (dúvida, execução de ação, reclamação…).',\n  'Dado Pessoal da Conta Solicitado':'Se a conversa pediu algum dado pessoal da conta.',\n  'Ação Transacional Solicitada':'Se o cliente pediu uma ação transacional (executar algo).',\n  'Envio de Arquivo pelo Cliente':'Se o cliente enviou algum arquivo ou documento.',\n  'Desfecho da Justina':'Como terminou do ponto de vista da IA (resolvida pela Justina, após transbordo ou não resolvida).',\n  'Origem da Limitação da Justina':'Por que a Justina não resolveu sozinha (falta de dado, de capacidade ou de conteúdo).',\n  'Tentativa Prévia no App':'Se o cliente já tinha tentado resolver no app antes.',\n  'Redirecionamento ao Autosserviço':'Se e para onde o cliente foi direcionado ao autosserviço.',\n  'Reincidência Declarada':'Se o cliente declarou que o problema é recorrente.',\n  'Dado Consultado':'Que dado a Justina precisaria consultar (ex.: status de sinistro).',\n  'Adequação da Resposta da Justina':'Se a resposta da Justina foi adequada ao que foi pedido.',\n  'Motivo do Transbordo':'Por que a conversa foi encaminhada ao atendente humano.',\n  'Ação do Atendente Humano':'O que o atendente humano fez (consultou sistema, repassou informação…).',\n  'Transação Solicitada':'Que transação o cliente pediu (segunda via, cancelar, agendar…).',\n  'Lacuna de Base de Conhecimento':'Tema que faltou na base de conhecimento da IA.',\n  'Pendência no Encerramento':'Se ficou alguma pendência ao encerrar a conversa.',\n  'Oportunidade de Notificação Proativa':'Gatilho que a Justos poderia avisar de forma proativa.',\n  'Sintoma Técnico Relatado':'Problema técnico do app relatado pelo cliente.'\n};\nconst fieldValues = (r, obj, field) => {\n  if(obj==='class'){\n    if(field==='keywords') return kwOf(r).map(x=>String(x));\n    const v=r?r[field]:null; if(v==null||String(v).trim()==='') return [];\n    if(field==='avr_sentiment'){ const n=Number(v); if(isNaN(n)) return []; return [ n>=75?'Alto (75–100)': n>=50?'Médio (50–74)': n>=25?'Baixo (25–49)':'Muito baixo (0–24)' ]; }\n    return [shortVal(v)];\n  }\n  const OBJ={traits:trOf,cx:cxOf,bot:botOf}[obj]; if(!OBJ) return [];\n  const o=OBJ(r); const raw=o?o[field]:null; if(raw==null) return [];\n  const out=[]; for(const x of asArray(raw)){ const s=shortVal(x); if(s!=null && String(s).trim()!=='') out.push(String(s)); } return out;\n};\nconst buildFieldProfile = (rows, obj, field) => {\n  const freq={}; let covered=0;\n  for(const r of rows){ const vals=fieldValues(r,obj,field); if(vals.length) covered++; for(const v of vals){ freq[v]=(freq[v]||0)+1; } }\n  const values=Object.keys(freq).map(v=>({v,count:freq[v]})).sort((a,b)=>b.count-a.count);\n  return { values, covered, total:rows.length, options:values.length };\n};\nconst renderFieldProfile = (rows, obj, field) => {\n  const data=buildFieldProfile(rows,obj,field);\n  const desc=FIELD_DESC[field]||('Classificação de IA da extração '+(EXTR_LBL[obj]||obj)+'. As opções observadas na base estão listadas abaixo.');\n  const isFree=FIELD_FREETEXT.has(field);\n  const head='<div class=\"fp-head\"><span class=\"fp-cat\">'+esc(EXTR_LBL[obj]||obj)+'</span><div class=\"fp-field\">'+esc(field)+'</div></div><div class=\"fp-desc\">'+esc(desc)+'</div>';\n  const meta='<div class=\"fp-meta\"><b>'+num(data.covered)+'</b> de '+num(data.total)+' conversas têm este campo'+(isFree?'':' · <b>'+num(data.options)+'</b> '+(data.options===1?'opção':'opções'))+'</div>';\n  let body;\n  if(isFree){ body='<div class=\"fp-free\">Campo de texto livre — sem opções fixas.</div><div class=\"fp-val\" data-drill=\"extrf:'+esc(obj)+':'+esc(field)+'\"><div class=\"fp-val-top\"><span class=\"fp-val-lbl\">Ver todas as conversas com este campo</span><span class=\"fp-val-n\">'+num(data.covered)+'</span></div></div>'; }\n  else if(!data.values.length){ body='<div class=\"jr-empty\">Nenhum valor encontrado nesta amostra.</div>'; }\n  else { const max=Math.max(1,...data.values.map(v=>v.count)); const top=data.values.slice(0,30); const rest=data.values.length-top.length; body='<div class=\"fp-vals\">'+top.map(v=>{ const w=Math.max(3,v.count/max*100); const p=data.covered?v.count/data.covered:0; return '<div class=\"fp-val\" data-drill=\"fieldv:'+esc(obj)+'~'+esc(field)+'~'+esc(v.v)+'\" title=\"ver conversas\"><div class=\"fp-val-top\"><span class=\"fp-val-lbl\">'+esc(v.v)+'</span><span class=\"fp-val-n\">'+num(v.count)+' · '+pct(p,0)+'</span></div><div class=\"fp-val-track\"><div class=\"fp-val-fill\" style=\"width:'+w+'%\"></div></div></div>'; }).join('')+'</div>'+(rest>0?'<div class=\"fp-more\">+'+num(rest)+' outros valores (contagem menor)</div>':''); }\n  return '<div class=\"fp\">'+head+meta+body+'<div class=\"fp-foot\">Contagem direta das conversas (fato). Clique num valor para ver e auditar as conversas.</div></div>';\n};\nconst routeDrill = (d2, t) => {\n  if(!t) return;\n  const rows=analyzedRows(d2);\n  if(t.indexOf('acct:')===0){ d2.state.fichaSel={phone:t.slice(5)}; d2.state.drill=null; return; }\n  if(t.indexOf('ficha:')===0){ d2.state.fichaSel={phone:t.slice(6)}; d2.state.drill=null; return; }\n  if(t.indexOf('ticket:')===0){ d2.state.fichaSel={ticket:t.slice(7)}; return; }\n  if(t.indexOf('conv:')===0){ d2.state.fichaSel={ticket:t.slice(5)}; return; }\n  if(t.indexOf('sess:')===0){ const id=t.slice(5); const r=rows.find(x=>x._id===id); d2.state.fichaSel=r?{ticket:String(r.ticket_id)}:null; return; }\n  if(t.indexOf('field:')===0){ const rest=t.slice(6); const gi=rest.indexOf('~'); const obj=gi<0?rest:rest.slice(0,gi); const field=gi<0?'':rest.slice(gi+1); d2.state.fieldProfile={obj,field}; d2.state.drill=null; d2.state.fichaSel=null; d2.state.guide=null; return; }\n  d2.state.fichaSel=null; d2.state.drill=drillFor(rows,t); d2.state.listPage=0;\n};\n\nexport default {\n  css: `\n:host,.shell-root{display:block;width:100%;height:100%}\n*{box-sizing:border-box}\n.shell{display:flex;flex-direction:column;width:100%;height:100%;background:#FAF9F6;color:#373435;font-family:-apple-system,BlinkMacSystemFont,'Inter','SF Pro Text','Helvetica Neue',sans-serif;overflow:hidden;position:relative}\n.pb{background:#fff;border-bottom:1px solid rgba(0,0,0,.06);padding:12px 18px 10px;display:flex;flex-direction:column;gap:9px;flex-shrink:0}\n.pb-top{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}\n.pb-brand{display:flex;align-items:baseline;gap:10px}\n.pb-title{font-size:17px;font-weight:800;color:var(--ink,#051216);letter-spacing:-0.02em}\n.pb-sub{font-size:11px;color:#747474}\n.pb-live{display:inline-flex;align-items:center;gap:6px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:#0A4A44;background:rgba(130,216,208,.18);padding:4px 9px;border-radius:999px}\n.pb-live .dot{width:6px;height:6px;border-radius:50%;background:var(--accent,#82D8D0);animation:pulse 2s infinite}\n@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}\n.pb-params{display:flex;flex-wrap:wrap;gap:14px;align-items:flex-end}\n.pb-field{display:flex;flex-direction:column;gap:2px}\n.pb-lab{font-size:9px;color:#747474;text-transform:uppercase;letter-spacing:.05em;font-weight:700}\n.pb-in{width:112px;padding:5px 8px;font-size:12px;border:1px solid rgba(0,0,0,.12);border-radius:7px;background:#FAF9F6;color:#051216;font-variant-numeric:tabular-nums}\n.pb-in:focus{outline:none;border-color:var(--accent,#82D8D0);background:#fff}\n.pb-note{font-size:10px;color:#8a8580;max-width:320px;line-height:1.35}\n.pb-scn{font-size:10px;color:#8a6d1a;background:rgba(232,169,59,.14);padding:3px 8px;border-radius:6px;font-weight:700}\n.nav{display:flex;gap:2px;padding:0 12px;background:#fff;border-bottom:1px solid rgba(0,0,0,.06);overflow-x:auto;flex-shrink:0}\n.nav-tab{padding:9px 12px;font-size:12px;font-weight:600;color:#747474;border:none;background:none;cursor:pointer;white-space:nowrap;border-bottom:2px solid transparent;display:flex;align-items:center;gap:6px}\n.nav-tab:hover{color:var(--ink,#051216)}\n.nav-tab.on{color:var(--ink,#051216);border-bottom-color:var(--accent,#82D8D0)}\n.nav-tab .nt-n{font-size:9px;font-weight:800;color:#fff;background:#C9C4BB;border-radius:5px;padding:1px 5px}\n.nav-tab.on .nt-n{background:var(--accent,#82D8D0);color:#0A4A44}\n.content{flex:1;min-height:0;overflow:auto;position:relative}\n.ph-wrap{display:flex;align-items:center;justify-content:center;padding:48px 20px;min-height:60%}\n.ph-card{max-width:520px;text-align:center;background:#fff;border:1px solid rgba(0,0,0,.07);border-radius:18px;padding:30px 28px}\n.ph-n{font-size:11px;font-weight:800;color:var(--accent,#82D8D0);letter-spacing:.08em;text-transform:uppercase}\n.ph-title{font-size:22px;font-weight:800;color:var(--ink,#051216);margin-top:4px;letter-spacing:-0.02em}\n.ph-meta{font-size:12px;color:#747474;margin-top:6px}\n.ph-q{font-size:15px;color:#57534e;font-style:italic;margin-top:14px}\n.ph-tag{font-size:11px;color:#8a8580;margin-top:16px;line-height:1.5;background:#FAF9F6;border-radius:10px;padding:10px 12px}\n.jr-empty{color:#747474;font-size:12px;padding:12px;text-align:center;border:1px dashed rgba(0,0,0,.12);border-radius:10px}\n.dw-scrim{position:absolute;inset:0;background:rgba(5,18,22,.35);z-index:20;animation:fade .15s}\n@keyframes fade{from{opacity:0}to{opacity:1}}\n.dw{position:absolute;top:0;right:0;bottom:0;width:min(640px,96%);background:#fff;z-index:21;display:flex;flex-direction:column;box-shadow:-8px 0 32px rgba(5,18,22,.16);animation:slidein .18s}\n@keyframes slidein{from{transform:translateX(30px);opacity:.4}to{transform:translateX(0);opacity:1}}\n.dw-bar{display:flex;align-items:center;gap:10px;padding:12px 16px;border-bottom:1px solid rgba(0,0,0,.07);flex-shrink:0}\n.dw-close,.dw-back{border:none;background:#F0EDE8;width:30px;height:30px;border-radius:8px;cursor:pointer;font-size:14px;color:#373435}\n.dw-close:hover,.dw-back:hover{background:#e3ddd4}\n.dw-bar-title{font-size:13px;font-weight:700;color:var(--ink,#051216)}\n.dw-scroll{flex:1;min-height:0;overflow:auto;padding:14px 16px}\n.dw-list-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:8px}\n.dw-title{font-size:15px;font-weight:800;color:var(--ink,#051216);letter-spacing:-0.01em}\n.dw-count{font-size:11px;color:#747474}\n.dw-list{display:flex;flex-direction:column;gap:6px}\n.dw-more{font-size:11px;color:#747474;text-align:center;padding:8px}\n.dw-pager{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 2px 4px;margin-top:8px;border-top:1px solid rgba(0,0,0,.06)}\n.dw-pg{border:1px solid rgba(0,0,0,.12);background:#fff;color:#0A4A44;font-size:12px;font-weight:700;padding:6px 12px;border-radius:8px;cursor:pointer;white-space:nowrap}\n.dw-pg:hover:not([disabled]){border-color:var(--accent,#82D8D0);background:rgba(130,216,208,.10)}\n.dw-pg[disabled]{opacity:.4;cursor:default}\n.dw-pg-info{font-size:11px;color:#747474;font-variant-numeric:tabular-nums;text-align:center;flex:1}\n.dw-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 11px;border:1px solid rgba(0,0,0,.07);border-radius:10px;cursor:pointer;background:#fff;transition:border-color .12s,background .12s}\n.dw-row:hover{border-color:var(--accent,#82D8D0);background:rgba(130,216,208,.06)}\n.dw-row-t{font-size:12px;font-weight:700;color:var(--ink,#051216)}\n.dw-row-s{font-size:11px;color:#747474;margin-top:1px}\n.dw-row-tags{display:flex;gap:4px;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;max-width:200px}\n.jr-chip{display:inline-flex;align-items:center;font-size:10px;font-weight:600;padding:2px 8px;border-radius:999px;background:#F0EDE8;color:#373435;white-space:nowrap}\n.jr-chip.bad{background:rgba(162,37,96,.12);color:var(--neg,#A22560)}\n.jr-chip.warn{background:rgba(232,169,59,.18);color:#8a6d1a}\n.jr-chip.ok{background:rgba(130,216,208,.22);color:#0A4A44}\n.dw-fichawrap{padding:0}\n.tabhdr{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:7px 18px;background:#fff;border-bottom:1px solid rgba(0,0,0,.06);flex-shrink:0}\n.tabhdr-q{display:flex;align-items:center;gap:9px;min-width:0}\n.tabhdr-n{font-size:9px;font-weight:800;color:#0A4A44;background:rgba(130,216,208,.22);border-radius:5px;padding:2px 7px;flex-shrink:0;letter-spacing:.03em}\n.tabhdr-qt{font-size:12.5px;color:#57534e;font-style:italic;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.tabhdr-help{border:1px solid rgba(0,0,0,.12);background:#fff;color:#0A4A44;font-size:11px;font-weight:700;padding:5px 11px;border-radius:999px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;flex-shrink:0;white-space:nowrap}\n.tabhdr-help:hover{border-color:var(--accent,#82D8D0);background:rgba(130,216,208,.10)}\n.tabhdr-help::before{content:\"?\";display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:50%;background:var(--accent,#82D8D0);color:#0A4A44;font-size:10px;font-weight:800}\n.gd{font-size:13px;color:#373435;line-height:1.5}\n.gd-head{display:flex;align-items:baseline;gap:9px;margin-bottom:2px}\n.gd-n{font-size:9px;font-weight:800;color:#0A4A44;background:rgba(130,216,208,.22);border-radius:5px;padding:2px 7px}\n.gd-title{font-size:16px;font-weight:800;color:var(--ink,#051216);letter-spacing:-0.01em}\n.gd-q{font-size:13px;color:#57534e;font-style:italic;margin:6px 0 14px}\n.gd-sec{margin-bottom:16px}\n.gd-lab{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:#8a8580;margin-bottom:6px}\n.gd-p{margin:0;color:#373435}\n.gd-ul{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:5px}\n.gd-ul li{color:#373435}\n.gd-terms{display:flex;flex-direction:column;gap:8px}\n.gd-term{background:#FAF9F6;border:1px solid rgba(0,0,0,.06);border-radius:9px;padding:8px 11px}\n.gd-term-t{font-size:12px;font-weight:700;color:var(--ink,#051216)}\n.gd-term-d{font-size:12px;color:#57534e;margin-top:2px}\n.gd-foot{margin-top:8px;font-size:11.5px;color:#8a6d1a;background:rgba(232,169,59,.12);border-radius:10px;padding:10px 12px;line-height:1.45}\n.fp{font-size:13px;color:#373435;line-height:1.5}\n.fp-head{display:flex;flex-direction:column;gap:3px;margin-bottom:6px}\n.fp-cat{align-self:flex-start;font-size:9px;font-weight:800;color:#0A4A44;background:rgba(130,216,208,.22);border-radius:5px;padding:2px 7px;letter-spacing:.03em}\n.fp-field{font-size:16px;font-weight:800;color:var(--ink,#051216);letter-spacing:-0.01em}\n.fp-desc{font-size:12.5px;color:#57534e;line-height:1.45;margin-bottom:10px}\n.fp-meta{font-size:11px;color:#747474;margin-bottom:12px}\n.fp-meta b{color:var(--ink,#051216)}\n.fp-vals{display:flex;flex-direction:column;gap:7px}\n.fp-val{border:1px solid rgba(0,0,0,.07);border-radius:9px;padding:8px 10px;cursor:pointer;background:#fff;transition:border-color .12s,background .12s}\n.fp-val:hover{border-color:var(--accent,#82D8D0);background:rgba(130,216,208,.06)}\n.fp-val-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}\n.fp-val-lbl{font-size:12px;font-weight:600;color:var(--ink,#051216);overflow:hidden;text-overflow:ellipsis}\n.fp-val-n{font-size:11px;color:#57534e;font-variant-numeric:tabular-nums;white-space:nowrap}\n.fp-val-track{height:6px;background:#F0EDE8;border-radius:3px;overflow:hidden;margin-top:6px}\n.fp-val-fill{height:100%;border-radius:3px;background:var(--accent,#82D8D0)}\n.fp-more{font-size:11px;color:#747474;text-align:center;padding:8px}\n.fp-free{font-size:12px;color:#747474;background:#FAF9F6;border-radius:8px;padding:8px 10px;margin-bottom:8px}\n.fp-foot{margin-top:12px;font-size:11px;color:#57534e;background:#FAF9F6;border-radius:9px;padding:9px 11px;line-height:1.4}\n`,\n  render(d2){\n    const accent=cxColor(d2.param('accent'),'#82D8D0'), neg=cxColor(d2.param('negativeAccent'),'#A22560'), ink=cxColor(d2.param('brandInk'),'#051216');\n    const ov=d2.state.params||{};\n    const P={ premio:nparse(ov.premio,d2.param('premioAnual',2250)), custoHumano:nparse(ov.custoHumano,d2.param('custoHumano',15)), custoJustina:nparse(ov.custoJustina,d2.param('custoJustina',3)), containment:nparse(ov.containment,d2.param('containment',0.85)), pctThreshold:nparse(ov.pctThreshold,d2.param('pctThreshold',0.05)) };\n    const zsub=d2.param('zendeskSub','justosseguros');\n    const ds=d2.data&&d2.data();\n    const all=(d2.state.allRows&&d2.state.allRows.length)?d2.state.allRows:((ds&&!ds.loading)?(ds.records()||[]):[]);\n    const analyzed=all.filter(r=>r&&(r.summarized||r.contact_analyzed||r.bot_analyzed));\n    const rows=analyzed.length?analyzed:all;\n    const acts=d2.state.acts||[];\n    const active=d2.state.activeTab||'exec';\n    const loading=!all.length && (!ds||ds.loading);\n    const ep=effPrem(d2);\n\n    const pbField=(k,lab,v,suffix)=>'<div class=\"pb-field\"><label class=\"pb-lab\">'+esc(lab)+'</label><input class=\"pb-in\" data-k=\"'+k+'\" type=\"text\" inputmode=\"decimal\" value=\"'+esc(v)+'\"'+(suffix?' data-suffix=\"'+suffix+'\"':'')+'></div>';\n    const scnLbl={conservador:'Conservador',base:'Base',otimista:'Otimista'}[ep.scenario]||'Base';\n    const pb='<div class=\"pb\">'+\n      '<div class=\"pb-top\">'+\n        '<div class=\"pb-brand\"><div class=\"pb-title\">Hera Reveal · Justos</div><div class=\"pb-sub\">1 linha por conversa · WhatsApp (Justina + humano) · 4 extrações</div></div>'+\n        '<div style=\"display:flex;gap:8px;align-items:center\"><span class=\"pb-scn\">Cenário: '+esc(scnLbl)+'</span><span class=\"pb-live\"><span class=\"dot\"></span>'+(loading?'carregando…':num(rows.length)+' de '+num(all.length)+' analisadas')+'</span></div>'+\n      '</div>'+\n      '<div class=\"pb-params\">'+\n        pbField('premio','Ticket médio anual (R$)',P.premio)+\n        pbField('custoHumano','Custo humano / transbordo (R$)',P.custoHumano)+\n        pbField('custoJustina','Custo Justina / conversa (R$)',P.custoJustina)+\n        pbField('containment','Contenção esperada (%)',Math.round(P.containment*100),'pct')+\n        pbField('pctThreshold','Alerta custo × ticket (%)',(P.pctThreshold*100).toString().replace('.',','),'pct')+\n        '<div class=\"pb-note\">Editáveis — recalculam todas as abas. R$ = <b>estimativa</b> (ver Aba 10, premissas e cenários). Contagens e tags = <b>fato</b>.</div>'+\n      '</div>'+\n    '</div>';\n\n    const nav='<div class=\"nav\">'+TABS.map(t=>'<button class=\"nav-tab'+(t[0]===active?' on':'')+'\" data-tab=\"'+t[0]+'\"><span class=\"nt-n\">'+t[2]+'</span>'+esc(t[1])+'</button>').join('')+'</div>';\n\n    const baseBag = { rows:rows, acts:acts, totalAll:all.length||rows.length, premio:P.premio, custoHumano:P.custoHumano, custoJustina:P.custoJustina, containment:P.containment, pctThreshold:P.pctThreshold, accent:accent, neg:neg, ink:ink };\n    const bagFor = id => {\n      if(id==='premissas') return Object.assign({}, baseBag, { cancelRates:ep.raw.cancelRates, convRates:ep.raw.convRates, scenario:ep.scenario });\n      if(id==='ficha') return Object.assign({}, baseBag, { selected:{}, mode:'tab', zendeskSub:zsub });\n      return Object.assign({}, baseBag, { cancelRates:ep.effCancel, convProb:ep.effConv, scenario:ep.scenario });\n    };\n\n    let content;\n    if(loading) content='<div class=\"ph-wrap\"><div class=\"jr-empty\" style=\"border:none\">Carregando conversas analisadas…</div></div>';\n    else if(TAB_UC[active]) content=d2.render(TAB_UC[active], bagFor(active), {key:active, style:'height:auto;min-height:100%', onDrill:(t)=>routeDrill(d2,t), onStatusChange:(p)=>applyStatus(d2,p), onPremiseChange:(p)=>applyPremise(d2,p), onParam:(p)=>applyParam(d2,p)});\n    else content=placeholder(active);\n\n    let drawer='';\n    if(d2.state.fichaSel){\n      const backBtn = (d2.state.drill||d2.state.fieldProfile) ? '<button class=\"dw-back\" title=\"Voltar\">←</button>' : '';\n      const fbag = Object.assign({}, baseBag, { selected:d2.state.fichaSel, mode:'drawer', zendeskSub:zsub });\n      drawer='<div class=\"dw-scrim\"></div><div class=\"dw\"><div class=\"dw-bar\">'+backBtn+'<button class=\"dw-close\" title=\"Fechar\">✕</button><div class=\"dw-bar-title\">Ficha / Conversa</div></div><div class=\"dw-scroll dw-fichawrap\">'+d2.render(TAB_UC.ficha, fbag, {key:'fichaDrawer', style:'height:auto', onDrill:(t)=>routeDrill(d2,t)})+'</div></div>';\n    } else if(d2.state.drill){\n      const backBtn = d2.state.fieldProfile ? '<button class=\"dw-back\" title=\"Voltar ao campo\">←</button>' : '';\n      drawer='<div class=\"dw-scrim\"></div><div class=\"dw\"><div class=\"dw-bar\">'+backBtn+'<button class=\"dw-close\" title=\"Fechar\">✕</button><div class=\"dw-bar-title\">Conversas</div></div><div class=\"dw-scroll\">'+renderList(d2.state.drill, d2.state.listPage||0)+'</div></div>';\n    } else if(d2.state.fieldProfile){\n      const fp=d2.state.fieldProfile;\n      drawer='<div class=\"dw-scrim\"></div><div class=\"dw\"><div class=\"dw-bar\"><button class=\"dw-close\" title=\"Fechar\">✕</button><div class=\"dw-bar-title\">Perfil do campo</div></div><div class=\"dw-scroll\">'+renderFieldProfile(rows, fp.obj, fp.field)+'</div></div>';\n    }\n\n    if(d2.state.guide){ drawer='<div class=\"dw-scrim\"></div><div class=\"dw\"><div class=\"dw-bar\"><button class=\"dw-close\" title=\"Fechar\">✕</button><div class=\"dw-bar-title\">Como ler esta aba</div></div><div class=\"dw-scroll\">'+renderGuide(d2.state.guide)+'</div></div>'; }\n    const _tm=TAB_META[active]||['',''];\n    const _tn=(TABS.find(x=>x[0]===active)||[])[2]||'';\n    const tabhdr='<div class=\"tabhdr\"><div class=\"tabhdr-q\"><span class=\"tabhdr-n\">Aba '+esc(_tn)+'</span><span class=\"tabhdr-qt\">'+esc(_tm[1])+'</span></div><button class=\"tabhdr-help\" data-guide=\"1\">Como ler esta aba</button></div>';\n    return '<div class=\"shell\" style=\"--ink:'+ink+';--accent:'+accent+';--neg:'+neg+'\">'+pb+nav+tabhdr+'<div class=\"content\">'+content+'</div>'+drawer+'</div>';\n  },\n  mounted(d2){\n    const SLUG='babi-hera';\n    const fetchAll=async(ref,filter)=>{ if(!ref) return null; try{ const url='https://'+SLUG+'.data2apis.com/dataset/'+ref; const size=1000; let out=[],skip=0; for(let i=0;i<60;i++){ const query=Object.assign({},filter||{},{$limit:size,$skip:skip}); const res=await fetch(url,{method:'POST',credentials:'include',headers:{'content-type':'application/json','x-data2-dataset-reference':ref},body:JSON.stringify({$method:'find',params:{query}})}); if(!res.ok){ d2.log&&d2.log('[shell] '+ref+' HTTP '+res.status); break; } const data=await res.json(); const page=Array.isArray(data)?data:(data.data||data.records||data.results||(data.value&&data.value.data)||[]); if(!Array.isArray(page)||!page.length) break; out=out.concat(page); if(page.length<size) break; skip+=size; } return out; }catch(e){ d2.log&&d2.log('[shell] fetch err',e&&e.message); return null; } };\n    (async()=>{ const rows=await fetchAll('GVqgvzyYNQVEE2B_KNttC',null); if(rows&&rows.length) d2.state.allRows=rows; const acts=await fetchAll('poc-justus-actionsDataSet',null); if(acts) d2.state.acts=acts; })();\n    try{ const store=d2.store&&d2.store(PREM_STORE); if(store&&store.get){ const cr=store.get('cancelRates'), co=store.get('convRates'), sc=store.get('scenario'); if(cr||co||sc){ d2.state.prem={ cancelRates:cr||DEF_PREM.cancelRates, convRates:co||DEF_PREM.convRates, scenario:(sc&&SCEN_F[sc])?sc:'base' }; } } }catch(e){}\n    if(!d2.state.prem) d2.state.prem=DEF_PREM;\n    d2.on('.nav-tab','click',(e,el)=>{ d2.state.activeTab=el.dataset.tab; d2.state.drill=null; d2.state.fichaSel=null; d2.state.guide=null; d2.state.fieldProfile=null; });\n    d2.on('.tabhdr-help','click',()=>{ d2.state.guide=d2.state.activeTab||'exec'; d2.state.drill=null; d2.state.fichaSel=null; d2.state.fieldProfile=null; });\n    d2.on('.pb-in','change',(e,el)=>{ const p={...(d2.state.params||{})}; const raw=String(el.value).replace(',','.'); let v=parseFloat(raw); if(isNaN(v)){ p[el.dataset.k]=undefined; } else { if(el.dataset.suffix==='pct') v=v/100; p[el.dataset.k]=v; } d2.state.params=p; });\n    d2.on('.dw-scrim','click',()=>{ d2.state.fichaSel=null; d2.state.drill=null; d2.state.guide=null; d2.state.fieldProfile=null; });\n    d2.on('.dw-close','click',()=>{ d2.state.fichaSel=null; d2.state.drill=null; d2.state.guide=null; d2.state.fieldProfile=null; });\n    d2.on('.dw-back','click',()=>{ if(d2.state.fichaSel){ d2.state.fichaSel=null; } else if(d2.state.drill){ d2.state.drill=null; } });\n    d2.on('.dw-row','click',(e,el)=>{ const t=el.getAttribute('data-drill'); if(t) routeDrill(d2,t); });\n    d2.on('.fp-val','click',(e,el)=>{ const t=el.getAttribute('data-drill'); if(t) routeDrill(d2,t); });\n    d2.on('.dw-pg','click',(e,el)=>{ if(el.hasAttribute('disabled')) return; const dir=el.getAttribute('data-dir'); const cur=d2.state.listPage||0; d2.state.listPage = dir==='next'?cur+1:Math.max(0,cur-1); });\n    d2.on('.content','click',(e,el)=>{ let hit=null; const path=(e&&e.composedPath)?e.composedPath():[]; for(const n of path){ if(n&&n.nodeType===1&&n.getAttribute&&n.getAttribute('data-drill')){ hit=n; break; } } if(!hit&&el&&el.getAttribute&&el.getAttribute('data-drill')) hit=el; if(hit){ const t=hit.getAttribute('data-drill'); if(t) routeDrill(d2,t); } });\n  }\n};\n\nfunction applyStatus(d2, p){\n  if(!p) return;\n  const tid=p.ticket_id, phone=p.phone, status=p.status;\n  const acts=(d2.state.acts||[]).slice();\n  let found=false;\n  for(let i=0;i<acts.length;i++){ if(acts[i]&&(tid!=null&&acts[i].ticket_id===tid)){ acts[i]=Object.assign({},acts[i],{status:status,phone:phone,reviewed_at:new Date().toISOString()}); found=true; break; } }\n  if(!found) acts.push({ticket_id:tid,phone:phone,status:status,reviewed_at:new Date().toISOString()});\n  d2.state.acts=acts;\n  try{ const ads=d2.data&&d2.data('actionsDataset'); if(ads){ const existing=(ads.records&&ads.records()||[]).find(r=>r&&r.ticket_id===tid); const payload={ticket_id:tid,phone:phone,status:status,reviewed_at:new Date().toISOString()}; if(existing&&ads.update) ads.update(Object.assign({},existing,payload)); else if(ads.create) ads.create(payload); } }catch(e){ d2.log&&d2.log('[shell] status write err',e&&e.message); }\n}\nfunction applyPremise(d2, p){\n  if(!p) return;\n  d2.state.prem={ cancelRates:p.cancelRates||DEF_PREM.cancelRates, convRates:p.convRates||DEF_PREM.convRates, scenario:(p.scenario&&SCEN_F[p.scenario])?p.scenario:'base' };\n}\nfunction applyParam(d2, p){\n  if(!p || !p.key) return;\n  const cur = d2.state.prem || DEF_PREM;\n  const next = { cancelRates:cur.cancelRates||DEF_PREM.cancelRates, convRates:cur.convRates||DEF_PREM.convRates, scenario:cur.scenario||'base' };\n  if(p.key==='scenario'){ next.scenario=(p.value&&SCEN_F[p.value])?p.value:'base'; }\n  else if(p.key==='cancelRates'){ next.cancelRates=p.value||next.cancelRates; }\n  else if(p.key==='convRates'){ next.convRates=p.value||next.convRates; }\n  d2.state.prem=next;\n  try{ const store=d2.store&&d2.store(PREM_STORE); if(store&&store.set){ store.set('cancelRates',next.cancelRates); store.set('convRates',next.convRates); store.set('scenario',next.scenario); } }catch(e){}\n}"}},"dataset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"dataset"}}}},"actionsDataset":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"actionsDataset"}}}},"premioAnual":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"premioAnual"}}}},"custoHumano":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"custoHumano"}}}},"custoJustina":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"custoJustina"}}}},"containment":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"containment"}}}},"pctThreshold":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"pctThreshold"}}}},"accent":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"accent"}}}},"negativeAccent":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"negativeAccent"}}}},"brandInk":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"brandInk"}}}},"zendeskSub":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"zendeskSub"}}}}}}}},"__d2PrevCode":{"code":"/* ===== JUSTOS \"HERA REVEAL\" — SHARED KIT (concatenated) ===== */\nconst esc = s => s == null ? '' : String(s).replace(/[&<>\"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;'}[c]));\nconst num = n => (n==null||isNaN(n)) ? '—' : new Intl.NumberFormat('pt-BR').format(Math.round(n));\nconst pct = (n,d=0) => (n==null||isNaN(n)) ? '—' : (n*100).toFixed(d).replace('.',',')+'%';\nconst money = n => new Intl.NumberFormat('pt-BR',{style:'currency',currency:'BRL',maximumFractionDigits:0}).format(Math.round(n||0));\nconst moneyK = n => { const v=n||0, a=Math.abs(v); if(a>=1e6) return 'R$ '+(v/1e6).toFixed(1).replace('.',',')+'M'; if(a>=1e3) return 'R$ '+(v/1e3).toFixed(0)+'k'; return money(v); };\nconst fmtDate = iso => { if(!iso) return '—'; const d=new Date(iso); if(isNaN(d)) return String(iso).slice(0,10); return d.toLocaleDateString('pt-BR',{day:'2-digit',month:'2-digit',year:'2-digit'}); };\nconst cxColor = (c, fb) => !c ? fb : (typeof c==='string' ? c : (c.rgba || (c.color && c.color.rgba) || fb));\nconst kwOf  = r => Array.isArray(r && r.keywords) ? r.keywords : [];\nconst trOf  = r => (r && r.traits   && typeof r.traits==='object'   && !Array.isArray(r.traits))   ? r.traits   : {};\nconst cxOf  = r => (r && r.cx_tags  && typeof r.cx_tags==='object'  && !Array.isArray(r.cx_tags))  ? r.cx_tags  : {};\nconst botOf = r => (r && r.bot_tags && typeof r.bot_tags==='object' && !Array.isArray(r.bot_tags)) ? r.bot_tags : {};\nconst shortVal = v => v==null ? null : (Array.isArray(v) ? (v[0]==null?null:String(v[0]).split(':')[0].trim()) : String(v).split(':')[0].trim());\nconst trait = (r,k) => shortVal(trOf(r)[k]);\nconst bot   = (r,k) => shortVal(botOf(r)[k]);\nconst CX_ALIASES = [['Empatia do bot','Empatia do bot (Justina)']];\nconst cxTag = (r,k) => { const o=cxOf(r); if(o[k]!=null) return shortVal(o[k]); for(const [a,b] of CX_ALIASES){ if(k===a&&o[b]!=null) return shortVal(o[b]); if(k===b&&o[a]!=null) return shortVal(o[a]); } return null; };\nconst asArray = v => v==null ? [] : (Array.isArray(v) ? v.filter(x=>x!=null) : [v]);\nconst botArr = (r,k) => asArray(botOf(r)[k]).map(x=>String(x));\nconst timeToMin = t => { if(t==null) return 0; if(typeof t==='number') return t; const p=String(t).trim().split(':').map(Number); if(!p.length||p.some(isNaN)) return 0; let h=0,m=0,s=0; if(p.length===3)[h,m,s]=p; else if(p.length===2)[m,s]=p; else s=p[0]; return h*60+m+s/60; };\nconst riskLevel = r => { const s=trait(r,'Risco de churn'); if(!s) return null; if(s.startsWith('Churn em andamento')) return 'Saindo'; if(s.startsWith('Risco declarado')) return 'Declarou'; if(s.startsWith('Risco latente')) return 'Sinalizou'; if(s.startsWith('Sem risco')) return 'Estável'; return null; };\nconst RISK_CANCEL = { Saindo:0.90, Declarou:0.50, Sinalizou:0.15, 'Estável':0 };\nconst satBucket = r => { const s=trait(r,'Satisfação'); if(!s) return null; if(s.startsWith('Promotor')) return 'Promotor'; if(s.startsWith('Satisfeito')) return 'Satisfeito'; if(s.startsWith('Neutro')) return 'Neutro'; if(s.startsWith('Detrator')) return 'Detrator'; if(s.startsWith('Insatisf')) return 'Insatisfeito'; return null; };\nconst transbordou = r => bot(r,'Transbordo')==='Sim' || cxTag(r,'Transbordo')==='Sim' || kwOf(r).includes('Justina transferiu para o atendimento humano') || bot(r,'Desfecho da Justina')==='Resolvida após transbordo';\nconst desfecho = r => { const d=bot(r,'Desfecho da Justina'); if(d==='Resolvida pela Justina') return 'justina'; if(d==='Resolvida após transbordo') return 'transbordo_ok'; if(d==='Não resolvida') return 'nao_resolvida'; const nr=kwOf(r).includes('Não resolvido'), ok=kwOf(r).includes('Resolvido com sucesso'), tb=transbordou(r); if(nr) return 'nao_resolvida'; if(tb) return 'transbordo_ok'; if(ok) return 'justina'; return 'sem_evidencia'; };\nconst isRetrabalho = r => { if(!transbordou(r)) return false; const adeq=bot(r,'Adequação da Resposta da Justina')||''; return desfecho(r)==='nao_resolvida' || cxTag(r,'Loop do Bot')==='Sim' || cxTag(r,'Beco sem saída')==='Sim' || /tema diferente/i.test(adeq) || /contestad/i.test(adeq) || bot(r,'Reincidência Declarada')==='Sim'; };\nconst commSignal = r => { const sigs=[]; const tsol=botArr(r,'Transação Solicitada').join(' ').toLowerCase(); const obj=(bot(r,'Objeto da Demanda Principal')||'').toLowerCase(); const kw=kwOf(r).join(' ').toLowerCase(); const opp=trait(r,'Oportunidade comercial'); if(opp) sigs.push(opp); if(/assist|vidro|carro reserva|guincho|buraco/.test(tsol+' '+obj+' '+kw)) sigs.push('Upsell de cobertura'); if(/novo ve[ií]culo|segundo carro|troca de ve[ií]culo|multive/.test(kw+' '+obj+' '+String(trait(r,'Perfil')||'').toLowerCase())) sigs.push('Novo veículo'); if(/indica|mgm/.test(kw+' '+tsol)) sigs.push('Indicação (MGM)'); return Array.from(new Set(sigs)); };\nconst buildAccounts = rows => { const acc={}; for(const r of rows){ const k=r.phone||r.contact||r._id; if(!k) continue; (acc[k]=acc[k]||{key:k,phone:r.phone,contact:r.contact,contact_type:r.contact_type,sessions:[]}).sessions.push(r); } const out=[]; for(const k in acc){ const a=acc[k]; a.sessions.sort((x,y)=>String(y.ticket_date||'').localeCompare(String(x.ticket_date||''))); const latest=a.sessions[0]||{}; a.latest=latest; a.sessionCount=a.sessions.length; a.lastDate=latest.ticket_date; a.risk=riskLevel(latest); a.sat=satBucket(latest); out.push(a); } return out; };\nconst gatilhosOf = r => asArray(trOf(r)['Gatilhos de churn']).map(x=>String(x).split(':')[0].trim()).filter(Boolean);\nconst RX_PUBLIC = /(procon|reclame aqui|jur[ií]dic|ju[íi]zad|advogad|processo)/i;\nconst RX_LEAK = /(dado sens[íi]vel|exposi[çc][ãa]o de info|info interna|captura de ferramenta|vazamento)/i;\n\n/* ---- perfis (Aba 3) helpers — MUST match tab-perfis source ---- */\nconst pfDimValue = (r, dim) => { switch(dim){ case 'SAT': return satBucket(r); case 'RISCO': return riskLevel(r); case 'TRANSB': return transbordou(r)?'Transbordou':'Contida'; case 'ASSUNTO': return r&&r.contact_reason?r.contact_reason:null; case 'PRECO': return trait(r,'Sensibilidade a preço'); case 'MATUR': return trait(r,'Maturidade digital e autoatendimento'); case 'ENGAJ': return trait(r,'Engajamento com o produto'); case 'ESTILO': return trait(r,'Estilo de comunicação'); case 'CICLO': return trait(r,'Momento no ciclo de vida'); case 'PAGTO': return trait(r,'Comportamento de pagamento'); case 'PERFIL': { const v=trait(r,'Perfil'); return v?String(v).split(';')[0].trim():null; } default: return null; } };\nconst pfExcl = r => { const kw=kwOf(r).join(' '); const hay=((r&&r.summary)||'')+' '+kw; const L=hay.toLowerCase(); if(/sem resposta|sem retorno|n[aã]o respondeu|sem manifesta[çc][aã]o do cliente/.test(kw.toLowerCase())) return 'sem_resposta'; if(/por engano|n[uú]mero errado|pessoa errada|n[aã]o reconhe[çc]|n[aã]o sou cliente|engano\\b/.test(L)) return 'engano'; if(/desatualiz|n[uú]mero n[aã]o pertence|dono anterior|antigo dono|n[aã]o [eé] mais (o|a) (dono|cliente)/.test(L)) return 'desatualizado'; if(/\\bspam\\b|propaganda|divulga[çc][aã]o|marketing n[aã]o solicitado/.test(L)) return 'spam'; if(/assistente virtual do cliente|bot do cliente|respondid[oa] por (ia|bot|assistente)|agente de ia|resposta autom[aá]tica|mensagem autom[aá]tica/.test(L)) return 'agente_ia'; return null; };\nconst pfPersona = r => { const perfil=trait(r,'Perfil')||''; if(/Corretor/i.test(perfil)||(r&&r.contact_type==='Corretor')) return 'corretor'; const rk=riskLevel(r), ciclo=trait(r,'Momento no ciclo de vida'); if(rk==='Saindo'||rk==='Declarou'||ciclo==='Em cancelamento') return 'saida'; const eng=trait(r,'Engajamento com o produto')||''; if(/telemetria|privacidade/i.test(eng)) return 'telemetria'; const preco=trait(r,'Sensibilidade a preço'); if(preco==='Alta sensibilidade'||preco==='Busca ativa por desconto') return 'preco'; if(/Sinistralidade/i.test(perfil)) return 'sinistro'; const mat=trait(r,'Maturidade digital e autoatendimento'), sb=satBucket(r); if((mat==='Alta autonomia digital'||mat==='Adepto ao autoatendimento')&&(sb==='Promotor'||sb==='Satisfeito')) return 'autonomo'; return 'padrao'; };\nconst PF_LABELS = {SAT:'Satisfação',PRECO:'Sensibilidade a preço',MATUR:'Maturidade digital',ENGAJ:'Engajamento c/ app',ESTILO:'Estilo de comunicação',CICLO:'Momento no ciclo',PAGTO:'Comportamento de pagamento',PERFIL:'Perfil de uso',RISCO:'Risco de churn',TRANSB:'Transbordo',ASSUNTO:'Assunto'};\nconst PF_PERSONA_LBL = {corretor:'Corretor / canal B2B',saida:'Em cancelamento / saída',telemetria:'Resistente à telemetria',preco:'Sensível a preço',sinistro:'Sinistralidade recente',autonomo:'Autônomo digital',padrao:'Cliente ativo padrão'};\nconst PF_EXCL_LBL = {sem_resposta:'Sem resposta',engano:'Contato por engano',desatualizado:'Número desatualizado',spam:'Spam / propaganda',agente_ia:'Agente de IA do cliente'};\n\n/* ---- atrito (Aba 4) helpers — MUST match tab-atrito source ---- */\nconst REFORM_KEYS = ['Reformulação do pedido ou pergunta','Reformulação'];\nconst effortSig = r => ({ rep:cxTag(r,'Repetição de Informação')==='Sim', ref:REFORM_KEYS.some(k=>cxTag(r,k)==='Sim'), loop:cxTag(r,'Loop do Bot')==='Sim', beco:cxTag(r,'Beco sem saída')==='Sim', tb:transbordou(r), duv:cxTag(r,'Dúvidas pendentes no encerramento')==='Dúvida não respondida', reinc:bot(r,'Reincidência Declarada')==='Sim', fric:kwOf(r).includes('Resolvido com alta fricção') });\nconst effortCount = r => { const s=effortSig(r); let n=0; for(const k in s) if(s[k]) n++; return n; };\nconst hasAtrito = r => { const s=effortSig(r); return s.loop||s.rep||s.ref||s.beco; };\nconst fcrResolved = r => { const d=desfecho(r); return (d==='justina'||d==='transbordo_ok')&&bot(r,'Reincidência Declarada')!=='Sim'; };\nconst isBeco = r => !transbordou(r)&&bot(r,'Redirecionamento ao Autosserviço')==='Não houve direcionamento'&&(desfecho(r)==='nao_resolvida'||cxTag(r,'Beco sem saída')==='Sim');\nconst AUTOMATIZAVEL_RX = /(acesso a dado|capacidade de execu)/i;\nconst transbordoEvitavel = r => transbordou(r)&&(isRetrabalho(r)||AUTOMATIZAVEL_RX.test(bot(r,'Origem da Limitação da Justina')||''));\nconst pendBucket = r => { const pend=desfecho(r)==='nao_resolvida'||cxTag(r,'Dúvidas pendentes no encerramento')==='Dúvida não respondida'; if(!pend) return null; const redir=bot(r,'Redirecionamento ao Autosserviço'); if(!transbordou(r)&&redir==='Não houve direcionamento') return 'semresp'; if(transbordou(r)||cxTag(r,'Protocolo informado')==='Sim'||cxTag(r,'Prazo definido')==='Sim') return 'justos'; return 'cliente'; };\nconst canonReason = s => ({ 'Assistência':'Assistência','Sinistro':'Sinistro','Geral':'Outro','Cancelamento':'Cancelamento','Pagamento':'Pagamento','Aquisição':'Cotação','Aplicativo':'Aplicativo','Rewards':'Clube','Endosso':'Endosso','Apólice':'Apólice','Profile':'Cadastro','Portal':'Aplicativo','Driving Test':'Telemetria','Erro Justina':'Outro','Proposta':'Cotação' }[s] || (s?'Outro':null));\nconst canonObjeto = s => ({ 'Sinistro':'Sinistro','Assistência 24h':'Assistência','Pagamento e Cobrança':'Pagamento','Cancelamento':'Cancelamento','Cotação e Contratação':'Cotação','Outro':'Outro','Vistoria':'Vistoria','Apólice e Documentos':'Apólice','Aplicativo e Permissões':'Aplicativo','Clube Justos e Pontos':'Clube','Endosso':'Endosso','Dados Cadastrais':'Cadastro','Telemetria e Perfil de Direção':'Telemetria','Renovação Anual':'Renovação','Rastreador':'Telemetria','Alteração de Plano':'Endosso' }[s] || (s?'Outro':null));\nconst ATR_SIGKEY = {rep:'rep',ref:'ref',loop:'loop',beco:'beco',tb:'tb',duv:'duv',reinc:'reinc',fric:'fric'};\n\n/* ---- receita (Aba 2) helpers — MUST match tab-receita source ---- */\nconst COMM_SIGS = ['Upsell de cobertura','Novo veículo','Engajado com indicação','Receptivo a campanhas','Cliente referenciável','Mensal→Anual'];\nconst commSignalX = r => { const out={}; const opp=trait(r,'Oportunidade comercial'); if(opp){ const n=COMM_SIGS.find(s=>opp.toLowerCase().startsWith(s.toLowerCase().split('→')[0]))||opp; out[n]='trait'; } const tsol=botArr(r,'Transação Solicitada').join(' ').toLowerCase(); const objP=(bot(r,'Objeto da Demanda Principal')||'').toLowerCase(); const objS=botArr(r,'Objeto da Demanda Secundário').join(' ').toLowerCase(); const kw=kwOf(r).join(' ').toLowerCase(); const perfil=String(trait(r,'Perfil')||'').toLowerCase(); const sens=String(trait(r,'Sensibilidade a preço')||'').toLowerCase(); const hay=[tsol,objP,objS,kw].join(' '); const add=n=>{ if(!out[n]) out[n]='derivado'; }; if(/assist|vidro|carro reserva|guincho|buraco|reboque|p[aá]ra-choque|dano/.test(hay)||objP==='assistência 24h') add('Upsell de cobertura'); if(/novo ve[ií]culo|segundo carro|troca de ve[ií]culo|multive/.test(hay+' '+perfil)||objP==='endosso'||objP==='cotação e contratação') add('Novo veículo'); if(/indica|mgm|clube justos|pontos/.test(hay)||objP==='clube justos e pontos') add('Engajado com indicação'); if(/desconto/.test(sens)) add('Mensal→Anual'); if(satBucket(r)==='Promotor'&&Number(r.avr_sentiment)>=75) add('Cliente referenciável'); return Object.keys(out).map(n=>({name:n,src:out[n]})); };\nconst OPP_REV = { 'Upsell de cobertura':{factor:0.15,prob:0.30}, 'Novo veículo':{factor:1.00,prob:0.20}, 'Engajado com indicação':{factor:0.15,prob:0.35}, 'Receptivo a campanhas':{factor:0.10,prob:0.25}, 'Cliente referenciável':{factor:0.05,prob:0.20}, 'Mensal→Anual':{factor:0.08,prob:0.30} };\nconst oppApproach = (nSig, cond, atRisk) => { if(atRisk) return 'BLOCK'; if(nSig>=2) return cond>=2?'A1':'NAO'; if(nSig===1) return cond===3?'A1':(cond===2?'A2':'NAO'); if(nSig===0) return cond===3?'A3':'NONE'; return 'NONE'; };\nconst buildOpps = (rows, premio) => { const pr=premio==null?2250:premio; const accs=buildAccounts(rows); return accs.map(a=>{ const smap={}; for(const s of a.sessions){ for(const g of commSignalX(s)){ if(smap[g.name]!=='trait') smap[g.name]=g.src; } } const signals=Object.keys(smap).map(n=>({name:n,src:smap[n]})); const nSig=signals.length; const satisfeito=a.sat==='Promotor'||a.sat==='Satisfeito'; const semRisco=a.risk==='Estável'; const ciclo=trait(a.latest,'Momento no ciclo de vida'); const janela=(ciclo&&ciclo.startsWith('Em renovação'))||a.sessions.some(s=>desfecho(s)==='justina'||desfecho(s)==='transbordo_ok'||kwOf(s).includes('Resolvido com sucesso')); const cond=(satisfeito?1:0)+(semRisco?1:0)+(janela?1:0); const atRisk=a.risk==='Saindo'||a.risk==='Declarou'||a.sat==='Detrator'||a.sat==='Insatisfeito'; const approach=oppApproach(nSig,cond,atRisk); let revenue=0; for(const g of signals){ const m=OPP_REV[g.name]; if(m) revenue+=pr*m.factor*m.prob; } return { key:a.key, sessions:a.sessions, signals, nSig, approach, atRisk, revenue }; }); };\n\n/* ---- justina (Aba 5) helpers — verbatim from tab-justina ---- */\nconst J5_ASSUNTO = r => bot(r,'Objeto da Demanda Principal') || r.contact_reason || 'Sem assunto';\nconst j5adeq = r => { const a=bot(r,'Adequação da Resposta da Justina'); if(!a) return null; if(/tema diferente/i.test(a)) return 'tema_diferente'; if(/contestada/i.test(a)) return 'contestada'; if(/parcial/i.test(a)) return 'parcial'; if(/resolveu/i.test(a)) return 'resolveu'; return null; };\nconst j5origem = r => { const o=bot(r,'Origem da Limitação da Justina'); if(!o) return null; if(/sem limita/i.test(o)) return null; if(/tema ausente/i.test(o)) return {k:'conteudo',sub:'Tema ausente na base'}; if(/informa[çc][ãa]o.*(aplicad|caso)/i.test(o)) return {k:'conteudo',sub:'Info não aplicada ao caso'}; if(/incorret|contradit/i.test(o)) return {k:'conteudo',sub:'Info incorreta/contraditória'}; if(/capacidade de execu/i.test(o)) return {k:'capacidade',sub:'Falta de capacidade de execução'}; if(/acesso a dado/i.test(o)) return {k:'capacidade',sub:'Falta de acesso a dado'}; if(/formato/i.test(o)) return {k:'capacidade',sub:'Limitação de formato'}; return {k:'outro',sub:o}; };\nconst j5motivo = r => { const m=bot(r,'Motivo do Transbordo'); if(!m) return null; if(/capacidade de execu/i.test(m)) return 'Falta de capacidade de execução'; if(/acesso a dado/i.test(m)) return 'Falta de acesso a dado'; if(/solicitado pelo cliente/i.test(m)) return 'Solicitado pelo cliente'; if(/informa/i.test(m)) return 'Ausência de informação'; if(/regra de encaminh/i.test(m)) return 'Regra de encaminhamento'; return m; };\nconst j5kbgap = r => { const g=bot(r,'Lacuna de Base de Conhecimento'); if(g && !/^sem/i.test(g)) return g; const o=j5origem(r); if(o && o.k==='conteudo') return o.sub; return null; };\nconst j5loop = r => cxTag(r,'Loop do Bot')==='Sim';\nconst j5beco = r => cxTag(r,'Beco sem saída')==='Sim';\nconst j5empatia = r => cxTag(r,'Empatia do bot')==='Empatia Demonstrada';\n\n/* ---- humano (Aba 6) helpers — verbatim from tab-humano ---- */\nconst CHK = [\n  {key:'apres',label:'Apresentou-se com nome',get:r=>{const v=cxTag(r,'Apresentação do analista');return v==null?null:(v==='Apresentou-se com nome'?1:0);}},\n  {key:'contexto',label:'Recebeu transbordo com contexto',get:r=>{const v=cxTag(r,'Transbordo para humano com contexto');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'seg',label:'Validação de dados de segurança',get:r=>{const v=cxTag(r,'Validação de dados de segurança');if(v==null) return null;if(/completa/i.test(v)) return 1;if(/parcial/i.test(v)) return 0.5;return 0;}},\n  {key:'prazo',label:'Informou prazo concreto',get:r=>{const v=cxTag(r,'Prazo definido');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'proto',label:'Informou protocolo quando devido',get:r=>{const v=cxTag(r,'Protocolo informado');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'retomada',label:'Retomou após pausa com posição',get:r=>{const v=cxTag(r,'Retomada após pausa declarada');if(v==null) return null;return /retomou com posicionamento/i.test(v)?1:0;}},\n  {key:'abertura',label:'Abriu espaço p/ novas dúvidas',get:r=>{const v=cxTag(r,'Abertura para novas dúvidas');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'pesquisa',label:'Convidou p/ pesquisa de satisfação',get:r=>{const v=cxTag(r,'Convite à pesquisa de satisfação');return v==null?null:(v==='Sim'?1:0);}},\n  {key:'empatia',label:'Empatia do atendente humano',get:r=>{const v=cxTag(r,'Empatia do Atendente Humano');if(v==null) return null;return /demonstrada/i.test(v)?1:0;}}\n];\nconst CHK_W = {apres:1,contexto:3,seg:3,prazo:1.5,proto:1.5,retomada:1.5,abertura:1,pesquisa:0.5,empatia:2};\nconst qIndex = r => { let sw=0,ss=0; for(const c of CHK){ const s=c.get(r); if(s==null) continue; const w=CHK_W[c.key]||1; sw+=w; ss+=w*s; } return sw>0?ss/sw:null; };\nconst RX_LEAK2 = /(dado sens[íi]vel|captura de (tela|ferramenta)|print (do|da) (sistema|tela)|vazamento|informa[çc][ãa]o interna|dado de terceiro|expos(i[çc][ãa]o|to) de (info|dado))/i;\nconst cSegAusente = r => cxTag(r,'Validação de dados de segurança')==='Validação ausente';\nconst cExposicao = r => cxTag(r,'Exposição de info interna')==='Sim' || RX_LEAK2.test(String(r&&r.summary||''));\nconst cTom = r => cxTag(r,'Tom inadequado')==='Sim' || (cxTag(r,'Empatia do Atendente Humano')==='Empatia Ausente' && Number(r&&r.avr_sentiment)<35);\nconst cCorrecao = r => cxTag(r,'Correção da informação')==='Não corrigida' || cxTag(r,'Correção de informação')==='Não corrigida';\nconst humBand = q => q==null?null:(q>=0.85?'alto':q>=0.70?'bom':q>=0.50?'medio':'baixo');\n\n/* ---- app (Aba 8) helpers — verbatim from tab-app ---- */\nconst SYMPTOM_DEFS = [{key:'viagens',rx:/viagen/i},{key:'permissoes',rx:/permiss|localiza/i},{key:'bateria',rx:/bateria/i},{key:'naoabre',rx:/n[ãa]o abre|trava|instalar|baixar/i},{key:'login',rx:/login|acesso/i},{key:'fotos',rx:/foto|documento/i},{key:'pontuacao',rx:/pontua/i},{key:'notificacao',rx:/notifica/i},{key:'versao',rx:/vers[ãa]o/i}];\nconst symptomKeyOf = v => { const s=String(v||'').toLowerCase(); for(const d of SYMPTOM_DEFS){ if(d.rx.test(s)) return d.key; } return 'outros'; };\nconst symptomsOf = r => { const out=[]; for(const v of botArr(r,'Sintoma Técnico Relatado')){ const k=symptomKeyOf(v); if(k!=='outros'&&out.indexOf(k)<0) out.push(k); } return out; };\nconst hasSymptom = r => botArr(r,'Sintoma Técnico Relatado').length>0;\nconst APP_RX = /\\bapp\\b|aplicativo|telemetr|rastread|driving test|registro de viagens|permiss|vistoria|inspe[çc]|pontua[çc]/i;\nconst appHay = r => (kwOf(r).join(' ')+' '+(bot(r,'Objeto da Demanda Principal')||'')+' '+String(r&&r.summary||'').slice(0,400));\nconst isAppContext = r => hasSymptom(r) || APP_RX.test(appHay(r));\nconst isAppComplaint = r => isAppContext(r) && (bot(r,'Natureza da Demanda')==='Reclamação' || /reclama[çc][ãa]o sobre o app|reclama[çc][ãa]o sobre permiss/i.test(kwOf(r).join(' ')));\nconst isRiskyA = r => { const lv=riskLevel(r); return lv==='Saindo'||lv==='Declarou'||lv==='Sinalizou'; };\nconst isGap = r => bot(r,'Tentativa Prévia no App')==='Sim' && transbordou(r);\nconst redirOf = r => bot(r,'Redirecionamento ao Autosserviço');\nconst isRedirApp = r => redirOf(r)==='Direcionado ao app';\nconst isRedirReincid = r => isRedirApp(r) && (bot(r,'Reincidência Declarada')==='Sim' || desfecho(r)==='nao_resolvida');\nconst PRIV_RX = /telemetr|privacidad|rastread|monitorament|dados pessoais|invas[ãa]o|n[ãa]o quero ser (rastrea|monitor)/i;\nconst isPrivacy = r => PRIV_RX.test(appHay(r));\nconst FLOW_DEFS = [{key:'inspecao',label:'Inspeção / Fotos',rx:/inspe[çc]|vistoria|foto|documento/i},{key:'permissoes',label:'Permissões',rx:/permiss|localiza/i},{key:'login',label:'Login / Acesso',rx:/login|acesso|baixar|instalar/i},{key:'viagens',label:'Validação de viagens',rx:/viagen|telemetr|registro de viagens/i},{key:'driving',label:'Driving Test',rx:/driving test|pontua|score/i},{key:'pagamento',label:'Pagamento',rx:/pagamento|cobran[çc]a|fatura|boleto|cart[ãa]o/i}];\nconst flowHay = r => (botArr(r,'Sintoma Técnico Relatado').join(' ')+' '+kwOf(r).join(' ')+' '+(bot(r,'Objeto da Demanda Principal')||'')+' '+String(r&&r.summary||'').slice(0,300)).toLowerCase();\nconst inFlow = (r,def) => def.rx.test(flowHay(r));\n\n/* ---- automacao (Aba 7) helpers — verbatim from tab-automacao ---- */\nconst normOrig = r => { const o=(bot(r,'Origem da Limitação da Justina')||'').toLowerCase(); if(/acesso a dado/.test(o)) return 'dado'; if(/capacidade de execu/.test(o)) return 'exec'; return null; };\nconst splitVals = arr => arr.map(x=>String(x).trim()).filter(Boolean);\nconst autoClassify = r => { if(!transbordou(r)) return null; const og=normOrig(r); if(og==='dado'){ const c=splitVals(botArr(r,'Dado Consultado')); return {tipo:'consulta',caps:c.length?c:['Consulta não especificada']}; } if(og==='exec'){ const c=splitVals(botArr(r,'Transação Solicitada')); return {tipo:'transacao',caps:c.length?c:['Transação não especificada']}; } if(bot(r,'Ação do Atendente Humano')==='Apenas repassou informação'){ return {tipo:'conteudo',caps:['Conteúdo — '+(bot(r,'Objeto da Demanda Principal')||'Assunto geral')]}; } return null; };\nconst hasV = (r,k,rx)=> botArr(r,k).some(v=>rx.test(String(v)));\nconst NOTIF=[\n  {key:'pagamento',title:'Vencimento / falha de pagamento',m:r=> /pagamento|cobran|fatura/i.test(r.contact_reason||'')||hasV(r,'Dado Consultado',/vencimento|fatura/i)||hasV(r,'Transação Solicitada',/segunda via de cobran|forma ou cart[ãa]o de pagamento/i)},\n  {key:'sinistro',title:'Mudança de status de sinistro',m:r=> hasV(r,'Dado Consultado',/status de sinistro/i)||(/sinistro/i.test(r.contact_reason||'')&&/acompanh/i.test(kwOf(r).join(' ')))},\n  {key:'vistoria',title:'Pendência de documento / vistoria',m:r=> hasV(r,'Transação Solicitada',/enviar documentos|agendar vistoria/i)||hasV(r,'Dado Consultado',/status de vistoria/i)},\n  {key:'assistencia',title:'Conclusão / status de assistência',m:r=> hasV(r,'Dado Consultado',/assist[êe]ncia acionada/i)||hasV(r,'Transação Solicitada',/acionar assist[êe]ncia/i)},\n  {key:'renovacao',title:'Prazo de renovação',m:r=> hasV(r,'Transação Solicitada',/renova/i)||/renova/i.test(r.contact_reason||'')||trait(r,'Momento no ciclo de vida')==='Em renovação'},\n  {key:'voucher',title:'Voucher / pontos expirando',m:r=> hasV(r,'Dado Consultado',/voucher|pontos/i)||hasV(r,'Transação Solicitada',/resgatar pontos|voucher/i)},\n  {key:'permissao',title:'Permissão do app desativada',m:r=> hasV(r,'Sintoma Técnico Relatado',/permiss/i)}\n];\n/* ===== END KIT + drill helpers ===== */\n\nconst TABS = [['exec','Visão Executiva','0'],['churn','Risco de Churn','1'],['receita','Oportunidades de Receita','2'],['perfis','Perfis de Cliente','3'],['atrito','Experiência e Atrito','4'],['justina','Qualidade Justina','5'],['humano','Qualidade do Atendimento','6'],['automacao','Automação da Justina','7'],['app','Melhorias do App','8'],['ficha','Ficha / Conversa','9'],['premissas','Premissas e Cobertura','10']];\nconst TAB_META = {exec:['CEO','Onde está o dinheiro e o risco neste mês?'],churn:['CS/CX','Quem eu ligo amanhã?'],receita:['CS/Comercial','Quem eu abordo e com qual oferta?'],perfis:['Todos','Quem são meus clientes, de verdade?'],atrito:['CX','Onde o cliente sofre?'],justina:['Produto','A IA está entregando?'],humano:['CS/CX','O time está entregando?'],automacao:['Produto/COO','O que integrar primeiro, e quanto economiza?'],app:['Produto','O que o app está causando de atendimento?'],ficha:['Todos','Drill-down universal — destino de todo clique'],premissas:['CFO','Em que eu posso confiar aqui?']};\nconst TAB_GUIDE = {\n  exec:{ what:\"Resumo do mês em dinheiro e risco: quanto o atendimento custa, quanto a Justina economiza, onde há receita a capturar e quais clientes são os mais caros de servir.\", method:[\"Valores em R$ são estimativas, calculadas a partir das premissas da Aba 10 (ticket médio, custo por transbordo, taxas). Contagens e tags são fato.\",\"O custo de servir de um cliente soma o custo das conversas dele: Justina mais os transbordos humanos.\",\"O ranking mostra os 15 clientes de maior custo, coloridos por risco e satisfação.\"], terms:[[\"Transbordo\",\"Quando a Justina (IA) passa a conversa para um atendente humano.\"],[\"Contenção\",\"Percentual de conversas que a Justina resolve sozinha, sem transbordo.\"],[\"Sinal comercial\",\"Indício, dentro da conversa, de oportunidade de venda (upsell, novo veículo, indicação).\"]] },\n  churn:{ what:\"Lista de clientes com risco de sair, priorizada por gravidade, para a ação de retenção: a resposta de quem ligar primeiro.\", method:[\"O risco vem da extração de IA Risco de churn na conversa mais recente de cada cliente.\",\"É agregado por cliente (telefone/contato), não por conversa: cada linha é uma pessoa.\",\"Os gatilhos são os motivos declarados do risco (preço, sinistro, atendimento).\"], terms:[[\"Saindo\",\"Churn em andamento: o cliente já está cancelando.\"],[\"Declarou\",\"Risco declarado: o cliente disse que pensa em sair.\"],[\"Sinalizou\",\"Risco latente: sinais indiretos de insatisfação, sem declaração.\"],[\"Estável\",\"Sem risco aparente na conversa.\"]] },\n  receita:{ what:\"Clientes com oportunidade de venda e qual abordagem faz sentido para cada um, para o time comercial e de CS priorizar.\", method:[\"Sinais comerciais são detectados na conversa (pedido de assistência, menção a novo veículo, indicação).\",\"A abordagem cruza o número de sinais com as condições do cliente: satisfeito, sem risco e em janela de renovação.\",\"A receita potencial é estimativa: aplica fatores e probabilidades de conversão (Aba 10) sobre o ticket médio.\"], terms:[[\"Upsell de cobertura\",\"Ampliar a cobertura atual do cliente (por exemplo vidros ou carro reserva).\"],[\"Regra de ouro\",\"Cliente em risco que também tem sinal comercial: retenção antes de oferta.\"],[\"Abordagem A1/A2/A3\",\"Prontidão para oferta: A1 aborda já, A3 apenas nutre, BLOCK não oferta (cliente em risco).\"]] },\n  perfis:{ what:\"Retrato dos clientes por dimensões de comportamento e atitude (satisfação, sensibilidade a preço, maturidade digital) e o agrupamento em personas.\", method:[\"Cada dimensão vem de uma extração de IA sobre a conversa (traits).\",\"Personas são regras que combinam essas dimensões (por exemplo resistente à telemetria ou sensível a preço).\",\"Conversas que não são de um cliente real (engano, spam, número desatualizado, agente de IA do cliente) ficam separadas como exclusões.\"], terms:[[\"Persona\",\"Grupo de clientes com perfil semelhante, derivado das traits.\"],[\"Maturidade digital\",\"O quanto o cliente resolve sozinho no app e no autoatendimento.\"],[\"Exclusão\",\"Conversa que não representa um cliente real e sai das análises de perfil.\"]] },\n  atrito:{ what:\"Onde o cliente teve esforço ou fricção: repetir informação, entrar em loop, ficar sem resposta. Aponta os assuntos que mais geram sofrimento.\", method:[\"Cada sinal de esforço é uma tag de IA (repetição, reformulação, loop do bot, beco sem saída).\",\"O FCR mede quantas conversas foram resolvidas já no primeiro contato.\",\"O custo do atrito estima o gasto com transbordos que poderiam ter sido evitados.\"], terms:[[\"Loop do bot\",\"A Justina repete respostas sem fazer a conversa avançar.\"],[\"Beco sem saída\",\"Conversa que trava sem solução e sem transbordo.\"],[\"FCR\",\"Resolução no primeiro contato, sem reincidência.\"],[\"Transbordo evitável\",\"Transbordo que uma automação ou base melhor teria evitado.\"]] },\n  justina:{ what:\"Qualidade da IA (Justina): quando resolve, quando erra e por quê. Separa falhas de conteúdo (base de conhecimento) de falhas de capacidade (integração).\", method:[\"A adequação da resposta classifica cada resposta da Justina (resolveu, parcial, contestada, fora do tema).\",\"A origem da limitação diz se faltou conteúdo (informação) ou capacidade (acesso a dado ou execução).\",\"As lacunas de base apontam assuntos em que falta conteúdo para a IA responder.\"], terms:[[\"Conteúdo\",\"Limitação por falta ou erro de informação na base de conhecimento.\"],[\"Capacidade\",\"Limitação por falta de acesso a dado ou de executar uma ação (integração).\"],[\"Lacuna de base\",\"Tema recorrente que a base de conhecimento não cobre.\"],[\"Empatia do bot\",\"A Justina demonstrou acolhimento na conversa.\"]] },\n  humano:{ what:\"Qualidade do atendimento humano após o transbordo: aderência a um checklist de conduta e riscos de compliance (segurança, exposição de dados, tom).\", method:[\"O índice de qualidade é uma média ponderada de um checklist de conduta: os itens mais críticos pesam mais.\",\"Cada item vem de uma tag de IA sobre a conversa (apresentou-se, validou segurança, informou prazo e protocolo).\",\"Considera apenas conversas que passaram para o atendente humano (transbordo).\"], terms:[[\"Índice de qualidade\",\"Nota de 0 a 100% do atendimento, ponderada pela criticidade de cada item.\"],[\"Validação de segurança\",\"Confirmar a identidade do cliente antes de tratar dados sensíveis.\"],[\"Exposição de info interna\",\"Vazamento de dado interno ou de terceiro na conversa: risco de compliance.\"]] },\n  automacao:{ what:\"O que vale integrar ou automatizar primeiro: agrupa os transbordos pela capacidade que falta à Justina e estima a economia de cada uma.\", method:[\"Cada transbordo automatizável é classificado por tipo: consulta (falta acesso a dado), transação (falta executar ação) ou conteúdo.\",\"As capacidades são agrupadas e ranqueadas por economia líquida estimada por mês.\",\"As notificações proativas listam gatilhos que a Justina poderia avisar antes de o cliente perguntar.\"], terms:[[\"Consulta\",\"A Justina precisaria acessar um dado que hoje não tem (por exemplo status de sinistro).\"],[\"Transação\",\"A Justina precisaria executar uma ação (por exemplo segunda via ou agendar vistoria).\"],[\"Notificação proativa\",\"Aviso automático antes de o cliente precisar perguntar (por exemplo vencimento de pagamento).\"]] },\n  app:{ what:\"O que o app Justos está gerando de atendimento: sintomas técnicos relatados, fluxos com mais fricção e reclamações. Insumo para o time de Produto.\", method:[\"Sintomas técnicos são problemas de app citados na conversa (viagens, permissões, login, fotos).\",\"As conversas são marcadas como contexto de app por palavras-chave e pelo objeto da demanda.\",\"App falhou e virou contato humano mostra onde o autoatendimento não resolveu e gerou atendimento.\"], terms:[[\"Sintoma técnico\",\"Problema de app relatado pelo cliente na conversa.\"],[\"Gap do app\",\"O cliente tentou resolver no app, não conseguiu e precisou de humano.\"],[\"Telemetria\",\"Rastreamento de direção (Driving Test): fonte comum de dúvida e de privacidade.\"]] },\n  ficha:{ what:\"O destino de todo clique. Qualquer número ou barra do dashboard abre aqui, já filtrado: a conversa completa, as extrações de IA e o link do ticket no Zendesk. É o que torna cada número auditável.\", method:[\"Mostra a conversa transcrita e as quatro extrações de IA: resumo, traits, cx_tags e bot_tags.\",\"Quando aberta por um clique, já vem filtrada pelo recorte que você clicou.\",\"O link leva ao ticket original no Zendesk para conferência.\"], terms:[[\"Extração\",\"Análise de IA sobre a conversa: resumo, perfil e tags de experiência e de bot.\"],[\"Auditabilidade\",\"Poder rastrear qualquer número até as conversas reais que o formam.\"]] },\n  premissas:{ what:\"Onde ficam as premissas e cenários que alimentam TODAS as estimativas em R$, e a cobertura da análise (quantas conversas foram efetivamente processadas). Responde em que confiar.\", method:[\"Separa o que é fato (contagens, tags) do que é estimativa (todo valor em R$).\",\"O cenário (conservador, base ou otimista) multiplica as taxas e reprecifica o dashboard inteiro.\",\"Você pode editar aqui as taxas de cancelamento e de conversão: as demais abas recalculam.\"], terms:[[\"Fato\",\"Número contado direto das conversas, não depende de premissa.\"],[\"Estimativa\",\"Valor em R$ derivado de premissas: muda com o cenário.\"],[\"Cenário\",\"Ajuste global otimista, base ou conservador aplicado às taxas.\"]] }\n};\nconst TAB_UC = {\n  exec:'babi-hera@justos-tab-exec',\n  churn:'babi-hera@justos-tab-churn',\n  receita:'babi-hera@justos-tab-receita',\n  perfis:'babi-hera@justos-tab-perfis',\n  atrito:'babi-hera@justos-tab-atrito',\n  justina:'babi-hera@justos-tab-justina',\n  humano:'babi-hera@justos-tab-humano',\n  automacao:'babi-hera@justos-tab-automacao',\n  app:'babi-hera@justos-tab-app',\n  ficha:'babi-hera@justos-tab-ficha',\n  premissas:'babi-hera@justos-tab-premissas'\n};\nconst SCEN_F = { conservador:0.7, base:1.0, otimista:1.3 };\nconst DEF_PREM = { cancelRates:{Saindo:0.90,Declarou:0.50,Sinalizou:0.15}, convRates:{upsell:0.25,mensalAnual:0.30,novoVeiculo:0.15,indicacao:0.20,campanha:0.10,referenciavel:0.05}, scenario:'base' };\nconst PREM_STORE = 'poc-justus-premises';\nconst DESF_LBL = {justina:'Resolvida pela Justina',transbordo_ok:'Resolvida após transbordo',nao_resolvida:'Não resolvida',sem_evidencia:'Sem evidência'};\nconst desfChip = r => { const st=desfecho(r); const tone=st==='justina'?'ok':st==='nao_resolvida'?'bad':st==='transbordo_ok'?'warn':''; return '<span class=\"jr-chip '+tone+'\">'+esc(DESF_LBL[st]||st)+'</span>'; };\nconst byDateDesc = (a,b) => String(b.ticket_date||'').localeCompare(String(a.ticket_date||''));\nconst nparse = (a,b) => { const v=(a==null||a==='')?b:a; const n=Number(v); return isNaN(n)?Number(b):n; };\nconst acctKey = r => r.phone||r.contact||r._id;\n\n/* ---- account-level drill: sessions of matching accounts ---- */\nconst acctDrill = (rows, title, matchAcc) => { const accs=buildAccounts(rows); const keys=new Set(accs.filter(matchAcc).map(a=>a.key)); return { title, list: rows.filter(r=>keys.has(acctKey(r))).sort(byDateDesc) }; };\n\n/* ================= drillFor: token -> {title, list of sessions} ================= */\nconst drillFor = (rows, token) => {\n  if(!token) return null;\n  const R = (title, f) => ({ title, list: rows.filter(f).sort(byDateDesc) });\n  if(token==='all') return R('Todas as conversas analisadas', ()=>true);\n  const ci = token.indexOf(':'); const kind = ci<0?token:token.slice(0,ci); const val = ci<0?'':token.slice(ci+1);\n\n  if(kind==='desf'){ if(val==='transb') return R('Conversas transbordadas', transbordou); if(val==='retrab') return R('Retrabalho — Justina + humano que falharam', isRetrabalho); return R(DESF_LBL[val]||'Conversas', r=>desfecho(r)===val); }\n  if(kind==='sat') return R('Satisfação: '+val, r=>satBucket(r)===val);\n  if(kind==='reason') return R('Assunto: '+val, r=>(r.contact_reason||'Sem motivo')===val);\n  if(kind==='risk') return R('Nível de risco: '+val, r=>riskLevel(r)===val);\n  if(kind==='alert'){ if(val==='churn') return R('Churn em andamento', r=>riskLevel(r)==='Saindo'); if(val==='publica') return R('Ameaça de exposição pública', r=>RX_PUBLIC.test((r.summary||'')+' '+kwOf(r).join(' ')+' '+botArr(r,'Sinal de Risco').join(' '))); if(val==='exposicao') return R('Exposição indevida de info', r=>RX_LEAK.test((r.summary||'')+' '+kwOf(r).join(' '))||cxTag(r,'Exposição de info interna')==='Sim'); }\n\n  if(kind==='churn'){\n    if(val==='risco') return acctDrill(rows,'Clientes em risco', a=>{const l=a.risk;return l&&l!=='Estável';});\n    if(val.indexOf('nivel:')===0){ const lv=val.slice(6); return acctDrill(rows,'Nível: '+lv, a=>a.risk===lv); }\n    if(val.indexOf('gatilho:')===0){ const g=val.slice(8).toLowerCase(); return R('Gatilho: '+val.slice(8), r=>gatilhosOf(r).some(x=>x.toLowerCase().startsWith(g))); }\n  }\n\n  if(kind==='abord'){ const opps=buildOpps(rows,2250); const keys=new Set(opps.filter(o=>o.approach===val).map(o=>o.key)); return { title:'Abordagem '+val, list: rows.filter(r=>keys.has(acctKey(r))).sort(byDateDesc) }; }\n  if(token==='abordrisco'){ const opps=buildOpps(rows,2250); const keys=new Set(opps.filter(o=>o.atRisk&&o.nSig>0).map(o=>o.key)); return { title:'Em risco com sinal comercial (regra de ouro)', list: rows.filter(r=>keys.has(acctKey(r))).sort(byDateDesc) }; }\n  if(token==='sinalcom') return R('Contas com sinal comercial', r=>commSignalX(r).length>0);\n  if(kind==='sinal'){ return R('Sinal comercial: '+val, r=>commSignalX(r).some(g=>g.name===val)); }\n\n  if(kind==='ptrait'){ const p=val.split('~'); const code=p[0], v=p.slice(1).join('~'); return R((PF_LABELS[code]||code)+': '+v, r=>pfDimValue(r,code)===v); }\n  if(kind==='pcross'){ const parts=val.split('__'); const a=(parts[0]||'').split('~'), b=(parts[1]||'').split('~'); const px=a[0], cv=a.slice(1).join('~'), py=b[0], rv=b.slice(1).join('~'); return R((PF_LABELS[px]||px)+' '+cv+' × '+(PF_LABELS[py]||py)+' '+rv, r=>pfDimValue(r,px)===cv&&pfDimValue(r,py)===rv); }\n  if(kind==='ppersona'){ return acctDrill(rows,'Persona: '+(PF_PERSONA_LBL[val]||val), a=>pfPersona(a.latest)===val); }\n  if(kind==='pexcl'){ return R('Exclusão: '+(PF_EXCL_LBL[val]||val), r=>pfExcl(r)===val); }\n\n  if(kind==='atrito'){\n    if(val==='fcr') return R('Resolvidas no 1º contato', fcrResolved);\n    if(val==='effort') return R('Maior esforço (3+ sinais)', r=>effortCount(r)>=3);\n    if(val==='custo') return R('Custo do atrito (transbordo evitável)', transbordoEvitavel);\n    if(val.indexOf('signal:')===0){ const s=val.slice(7); if(s==='atrito') return R('Conversas com atrito', hasAtrito); return R('Sinal de esforço: '+s, r=>!!effortSig(r)[ATR_SIGKEY[s]]); }\n    if(val.indexOf('assunto:')===0){ const o=val.slice(8); return R('Assunto (objeto): '+o, r=>(bot(r,'Objeto da Demanda Principal')||'Sem objeto')===o); }\n    if(val.indexOf('naoresolv:')===0){ const o=val.slice(10); return R('Não resolvido — '+o, r=>(bot(r,'Objeto da Demanda Principal')||'Sem objeto')===o&&desfecho(r)==='nao_resolvida'); }\n    if(val.indexOf('pend:')===0){ const b=val.slice(5); return R('Pendência: '+b, r=>pendBucket(r)===b); }\n    if(val.indexOf('cell:')===0){ const cv=val.slice(5); const bar=cv.lastIndexOf('|'); const obj=cv.slice(0,bar), sig=cv.slice(bar+1); return R(obj+' · '+sig, r=>(bot(r,'Objeto da Demanda Principal')||'Sem objeto')===obj&&!!effortSig(r)[ATR_SIGKEY[sig]]); }\n    if(val.indexOf('conf:')===0){ const cv=val.slice(5); const bar=cv.lastIndexOf('|'); const decl=cv.slice(0,bar), real=cv.slice(bar+1); return R('Declarado '+decl+' → real '+real, r=>canonReason(r.contact_reason)===decl&&canonObjeto(bot(r,'Objeto da Demanda Principal'))===real); }\n  }\n\n  if(kind==='j5'){\n    if(val==='loop') return R('Loop do bot', j5loop);\n    if(val==='beco') return R('Beco sem saída', j5beco);\n    if(val==='empatia') return R('Empatia do bot demonstrada', j5empatia);\n    if(val==='adeq:falha') return R('Falhas de conteúdo (tema diferente / contestada)', r=>{const a=j5adeq(r);return a==='tema_diferente'||a==='contestada';});\n    if(val.indexOf('adeq:')===0){ const k=val.slice(5); return R('Adequação da resposta: '+k, r=>j5adeq(r)===k); }\n    if(val.indexOf('assunto:')===0){ const a=val.slice(8); return R('Assunto: '+a, r=>J5_ASSUNTO(r)===a); }\n    if(val==='origem:conteudo') return R('Limitação de conteúdo (base de conhecimento)', r=>{const o=j5origem(r);return o&&o.k==='conteudo';});\n    if(val==='origem:capacidade') return R('Limitação de capacidade (integração)', r=>{const o=j5origem(r);return o&&o.k==='capacidade';});\n    if(val.indexOf('origemsub:')===0){ const s=val.slice(10); return R('Origem: '+s, r=>{const o=j5origem(r);return o&&o.sub===s;}); }\n    if(val.indexOf('kbgap:')===0){ const a=val.slice(6); return R('Lacuna de base — '+a, r=>J5_ASSUNTO(r)===a&&!!j5kbgap(r)); }\n    if(val.indexOf('motivo:')===0){ const m=val.slice(7); return R('Motivo do transbordo: '+m, r=>j5motivo(r)===m); }\n    if(val.indexOf('loopbeco:')===0){ const a=val.slice(9); return R('Loop/beco — '+a, r=>J5_ASSUNTO(r)===a&&(j5loop(r)||j5beco(r))); }\n    if(val.indexOf('retrab:')===0){ const a=val.slice(7); return R('Retrabalho — '+a, r=>J5_ASSUNTO(r)===a&&isRetrabalho(r)); }\n    return R('Qualidade da Justina', transbordou);\n  }\n\n  if(kind==='hum'){\n    const H = (title,f)=>({title, list: rows.filter(r=>transbordou(r)&&f(r)).sort(byDateDesc)});\n    if(val==='all') return H('Atendimentos humanos', ()=>true);\n    if(val==='sem_contexto') return H('Transbordo sem contexto', r=>cxTag(r,'Transbordo para humano com contexto')==='Não');\n    if(val==='repassou') return H('Apenas repassou informação', r=>bot(r,'Ação do Atendente Humano')==='Apenas repassou informação');\n    if(val==='seg_ausente') return H('Validação de segurança ausente', cSegAusente);\n    if(val==='exposicao') return H('Exposição de info interna', cExposicao);\n    if(val==='tom') return H('Tom inadequado', cTom);\n    if(val==='correcao') return H('Correção de info não corrigida', cCorrecao);\n    if(val==='index') return H('Índice de qualidade do atendimento', ()=>true);\n    if(val.indexOf('index:')===0){ const k=val.slice(6); return H('Qualidade: '+k, r=>humBand(qIndex(r))===k); }\n    if(val.indexOf('check:')===0){ const key=val.slice(6); const c=CHK.find(x=>x.key===key); if(c) return H(c.label, r=>c.get(r)===1); return H('Checklist de conduta', ()=>true); }\n    if(val.indexOf('acao:')===0){ const a=val.slice(5); return H('Ação do atendente: '+a, r=>bot(r,'Ação do Atendente Humano')===a); }\n    if(val.indexOf('team:')===0){ const t=val.slice(5); return H('Time: '+t, r=>r.team===t); }\n    if(val.indexOf('analyst:')===0){ const a=val.slice(8); return H('Atendente: '+a, r=>r.analyst===a); }\n    return H('Atendimento humano', ()=>true);\n  }\n\n  if(kind==='auto'){\n    if(val==='all') return R('Transbordos automatizáveis', r=>!!autoClassify(r));\n    if(val.indexOf('cap:')===0){ const cap=val.slice(4); return R('Capacidade: '+cap, r=>{const c=autoClassify(r);return c&&c.caps&&c.caps[0]===cap;}); }\n    if(val.indexOf('notif:')===0){ const key=val.slice(6); const n=NOTIF.find(x=>x.key===key); if(n) return R('Notificação proativa: '+(n.title||key), n.m); return R('Notificação proativa', transbordou); }\n    return R('Automação da Justina', r=>!!autoClassify(r));\n  }\n\n  if(kind==='app'){\n    if(val==='ctx') return R('Conversas com contexto de app', isAppContext);\n    if(val==='gap') return R('App falhou → contato humano', isGap);\n    if(val==='tentativa') return R('Tentativa prévia no app', r=>bot(r,'Tentativa Prévia no App')==='Sim');\n    if(val==='reclama') return R('Reclamações sobre o app', isAppComplaint);\n    if(val==='reclama:risco') return R('Reclamações de app com risco de churn', r=>isAppComplaint(r)&&isRiskyA(r));\n    if(val==='neutro') return R('Dúvidas neutras sobre o app', r=>isAppContext(r)&&!isAppComplaint(r));\n    if(val==='privacidade') return R('Privacidade / telemetria', isPrivacy);\n    if(val.indexOf('sintoma:')===0){ const k=val.slice(8); return R('Sintoma técnico: '+k, r=>symptomsOf(r).indexOf(k)>=0); }\n    if(val.indexOf('redir:')===0){ const k=val.slice(6); if(k==='app') return R('Direcionado ao app', isRedirApp); if(k==='reincid') return R('Redirecionado ao app e reincidiu', isRedirReincid); if(k==='none') return R('Sem direcionamento', r=>redirOf(r)==='Não houve direcionamento'); if(k==='outro') return R('Outro direcionamento', r=>{const x=redirOf(r);return x&&x!=='Direcionado ao app'&&x!=='Não houve direcionamento';}); return R('Redirecionamento ao autosserviço', r=>!!redirOf(r)); }\n    if(val.indexOf('fluxo:')===0){ const k=val.slice(6); const f=FLOW_DEFS.find(x=>x.key===k); if(f) return R('Fricção por fluxo: '+f.label, r=>inFlow(r,f)); return R('Fricção por fluxo', isAppContext); }\n    return R('Sinais do app', isAppContext);\n  }\n\n  if(kind==='fieldv'){ const parts=val.split('~'); const obj=parts[0], field=parts[1], value=parts.slice(2).join('~'); const LBL={traits:'Trait',cx:'Qualidade',bot:'Automação',class:'Classificação'}[obj]||obj; return R(LBL+' · '+field+': '+value, r=>fieldValues(r,obj,field).indexOf(value)>=0); }\n  if(kind==='extr'){\n    if(val==='e1') return R('E1 · Classificação — conversas classificadas', r=>!!(r.summarized||r.contact_analyzed||r.summary));\n    if(val==='e2') return R('E2 · Traits do cliente — conversas com traits', r=>Object.keys(trOf(r)).length>0);\n    if(val==='e3') return R('E3 · Qualidade — conversas com cx_tags', r=>!!r.cx_analyzed||Object.keys(cxOf(r)).length>0);\n    if(val==='e4') return R('E4 · Automação e produto — conversas com bot_tags', r=>!!r.bot_analyzed||Object.keys(botOf(r)).length>0);\n  }\n  if(kind==='extrf'){ const ci2=val.indexOf(':'); const obj=ci2<0?val:val.slice(0,ci2); const field=ci2<0?'':val.slice(ci2+1); const OBJ={traits:trOf,cx:cxOf,bot:botOf}[obj]; const LBL={traits:'Trait',cx:'Qualidade',bot:'Automação',class:'Classificação'}[obj]||obj; if(obj==='class'){ const has=field==='keywords'?(r=>kwOf(r).length>0):(r=>r[field]!=null&&String(r[field]).trim()!==''); return R(LBL+': '+field, has); } if(OBJ) return R(LBL+': '+field, r=>{ const o=OBJ(r); return o&&o[field]!=null&&String(o[field]).trim()!==''; }); }\n  return { title: 'Conversas ('+token+')', list: rows.slice().sort(byDateDesc) };\n};\n\nconst listRowHtml = r => '<div class=\"dw-row\" data-drill=\"ticket:'+esc(r.ticket_id)+'\">'+\n  '<div class=\"dw-row-main\"><div class=\"dw-row-t\">#'+esc(r.ticket_id)+' · '+esc(r.contact||'—')+'</div>'+\n  '<div class=\"dw-row-s\">'+esc(fmtDate(r.ticket_date))+' · '+esc(r.contact_reason||'—')+' · '+esc(r.analyst||'Justina')+'</div></div>'+\n  '<div class=\"dw-row-tags\">'+desfChip(r)+(satBucket(r)?'<span class=\"jr-chip\">'+esc(satBucket(r))+'</span>':'')+(riskLevel(r)?'<span class=\"jr-chip bad\">'+esc(riskLevel(r))+'</span>':'')+'</div>'+\n'</div>';\nconst LIST_PAGE = 100;\nconst renderList = (drill, page) => {\n  const total = drill.list.length;\n  const pages = Math.max(1, Math.ceil(total/LIST_PAGE));\n  const p = Math.min(Math.max(0, page||0), pages-1);\n  const start = p*LIST_PAGE, end = Math.min(total, start+LIST_PAGE);\n  const slice = drill.list.slice(start, end);\n  const head = '<div class=\"dw-list-head\"><div class=\"dw-title\">'+esc(drill.title)+'</div><div class=\"dw-count\">'+num(total)+' conversa'+(total===1?'':'s')+'</div></div>';\n  const body = '<div class=\"dw-list\">'+(total?slice.map(listRowHtml).join(''):'<div class=\"jr-empty\">Nenhuma conversa neste recorte.</div>')+'</div>';\n  const pager = pages>1 ? '<div class=\"dw-pager\"><button class=\"dw-pg\" data-dir=\"prev\"'+(p===0?' disabled':'')+'>‹ Anterior</button><span class=\"dw-pg-info\">'+num(start+1)+'–'+num(end)+' de '+num(total)+' · pág. '+(p+1)+'/'+num(pages)+'</span><button class=\"dw-pg\" data-dir=\"next\"'+(p>=pages-1?' disabled':'')+'>Próxima ›</button></div>' : '';\n  return head + body + pager;\n};\n\nconst placeholder = (id) => { const m=TAB_META[id]||['','']; const t=(TABS.find(x=>x[0]===id)||[])[1]||id, n=(TABS.find(x=>x[0]===id)||[])[2]||''; return '<div class=\"ph-wrap\"><div class=\"ph-card\"><div class=\"ph-n\">Aba '+esc(n)+'</div><div class=\"ph-title\">'+esc(t)+'</div><div class=\"ph-meta\">Dono: <b>'+esc(m[0])+'</b></div><div class=\"ph-q\">“'+esc(m[1])+'”</div><div class=\"ph-tag\">Aba ainda não integrada.</div></div></div>'; };\nconst renderGuide = (id) => {\n  const g=TAB_GUIDE[id]; if(!g) return '<div class=\"jr-empty\">Sem guia para esta aba.</div>';\n  const meta=TAB_META[id]||['','']; const tb=TABS.find(x=>x[0]===id)||[];\n  const method=(g.method||[]).map(m=>'<li>'+esc(m)+'</li>').join('');\n  const terms=(g.terms||[]).map(t=>'<div class=\"gd-term\"><div class=\"gd-term-t\">'+esc(t[0])+'</div><div class=\"gd-term-d\">'+esc(t[1])+'</div></div>').join('');\n  return '<div class=\"gd\">'+\n    '<div class=\"gd-head\"><span class=\"gd-n\">Aba '+esc(tb[2]||'')+'</span><span class=\"gd-title\">'+esc(tb[1]||id)+'</span></div>'+\n    '<div class=\"gd-q\">'+esc(meta[1])+'</div>'+\n    '<div class=\"gd-sec\"><div class=\"gd-lab\">O que você vê aqui</div><p class=\"gd-p\">'+esc(g.what)+'</p></div>'+\n    (method?'<div class=\"gd-sec\"><div class=\"gd-lab\">Como os números são construídos</div><ul class=\"gd-ul\">'+method+'</ul></div>':'')+\n    (terms?'<div class=\"gd-sec\"><div class=\"gd-lab\">Termos desta aba</div><div class=\"gd-terms\">'+terms+'</div></div>':'')+\n    '<div class=\"gd-foot\">Contagens e tags são <b>fato</b>. Todo valor em <b>R$</b> é estimativa, ajustável na Aba 10. Clique em qualquer número do dashboard para abrir as conversas por trás dele.</div>'+\n  '</div>';\n};\n\nconst effPrem = d2 => { const prem=d2.state.prem||DEF_PREM; const f=SCEN_F[prem.scenario]||1; const ec={}; const cr=prem.cancelRates||DEF_PREM.cancelRates; for(const k in cr) ec[k]=Math.min(1,cr[k]*f); const cvs=Object.keys(prem.convRates||{}).map(k=>prem.convRates[k]); const blended=cvs.length?cvs.reduce((a,b)=>a+b,0)/cvs.length:0.25; return { raw:prem, effCancel:ec, effConv:Math.min(1,blended*f), scenario:prem.scenario }; };\nconst analyzedRows = d2 => { const all=(d2.state.allRows&&d2.state.allRows.length)?d2.state.allRows:[]; const az=all.filter(r=>r&&(r.summarized||r.contact_analyzed||r.bot_analyzed)); return az.length?az:all; };\nconst FIELD_FREETEXT = new Set(['summary']);\nconst EXTR_LBL = {class:'E1 · Classificação', traits:'E2 · Traits do cliente', cx:'E3 · Qualidade', bot:'E4 · Automação e produto'};\nconst FIELD_DESC = {\n  'summary':'Resumo em texto do que aconteceu na conversa.',\n  'contact_reason':'Assunto principal do contato, na taxonomia da Justos (ex.: Aquisição, Sinistro, Cancelamento).',\n  'contact_reason_detail':'Detalhamento do assunto do contato.',\n  'keywords':'Etiquetas livres que resumem temas e desfechos da conversa.',\n  'avr_sentiment':'Sentimento médio do cliente na conversa, de 0 (muito negativo) a 100 (muito positivo).',\n  'Risco de churn':'Nível de risco de o cliente cancelar, inferido da conversa.',\n  'Satisfação':'Grau de satisfação percebido, de detrator a promotor.',\n  'Gatilhos de churn':'O que está por trás do risco (preço, fricção, sinistro…).',\n  'Oportunidade comercial':'Sinal de oportunidade de venda percebido na conversa.',\n  'Perfil':'Perfil do cliente ou de uso inferido (ex.: multiveículo, corretor).',\n  'Estilo de comunicação':'Como o cliente se comunica (objetivo, detalhista…).',\n  'Momento no ciclo de vida':'Fase do cliente com a Justos (onboarding, renovação, cancelamento…).',\n  'Sensibilidade a preço':'O quanto o cliente reage a preço e desconto.',\n  'Maturidade digital e autoatendimento':'Autonomia do cliente para resolver sozinho no digital.',\n  'Engajamento com o produto':'Nível de uso e engajamento com o produto e o app.',\n  'Comportamento de pagamento':'Padrão de pagamento do cliente.',\n  'Natureza do contato':'Se o contato foi proativo do cliente, reativo, etc.',\n  'Sinistralidade recente':'Se o cliente teve sinistro recente.',\n  'Repetição de Informação':'Se o cliente teve de repetir informação já fornecida.',\n  'Reformulação':'Se o cliente teve de reformular o pedido para ser entendido.',\n  'Reformulação do pedido ou pergunta':'Se o cliente teve de reformular o pedido para ser entendido.',\n  'Loop do Bot':'Se a Justina ficou repetindo respostas sem avançar.',\n  'Beco sem saída':'Se a conversa travou sem solução e sem transbordo.',\n  'Transbordo':'Se a conversa passou da Justina para um atendente humano.',\n  'Modo de Transbordo':'Como o transbordo aconteceu (decidido pelo bot, pedido pelo cliente…).',\n  'Transbordo para humano com contexto':'Se o humano recebeu o histórico e o contexto ao assumir.',\n  'Prazo definido':'Se o atendente informou um prazo concreto.',\n  'Protocolo informado':'Se foi informado número de protocolo quando devido.',\n  'Jargão não explicado':'Se houve termo técnico usado sem explicação ao cliente.',\n  'Empatia do Atendente Humano':'Se o atendente humano demonstrou empatia.',\n  'Empatia do bot':'Se a Justina demonstrou empatia e acolhimento.',\n  'Empatia do bot (Justina)':'Se a Justina demonstrou empatia e acolhimento.',\n  'Dúvidas pendentes no encerramento':'Se sobraram dúvidas sem resposta no encerramento.',\n  'Apresentação do analista':'Se o atendente se apresentou com nome.',\n  'Validação de dados de segurança':'Se houve confirmação de identidade antes de tratar dados sensíveis.',\n  'Retomada após pausa declarada':'Se o atendente retomou a conversa com posicionamento após uma pausa.',\n  'Abertura para novas dúvidas':'Se o atendente abriu espaço para novas perguntas.',\n  'Convite à pesquisa de satisfação':'Se o cliente foi convidado à pesquisa de satisfação.',\n  'Tom inadequado':'Se houve tom inadequado no atendimento.',\n  'Exposição de info interna':'Se houve exposição de informação interna ou de terceiros (risco de compliance).',\n  'Exposição de informação interna':'Se houve exposição de informação interna ou de terceiros (risco de compliance).',\n  'Correção da informação':'Se uma informação incorreta foi corrigida durante a conversa.',\n  'Correção de informação':'Se uma informação incorreta foi corrigida durante a conversa.',\n  'Ameaça do Cliente':'Se o cliente ameaçou tomar alguma ação (reclamação pública, jurídica…).',\n  'Ameaça do Cliente Procon':'Se o cliente ameaçou acionar o Procon.',\n  'Ameaça do Cliente Reclame Aqui':'Se o cliente ameaçou reclamar no Reclame Aqui.',\n  'Ameaça do Cliente Jurídica':'Se o cliente ameaçou acionar via jurídica.',\n  'Ameaça do Cliente - Cancelamento':'Se o cliente ameaçou cancelar.',\n  'Jurídica':'Sinal de teor jurídico na conversa.',\n  'Mudança para concorrência':'Se o cliente mencionou ir para a concorrência.',\n  'Perfil do Solicitante':'Quem falou com a Justos na conversa (segurado, corretor, terceiro…).',\n  'Objeto da Demanda Principal':'Sobre o que era a demanda principal (sinistro, pagamento, cotação…).',\n  'Objeto da Demanda Secundário':'Demanda secundária tratada na mesma conversa.',\n  'Natureza da Demanda':'Tipo de demanda (dúvida, execução de ação, reclamação…).',\n  'Dado Pessoal da Conta Solicitado':'Se a conversa pediu algum dado pessoal da conta.',\n  'Ação Transacional Solicitada':'Se o cliente pediu uma ação transacional (executar algo).',\n  'Envio de Arquivo pelo Cliente':'Se o cliente enviou algum arquivo ou documento.',\n  'Desfecho da Justina':'Como terminou do ponto de vista da IA (resolvida pela Justina, após transbordo ou não resolvida).',\n  'Origem da Limitação da Justina':'Por que a Justina não resolveu sozinha (falta de dado, de capacidade ou de conteúdo).',\n  'Tentativa Prévia no App':'Se o cliente já tinha tentado resolver no app antes.',\n  'Redirecionamento ao Autosserviço':'Se e para onde o cliente foi direcionado ao autosserviço.',\n  'Reincidência Declarada':'Se o cliente declarou que o problema é recorrente.',\n  'Dado Consultado':'Que dado a Justina precisaria consultar (ex.: status de sinistro).',\n  'Adequação da Resposta da Justina':'Se a resposta da Justina foi adequada ao que foi pedido.',\n  'Motivo do Transbordo':'Por que a conversa foi encaminhada ao atendente humano.',\n  'Ação do Atendente Humano':'O que o atendente humano fez (consultou sistema, repassou informação…).',\n  'Transação Solicitada':'Que transação o cliente pediu (segunda via, cancelar, agendar…).',\n  'Lacuna de Base de Conhecimento':'Tema que faltou na base de conhecimento da IA.',\n  'Pendência no Encerramento':'Se ficou alguma pendência ao encerrar a conversa.',\n  'Oportunidade de Notificação Proativa':'Gatilho que a Justos poderia avisar de forma proativa.',\n  'Sintoma Técnico Relatado':'Problema técnico do app relatado pelo cliente.'\n};\nconst fieldValues = (r, obj, field) => {\n  if(obj==='class'){\n    if(field==='keywords') return kwOf(r).map(x=>String(x));\n    const v=r?r[field]:null; if(v==null||String(v).trim()==='') return [];\n    if(field==='avr_sentiment'){ const n=Number(v); if(isNaN(n)) return []; return [ n>=75?'Alto (75–100)': n>=50?'Médio (50–74)': n>=25?'Baixo (25–49)':'Muito baixo (0–24)' ]; }\n    return [shortVal(v)];\n  }\n  const OBJ={traits:trOf,cx:cxOf,bot:botOf}[obj]; if(!OBJ) return [];\n  const o=OBJ(r); const raw=o?o[field]:null; if(raw==null) return [];\n  const out=[]; for(const x of asArray(raw)){ const s=shortVal(x); if(s!=null && String(s).trim()!=='') out.push(String(s)); } return out;\n};\nconst buildFieldProfile = (rows, obj, field) => {\n  const freq={}; let covered=0;\n  for(const r of rows){ const vals=fieldValues(r,obj,field); if(vals.length) covered++; for(const v of vals){ freq[v]=(freq[v]||0)+1; } }\n  const values=Object.keys(freq).map(v=>({v,count:freq[v]})).sort((a,b)=>b.count-a.count);\n  return { values, covered, total:rows.length, options:values.length };\n};\nconst renderFieldProfile = (rows, obj, field) => {\n  const data=buildFieldProfile(rows,obj,field);\n  const desc=FIELD_DESC[field]||('Classificação de IA da extração '+(EXTR_LBL[obj]||obj)+'. As opções observadas na base estão listadas abaixo.');\n  const isFree=FIELD_FREETEXT.has(field);\n  const head='<div class=\"fp-head\"><span class=\"fp-cat\">'+esc(EXTR_LBL[obj]||obj)+'</span><div class=\"fp-field\">'+esc(field)+'</div></div><div class=\"fp-desc\">'+esc(desc)+'</div>';\n  const meta='<div class=\"fp-meta\"><b>'+num(data.covered)+'</b> de '+num(data.total)+' conversas têm este campo'+(isFree?'':' · <b>'+num(data.options)+'</b> '+(data.options===1?'opção':'opções'))+'</div>';\n  let body;\n  if(isFree){ body='<div class=\"fp-free\">Campo de texto livre — sem opções fixas.</div><div class=\"fp-val\" data-drill=\"extrf:'+esc(obj)+':'+esc(field)+'\"><div class=\"fp-val-top\"><span class=\"fp-val-lbl\">Ver todas as conversas com este campo</span><span class=\"fp-val-n\">'+num(data.covered)+'</span></div></div>'; }\n  else if(!data.values.length){ body='<div class=\"jr-empty\">Nenhum valor encontrado nesta amostra.</div>'; }\n  else { const max=Math.max(1,...data.values.map(v=>v.count)); const top=data.values.slice(0,30); const rest=data.values.length-top.length; body='<div class=\"fp-vals\">'+top.map(v=>{ const w=Math.max(3,v.count/max*100); const p=data.covered?v.count/data.covered:0; return '<div class=\"fp-val\" data-drill=\"fieldv:'+esc(obj)+'~'+esc(field)+'~'+esc(v.v)+'\" title=\"ver conversas\"><div class=\"fp-val-top\"><span class=\"fp-val-lbl\">'+esc(v.v)+'</span><span class=\"fp-val-n\">'+num(v.count)+' · '+pct(p,0)+'</span></div><div class=\"fp-val-track\"><div class=\"fp-val-fill\" style=\"width:'+w+'%\"></div></div></div>'; }).join('')+'</div>'+(rest>0?'<div class=\"fp-more\">+'+num(rest)+' outros valores (contagem menor)</div>':''); }\n  return '<div class=\"fp\">'+head+meta+body+'<div class=\"fp-foot\">Contagem direta das conversas (fato). Clique num valor para ver e auditar as conversas.</div></div>';\n};\nconst routeDrill = (d2, t) => {\n  if(!t) return;\n  const rows=analyzedRows(d2);\n  if(t.indexOf('acct:')===0){ d2.state.fichaSel={phone:t.slice(5)}; d2.state.drill=null; return; }\n  if(t.indexOf('ficha:')===0){ d2.state.fichaSel={phone:t.slice(6)}; d2.state.drill=null; return; }\n  if(t.indexOf('ticket:')===0){ d2.state.fichaSel={ticket:t.slice(7)}; return; }\n  if(t.indexOf('conv:')===0){ d2.state.fichaSel={ticket:t.slice(5)}; return; }\n  if(t.indexOf('sess:')===0){ const id=t.slice(5); const r=rows.find(x=>x._id===id); d2.state.fichaSel=r?{ticket:String(r.ticket_id)}:null; return; }\n  if(t.indexOf('field:')===0){ const rest=t.slice(6); const gi=rest.indexOf('~'); const obj=gi<0?rest:rest.slice(0,gi); const field=gi<0?'':rest.slice(gi+1); d2.state.fieldProfile={obj,field}; d2.state.drill=null; d2.state.fichaSel=null; d2.state.guide=null; return; }\n  d2.state.fichaSel=null; d2.state.drill=drillFor(rows,t); d2.state.listPage=0;\n};\n\nexport default {\n  css: `\n:host,.shell-root{display:block;width:100%;height:100%}\n*{box-sizing:border-box}\n.shell{display:flex;flex-direction:column;width:100%;height:100%;background:#FAF9F6;color:#373435;font-family:-apple-system,BlinkMacSystemFont,'Inter','SF Pro Text','Helvetica Neue',sans-serif;overflow:hidden;position:relative}\n.pb{background:#fff;border-bottom:1px solid rgba(0,0,0,.06);padding:12px 18px 10px;display:flex;flex-direction:column;gap:9px;flex-shrink:0}\n.pb-top{display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap}\n.pb-brand{display:flex;align-items:baseline;gap:10px}\n.pb-title{font-size:17px;font-weight:800;color:var(--ink,#051216);letter-spacing:-0.02em}\n.pb-sub{font-size:11px;color:#747474}\n.pb-live{display:inline-flex;align-items:center;gap:6px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:#0A4A44;background:rgba(130,216,208,.18);padding:4px 9px;border-radius:999px}\n.pb-live .dot{width:6px;height:6px;border-radius:50%;background:var(--accent,#82D8D0);animation:pulse 2s infinite}\n@keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}\n.pb-params{display:flex;flex-wrap:wrap;gap:14px;align-items:flex-end}\n.pb-field{display:flex;flex-direction:column;gap:2px}\n.pb-lab{font-size:9px;color:#747474;text-transform:uppercase;letter-spacing:.05em;font-weight:700}\n.pb-in{width:112px;padding:5px 8px;font-size:12px;border:1px solid rgba(0,0,0,.12);border-radius:7px;background:#FAF9F6;color:#051216;font-variant-numeric:tabular-nums}\n.pb-in:focus{outline:none;border-color:var(--accent,#82D8D0);background:#fff}\n.pb-note{font-size:10px;color:#8a8580;max-width:320px;line-height:1.35}\n.pb-scn{font-size:10px;color:#8a6d1a;background:rgba(232,169,59,.14);padding:3px 8px;border-radius:6px;font-weight:700}\n.nav{display:flex;gap:2px;padding:0 12px;background:#fff;border-bottom:1px solid rgba(0,0,0,.06);overflow-x:auto;flex-shrink:0}\n.nav-tab{padding:9px 12px;font-size:12px;font-weight:600;color:#747474;border:none;background:none;cursor:pointer;white-space:nowrap;border-bottom:2px solid transparent;display:flex;align-items:center;gap:6px}\n.nav-tab:hover{color:var(--ink,#051216)}\n.nav-tab.on{color:var(--ink,#051216);border-bottom-color:var(--accent,#82D8D0)}\n.nav-tab .nt-n{font-size:9px;font-weight:800;color:#fff;background:#C9C4BB;border-radius:5px;padding:1px 5px}\n.nav-tab.on .nt-n{background:var(--accent,#82D8D0);color:#0A4A44}\n.content{flex:1;min-height:0;overflow:auto;position:relative}\n.ph-wrap{display:flex;align-items:center;justify-content:center;padding:48px 20px;min-height:60%}\n.ph-card{max-width:520px;text-align:center;background:#fff;border:1px solid rgba(0,0,0,.07);border-radius:18px;padding:30px 28px}\n.ph-n{font-size:11px;font-weight:800;color:var(--accent,#82D8D0);letter-spacing:.08em;text-transform:uppercase}\n.ph-title{font-size:22px;font-weight:800;color:var(--ink,#051216);margin-top:4px;letter-spacing:-0.02em}\n.ph-meta{font-size:12px;color:#747474;margin-top:6px}\n.ph-q{font-size:15px;color:#57534e;font-style:italic;margin-top:14px}\n.ph-tag{font-size:11px;color:#8a8580;margin-top:16px;line-height:1.5;background:#FAF9F6;border-radius:10px;padding:10px 12px}\n.jr-empty{color:#747474;font-size:12px;padding:12px;text-align:center;border:1px dashed rgba(0,0,0,.12);border-radius:10px}\n.dw-scrim{position:absolute;inset:0;background:rgba(5,18,22,.35);z-index:20;animation:fade .15s}\n@keyframes fade{from{opacity:0}to{opacity:1}}\n.dw{position:absolute;top:0;right:0;bottom:0;width:min(640px,96%);background:#fff;z-index:21;display:flex;flex-direction:column;box-shadow:-8px 0 32px rgba(5,18,22,.16);animation:slidein .18s}\n@keyframes slidein{from{transform:translateX(30px);opacity:.4}to{transform:translateX(0);opacity:1}}\n.dw-bar{display:flex;align-items:center;gap:10px;padding:12px 16px;border-bottom:1px solid rgba(0,0,0,.07);flex-shrink:0}\n.dw-close,.dw-back{border:none;background:#F0EDE8;width:30px;height:30px;border-radius:8px;cursor:pointer;font-size:14px;color:#373435}\n.dw-close:hover,.dw-back:hover{background:#e3ddd4}\n.dw-bar-title{font-size:13px;font-weight:700;color:var(--ink,#051216)}\n.dw-scroll{flex:1;min-height:0;overflow:auto;padding:14px 16px}\n.dw-list-head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:8px}\n.dw-title{font-size:15px;font-weight:800;color:var(--ink,#051216);letter-spacing:-0.01em}\n.dw-count{font-size:11px;color:#747474}\n.dw-list{display:flex;flex-direction:column;gap:6px}\n.dw-more{font-size:11px;color:#747474;text-align:center;padding:8px}\n.dw-pager{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 2px 4px;margin-top:8px;border-top:1px solid rgba(0,0,0,.06)}\n.dw-pg{border:1px solid rgba(0,0,0,.12);background:#fff;color:#0A4A44;font-size:12px;font-weight:700;padding:6px 12px;border-radius:8px;cursor:pointer;white-space:nowrap}\n.dw-pg:hover:not([disabled]){border-color:var(--accent,#82D8D0);background:rgba(130,216,208,.10)}\n.dw-pg[disabled]{opacity:.4;cursor:default}\n.dw-pg-info{font-size:11px;color:#747474;font-variant-numeric:tabular-nums;text-align:center;flex:1}\n.dw-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 11px;border:1px solid rgba(0,0,0,.07);border-radius:10px;cursor:pointer;background:#fff;transition:border-color .12s,background .12s}\n.dw-row:hover{border-color:var(--accent,#82D8D0);background:rgba(130,216,208,.06)}\n.dw-row-t{font-size:12px;font-weight:700;color:var(--ink,#051216)}\n.dw-row-s{font-size:11px;color:#747474;margin-top:1px}\n.dw-row-tags{display:flex;gap:4px;flex-shrink:0;flex-wrap:wrap;justify-content:flex-end;max-width:200px}\n.jr-chip{display:inline-flex;align-items:center;font-size:10px;font-weight:600;padding:2px 8px;border-radius:999px;background:#F0EDE8;color:#373435;white-space:nowrap}\n.jr-chip.bad{background:rgba(162,37,96,.12);color:var(--neg,#A22560)}\n.jr-chip.warn{background:rgba(232,169,59,.18);color:#8a6d1a}\n.jr-chip.ok{background:rgba(130,216,208,.22);color:#0A4A44}\n.dw-fichawrap{padding:0}\n.tabhdr{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:7px 18px;background:#fff;border-bottom:1px solid rgba(0,0,0,.06);flex-shrink:0}\n.tabhdr-q{display:flex;align-items:center;gap:9px;min-width:0}\n.tabhdr-n{font-size:9px;font-weight:800;color:#0A4A44;background:rgba(130,216,208,.22);border-radius:5px;padding:2px 7px;flex-shrink:0;letter-spacing:.03em}\n.tabhdr-qt{font-size:12.5px;color:#57534e;font-style:italic;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.tabhdr-help{border:1px solid rgba(0,0,0,.12);background:#fff;color:#0A4A44;font-size:11px;font-weight:700;padding:5px 11px;border-radius:999px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;flex-shrink:0;white-space:nowrap}\n.tabhdr-help:hover{border-color:var(--accent,#82D8D0);background:rgba(130,216,208,.10)}\n.tabhdr-help::before{content:\"?\";display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;border-radius:50%;background:var(--accent,#82D8D0);color:#0A4A44;font-size:10px;font-weight:800}\n.gd{font-size:13px;color:#373435;line-height:1.5}\n.gd-head{display:flex;align-items:baseline;gap:9px;margin-bottom:2px}\n.gd-n{font-size:9px;font-weight:800;color:#0A4A44;background:rgba(130,216,208,.22);border-radius:5px;padding:2px 7px}\n.gd-title{font-size:16px;font-weight:800;color:var(--ink,#051216);letter-spacing:-0.01em}\n.gd-q{font-size:13px;color:#57534e;font-style:italic;margin:6px 0 14px}\n.gd-sec{margin-bottom:16px}\n.gd-lab{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:#8a8580;margin-bottom:6px}\n.gd-p{margin:0;color:#373435}\n.gd-ul{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:5px}\n.gd-ul li{color:#373435}\n.gd-terms{display:flex;flex-direction:column;gap:8px}\n.gd-term{background:#FAF9F6;border:1px solid rgba(0,0,0,.06);border-radius:9px;padding:8px 11px}\n.gd-term-t{font-size:12px;font-weight:700;color:var(--ink,#051216)}\n.gd-term-d{font-size:12px;color:#57534e;margin-top:2px}\n.gd-foot{margin-top:8px;font-size:11.5px;color:#8a6d1a;background:rgba(232,169,59,.12);border-radius:10px;padding:10px 12px;line-height:1.45}\n.fp{font-size:13px;color:#373435;line-height:1.5}\n.fp-head{display:flex;flex-direction:column;gap:3px;margin-bottom:6px}\n.fp-cat{align-self:flex-start;font-size:9px;font-weight:800;color:#0A4A44;background:rgba(130,216,208,.22);border-radius:5px;padding:2px 7px;letter-spacing:.03em}\n.fp-field{font-size:16px;font-weight:800;color:var(--ink,#051216);letter-spacing:-0.01em}\n.fp-desc{font-size:12.5px;color:#57534e;line-height:1.45;margin-bottom:10px}\n.fp-meta{font-size:11px;color:#747474;margin-bottom:12px}\n.fp-meta b{color:var(--ink,#051216)}\n.fp-vals{display:flex;flex-direction:column;gap:7px}\n.fp-val{border:1px solid rgba(0,0,0,.07);border-radius:9px;padding:8px 10px;cursor:pointer;background:#fff;transition:border-color .12s,background .12s}\n.fp-val:hover{border-color:var(--accent,#82D8D0);background:rgba(130,216,208,.06)}\n.fp-val-top{display:flex;align-items:baseline;justify-content:space-between;gap:10px}\n.fp-val-lbl{font-size:12px;font-weight:600;color:var(--ink,#051216);overflow:hidden;text-overflow:ellipsis}\n.fp-val-n{font-size:11px;color:#57534e;font-variant-numeric:tabular-nums;white-space:nowrap}\n.fp-val-track{height:6px;background:#F0EDE8;border-radius:3px;overflow:hidden;margin-top:6px}\n.fp-val-fill{height:100%;border-radius:3px;background:var(--accent,#82D8D0)}\n.fp-more{font-size:11px;color:#747474;text-align:center;padding:8px}\n.fp-free{font-size:12px;color:#747474;background:#FAF9F6;border-radius:8px;padding:8px 10px;margin-bottom:8px}\n.fp-foot{margin-top:12px;font-size:11px;color:#57534e;background:#FAF9F6;border-radius:9px;padding:9px 11px;line-height:1.4}\n`,\n  render(d2){\n    const accent=cxColor(d2.param('accent'),'#82D8D0'), neg=cxColor(d2.param('negativeAccent'),'#A22560'), ink=cxColor(d2.param('brandInk'),'#051216');\n    const ov=d2.state.params||{};\n    const P={ premio:nparse(ov.premio,d2.param('premioAnual',2250)), custoHumano:nparse(ov.custoHumano,d2.param('custoHumano',15)), custoJustina:nparse(ov.custoJustina,d2.param('custoJustina',3)), containment:nparse(ov.containment,d2.param('containment',0.85)), pctThreshold:nparse(ov.pctThreshold,d2.param('pctThreshold',0.05)) };\n    const zsub=d2.param('zendeskSub','justosseguros');\n    const ds=d2.data&&d2.data();\n    const all=(d2.state.allRows&&d2.state.allRows.length)?d2.state.allRows:((ds&&!ds.loading)?(ds.records()||[]):[]);\n    const analyzed=all.filter(r=>r&&(r.summarized||r.contact_analyzed||r.bot_analyzed));\n    const rows=analyzed.length?analyzed:all;\n    const acts=d2.state.acts||[];\n    const active=d2.state.activeTab||'exec';\n    const loading=!all.length && (!ds||ds.loading);\n    const ep=effPrem(d2);\n\n    const pbField=(k,lab,v,suffix)=>'<div class=\"pb-field\"><label class=\"pb-lab\">'+esc(lab)+'</label><input class=\"pb-in\" data-k=\"'+k+'\" type=\"text\" inputmode=\"decimal\" value=\"'+esc(v)+'\"'+(suffix?' data-suffix=\"'+suffix+'\"':'')+'></div>';\n    const scnLbl={conservador:'Conservador',base:'Base',otimista:'Otimista'}[ep.scenario]||'Base';\n    const pb='<div class=\"pb\">'+\n      '<div class=\"pb-top\">'+\n        '<div class=\"pb-brand\"><div class=\"pb-title\">Hera Reveal · Justos</div><div class=\"pb-sub\">1 linha por conversa · WhatsApp (Justina + humano) · 4 extrações</div></div>'+\n        '<div style=\"display:flex;gap:8px;align-items:center\"><span class=\"pb-scn\">Cenário: '+esc(scnLbl)+'</span><span class=\"pb-live\"><span class=\"dot\"></span>'+(loading?'carregando…':num(rows.length)+' de '+num(all.length)+' analisadas')+'</span></div>'+\n      '</div>'+\n      '<div class=\"pb-params\">'+\n        pbField('premio','Ticket médio anual (R$)',P.premio)+\n        pbField('custoHumano','Custo humano / transbordo (R$)',P.custoHumano)+\n        pbField('custoJustina','Custo Justina / conversa (R$)',P.custoJustina)+\n        pbField('containment','Contenção esperada (%)',Math.round(P.containment*100),'pct')+\n        pbField('pctThreshold','Alerta custo × ticket (%)',(P.pctThreshold*100).toString().replace('.',','),'pct')+\n        '<div class=\"pb-note\">Editáveis — recalculam todas as abas. R$ = <b>estimativa</b> (ver Aba 10, premissas e cenários). Contagens e tags = <b>fato</b>.</div>'+\n      '</div>'+\n    '</div>';\n\n    const nav='<div class=\"nav\">'+TABS.map(t=>'<button class=\"nav-tab'+(t[0]===active?' on':'')+'\" data-tab=\"'+t[0]+'\"><span class=\"nt-n\">'+t[2]+'</span>'+esc(t[1])+'</button>').join('')+'</div>';\n\n    const baseBag = { rows:rows, acts:acts, totalAll:all.length||rows.length, premio:P.premio, custoHumano:P.custoHumano, custoJustina:P.custoJustina, containment:P.containment, pctThreshold:P.pctThreshold, accent:accent, neg:neg, ink:ink };\n    const bagFor = id => {\n      if(id==='premissas') return Object.assign({}, baseBag, { cancelRates:ep.raw.cancelRates, convRates:ep.raw.convRates, scenario:ep.scenario });\n      if(id==='ficha') return Object.assign({}, baseBag, { selected:{}, mode:'tab', zendeskSub:zsub });\n      return Object.assign({}, baseBag, { cancelRates:ep.effCancel, convProb:ep.effConv, scenario:ep.scenario });\n    };\n\n    let content;\n    if(loading) content='<div class=\"ph-wrap\"><div class=\"jr-empty\" style=\"border:none\">Carregando conversas analisadas…</div></div>';\n    else if(TAB_UC[active]) content=d2.render(TAB_UC[active], bagFor(active), {key:active, style:'height:auto;min-height:100%', onDrill:(t)=>routeDrill(d2,t), onStatusChange:(p)=>applyStatus(d2,p), onPremiseChange:(p)=>applyPremise(d2,p), onParam:(p)=>applyParam(d2,p)});\n    else content=placeholder(active);\n\n    let drawer='';\n    if(d2.state.fichaSel){\n      const backBtn = (d2.state.drill||d2.state.fieldProfile) ? '<button class=\"dw-back\" title=\"Voltar\">←</button>' : '';\n      const fbag = Object.assign({}, baseBag, { selected:d2.state.fichaSel, mode:'drawer', zendeskSub:zsub });\n      drawer='<div class=\"dw-scrim\"></div><div class=\"dw\"><div class=\"dw-bar\">'+backBtn+'<button class=\"dw-close\" title=\"Fechar\">✕</button><div class=\"dw-bar-title\">Ficha / Conversa</div></div><div class=\"dw-scroll dw-fichawrap\">'+d2.render(TAB_UC.ficha, fbag, {key:'fichaDrawer', style:'height:auto', onDrill:(t)=>routeDrill(d2,t)})+'</div></div>';\n    } else if(d2.state.drill){\n      const backBtn = d2.state.fieldProfile ? '<button class=\"dw-back\" title=\"Voltar ao campo\">←</button>' : '';\n      drawer='<div class=\"dw-scrim\"></div><div class=\"dw\"><div class=\"dw-bar\">'+backBtn+'<button class=\"dw-close\" title=\"Fechar\">✕</button><div class=\"dw-bar-title\">Conversas</div></div><div class=\"dw-scroll\">'+renderList(d2.state.drill, d2.state.listPage||0)+'</div></div>';\n    } else if(d2.state.fieldProfile){\n      const fp=d2.state.fieldProfile;\n      drawer='<div class=\"dw-scrim\"></div><div class=\"dw\"><div class=\"dw-bar\"><button class=\"dw-close\" title=\"Fechar\">✕</button><div class=\"dw-bar-title\">Perfil do campo</div></div><div class=\"dw-scroll\">'+renderFieldProfile(rows, fp.obj, fp.field)+'</div></div>';\n    }\n\n    if(d2.state.guide){ drawer='<div class=\"dw-scrim\"></div><div class=\"dw\"><div class=\"dw-bar\"><button class=\"dw-close\" title=\"Fechar\">✕</button><div class=\"dw-bar-title\">Como ler esta aba</div></div><div class=\"dw-scroll\">'+renderGuide(d2.state.guide)+'</div></div>'; }\n    const _tm=TAB_META[active]||['',''];\n    const _tn=(TABS.find(x=>x[0]===active)||[])[2]||'';\n    const tabhdr='<div class=\"tabhdr\"><div class=\"tabhdr-q\"><span class=\"tabhdr-n\">Aba '+esc(_tn)+'</span><span class=\"tabhdr-qt\">'+esc(_tm[1])+'</span></div><button class=\"tabhdr-help\" data-guide=\"1\">Como ler esta aba</button></div>';\n    return '<div class=\"shell\" style=\"--ink:'+ink+';--accent:'+accent+';--neg:'+neg+'\">'+pb+nav+tabhdr+'<div class=\"content\">'+content+'</div>'+drawer+'</div>';\n  },\n  mounted(d2){\n    const SLUG='babi-hera';\n    const fetchAll=async(ref,filter)=>{ if(!ref) return null; try{ const url='https://'+SLUG+'.data2apis.com/dataset/'+ref; const size=1000; let out=[],skip=0; for(let i=0;i<60;i++){ const query=Object.assign({},filter||{},{$limit:size,$skip:skip}); const res=await fetch(url,{method:'POST',credentials:'include',headers:{'content-type':'application/json','x-data2-dataset-reference':ref},body:JSON.stringify({$method:'find',params:{query}})}); if(!res.ok){ d2.log&&d2.log('[shell] '+ref+' HTTP '+res.status); break; } const data=await res.json(); const page=Array.isArray(data)?data:(data.data||data.records||data.results||(data.value&&data.value.data)||[]); if(!Array.isArray(page)||!page.length) break; out=out.concat(page); if(page.length<size) break; skip+=size; } return out; }catch(e){ d2.log&&d2.log('[shell] fetch err',e&&e.message); return null; } };\n    (async()=>{ const rows=await fetchAll('GVqgvzyYNQVEE2B_KNttC',null); if(rows&&rows.length) d2.state.allRows=rows; const acts=await fetchAll('poc-justus-actionsDataSet',null); if(acts) d2.state.acts=acts; })();\n    try{ const store=d2.store&&d2.store(PREM_STORE); if(store&&store.get){ const cr=store.get('cancelRates'), co=store.get('convRates'), sc=store.get('scenario'); if(cr||co||sc){ d2.state.prem={ cancelRates:cr||DEF_PREM.cancelRates, convRates:co||DEF_PREM.convRates, scenario:(sc&&SCEN_F[sc])?sc:'base' }; } } }catch(e){}\n    if(!d2.state.prem) d2.state.prem=DEF_PREM;\n    d2.on('.nav-tab','click',(e,el)=>{ d2.state.activeTab=el.dataset.tab; d2.state.drill=null; d2.state.fichaSel=null; d2.state.guide=null; d2.state.fieldProfile=null; });\n    d2.on('.tabhdr-help','click',()=>{ d2.state.guide=d2.state.activeTab||'exec'; d2.state.drill=null; d2.state.fichaSel=null; d2.state.fieldProfile=null; });\n    d2.on('.pb-in','change',(e,el)=>{ const p={...(d2.state.params||{})}; const raw=String(el.value).replace(',','.'); let v=parseFloat(raw); if(isNaN(v)){ p[el.dataset.k]=undefined; } else { if(el.dataset.suffix==='pct') v=v/100; p[el.dataset.k]=v; } d2.state.params=p; });\n    d2.on('.dw-scrim','click',()=>{ d2.state.fichaSel=null; d2.state.drill=null; d2.state.guide=null; d2.state.fieldProfile=null; });\n    d2.on('.dw-close','click',()=>{ d2.state.fichaSel=null; d2.state.drill=null; d2.state.guide=null; d2.state.fieldProfile=null; });\n    d2.on('.dw-back','click',()=>{ if(d2.state.fichaSel){ d2.state.fichaSel=null; } else if(d2.state.drill){ d2.state.drill=null; } });\n    d2.on('.dw-row','click',(e,el)=>{ const t=el.getAttribute('data-drill'); if(t) routeDrill(d2,t); });\n    d2.on('.fp-val','click',(e,el)=>{ const t=el.getAttribute('data-drill'); if(t) routeDrill(d2,t); });\n    d2.on('.dw-pg','click',(e,el)=>{ if(el.hasAttribute('disabled')) return; const dir=el.getAttribute('data-dir'); const cur=d2.state.listPage||0; d2.state.listPage = dir==='next'?cur+1:Math.max(0,cur-1); });\n    d2.on('.content','click',(e,el)=>{ let hit=null; const path=(e&&e.composedPath)?e.composedPath():[]; for(const n of path){ if(n&&n.nodeType===1&&n.getAttribute&&n.getAttribute('data-drill')){ hit=n; break; } } if(!hit&&el&&el.getAttribute&&el.getAttribute('data-drill')) hit=el; if(hit){ const t=hit.getAttribute('data-drill'); if(t) routeDrill(d2,t); } });\n  }\n};\n\nfunction applyStatus(d2, p){\n  if(!p) return;\n  const tid=p.ticket_id, phone=p.phone, status=p.status;\n  const acts=(d2.state.acts||[]).slice();\n  let found=false;\n  for(let i=0;i<acts.length;i++){ if(acts[i]&&(tid!=null&&acts[i].ticket_id===tid)){ acts[i]=Object.assign({},acts[i],{status:status,phone:phone,reviewed_at:new Date().toISOString()}); found=true; break; } }\n  if(!found) acts.push({ticket_id:tid,phone:phone,status:status,reviewed_at:new Date().toISOString()});\n  d2.state.acts=acts;\n  try{ const ads=d2.data&&d2.data('actionsDataset'); if(ads){ const existing=(ads.records&&ads.records()||[]).find(r=>r&&r.ticket_id===tid); const payload={ticket_id:tid,phone:phone,status:status,reviewed_at:new Date().toISOString()}; if(existing&&ads.update) ads.update(Object.assign({},existing,payload)); else if(ads.create) ads.create(payload); } }catch(e){ d2.log&&d2.log('[shell] status write err',e&&e.message); }\n}\nfunction applyPremise(d2, p){\n  if(!p) return;\n  d2.state.prem={ cancelRates:p.cancelRates||DEF_PREM.cancelRates, convRates:p.convRates||DEF_PREM.convRates, scenario:(p.scenario&&SCEN_F[p.scenario])?p.scenario:'base' };\n}\nfunction applyParam(d2, p){\n  if(!p || !p.key) return;\n  const cur = d2.state.prem || DEF_PREM;\n  const next = { cancelRates:cur.cancelRates||DEF_PREM.cancelRates, convRates:cur.convRates||DEF_PREM.convRates, scenario:cur.scenario||'base' };\n  if(p.key==='scenario'){ next.scenario=(p.value&&SCEN_F[p.value])?p.value:'base'; }\n  else if(p.key==='cancelRates'){ next.cancelRates=p.value||next.cancelRates; }\n  else if(p.key==='convRates'){ next.convRates=p.value||next.convRates; }\n  d2.state.prem=next;\n  try{ const store=d2.store&&d2.store(PREM_STORE); if(store&&store.set){ store.set('cancelRates',next.cancelRates); store.set('convRates',next.convRates); store.set('scenario',next.scenario); } }catch(e){}\n}","at":"2026-07-23T00:41:47.828Z"}}},{"_id":"5ed9bed7b9e0891ce913e884","component":"data2-core-types@Component","params":{"package":"data2-core","component":"DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5f472ae463c680de4ff296e9","component":"data2-core-types@Component","params":{"package":"data2-core","component":"Data2TableDataSource","extends":"data2-core@DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}}]}},{"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}}},"reference":"Data2BuilderAuthentication","updatedAt":"2025-10-28T02:48:49.233Z"},{"_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":"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":"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"},{"_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":"6a5feca9c19be2bc56e4e127","component":"data2-core-primitives@Artboard","system":"65901b6eeafc5e0931497047","displayName":"Justos Reveal — Cockpit (v2) NÃO MEXER","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Justos Reveal — Cockpit (v2) NÃO MEXER"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1366,"height":768}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"alNioh3bQ6tK_l1x1t_mp"},{"_id":"3af1f0f190a47a1c69e315aa","parent":"6a5feca9c19be2bc56e4e127","component":"babi-hera@justos-reveal-shell","system":"65901b6eeafc5e0931497047","displayName":"justos-reveal-shell","params":{"dataset":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"GVqgvzyYNQVEE2B_KNttC"}},"actionsDataset":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"poc-justus-actionsDataSet"}},"premioAnual":2250,"custoHumano":15,"custoJustina":3,"containment":0.85,"pctThreshold":0.05,"accent":{"component":"data2-core-types@Color","params":{"rgba":"#82D8D0"}},"negativeAccent":{"component":"data2-core-types@Color","params":{"rgba":"#A22560"}},"brandInk":{"component":"data2-core-types@Color","params":{"rgba":"#051216"}},"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":1366,"height":768}}}},"reference":"bM_MPf-U3D5Lj0GFbOdIm"}]}},{"_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":"6a57ab04fd3d6da490af7210","displayName":"Reveal App (next)","reference":"SFQKFrrsHTeyHLv-dGynQ","params":{"responseHeaders":{"X-Frame-Options":{"params":{"content":""},"component":"data2-core-primitives@String"},"Content-Security-Policy":{"params":{"content":""},"component":"data2-core-primitives@String"},"X-XSS-Protection":{"params":{"content":""},"component":"data2-core-primitives@String"}},"icon":{"component":"data2-core-types@FileComponentUrlReference","params":{"reference":"dKK9jKiPlvxe9FmlD2tRY"}},"domain":{"component":"data2-core-primitives@String","params":{"content":"app-reveal"}},"entryPoint":{"params":{"component":"data2-core-primitives@Artboard","reference":"alNioh3bQ6tK_l1x1t_mp"},"component":"data2-core-types@ComponentInstanceReference"}},"system":"65901b6eeafc5e0931497047","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a47d5e41d5442d873f6e078","component":"data2-core@DataSet","system":"65901b6eeafc5e0931497047","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"poc-justus-actions"}}},"reference":"poc-justus-actionsDataSet"},{"_id":"6a47cd08835e3d7a6c427b38","component":"data2-core@DataSet","system":"65901b6eeafc5e0931497047","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"T3hVXuepWkPKFfq2dbioy"}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":100}}},"filter":{"summarized":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"contact_analyzed":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"cx_analyzed":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"bot_analyzed":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}},"aggregations":[{"query":[{"#match":{"bot_tags.Transbordo":"Sim"}},{"#group":{"_id":"$bot_tags.Ação do Atendente Humano","n":{"#sum":1}}},{"#sort":{"n":-1}}]}]},"reference":"GVqgvzyYNQVEE2B_KNttC"},{"_id":"6a47d5e3d135f62a64eea780","component":"data2-core@Data2TableDataSource","system":"65901b6eeafc5e0931497047","params":{"table":"poc-justus-actions","schema":[{"component":"data2-core-types@Field","params":{"key":"ticket_id","title":"Ticket ID","component":"data2-core-primitives@Number","required":true}},{"component":"data2-core-types@Field","params":{"key":"status","title":"Status","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"responsavel","title":"Responsável","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"notes","title":"Notes","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"reviewed_at","title":"Reviewed At","component":"data2-core-primitives@String"}}]},"reference":"poc-justus-actions"},{"_id":"6a343b282c74b22971a5dddf","component":"data2-core@Data2TableDataSource","system":"65901b6eeafc5e0931497047","params":{"table":"T3hVXuepWkPKFfq2dbioy","super":{},"schema":[{"component":"data2-core-types@Field","params":{"component":"data2-core-primitives@Number","title":"ticket_id","key":"ticket_id"}},{"component":"data2-core-types@Field","params":{"title":"channel","key":"channel","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"ticket_date","key":"ticket_date","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"conversation","key":"conversation","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"total_time","key":"total_time","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"contact","key":"contact","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"contact_type","key":"contact_type","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"phone","key":"phone","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"analyst","key":"analyst","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"team","key":"team","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"contact_reason","key":"contact_reason","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"contact_reason_detail","key":"contact_reason_detail","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"keywords","key":"keywords","component":"data2-core-primitives@String","list":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}},{"component":"data2-core-types@Field","params":{"title":"summary","key":"summary","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"title":"avr_sentiment","key":"avr_sentiment","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"title":"summarized","key":"summarized","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"title":"traits","key":"traits","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"title":"contact_analyzed","key":"contact_analyzed","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"title":"summary_tokens","key":"summary_tokens","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"title":"traits_tokens","key":"traits_tokens","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"title":"cx_tags","key":"cx_tags","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"title":"cx_tags_tokens","key":"cx_tags_tokens","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"title":"cx_analyzed","key":"cx_analyzed","component":"data2-core-primitives@Boolean"}},{"component":"data2-core-types@Field","params":{"title":"bot_tags","key":"bot_tags","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"title":"bot_tags_tokens","key":"bot_tags_tokens","component":"data2-core-primitives@Number"}},{"component":"data2-core-types@Field","params":{"title":"bot_analyzed","key":"bot_analyzed","component":"data2-core-primitives@Boolean"}}]},"reference":"T3hVXuepWkPKFfq2dbioy"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}