{"context":{"domain":"tm-logistica-poc"},"layers":{"ApplicationLayer":{"reference":"ApplicationLayer","availableInstances":[{"reference":"ComponentsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"SystemsDataSet","params":{"filter":{"domain":"data2"},"pagination":{"size":1},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSource"}}}},{"reference":"ExternalComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"SystemsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"5e3b796d6228227ca637d0f4","name":"data2","domain":"data2","organization":"62292184611f480b3191c37c","visibility":"public","updatedAt":"2026-07-27T14:19:36.810Z"}]}},{"reference":"OrganizationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"DataComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"OneFileComponentInstancesDataSet","params":{"pagination":{"size":1},"master":{"dataset":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSet"}},"localField":"system","masterField":"_id"},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"FileComponentInstancesDataSource"}}}},{"reference":"ApplicationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ServiceComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@Data2TableDataSource","reference":"FileComponentInstancesDataSource","params":{"table":"fileComponentInstances","schema":[{"component":"data2-core-types@Field","params":{"key":"component","title":"Component","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"system","title":"System","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"displayName","title":"Display Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"params","title":"Params","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"reference","title":"Reference","component":"data2-core-primitives@String"}}]}},{"component":"data2-core@MemoryDataSource","reference":"EmptyDataSource","params":{"initialData":[]}},{"reference":"ComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"UserComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"DataComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ServiceComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ExternalComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ApplicationsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}}],"processesParams":{}},"HostApplicationLayer":{"reference":"HostApplicationLayer","availableInstances":[{"_id":"5f15ff190528b92601890f71","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"SystemsTableDataSource"}},"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"domain"}}},"pk":"_id","fields":[{"component":"data2-core-types@FieldReference","params":{"key":"_id"}},{"component":"data2-core-types@FieldReference","params":{"key":"name"}},{"component":"data2-core-types@FieldReference","params":{"key":"domain"}},{"component":"data2-core-types@FieldReference","params":{"key":"visibility"}},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization._id"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.name"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.billingStatus"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.publicTrial.active"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"settings.defaultAccessPolicy"}}},"break":true}],"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"staticPagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"policies":[{"component":"data2-core-auth@Policy","params":{"allow":{"params":{"actions":[{"params":{"components":[{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"_id"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"domain"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"}]},"component":"data2-core-logical-operators@Or"}]},"component":"data2-core-flow@Series"}}}]},"reference":"SystemsDataSet","updatedAt":"2026-08-07T21:51:24.037Z","createdAt":"2020-07-20T20:31:21.838Z"},{"_id":"5f1601ce0528b92601890f7c","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":1000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"sort":{"params.package":1,"params.component":1},"pk":"_id","autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"staticFilter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}},"filter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}}},"reference":"ComponentsDataSet","updatedAt":"2025-11-05T19:37:01.935Z","createdAt":"2020-07-20T20:42:54.898Z"},{"_id":"5f9041dbc8da12be8b94aea4","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":2000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"UserComponentsDataSet","updatedAt":"2025-11-06T21:06:58.095Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"65d8c4fabc9dbb8f94de8d53","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ExternalComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ExternalComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:23.742Z","createdAt":"2024-02-23T16:17:01.816Z"},{"reference":"SystemsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a8c48a1e9d7f931a6fd649e","name":"TM Logistica","domain":"tm-logistica-poc","visibility":"private","updatedAt":"2026-08-24T13:35:29.471Z","createdAt":"2026-08-24T13:35:29.471Z"}]}},{"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":"6a8f51d15633ff3659f77f9c","component":"data2-core-types@Component","system":"6a8c48a1e9d7f931a6fd649e","params":{"extends":"data2-core-primitives@Block","component":"prazoeprova","package":"tm-logistica-poc","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"const SIM_BASE = 19 * 60 + 40;\nconst META = 99.6;\n\nconst REGRAS = {\n  R1: 'Divergencia TRACKen x Marketplace',\n  R2: 'Hora declarada dentro do prazo, registro depois',\n  R3: 'Salto de status',\n  R4: 'Rajada no mesmo minuto',\n  R5: 'Recebedor generico ou ausente',\n  R7: 'Retencao de custodia',\n  R8: 'Tentativas incoerentes'\n};\n\nfunction hhmm(m) {\n  const x = ((m % 1440) + 1440) % 1440;\n  const h = Math.floor(x / 60), mi = x % 60;\n  return String(h).padStart(2, '0') + ':' + String(mi).padStart(2, '0');\n}\nfunction dur(m) {\n  const a = Math.abs(m);\n  const h = Math.floor(a / 60), mi = a % 60;\n  return h > 0 ? h + 'h' + String(mi).padStart(2, '0') : mi + ' min';\n}\nfunction diaLabel(off) {\n  if (off === 0) return 'hoje';\n  if (off === -1) return 'ontem';\n  return 'ha ' + Math.abs(off) + ' dias';\n}\nfunction esc(s) {\n  return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\nfunction temaCls(d2) { return d2.state.tema === 'light' ? 'light' : ''; }\nfunction temaInicial() {\n  try {\n    const salvo = window.localStorage.getItem('pp-tema');\n    if (salvo === 'light' || salvo === 'dark') return salvo;\n  } catch (e) { /* private mode / storage bloqueado */ }\n  try {\n    if (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) return 'light';\n  } catch (e) { /* sem matchMedia */ }\n  return 'dark';\n}\nfunction salvaTema(t) {\n  try { window.localStorage.setItem('pp-tema', t); } catch (e) { /* nao persiste, tudo bem */ }\n}\nfunction pct(n, d) { return d > 0 ? (n / d) * 100 : 0; }\nfunction fmtPct(v, casas) { return v.toFixed(casas == null ? 2 : casas).replace('.', ',') + '%'; }\nfunction fmtInt(v) { return Number(v || 0).toLocaleString('pt-BR'); }\nfunction fmtBRL(v) {\n  return 'R$ ' + Number(v || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });\n}\n\nfunction agoraMin(d2) {\n  if (d2.state.horaReal) {\n    const n = new Date();\n    return n.getHours() * 60 + n.getMinutes();\n  }\n  const decorrido = Math.floor((Date.now() - (d2.state.t0 || Date.now())) / 60000);\n  return SIM_BASE + decorrido;\n}\nfunction prazoMin(p) { return (p.prazo_dia || 0) * 1440 + (p.prazo_hora || 21) * 60; }\nfunction aberto(p) { return !(p.entregue_min >= 0); }\nfunction estado(p, agora) {\n  if (!aberto(p)) {\n    return p.entregue_min <= (p.prazo_hora || 21) * 60 ? 'entregue_no_prazo' : 'entregue_fora';\n  }\n  const r = prazoMin(p) - agora;\n  if (r < 0) return 'estourado';\n  if (r <= 30) return 'vai_estourar';\n  if (r <= 120) return 'em_risco';\n  return 'no_prazo';\n}\nconst ESTADO_LABEL = {\n  no_prazo: 'No prazo', em_risco: 'Em risco', vai_estourar: 'Vai estourar',\n  estourado: 'Estourado', entregue_no_prazo: 'Entregue no prazo', entregue_fora: 'Entregue fora'\n};\n\nfunction dados(d2) { return d2.state.dados || {}; }\nfunction lista(d2, k) { return (dados(d2)[k]) || []; }\n\nexport default {\n  css: `\n:host, .app { display:block }\n.app{\n  --bg:#0d1218; --panel:#151d26; --panel2:#1b2531; --line:#26333f; --line2:#2f3f4d;\n  --ink:#e8eef5; --ink2:#9fb0c0; --ink3:#6b7d8d;\n  --ok:#3ecf8e; --ok-bg:#122a22;\n  --warn:#f0b429; --warn-bg:#2b2313;\n  --crit:#f2604c; --crit-bg:#2c1a18;\n  --info:#5aa2ff; --info-bg:#14202f;\n  --scrim:rgba(5,8,11,.72); --shadow:none;\n  position:relative; width:100%; height:100%; background:var(--bg); color:var(--ink);\n  font-family:\"IBM Plex Sans\",-apple-system,\"Segoe UI\",Roboto,sans-serif;\n  font-size:14px; display:flex; flex-direction:column; overflow:hidden;\n}\n.app.light{\n  --bg:#eef1f5; --panel:#ffffff; --panel2:#f4f7fa; --line:#dfe5ec; --line2:#c6d1dd;\n  --ink:#111a23; --ink2:#48596a; --ink3:#68798a;\n  --ok:#0c7048; --ok-bg:#e3f4ec;\n  --warn:#8d5c05; --warn-bg:#fbf0d8;\n  --crit:#b53324; --crit-bg:#fbe5e1;\n  --info:#2558bd; --info-bg:#e5ecfb;\n  --scrim:rgba(17,26,35,.42); --shadow:0 1px 2px rgba(17,26,35,.05);\n}\n.app.light .panel,.app.light .counter{box-shadow:var(--shadow)}\n.app.light .nav button.on{background:var(--info-bg);border-color:var(--info);color:var(--info)}\n.app.light .seg button.on{background:var(--info-bg);color:var(--info)}\n.app.light .btn:hover{color:var(--info)}\n.app *{box-sizing:border-box}\n.mono{font-family:\"IBM Plex Mono\",ui-monospace,Menlo,monospace;font-variant-numeric:tabular-nums}\n\n/* topo */\n.top{display:flex;align-items:center;gap:20px;padding:12px 22px;border-bottom:1px solid var(--line);background:var(--panel);flex:none}\n.brand{display:flex;flex-direction:column;gap:2px;min-width:170px}\n.brand b{font-size:15px;letter-spacing:-.2px}\n.brand span{font-size:10.5px;color:var(--ink3);letter-spacing:.14em;text-transform:uppercase;font-family:\"IBM Plex Mono\",monospace}\n.nav{display:flex;gap:4px;flex:1}\n.nav button{\n  background:transparent;border:1px solid transparent;color:var(--ink2);padding:8px 14px;border-radius:4px;\n  font:inherit;font-size:13px;cursor:pointer;white-space:nowrap\n}\n.nav button:hover{background:var(--panel2);color:var(--ink)}\n.nav button.on{background:var(--info-bg);border-color:var(--info);color:#cfe2ff}\n.nav button:focus-visible{outline:2px solid var(--info);outline-offset:2px}\n.clock{display:flex;align-items:center;gap:12px}\n.clock .h{font-size:26px;font-weight:700;letter-spacing:-.5px}\n.clock .meta{display:flex;flex-direction:column;gap:2px;font-size:10.5px;color:var(--ink3);font-family:\"IBM Plex Mono\",monospace}\n.simbtn{background:var(--warn-bg);border:1px solid var(--warn);color:var(--warn);border-radius:3px;padding:3px 7px;font-size:10px;\n  letter-spacing:.1em;text-transform:uppercase;cursor:pointer;font-family:\"IBM Plex Mono\",monospace}\n.temabtn{background:var(--panel2);border:1px solid var(--line2);color:var(--ink2);border-radius:3px;width:28px;height:26px;\n  display:grid;place-items:center;font-size:13px;cursor:pointer;line-height:1;padding:0}\n.temabtn:hover{border-color:var(--info);color:var(--info)}\n.temabtn:focus-visible{outline:2px solid var(--info);outline-offset:2px}\n\n/* corpo */\n.body{flex:1;overflow:auto;padding:20px 22px 40px}\n.h2{font-size:17px;font-weight:700;margin:0 0 3px}\n.sub{font-size:12.5px;color:var(--ink3);margin:0 0 16px}\n.grid{display:grid;gap:14px}\n\n/* cards contador */\n.counters{grid-template-columns:repeat(4,1fr)}\n.counter{background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:16px 18px;border-left-width:3px}\n.counter .n{font-size:42px;font-weight:800;line-height:1;letter-spacing:-1.5px}\n.counter .l{font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink2);margin-top:8px;font-family:\"IBM Plex Mono\",monospace}\n.counter .x{font-size:11.5px;color:var(--ink3);margin-top:5px}\n.c-ok{border-left-color:var(--ok)} .c-ok .n{color:var(--ok)}\n.c-warn{border-left-color:var(--warn)} .c-warn .n{color:var(--warn)}\n.c-crit{border-left-color:var(--crit)} .c-crit .n{color:var(--crit)}\n.c-info{border-left-color:var(--info)} .c-info .n{color:var(--info)}\n\n.panel{background:var(--panel);border:1px solid var(--line);border-radius:6px;overflow:hidden}\n.panel h3{margin:0;padding:12px 16px;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink2);\n  border-bottom:1px solid var(--line);font-family:\"IBM Plex Mono\",monospace;font-weight:600;display:flex;justify-content:space-between;align-items:center}\n.panel h3 em{font-style:normal;color:var(--ink3);letter-spacing:0;text-transform:none;font-size:11.5px;font-family:\"IBM Plex Sans\",sans-serif}\n\ntable{width:100%;border-collapse:collapse}\nth{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink3);text-align:left;padding:9px 14px;\n  border-bottom:1px solid var(--line);font-weight:600;font-family:\"IBM Plex Mono\",monospace;white-space:nowrap}\ntd{padding:10px 14px;border-bottom:1px solid var(--line);font-size:13px;vertical-align:middle}\ntr:last-child td{border-bottom:0}\ntbody tr.sel:hover{background:var(--panel2);cursor:pointer}\n.num{text-align:right;font-family:\"IBM Plex Mono\",monospace;font-variant-numeric:tabular-nums}\n.tiny{font-size:11px;color:var(--ink3)}\n.strong{font-weight:600}\n\n.chip{display:inline-block;font-size:10px;letter-spacing:.09em;text-transform:uppercase;padding:3px 7px;border-radius:3px;\n  font-family:\"IBM Plex Mono\",monospace;font-weight:600;white-space:nowrap}\n.ch-ok{background:var(--ok-bg);color:var(--ok);border:1px solid var(--ok)}\n.ch-warn{background:var(--warn-bg);color:var(--warn);border:1px solid var(--warn)}\n.ch-crit{background:var(--crit-bg);color:var(--crit);border:1px solid var(--crit)}\n.ch-info{background:var(--info-bg);color:var(--info);border:1px solid var(--info)}\n.ch-mute{background:var(--panel2);color:var(--ink3);border:1px solid var(--line2)}\n\n.toolbar{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}\n.seg{display:inline-flex;border:1px solid var(--line2);border-radius:4px;overflow:hidden}\n.seg button{background:transparent;border:0;color:var(--ink2);padding:6px 13px;font:inherit;font-size:12.5px;cursor:pointer}\n.seg button.on{background:var(--info-bg);color:#cfe2ff}\n.seg button:focus-visible{outline:2px solid var(--info);outline-offset:-2px}\n.spacer{flex:1}\n\n.btn{background:var(--panel2);border:1px solid var(--line2);color:var(--ink);padding:6px 12px;border-radius:4px;\n  font:inherit;font-size:12.5px;cursor:pointer}\n.btn:hover{border-color:var(--info);color:#cfe2ff}\n.btn:focus-visible{outline:2px solid var(--info);outline-offset:2px}\n.btn-crit{background:var(--crit-bg);border-color:var(--crit);color:var(--crit)}\n.btn-ok{background:var(--ok-bg);border-color:var(--ok);color:var(--ok)}\n\n/* barras */\n.bars{display:flex;align-items:flex-end;gap:3px;height:150px;padding:14px 16px}\n.bar{flex:1;position:relative;background:var(--ok);border-radius:2px 2px 0 0;min-height:2px}\n.bar.miss{background:var(--crit)}\n.barwrap{flex:1;height:100%;display:flex;align-items:flex-end}\n.metaline{position:relative;height:0;border-top:1px dashed var(--warn);margin:0 16px}\n.metaline span{position:absolute;right:0;top:-16px;font-size:10px;color:var(--warn);font-family:\"IBM Plex Mono\",monospace}\n\n/* drawer */\n.drawer{position:absolute;inset:0;display:flex;justify-content:flex-end;z-index:20}\n.drawer .backdrop{position:absolute;inset:0;background:var(--scrim)}\n.drawer .sheet{position:relative;z-index:1}\n.drawer .sheet{width:min(620px,92%);background:var(--panel);border-left:1px solid var(--line2);height:100%;overflow:auto;padding:22px 24px}\n.drawer h4{margin:0 0 4px;font-size:17px}\n.drawer .close{position:absolute;top:14px;right:18px;background:transparent;border:0;color:var(--ink2);font-size:22px;cursor:pointer;line-height:1}\n.kv{display:grid;grid-template-columns:150px 1fr;gap:7px 14px;font-size:13px;margin:16px 0}\n.kv dt{color:var(--ink3);font-size:11px;letter-spacing:.09em;text-transform:uppercase;font-family:\"IBM Plex Mono\",monospace;padding-top:2px}\n.kv dd{margin:0}\n\n.tl{list-style:none;margin:14px 0 0;padding:0}\n.tl li{position:relative;padding:0 0 16px 22px;border-left:1px solid var(--line2)}\n.tl li:last-child{border-left-color:transparent;padding-bottom:0}\n.tl li::before{content:'';position:absolute;left:-5px;top:4px;width:9px;height:9px;border-radius:50%;background:var(--ink3);border:2px solid var(--panel)}\n.tl li.flag::before{background:var(--crit)}\n.tl .t{font-size:12.5px;font-weight:600}\n.tl .d{font-size:11.5px;color:var(--ink3);margin-top:2px}\n.tl .lag{color:var(--crit);font-weight:600}\n\n.note{background:var(--panel2);border:1px solid var(--line2);border-left:3px solid var(--info);border-radius:4px;padding:12px 14px;font-size:12.5px;color:var(--ink2);line-height:1.55}\n.note b{color:var(--ink)}\n.origem{font-size:11px;color:var(--ink3);font-family:\"IBM Plex Mono\",monospace;margin-top:14px;padding-top:10px;border-top:1px solid var(--line)}\n.center{display:flex;align-items:center;justify-content:center;height:100%;color:var(--ink3);font-size:14px}\n.err{color:var(--crit);max-width:640px;line-height:1.6}\n`,\n\n  render(d2) {\n    if (d2.state.erro) {\n      return `<div class=\"app ${temaCls(d2)}\"><div class=\"center\"><div class=\"err\"><b>Nao consegui carregar os dados.</b><br>${esc(d2.state.erro)}</div></div></div>`;\n    }\n    if (!d2.state.ready) {\n      return `<div class=\"app ${temaCls(d2)}\"><div class=\"center\">Carregando dados da operacao...</div></div>`;\n    }\n    const view = d2.state.view || 'painel';\n    const agora = agoraMin(d2);\n    const views = {\n      painel: viewPainel, scorecard: viewScorecard, casos: viewCasos,\n      fechamento: viewFechamento, comissao: viewComissao\n    };\n    const corpo = (views[view] || viewPainel)(d2, agora);\n    return `<div class=\"app ${temaCls(d2)}\">\n      ${topo(d2, agora, view)}\n      <div class=\"body\">${corpo}</div>\n      ${drawer(d2, agora)}\n    </div>`;\n  },\n\n  mounted(d2) {\n    d2.state.t0 = Date.now();\n    d2.state.tema = temaInicial();\n    d2.state.view = 'painel';\n    d2.state.periodo = 'hoje';\n    d2.state.agrupar = 'agente';\n    d2.state.filtroSev = 'todas';\n\n    d2.rush('api-dados').invoke({})\n      .then(res => {\n        const payload = (res && res.data) ? res.data : res;\n        d2.state.dados = payload || {};\n        d2.state.ready = true;\n      })\n      .catch(e => { d2.state.erro = (e && e.message) ? e.message : String(e); });\n\n    const t = setInterval(() => { d2.state.tick = (d2.state.tick || 0) + 1; }, 20000);\n    d2.onUnmount(() => clearInterval(t));\n\n    d2.on('[data-view]', 'click', e => {\n      const el = e.target.closest('[data-view]');\n      if (el) d2.state.view = el.dataset.view;\n    });\n    d2.on('[data-periodo]', 'click', e => {\n      const el = e.target.closest('[data-periodo]');\n      if (el) d2.state.periodo = el.dataset.periodo;\n    });\n    d2.on('[data-agrupar]', 'click', e => {\n      const el = e.target.closest('[data-agrupar]');\n      if (el) d2.state.agrupar = el.dataset.agrupar;\n    });\n    d2.on('[data-sev]', 'click', e => {\n      const el = e.target.closest('[data-sev]');\n      if (el) d2.state.filtroSev = el.dataset.sev;\n    });\n    d2.on('[data-abre-agente]', 'click', e => {\n      const el = e.target.closest('[data-abre-agente]');\n      if (el) { d2.state.drawer = { tipo: 'agente', id: el.dataset.abreAgente }; }\n    });\n    d2.on('[data-abre-caso]', 'click', e => {\n      const el = e.target.closest('[data-abre-caso]');\n      if (el) { d2.state.drawer = { tipo: 'caso', id: el.dataset.abreCaso }; }\n    });\n    d2.on('[data-abre-pedido]', 'click', e => {\n      const el = e.target.closest('[data-abre-pedido]');\n      if (el) { d2.state.drawer = { tipo: 'pedido', id: el.dataset.abrePedido }; }\n    });\n    d2.on('[data-fecha]', 'click', () => { d2.state.drawer = null; });\n    d2.on('[data-hora-real]', 'click', () => { d2.state.horaReal = !d2.state.horaReal; });\n    d2.on('[data-tema]', 'click', () => {\n      const novo = d2.state.tema === 'light' ? 'dark' : 'light';\n      d2.state.tema = novo;\n      salvaTema(novo);\n    });\n\n    d2.on('[data-bloquear]', 'click', async e => {\n      const el = e.target.closest('[data-bloquear]');\n      if (!el) return;\n      const usuario = el.dataset.bloquear;\n      const ag = lista(d2, 'agente').find(a => a.usuario === usuario);\n      if (!ag) return;\n      const bloqueando = ag.situacao !== 'bloqueado';\n      let motivo = '';\n      if (bloqueando) {\n        motivo = await d2.dialog.prompt(\n          'Motivo do bloqueio de ' + ag.nome + ' (obrigatorio):',\n          'Reincidencia em baixa com hora retroativa'\n        );\n        if (!motivo) return;\n      } else {\n        const ok = await d2.dialog.confirm('Desbloquear ' + ag.nome + '?');\n        if (!ok) return;\n      }\n      el.disabled = true;\n      el.textContent = 'salvando...';\n      try {\n        await d2.rush('act-bloquear').invoke({\n          usuario: usuario,\n          situacao: bloqueando ? 'bloqueado' : 'ativo',\n          motivo: bloqueando ? motivo : '',\n          por: bloqueando ? 'luan.marins' : '',\n          em: bloqueando ? '0' : ''\n        });\n        const novo = await d2.rush('api-dados').invoke({});\n        d2.state.dados = (novo && novo.data) ? novo.data : novo;\n        d2.state.tick = (d2.state.tick || 0) + 1;\n      } catch (err) {\n        d2.dialog.alert('Nao consegui salvar: ' + ((err && err.message) || err));\n        d2.state.tick = (d2.state.tick || 0) + 1;\n      }\n    });\n\n    d2.on('[data-caso-situacao]', 'click', async e => {\n      const el = e.target.closest('[data-caso-situacao]');\n      if (!el) return;\n      el.disabled = true;\n      el.textContent = 'salvando...';\n      try {\n        await d2.rush('act-caso').invoke({ id: el.dataset.casoId, situacao: el.dataset.casoSituacao });\n        const novo = await d2.rush('api-dados').invoke({});\n        d2.state.dados = (novo && novo.data) ? novo.data : novo;\n        d2.state.drawer = null;\n      } catch (err) {\n        d2.dialog.alert('Nao consegui salvar: ' + ((err && err.message) || err));\n        d2.state.tick = (d2.state.tick || 0) + 1;\n      }\n    });\n  }\n};\n\n/* ---------------- topo ---------------- */\nfunction topo(d2, agora, view) {\n  const abas = [\n    ['painel', 'Painel de Risco'], ['casos', 'Casos suspeitos'], ['scorecard', 'Scorecard'],\n    ['fechamento', 'Fechamento de SLA'], ['comissao', 'Comissionamento']\n  ];\n  const nCasos = lista(d2, 'caso').filter(c => c.situacao === 'aberto').length;\n  return `<div class=\"top\">\n    <div class=\"brand\"><b>Prazo e Prova</b><span>TM Logistica</span></div>\n    <div class=\"nav\">${abas.map(([k, t]) => `\n      <button data-view=\"${k}\" class=\"${view === k ? 'on' : ''}\">${t}${k === 'casos' && nCasos ? ' (' + nCasos + ')' : ''}</button>`).join('')}\n    </div>\n    <div class=\"clock\">\n      <div class=\"meta\">\n        <span>ultima leitura ${hhmm(agora - 5)}</span>\n        <span>${d2.state.horaReal ? 'hora real' : 'cena simulada'}</span>\n      </div>\n      <div class=\"h mono\">${hhmm(agora)}</div>\n      <button class=\"simbtn\" data-hora-real>${d2.state.horaReal ? 'usar cena' : 'usar hora real'}</button>\n      <button class=\"temabtn\" data-tema title=\"${d2.state.tema === 'light' ? 'Mudar para tema escuro' : 'Mudar para tema claro'}\" aria-label=\"${d2.state.tema === 'light' ? 'Mudar para tema escuro' : 'Mudar para tema claro'}\">${d2.state.tema === 'light' ? '☽' : '☀'}</button>\n    </div>\n  </div>`;\n}\n\n/* ---------------- tela 1 ---------------- */\nfunction viewPainel(d2, agora) {\n  const peds = lista(d2, 'pedido');\n  const abertos = peds.filter(aberto);\n  const grupos = { no_prazo: [], em_risco: [], vai_estourar: [], estourado: [] };\n  abertos.forEach(p => { const e = estado(p, agora); if (grupos[e]) grupos[e].push(p); });\n\n  const kpiHoje = lista(d2, 'kpidia').find(k => k.dia_offset === 0) || {};\n  const criticos = abertos\n    .map(p => ({ p: p, r: prazoMin(p) - agora, e: estado(p, agora) }))\n    .sort((a, b) => a.r - b.r).slice(0, 12);\n\n  const porAgente = {};\n  abertos.forEach(p => {\n    const e = estado(p, agora);\n    if (e === 'estourado' || e === 'vai_estourar' || e === 'em_risco') {\n      const k = p.agente_usuario || 'sem agente';\n      if (!porAgente[k]) porAgente[k] = { nome: p.agente_nome || 'Nao manifestado', equipe: p.equipe, estourado: 0, vai: 0, risco: 0 };\n      if (e === 'estourado') porAgente[k].estourado++;\n      else if (e === 'vai_estourar') porAgente[k].vai++;\n      else porAgente[k].risco++;\n    }\n  });\n  const ranking = Object.keys(porAgente).map(k => Object.assign({ usuario: k }, porAgente[k]))\n    .sort((a, b) => (b.estourado * 100 + b.vai * 10 + b.risco) - (a.estourado * 100 + a.vai * 10 + a.risco)).slice(0, 6);\n\n  return `\n  <div class=\"grid counters\">\n    ${counter('c-ok', grupos.no_prazo.length, 'No prazo', 'mais de 2h de folga')}\n    ${counter('c-warn', grupos.em_risco.length, 'Em risco', 'menos de 2h para o corte')}\n    ${counter('c-crit', grupos.vai_estourar.length, 'Vai estourar', 'menos de 30 min')}\n    ${counter('c-crit', grupos.estourado.length, 'Estourado', 'passou do prazo, sem baixa')}\n  </div>\n\n  <div class=\"grid\" style=\"grid-template-columns:1.55fr 1fr;margin-top:14px\">\n    <div class=\"panel\">\n      <h3>Vao estourar primeiro <em>${abertos.length} pedidos em rua</em></h3>\n      <table><thead><tr>\n        <th>Restante</th><th>Remessa</th><th>Cliente</th><th>Bairro</th><th>Agente</th><th>Corte</th>\n      </tr></thead><tbody>\n      ${criticos.map(({ p, r, e }) => `\n        <tr class=\"sel\" data-abre-pedido=\"${p.cod_remessa}\" data-key=\"${p._id}\">\n          <td><span class=\"chip ${e === 'estourado' || e === 'vai_estourar' ? 'ch-crit' : e === 'em_risco' ? 'ch-warn' : 'ch-ok'}\">${r < 0 ? '-' + dur(r) : dur(r)}</span></td>\n          <td class=\"mono\">${p.cod_remessa}</td>\n          <td>${esc(p.cliente_nome)}<div class=\"tiny\">${esc(p.marketplace)}</div></td>\n          <td>${esc(p.bairro)}<div class=\"tiny\">${esc(p.regiao)}</div></td>\n          <td>${esc(p.agente_nome)}<div class=\"tiny\">${esc(p.equipe)}</div></td>\n          <td class=\"mono\">${hhmm(p.prazo_hora * 60)}${p.prazo_dia < 0 ? ' <span class=\"tiny\">' + diaLabel(p.prazo_dia) + '</span>' : ''}</td>\n        </tr>`).join('')}\n      </tbody></table>\n    </div>\n\n    <div style=\"display:flex;flex-direction:column;gap:14px\">\n      <div class=\"panel\">\n        <h3>Puxando o SLA agora</h3>\n        <table><tbody>\n        ${ranking.map(a => `\n          <tr class=\"sel\" data-abre-agente=\"${a.usuario}\" data-key=\"${a.usuario}\">\n            <td><span class=\"strong\">${esc(a.nome)}</span><div class=\"tiny\">${esc(a.equipe)}</div></td>\n            <td class=\"num\" style=\"width:120px\">\n              ${a.estourado ? '<span class=\"chip ch-crit\">' + a.estourado + ' est.</span> ' : ''}\n              ${a.vai ? '<span class=\"chip ch-crit\">' + a.vai + '</span> ' : ''}\n              ${a.risco ? '<span class=\"chip ch-warn\">' + a.risco + '</span>' : ''}\n            </td>\n          </tr>`).join('')}\n        ${ranking.length ? '' : '<tr><td class=\"tiny\">Nenhum agente em risco no momento.</td></tr>'}\n        </tbody></table>\n      </div>\n\n      <div class=\"panel\">\n        <h3>O dia ate agora</h3>\n        <table><tbody>\n          <tr><td>Pedidos recebidos</td><td class=\"num strong\">${fmtInt(kpiHoje.recebidos)}</td></tr>\n          <tr><td>Baixados</td><td class=\"num strong\">${fmtInt(kpiHoje.entregues)}</td></tr>\n          <tr><td>Fora do prazo</td><td class=\"num strong\" style=\"color:var(--crit)\">${fmtInt(kpiHoje.fora_prazo)}</td></tr>\n          <tr><td>SLA do dia</td><td class=\"num strong\" style=\"color:var(--ok)\">${fmtPct(pct(kpiHoje.no_prazo, kpiHoje.entregues))}</td></tr>\n        </tbody></table>\n      </div>\n    </div>\n  </div>\n\n  <div class=\"origem\">Status: API TRACKen (simulada), leitura ${hhmm(agora - 5)} &middot; Agente: export da Torre de Operacoes &middot; Marketplace: coluna Historico Ecommerce</div>`;\n}\nfunction counter(cls, n, label, extra) {\n  return `<div class=\"counter ${cls}\"><div class=\"n mono\">${n}</div><div class=\"l\">${label}</div><div class=\"x\">${extra}</div></div>`;\n}\n\n/* ---------------- tela 2 ---------------- */\nfunction viewScorecard(d2) {\n  const periodo = d2.state.periodo || 'hoje';\n  const agrupar = d2.state.agrupar || 'agente';\n  const linhas = lista(d2, 'agenteperiodo').filter(r => r.periodo === periodo);\n  const agentes = lista(d2, 'agente');\n  const mapa = {};\n  agentes.forEach(a => { mapa[a.usuario] = a; });\n\n  let rows;\n  if (agrupar === 'equipe') {\n    const eq = {};\n    linhas.forEach(r => {\n      const k = r.equipe || '-';\n      if (!eq[k]) eq[k] = { chave: k, nome: k, sub: '', entregas: 0, no_prazo: 0, fora_prazo: 0, casos: 0, n: 0 };\n      eq[k].entregas += r.entregas || 0; eq[k].no_prazo += r.no_prazo || 0;\n      eq[k].fora_prazo += r.fora_prazo || 0; eq[k].casos += (r.casos_alta || 0) + (r.casos_media || 0); eq[k].n++;\n    });\n    rows = Object.values(eq).map(e => Object.assign(e, { sub: e.n + ' agentes' }));\n  } else {\n    rows = linhas.map(r => ({\n      chave: r.usuario, nome: r.nome, sub: r.equipe,\n      entregas: r.entregas || 0, no_prazo: r.no_prazo || 0, fora_prazo: r.fora_prazo || 0,\n      casos: (r.casos_alta || 0) + (r.casos_media || 0),\n      situacao: (mapa[r.usuario] || {}).situacao\n    }));\n  }\n  rows.forEach(r => {\n    r.pct = pct(r.no_prazo, r.entregas);\n    r.por1k = r.entregas > 0 ? (r.casos / r.entregas) * 1000 : 0;\n  });\n  rows.sort((a, b) => a.pct - b.pct);\n\n  return `\n  <h2 class=\"h2\">Scorecard</h2>\n  <p class=\"sub\">Ordenado do pior para o melhor. O par que importa e <b>% no prazo</b> ao lado de <b>casos por mil baixas</b> — um agente pode ter prazo impecavel justamente porque limpa a propria hora.</p>\n  <div class=\"toolbar\">\n    <div class=\"seg\">\n      ${['hoje', 'semana', 'mes'].map(p => `<button data-periodo=\"${p}\" class=\"${periodo === p ? 'on' : ''}\">${p === 'mes' ? 'mes' : p}</button>`).join('')}\n    </div>\n    <div class=\"seg\">\n      ${[['agente', 'por agente'], ['equipe', 'por equipe']].map(([k, t]) => `<button data-agrupar=\"${k}\" class=\"${agrupar === k ? 'on' : ''}\">${t}</button>`).join('')}\n    </div>\n    <div class=\"spacer\"></div>\n    <span class=\"tiny\">${rows.length} linhas &middot; periodo: ${periodo}</span>\n  </div>\n  <div class=\"panel\">\n    <table><thead><tr>\n      <th>${agrupar === 'equipe' ? 'Equipe' : 'Agente'}</th><th class=\"num\">Entregas</th><th class=\"num\">% no prazo</th>\n      <th class=\"num\">Fora</th><th class=\"num\">Casos</th><th class=\"num\">Casos / 1.000</th><th>Situacao</th><th></th>\n    </tr></thead><tbody>\n    ${rows.map(r => {\n    const bad = r.pct < 99.0, mid = r.pct < 99.5;\n    return `<tr class=\"sel\" ${agrupar === 'agente' ? 'data-abre-agente=\"' + r.chave + '\"' : ''} data-key=\"${r.chave}\">\n        <td><span class=\"strong\">${esc(r.nome)}</span><div class=\"tiny\">${esc(r.sub)}</div></td>\n        <td class=\"num\">${fmtInt(r.entregas)}</td>\n        <td class=\"num strong\" style=\"color:${bad ? 'var(--crit)' : mid ? 'var(--warn)' : 'var(--ok)'}\">${fmtPct(r.pct)}</td>\n        <td class=\"num\">${fmtInt(r.fora_prazo)}</td>\n        <td class=\"num\">${r.casos || '-'}</td>\n        <td class=\"num\" style=\"color:${r.por1k >= 1 ? 'var(--crit)' : r.por1k > 0 ? 'var(--warn)' : 'var(--ink3)'}\">${r.por1k > 0 ? r.por1k.toFixed(2).replace('.', ',') : '-'}</td>\n        <td>${r.situacao === 'bloqueado' ? '<span class=\"chip ch-crit\">bloqueado</span>' : agrupar === 'agente' ? '<span class=\"chip ch-mute\">ativo</span>' : ''}</td>\n        <td>${agrupar === 'agente' ? '<button class=\"btn ' + (r.situacao === 'bloqueado' ? 'btn-ok' : 'btn-crit') + '\" data-bloquear=\"' + r.chave + '\">' + (r.situacao === 'bloqueado' ? 'Desbloquear' : 'Bloquear') + '</button>' : ''}</td>\n      </tr>`;\n  }).join('')}\n    </tbody></table>\n  </div>\n  <div class=\"origem\">Volumes: rollup por agente e periodo &middot; Situacao e bloqueio: base propria (a ordem de bloqueio nao e escrita no TRACKen)</div>`;\n}\n\n/* ---------------- tela 3 ---------------- */\nfunction viewCasos(d2) {\n  const f = d2.state.filtroSev || 'todas';\n  let casos = lista(d2, 'caso').slice();\n  if (f !== 'todas') casos = casos.filter(c => f === 'abertos' ? c.situacao === 'aberto' : c.severidade === f);\n  const ordem = { alta: 0, media: 1, baixa: 2 };\n  casos.sort((a, b) => (ordem[a.severidade] - ordem[b.severidade]) || (b.detectado_dia - a.detectado_dia));\n  const todos = lista(d2, 'caso');\n  const nAlta = todos.filter(c => c.severidade === 'alta').length;\n\n  return `\n  <h2 class=\"h2\">Casos suspeitos</h2>\n  <p class=\"sub\">${todos.length} casos no mes, ${nAlta} de severidade alta. Cada caso ja vem com a evidencia montada — pronto para confrontar o agente ou defender o seller numa mediacao.</p>\n  <div class=\"toolbar\">\n    <div class=\"seg\">\n      ${[['todas', 'todos'], ['abertos', 'abertos'], ['alta', 'alta'], ['media', 'media'], ['baixa', 'baixa']]\n      .map(([k, t]) => `<button data-sev=\"${k}\" class=\"${f === k ? 'on' : ''}\">${t}</button>`).join('')}\n    </div>\n    <div class=\"spacer\"></div><span class=\"tiny\">${casos.length} casos listados</span>\n  </div>\n  <div class=\"panel\">\n    <table><thead><tr>\n      <th>Sev.</th><th>Regra</th><th>Remessa</th><th>Agente</th><th>Cliente</th><th>Quando</th><th>Situacao</th>\n    </tr></thead><tbody>\n    ${casos.map(c => `\n      <tr class=\"sel\" data-abre-caso=\"${c._id}\" data-key=\"${c._id}\">\n        <td><span class=\"chip ${c.severidade === 'alta' ? 'ch-crit' : c.severidade === 'media' ? 'ch-warn' : 'ch-mute'}\">${c.severidade}</span></td>\n        <td><span class=\"strong\">${c.regra}</span><div class=\"tiny\">${esc(REGRAS[c.regra] || c.regra_nome)}</div></td>\n        <td class=\"mono\">${c.cod_remessa}</td>\n        <td>${esc(c.agente_nome)}<div class=\"tiny\">${esc(c.equipe)}</div></td>\n        <td>${esc(c.cliente_nome)}</td>\n        <td>${diaLabel(c.detectado_dia)}<div class=\"tiny mono\">${hhmm(c.detectado_min)}</div></td>\n        <td>${c.situacao === 'aberto' ? '<span class=\"chip ch-info\">aberto</span>' : c.situacao === 'procedente' ? '<span class=\"chip ch-crit\">procedente</span>' : '<span class=\"chip ch-mute\">improcedente</span>'}</td>\n      </tr>`).join('')}\n    ${casos.length ? '' : '<tr><td class=\"tiny\">Nenhum caso com esse filtro.</td></tr>'}\n    </tbody></table>\n  </div>\n  <div class=\"origem\">Regras R1 a R8 aplicadas sobre o historico de status e a coluna Status Marketplace</div>`;\n}\n\n/* ---------------- tela 4 ---------------- */\nfunction viewFechamento(d2) {\n  const dias = lista(d2, 'kpidia').slice().sort((a, b) => a.dia_offset - b.dia_offset);\n  const tot = dias.reduce((s, d) => ({\n    entregues: s.entregues + (d.entregues || 0),\n    no_prazo: s.no_prazo + (d.no_prazo || 0),\n    fora: s.fora + (d.fora_prazo || 0)\n  }), { entregues: 0, no_prazo: 0, fora: 0 });\n  const slaMes = pct(tot.no_prazo, tot.entregues);\n  const tolerado = Math.round(tot.entregues * (100 - META) / 100);\n  const restante = tolerado - tot.fora;\n  const consumido = tolerado > 0 ? Math.min(100, (tot.fora / tolerado) * 100) : 0;\n\n  const peds = lista(d2, 'pedido').filter(p => !aberto(p));\n  const porRegiao = {};\n  peds.forEach(p => {\n    const k = p.regiao || '-';\n    if (!porRegiao[k]) porRegiao[k] = { n: 0, fora: 0 };\n    porRegiao[k].n++;\n    if (p.entregue_min > (p.prazo_hora || 21) * 60) porRegiao[k].fora++;\n  });\n\n  return `\n  <h2 class=\"h2\">Fechamento de SLA</h2>\n  <p class=\"sub\">Meta contratual com o Mercado Livre: <b>${fmtPct(META, 1)}</b> no mes. Abaixo, quanto da folga ja foi gasta.</p>\n\n  <div class=\"grid counters\">\n    ${counter(slaMes >= META ? 'c-ok' : 'c-crit', fmtPct(slaMes), 'SLA do mes', fmtInt(tot.entregues) + ' baixas apuradas')}\n    ${counter('c-info', fmtInt(tolerado), 'Folga do mes', 'pedidos que podem furar a meta')}\n    ${counter('c-warn', fmtInt(tot.fora), 'Folga gasta', fmtPct(consumido, 0) + ' do orcamento')}\n    ${counter(restante > 0 ? 'c-ok' : 'c-crit', fmtInt(restante), 'Folga restante', restante > 0 ? 'ainda cabe errar' : 'meta ja estourada')}\n  </div>\n\n  <div class=\"grid\" style=\"grid-template-columns:1.6fr 1fr;margin-top:14px\">\n    <div class=\"panel\">\n      <h3>SLA por dia <em>ultimos ${dias.length} dias &middot; barra vermelha = dia abaixo da meta</em></h3>\n      <div class=\"bars\">\n        ${dias.map(d => {\n    const p = pct(d.no_prazo, d.entregues);\n    const alt = Math.max(2, Math.min(100, ((p - 97.5) / (100 - 97.5)) * 100));\n    return `<div class=\"barwrap\" title=\"${diaLabel(d.dia_offset)}: ${fmtPct(p)}\"><div class=\"bar ${p < META ? 'miss' : ''}\" style=\"height:${alt}%\"></div></div>`;\n  }).join('')}\n      </div>\n      <div class=\"metaline\"><span>meta ${fmtPct(META, 1)}</span></div>\n      <div style=\"padding:14px 16px 16px\" class=\"tiny\">Escala de 97,5% a 100% — nessa faixa meio ponto percentual e a diferenca entre bater e furar o contrato.</div>\n    </div>\n\n    <div class=\"panel\">\n      <h3>O que consumiu a folga</h3>\n      <table><thead><tr><th>Regiao</th><th class=\"num\">Baixas</th><th class=\"num\">Fora</th></tr></thead><tbody>\n      ${Object.keys(porRegiao).sort((a, b) => porRegiao[b].fora - porRegiao[a].fora).map(k => `\n        <tr data-key=\"${k}\"><td>${esc(k)}</td><td class=\"num\">${porRegiao[k].n}</td>\n        <td class=\"num\" style=\"color:${porRegiao[k].fora ? 'var(--crit)' : 'var(--ink3)'}\">${porRegiao[k].fora || '-'}</td></tr>`).join('')}\n      </tbody></table>\n    </div>\n  </div>\n\n  <div class=\"note\" style=\"margin-top:14px\">\n    <b>Leitura:</b> a meta nao e um percentual abstrato — e um saldo. Neste mes cabem <b>${fmtInt(tolerado)}</b> pedidos fora do prazo; ${fmtInt(tot.fora)} ja foram gastos e sobram <b>${fmtInt(restante)}</b>. Os dois dias vermelhos do grafico sozinhos custaram mais de mil.\n  </div>\n  <div class=\"origem\">Denominador: pedidos cujo prazo cai no mes &middot; Meta a confirmar por marketplace (ver decisao D1)</div>`;\n}\n\n/* ---------------- tela 5 ---------------- */\nfunction viewComissao(d2) {\n  const rows = lista(d2, 'comissao').slice().sort((a, b) => (b.faturamento_mes || 0) - (a.faturamento_mes || 0));\n  const excecoes = rows.filter(r => r.alerta);\n  const validos = rows.filter(r => !r.alerta || r.alerta === 'duplicado');\n  const totalFat = validos.reduce((s, r) => s + (r.faturamento_mes || 0), 0);\n  const totalCom = validos.reduce((s, r) => s + (r.faturamento_mes || 0) * (r.percentual || 5) / 100, 0);\n\n  const porRep = {};\n  rows.forEach(r => {\n    if (!r.usuario_comercial) return;\n    if (!porRep[r.usuario_comercial]) porRep[r.usuario_comercial] = { fat: 0, com: 0, n: 0 };\n    porRep[r.usuario_comercial].fat += r.faturamento_mes || 0;\n    porRep[r.usuario_comercial].com += (r.faturamento_mes || 0) * (r.percentual || 5) / 100;\n    porRep[r.usuario_comercial].n++;\n  });\n\n  const ALERTA = {\n    duplicado: ['ch-warn', 'CNPJ com mais de um cadastro no TRACKen'],\n    sem_dono: ['ch-crit', 'Cliente sem responsavel comercial na carteira'],\n    sem_faturamento: ['ch-mute', 'Sem faturamento no mes']\n  };\n\n  return `\n  <h2 class=\"h2\">Previa de comissionamento</h2>\n  <p class=\"sub\">Faturamento do mes por cliente, cruzado com a carteira comercial. As excecoes vem antes do total — e isso que faz o financeiro confiar no numero em vez de conferir na mao.</p>\n\n  <div class=\"panel\" style=\"margin-bottom:14px\">\n    <h3>Excecoes a resolver antes de fechar <em>${excecoes.length} de ${rows.length} clientes</em></h3>\n    <table><tbody>\n    ${excecoes.map(r => `\n      <tr data-key=\"${r._id}\">\n        <td style=\"width:220px\"><span class=\"chip ${ALERTA[r.alerta][0]}\">${r.alerta.replace('_', ' ')}</span></td>\n        <td><span class=\"strong\">${esc(r.cliente_nome)}</span><div class=\"tiny mono\">${esc(r.cnpj)}</div></td>\n        <td class=\"tiny\">${ALERTA[r.alerta][1]}</td>\n        <td class=\"num\">${fmtBRL(r.faturamento_mes)}</td>\n      </tr>`).join('')}\n    ${excecoes.length ? '' : '<tr><td class=\"tiny\">Nenhuma excecao.</td></tr>'}\n    </tbody></table>\n  </div>\n\n  <div class=\"grid\" style=\"grid-template-columns:1.7fr 1fr\">\n    <div class=\"panel\">\n      <h3>Por cliente <em>total ${fmtBRL(totalCom)} sobre ${fmtBRL(totalFat)}</em></h3>\n      <table><thead><tr>\n        <th>Cliente</th><th>No TRACKen</th><th>Comercial</th><th>SDR</th><th class=\"num\">Pedidos</th><th class=\"num\">Faturamento</th><th class=\"num\">5%</th>\n      </tr></thead><tbody>\n      ${rows.map(r => `\n        <tr data-key=\"${r._id}\">\n          <td><span class=\"strong\">${esc(r.cliente_nome)}</span><div class=\"tiny mono\">${esc(r.cnpj)}</div></td>\n          <td class=\"tiny mono\">${r.nome_tracken ? esc(r.nome_tracken) : '<span style=\"color:var(--crit)\">nao mapeado</span>'}</td>\n          <td>${r.usuario_comercial ? esc(r.usuario_comercial) : '<span class=\"chip ch-crit\">sem dono</span>'}</td>\n          <td class=\"tiny\">${esc(r.sdr)}</td>\n          <td class=\"num\">${fmtInt(r.pedidos_mes)}</td>\n          <td class=\"num\">${fmtBRL(r.faturamento_mes)}</td>\n          <td class=\"num strong\">${fmtBRL((r.faturamento_mes || 0) * (r.percentual || 5) / 100)}</td>\n        </tr>`).join('')}\n      </tbody></table>\n    </div>\n\n    <div class=\"panel\">\n      <h3>Por representante</h3>\n      <table><thead><tr><th>Comercial</th><th class=\"num\">Clientes</th><th class=\"num\">Comissao</th></tr></thead><tbody>\n      ${Object.keys(porRep).sort((a, b) => porRep[b].com - porRep[a].com).map(k => `\n        <tr data-key=\"${k}\"><td>${esc(k)}</td><td class=\"num\">${porRep[k].n}</td>\n        <td class=\"num strong\">${fmtBRL(porRep[k].com)}</td></tr>`).join('')}\n      </tbody></table>\n    </div>\n  </div>\n  <div class=\"origem\">Faturamento: Financeiro &gt; Faturamento de Clientes do TRACKen &middot; Carteira comercial: base propria da TM &middot; Juncao por CNPJ</div>`;\n}\n\n/* ---------------- drawer ---------------- */\nfunction drawer(d2, agora) {\n  const dw = d2.state.drawer;\n  if (!dw) return '';\n  let corpo = '';\n  if (dw.tipo === 'caso') corpo = drawerCaso(d2, dw.id);\n  else if (dw.tipo === 'agente') corpo = drawerAgente(d2, dw.id);\n  else if (dw.tipo === 'pedido') corpo = drawerPedido(d2, dw.id, agora);\n  return `<div class=\"drawer\"><div class=\"backdrop\" data-fecha></div><div class=\"sheet\">\n    <button class=\"close\" data-fecha>&times;</button>${corpo}</div></div>`;\n}\n\nfunction drawerCaso(d2, id) {\n  const c = lista(d2, 'caso').find(x => x._id === id);\n  if (!c) return '<p>Caso nao encontrado.</p>';\n  const p = lista(d2, 'pedido').find(x => x.cod_remessa === c.cod_remessa) || {};\n  const evs = lista(d2, 'evento').filter(e => e.cod_remessa === c.cod_remessa).sort((a, b) => a.ordem - b.ordem);\n  const prazo = (p.prazo_hora || 21) * 60;\n\n  return `\n  <span class=\"chip ${c.severidade === 'alta' ? 'ch-crit' : c.severidade === 'media' ? 'ch-warn' : 'ch-mute'}\">${c.severidade}</span>\n  <span class=\"chip ch-mute\">${c.regra}</span>\n  <h4 style=\"margin-top:12px\">${esc(REGRAS[c.regra] || c.regra_nome)}</h4>\n  <p class=\"sub\" style=\"margin-bottom:0\">${esc(c.resumo)}</p>\n\n  <dl class=\"kv\">\n    <dt>Remessa</dt><dd class=\"mono\">${c.cod_remessa}</dd>\n    <dt>Pedido</dt><dd class=\"mono\">${esc(c.num_pedido)}</dd>\n    <dt>Agente</dt><dd>${esc(c.agente_nome)} <span class=\"tiny mono\">${esc(c.agente_usuario)}</span></dd>\n    <dt>Equipe</dt><dd>${esc(c.equipe)}</dd>\n    <dt>Cliente</dt><dd>${esc(c.cliente_nome)}</dd>\n    <dt>Detectado</dt><dd>${diaLabel(c.detectado_dia)} as ${hhmm(c.detectado_min)}</dd>\n    <dt>Prazo do pedido</dt><dd class=\"mono\">${hhmm(prazo)}</dd>\n  </dl>\n\n  <div class=\"note\"><b>Evidencia.</b><br>${esc(c.evidencia)}</div>\n\n  <h3 style=\"font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink2);margin:22px 0 0;font-family:'IBM Plex Mono',monospace\">Linha do tempo do pedido</h3>\n  <ul class=\"tl\">\n    ${evs.map(e => {\n    const lag = (e.coletado_min || 0) - (e.hora_min || 0);\n    const suspeito = lag > 20 || (e.status === 'ENTREGUE' && e.hora_min <= prazo && e.coletado_min > prazo);\n    return `<li class=\"${suspeito ? 'flag' : ''}\" data-key=\"${e.cod_remessa}-${e.ordem}\">\n        <div class=\"t\">${esc(e.status)} <span class=\"mono\" style=\"color:var(--ink2)\">${hhmm(e.hora_min)}</span></div>\n        <div class=\"d\">registro chegou ${hhmm(e.coletado_min)} <span class=\"${suspeito ? 'lag' : ''}\">(${lag >= 0 ? '+' : ''}${dur(lag)} de defasagem)</span> &middot; usuario <span class=\"mono\">${esc(e.usuario)}</span></div>\n        ${e.recebedor || e.observacao ? '<div class=\"d\">recebedor: <b>' + (esc(e.recebedor) || '<span style=\"color:var(--crit)\">vazio</span>') + '</b> &middot; documento: ' + (esc(e.documento) || '<span style=\"color:var(--crit)\">vazio</span>') + (e.observacao ? ' &middot; \"' + esc(e.observacao) + '\"' : '') + '</div>' : ''}\n      </li>`;\n  }).join('')}\n  </ul>\n\n  <div style=\"display:flex;gap:8px;margin-top:22px\">\n    <button class=\"btn btn-crit\" data-caso-id=\"${c._id}\" data-caso-situacao=\"procedente\">Marcar procedente</button>\n    <button class=\"btn\" data-caso-id=\"${c._id}\" data-caso-situacao=\"improcedente\">Improcedente</button>\n  </div>\n  <div class=\"origem\">Situacao atual: ${esc(c.situacao)}</div>`;\n}\n\nfunction drawerAgente(d2, usuario) {\n  const a = lista(d2, 'agente').find(x => x.usuario === usuario);\n  if (!a) return '<p>Agente nao encontrado.</p>';\n  const per = lista(d2, 'agenteperiodo').filter(r => r.usuario === usuario);\n  const casos = lista(d2, 'caso').filter(c => c.agente_usuario === usuario);\n  const abertos = lista(d2, 'pedido').filter(p => p.agente_usuario === usuario && aberto(p));\n\n  return `\n  <h4>${esc(a.nome)}</h4>\n  <p class=\"sub\">${esc(a.equipe)} &middot; coordenacao de ${esc(a.coordenador)}</p>\n  <dl class=\"kv\">\n    <dt>Usuario</dt><dd class=\"mono\">${esc(a.usuario)}</dd>\n    <dt>Telefone</dt><dd class=\"mono\">${esc(a.telefone)}</dd>\n    <dt>Veiculo</dt><dd>${esc(a.veiculo)}</dd>\n    <dt>Situacao</dt><dd>${a.situacao === 'bloqueado' ? '<span class=\"chip ch-crit\">bloqueado</span>' : '<span class=\"chip ch-ok\">ativo</span>'}</dd>\n    ${a.situacao === 'bloqueado' ? '<dt>Motivo</dt><dd>' + esc(a.motivo_bloqueio) + '</dd><dt>Bloqueado por</dt><dd class=\"mono\">' + esc(a.bloqueado_por) + '</dd>' : ''}\n    <dt>Em rua agora</dt><dd>${abertos.length} pedidos</dd>\n  </dl>\n\n  <div class=\"panel\" style=\"margin-top:16px\">\n    <h3>Desempenho</h3>\n    <table><thead><tr><th>Periodo</th><th class=\"num\">Entregas</th><th class=\"num\">% no prazo</th><th class=\"num\">Casos</th></tr></thead><tbody>\n    ${['hoje', 'semana', 'mes'].map(pd => {\n    const r = per.find(x => x.periodo === pd) || {};\n    const pp = pct(r.no_prazo, r.entregas);\n    return `<tr data-key=\"${pd}\"><td>${pd}</td><td class=\"num\">${fmtInt(r.entregas)}</td>\n      <td class=\"num strong\" style=\"color:${pp < 99 ? 'var(--crit)' : pp < 99.5 ? 'var(--warn)' : 'var(--ok)'}\">${r.entregas ? fmtPct(pp) : '-'}</td>\n      <td class=\"num\">${((r.casos_alta || 0) + (r.casos_media || 0)) || '-'}</td></tr>`;\n  }).join('')}\n    </tbody></table>\n  </div>\n\n  ${casos.length ? `<div class=\"panel\" style=\"margin-top:14px\"><h3>Casos do agente</h3><table><tbody>\n    ${casos.map(c => `<tr class=\"sel\" data-abre-caso=\"${c._id}\" data-key=\"${c._id}\">\n      <td><span class=\"chip ${c.severidade === 'alta' ? 'ch-crit' : c.severidade === 'media' ? 'ch-warn' : 'ch-mute'}\">${c.regra}</span></td>\n      <td class=\"tiny\">${esc(c.resumo)}</td><td class=\"tiny\">${diaLabel(c.detectado_dia)}</td></tr>`).join('')}\n  </tbody></table></div>` : ''}\n\n  <div style=\"margin-top:22px\">\n    <button class=\"btn ${a.situacao === 'bloqueado' ? 'btn-ok' : 'btn-crit'}\" data-bloquear=\"${a.usuario}\">\n      ${a.situacao === 'bloqueado' ? 'Desbloquear agente' : 'Bloquear agente'}\n    </button>\n  </div>\n  <div class=\"origem\">A decisao e registrada aqui com autor, hora e evidencia. A ordem de bloqueio e executada no TRACKen — este sistema nao escreve la.</div>`;\n}\n\nfunction drawerPedido(d2, cod, agora) {\n  const p = lista(d2, 'pedido').find(x => String(x.cod_remessa) === String(cod));\n  if (!p) return '<p>Pedido nao encontrado.</p>';\n  const e = estado(p, agora);\n  const r = prazoMin(p) - agora;\n  return `\n  <span class=\"chip ${e === 'estourado' || e === 'vai_estourar' ? 'ch-crit' : e === 'em_risco' ? 'ch-warn' : 'ch-ok'}\">${ESTADO_LABEL[e]}</span>\n  <h4 style=\"margin-top:12px\">Remessa ${p.cod_remessa}</h4>\n  <p class=\"sub\">${esc(p.cliente_nome)} &middot; ${esc(p.marketplace)}</p>\n  <dl class=\"kv\">\n    <dt>Restante</dt><dd class=\"strong mono\">${aberto(p) ? (r < 0 ? '-' + dur(r) : dur(r)) : 'entregue'}</dd>\n    <dt>Prazo</dt><dd class=\"mono\">${hhmm(p.prazo_hora * 60)} ${diaLabel(p.prazo_dia)}</dd>\n    <dt>Pedido</dt><dd class=\"mono\">${esc(p.num_pedido)}</dd>\n    <dt>Nota fiscal</dt><dd class=\"mono\">${esc(p.nota_fiscal)}</dd>\n    <dt>Destinatario</dt><dd>${esc(p.destinatario)}</dd>\n    <dt>Endereco</dt><dd>${esc(p.bairro)}, ${esc(p.cidade)} &middot; ${esc(p.cep)}<div class=\"tiny\">regiao ${esc(p.regiao)}</div></dd>\n    <dt>Valor NF</dt><dd>${fmtBRL(p.valor_nf)}</dd>\n    <dt>Agente</dt><dd>${esc(p.agente_nome)}<div class=\"tiny\">${esc(p.equipe)}</div></dd>\n    <dt>Manifesto</dt><dd class=\"mono\">${p.manifesto ? esc(p.manifesto) : '<span style=\"color:var(--warn)\">nao manifestado</span>'}</dd>\n    <dt>Tentativas</dt><dd>${p.tentativas}</dd>\n    <dt>Status TRACKen</dt><dd>${esc(p.status_atual)}</dd>\n    <dt>Status Marketplace</dt><dd>${esc(p.mkt_status)}<div class=\"tiny mono\">${hhmm(p.mkt_min)}</div></dd>\n  </dl>\n  <div class=\"origem\">Status: API TRACKen (simulada) &middot; Agente: export da Torre de Operacoes</div>`;\n}\n"}}}}}},"__d2PrevCode":{"code":"const SIM_BASE = 19 * 60 + 40;\nconst META = 99.6;\n\nconst REGRAS = {\n  R1: 'Divergencia TRACKen x Marketplace',\n  R2: 'Hora declarada dentro do prazo, registro depois',\n  R3: 'Salto de status',\n  R4: 'Rajada no mesmo minuto',\n  R5: 'Recebedor generico ou ausente',\n  R7: 'Retencao de custodia',\n  R8: 'Tentativas incoerentes'\n};\n\nfunction hhmm(m) {\n  const x = ((m % 1440) + 1440) % 1440;\n  const h = Math.floor(x / 60), mi = x % 60;\n  return String(h).padStart(2, '0') + ':' + String(mi).padStart(2, '0');\n}\nfunction dur(m) {\n  const a = Math.abs(m);\n  const h = Math.floor(a / 60), mi = a % 60;\n  return h > 0 ? h + 'h' + String(mi).padStart(2, '0') : mi + ' min';\n}\nfunction diaLabel(off) {\n  if (off === 0) return 'hoje';\n  if (off === -1) return 'ontem';\n  return 'ha ' + Math.abs(off) + ' dias';\n}\nfunction esc(s) {\n  return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n}\nfunction pct(n, d) { return d > 0 ? (n / d) * 100 : 0; }\nfunction fmtPct(v, casas) { return v.toFixed(casas == null ? 2 : casas).replace('.', ',') + '%'; }\nfunction fmtInt(v) { return Number(v || 0).toLocaleString('pt-BR'); }\nfunction fmtBRL(v) {\n  return 'R$ ' + Number(v || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });\n}\n\nfunction agoraMin(d2) {\n  if (d2.state.horaReal) {\n    const n = new Date();\n    return n.getHours() * 60 + n.getMinutes();\n  }\n  const decorrido = Math.floor((Date.now() - (d2.state.t0 || Date.now())) / 60000);\n  return SIM_BASE + decorrido;\n}\nfunction prazoMin(p) { return (p.prazo_dia || 0) * 1440 + (p.prazo_hora || 21) * 60; }\nfunction aberto(p) { return !(p.entregue_min >= 0); }\nfunction estado(p, agora) {\n  if (!aberto(p)) {\n    return p.entregue_min <= (p.prazo_hora || 21) * 60 ? 'entregue_no_prazo' : 'entregue_fora';\n  }\n  const r = prazoMin(p) - agora;\n  if (r < 0) return 'estourado';\n  if (r <= 30) return 'vai_estourar';\n  if (r <= 120) return 'em_risco';\n  return 'no_prazo';\n}\nconst ESTADO_LABEL = {\n  no_prazo: 'No prazo', em_risco: 'Em risco', vai_estourar: 'Vai estourar',\n  estourado: 'Estourado', entregue_no_prazo: 'Entregue no prazo', entregue_fora: 'Entregue fora'\n};\n\nfunction dados(d2) { return d2.state.dados || {}; }\nfunction lista(d2, k) { return (dados(d2)[k]) || []; }\n\nexport default {\n  css: `\n:host, .app { display:block }\n.app{\n  --bg:#0d1218; --panel:#151d26; --panel2:#1b2531; --line:#26333f; --line2:#2f3f4d;\n  --ink:#e8eef5; --ink2:#9fb0c0; --ink3:#6b7d8d;\n  --ok:#3ecf8e; --ok-bg:#122a22;\n  --warn:#f0b429; --warn-bg:#2b2313;\n  --crit:#f2604c; --crit-bg:#2c1a18;\n  --info:#5aa2ff; --info-bg:#14202f;\n  --scrim:rgba(5,8,11,.72); --shadow:none;\n  position:relative; width:100%; height:100%; background:var(--bg); color:var(--ink);\n  font-family:\"IBM Plex Sans\",-apple-system,\"Segoe UI\",Roboto,sans-serif;\n  font-size:14px; display:flex; flex-direction:column; overflow:hidden;\n}\n.app.light{\n  --bg:#eef1f5; --panel:#ffffff; --panel2:#f4f7fa; --line:#dfe5ec; --line2:#c6d1dd;\n  --ink:#111a23; --ink2:#48596a; --ink3:#68798a;\n  --ok:#0c7048; --ok-bg:#e3f4ec;\n  --warn:#8d5c05; --warn-bg:#fbf0d8;\n  --crit:#b53324; --crit-bg:#fbe5e1;\n  --info:#2558bd; --info-bg:#e5ecfb;\n  --scrim:rgba(17,26,35,.42); --shadow:0 1px 2px rgba(17,26,35,.05);\n}\n.app.light .panel,.app.light .counter{box-shadow:var(--shadow)}\n.app.light .nav button.on{background:var(--info-bg);border-color:var(--info);color:var(--info)}\n.app.light .seg button.on{background:var(--info-bg);color:var(--info)}\n.app.light .btn:hover{color:var(--info)}\n.app *{box-sizing:border-box}\n.mono{font-family:\"IBM Plex Mono\",ui-monospace,Menlo,monospace;font-variant-numeric:tabular-nums}\n\n/* topo */\n.top{display:flex;align-items:center;gap:20px;padding:12px 22px;border-bottom:1px solid var(--line);background:var(--panel);flex:none}\n.brand{display:flex;flex-direction:column;gap:2px;min-width:170px}\n.brand b{font-size:15px;letter-spacing:-.2px}\n.brand span{font-size:10.5px;color:var(--ink3);letter-spacing:.14em;text-transform:uppercase;font-family:\"IBM Plex Mono\",monospace}\n.nav{display:flex;gap:4px;flex:1}\n.nav button{\n  background:transparent;border:1px solid transparent;color:var(--ink2);padding:8px 14px;border-radius:4px;\n  font:inherit;font-size:13px;cursor:pointer;white-space:nowrap\n}\n.nav button:hover{background:var(--panel2);color:var(--ink)}\n.nav button.on{background:var(--info-bg);border-color:var(--info);color:#cfe2ff}\n.nav button:focus-visible{outline:2px solid var(--info);outline-offset:2px}\n.clock{display:flex;align-items:center;gap:12px}\n.clock .h{font-size:26px;font-weight:700;letter-spacing:-.5px}\n.clock .meta{display:flex;flex-direction:column;gap:2px;font-size:10.5px;color:var(--ink3);font-family:\"IBM Plex Mono\",monospace}\n.simbtn{background:var(--warn-bg);border:1px solid var(--warn);color:var(--warn);border-radius:3px;padding:3px 7px;font-size:10px;\n  letter-spacing:.1em;text-transform:uppercase;cursor:pointer;font-family:\"IBM Plex Mono\",monospace}\n.temabtn{background:var(--panel2);border:1px solid var(--line2);color:var(--ink2);border-radius:3px;width:28px;height:26px;\n  display:grid;place-items:center;font-size:13px;cursor:pointer;line-height:1;padding:0}\n.temabtn:hover{border-color:var(--info);color:var(--info)}\n.temabtn:focus-visible{outline:2px solid var(--info);outline-offset:2px}\n\n/* corpo */\n.body{flex:1;overflow:auto;padding:20px 22px 40px}\n.h2{font-size:17px;font-weight:700;margin:0 0 3px}\n.sub{font-size:12.5px;color:var(--ink3);margin:0 0 16px}\n.grid{display:grid;gap:14px}\n\n/* cards contador */\n.counters{grid-template-columns:repeat(4,1fr)}\n.counter{background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:16px 18px;border-left-width:3px}\n.counter .n{font-size:42px;font-weight:800;line-height:1;letter-spacing:-1.5px}\n.counter .l{font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--ink2);margin-top:8px;font-family:\"IBM Plex Mono\",monospace}\n.counter .x{font-size:11.5px;color:var(--ink3);margin-top:5px}\n.c-ok{border-left-color:var(--ok)} .c-ok .n{color:var(--ok)}\n.c-warn{border-left-color:var(--warn)} .c-warn .n{color:var(--warn)}\n.c-crit{border-left-color:var(--crit)} .c-crit .n{color:var(--crit)}\n.c-info{border-left-color:var(--info)} .c-info .n{color:var(--info)}\n\n.panel{background:var(--panel);border:1px solid var(--line);border-radius:6px;overflow:hidden}\n.panel h3{margin:0;padding:12px 16px;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink2);\n  border-bottom:1px solid var(--line);font-family:\"IBM Plex Mono\",monospace;font-weight:600;display:flex;justify-content:space-between;align-items:center}\n.panel h3 em{font-style:normal;color:var(--ink3);letter-spacing:0;text-transform:none;font-size:11.5px;font-family:\"IBM Plex Sans\",sans-serif}\n\ntable{width:100%;border-collapse:collapse}\nth{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink3);text-align:left;padding:9px 14px;\n  border-bottom:1px solid var(--line);font-weight:600;font-family:\"IBM Plex Mono\",monospace;white-space:nowrap}\ntd{padding:10px 14px;border-bottom:1px solid var(--line);font-size:13px;vertical-align:middle}\ntr:last-child td{border-bottom:0}\ntbody tr.sel:hover{background:var(--panel2);cursor:pointer}\n.num{text-align:right;font-family:\"IBM Plex Mono\",monospace;font-variant-numeric:tabular-nums}\n.tiny{font-size:11px;color:var(--ink3)}\n.strong{font-weight:600}\n\n.chip{display:inline-block;font-size:10px;letter-spacing:.09em;text-transform:uppercase;padding:3px 7px;border-radius:3px;\n  font-family:\"IBM Plex Mono\",monospace;font-weight:600;white-space:nowrap}\n.ch-ok{background:var(--ok-bg);color:var(--ok);border:1px solid var(--ok)}\n.ch-warn{background:var(--warn-bg);color:var(--warn);border:1px solid var(--warn)}\n.ch-crit{background:var(--crit-bg);color:var(--crit);border:1px solid var(--crit)}\n.ch-info{background:var(--info-bg);color:var(--info);border:1px solid var(--info)}\n.ch-mute{background:var(--panel2);color:var(--ink3);border:1px solid var(--line2)}\n\n.toolbar{display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap}\n.seg{display:inline-flex;border:1px solid var(--line2);border-radius:4px;overflow:hidden}\n.seg button{background:transparent;border:0;color:var(--ink2);padding:6px 13px;font:inherit;font-size:12.5px;cursor:pointer}\n.seg button.on{background:var(--info-bg);color:#cfe2ff}\n.seg button:focus-visible{outline:2px solid var(--info);outline-offset:-2px}\n.spacer{flex:1}\n\n.btn{background:var(--panel2);border:1px solid var(--line2);color:var(--ink);padding:6px 12px;border-radius:4px;\n  font:inherit;font-size:12.5px;cursor:pointer}\n.btn:hover{border-color:var(--info);color:#cfe2ff}\n.btn:focus-visible{outline:2px solid var(--info);outline-offset:2px}\n.btn-crit{background:var(--crit-bg);border-color:var(--crit);color:var(--crit)}\n.btn-ok{background:var(--ok-bg);border-color:var(--ok);color:var(--ok)}\n\n/* barras */\n.bars{display:flex;align-items:flex-end;gap:3px;height:150px;padding:14px 16px}\n.bar{flex:1;position:relative;background:var(--ok);border-radius:2px 2px 0 0;min-height:2px}\n.bar.miss{background:var(--crit)}\n.barwrap{flex:1;height:100%;display:flex;align-items:flex-end}\n.metaline{position:relative;height:0;border-top:1px dashed var(--warn);margin:0 16px}\n.metaline span{position:absolute;right:0;top:-16px;font-size:10px;color:var(--warn);font-family:\"IBM Plex Mono\",monospace}\n\n/* drawer */\n.drawer{position:absolute;inset:0;display:flex;justify-content:flex-end;z-index:20}\n.drawer .backdrop{position:absolute;inset:0;background:var(--scrim)}\n.drawer .sheet{position:relative;z-index:1}\n.drawer .sheet{width:min(620px,92%);background:var(--panel);border-left:1px solid var(--line2);height:100%;overflow:auto;padding:22px 24px}\n.drawer h4{margin:0 0 4px;font-size:17px}\n.drawer .close{position:absolute;top:14px;right:18px;background:transparent;border:0;color:var(--ink2);font-size:22px;cursor:pointer;line-height:1}\n.kv{display:grid;grid-template-columns:150px 1fr;gap:7px 14px;font-size:13px;margin:16px 0}\n.kv dt{color:var(--ink3);font-size:11px;letter-spacing:.09em;text-transform:uppercase;font-family:\"IBM Plex Mono\",monospace;padding-top:2px}\n.kv dd{margin:0}\n\n.tl{list-style:none;margin:14px 0 0;padding:0}\n.tl li{position:relative;padding:0 0 16px 22px;border-left:1px solid var(--line2)}\n.tl li:last-child{border-left-color:transparent;padding-bottom:0}\n.tl li::before{content:'';position:absolute;left:-5px;top:4px;width:9px;height:9px;border-radius:50%;background:var(--ink3);border:2px solid var(--panel)}\n.tl li.flag::before{background:var(--crit)}\n.tl .t{font-size:12.5px;font-weight:600}\n.tl .d{font-size:11.5px;color:var(--ink3);margin-top:2px}\n.tl .lag{color:var(--crit);font-weight:600}\n\n.note{background:var(--panel2);border:1px solid var(--line2);border-left:3px solid var(--info);border-radius:4px;padding:12px 14px;font-size:12.5px;color:var(--ink2);line-height:1.55}\n.note b{color:var(--ink)}\n.origem{font-size:11px;color:var(--ink3);font-family:\"IBM Plex Mono\",monospace;margin-top:14px;padding-top:10px;border-top:1px solid var(--line)}\n.center{display:flex;align-items:center;justify-content:center;height:100%;color:var(--ink3);font-size:14px}\n.err{color:var(--crit);max-width:640px;line-height:1.6}\n`,\n\n  render(d2) {\n    if (d2.state.erro) {\n      return `<div class=\"app\"><div class=\"center\"><div class=\"err\"><b>Nao consegui carregar os dados.</b><br>${esc(d2.state.erro)}</div></div></div>`;\n    }\n    if (!d2.state.ready) {\n      return `<div class=\"app\"><div class=\"center\">Carregando dados da operacao...</div></div>`;\n    }\n    const view = d2.state.view || 'painel';\n    const agora = agoraMin(d2);\n    const views = {\n      painel: viewPainel, scorecard: viewScorecard, casos: viewCasos,\n      fechamento: viewFechamento, comissao: viewComissao\n    };\n    const corpo = (views[view] || viewPainel)(d2, agora);\n    return `<div class=\"app\">\n      ${topo(d2, agora, view)}\n      <div class=\"body\">${corpo}</div>\n      ${drawer(d2, agora)}\n    </div>`;\n  },\n\n  mounted(d2) {\n    d2.state.t0 = Date.now();\n    d2.state.view = 'painel';\n    d2.state.periodo = 'hoje';\n    d2.state.agrupar = 'agente';\n    d2.state.filtroSev = 'todas';\n\n    d2.rush('api-dados').invoke({})\n      .then(res => {\n        const payload = (res && res.data) ? res.data : res;\n        d2.state.dados = payload || {};\n        d2.state.ready = true;\n      })\n      .catch(e => { d2.state.erro = (e && e.message) ? e.message : String(e); });\n\n    const t = setInterval(() => { d2.state.tick = (d2.state.tick || 0) + 1; }, 20000);\n    d2.onUnmount(() => clearInterval(t));\n\n    d2.on('[data-view]', 'click', e => {\n      const el = e.target.closest('[data-view]');\n      if (el) d2.state.view = el.dataset.view;\n    });\n    d2.on('[data-periodo]', 'click', e => {\n      const el = e.target.closest('[data-periodo]');\n      if (el) d2.state.periodo = el.dataset.periodo;\n    });\n    d2.on('[data-agrupar]', 'click', e => {\n      const el = e.target.closest('[data-agrupar]');\n      if (el) d2.state.agrupar = el.dataset.agrupar;\n    });\n    d2.on('[data-sev]', 'click', e => {\n      const el = e.target.closest('[data-sev]');\n      if (el) d2.state.filtroSev = el.dataset.sev;\n    });\n    d2.on('[data-abre-agente]', 'click', e => {\n      const el = e.target.closest('[data-abre-agente]');\n      if (el) { d2.state.drawer = { tipo: 'agente', id: el.dataset.abreAgente }; }\n    });\n    d2.on('[data-abre-caso]', 'click', e => {\n      const el = e.target.closest('[data-abre-caso]');\n      if (el) { d2.state.drawer = { tipo: 'caso', id: el.dataset.abreCaso }; }\n    });\n    d2.on('[data-abre-pedido]', 'click', e => {\n      const el = e.target.closest('[data-abre-pedido]');\n      if (el) { d2.state.drawer = { tipo: 'pedido', id: el.dataset.abrePedido }; }\n    });\n    d2.on('[data-fecha]', 'click', () => { d2.state.drawer = null; });\n    d2.on('[data-hora-real]', 'click', () => { d2.state.horaReal = !d2.state.horaReal; });\n\n    d2.on('[data-bloquear]', 'click', async e => {\n      const el = e.target.closest('[data-bloquear]');\n      if (!el) return;\n      const usuario = el.dataset.bloquear;\n      const ag = lista(d2, 'agente').find(a => a.usuario === usuario);\n      if (!ag) return;\n      const bloqueando = ag.situacao !== 'bloqueado';\n      let motivo = '';\n      if (bloqueando) {\n        motivo = await d2.dialog.prompt(\n          'Motivo do bloqueio de ' + ag.nome + ' (obrigatorio):',\n          'Reincidencia em baixa com hora retroativa'\n        );\n        if (!motivo) return;\n      } else {\n        const ok = await d2.dialog.confirm('Desbloquear ' + ag.nome + '?');\n        if (!ok) return;\n      }\n      el.disabled = true;\n      el.textContent = 'salvando...';\n      try {\n        await d2.rush('act-bloquear').invoke({\n          usuario: usuario,\n          situacao: bloqueando ? 'bloqueado' : 'ativo',\n          motivo: bloqueando ? motivo : '',\n          por: bloqueando ? 'luan.marins' : '',\n          em: bloqueando ? '0' : ''\n        });\n        const novo = await d2.rush('api-dados').invoke({});\n        d2.state.dados = (novo && novo.data) ? novo.data : novo;\n        d2.state.tick = (d2.state.tick || 0) + 1;\n      } catch (err) {\n        d2.dialog.alert('Nao consegui salvar: ' + ((err && err.message) || err));\n        d2.state.tick = (d2.state.tick || 0) + 1;\n      }\n    });\n\n    d2.on('[data-caso-situacao]', 'click', async e => {\n      const el = e.target.closest('[data-caso-situacao]');\n      if (!el) return;\n      el.disabled = true;\n      el.textContent = 'salvando...';\n      try {\n        await d2.rush('act-caso').invoke({ id: el.dataset.casoId, situacao: el.dataset.casoSituacao });\n        const novo = await d2.rush('api-dados').invoke({});\n        d2.state.dados = (novo && novo.data) ? novo.data : novo;\n        d2.state.drawer = null;\n      } catch (err) {\n        d2.dialog.alert('Nao consegui salvar: ' + ((err && err.message) || err));\n        d2.state.tick = (d2.state.tick || 0) + 1;\n      }\n    });\n  }\n};\n\n/* ---------------- topo ---------------- */\nfunction topo(d2, agora, view) {\n  const abas = [\n    ['painel', 'Painel de Risco'], ['casos', 'Casos suspeitos'], ['scorecard', 'Scorecard'],\n    ['fechamento', 'Fechamento de SLA'], ['comissao', 'Comissionamento']\n  ];\n  const nCasos = lista(d2, 'caso').filter(c => c.situacao === 'aberto').length;\n  return `<div class=\"top\">\n    <div class=\"brand\"><b>Prazo e Prova</b><span>TM Logistica</span></div>\n    <div class=\"nav\">${abas.map(([k, t]) => `\n      <button data-view=\"${k}\" class=\"${view === k ? 'on' : ''}\">${t}${k === 'casos' && nCasos ? ' (' + nCasos + ')' : ''}</button>`).join('')}\n    </div>\n    <div class=\"clock\">\n      <div class=\"meta\">\n        <span>ultima leitura ${hhmm(agora - 5)}</span>\n        <span>${d2.state.horaReal ? 'hora real' : 'cena simulada'}</span>\n      </div>\n      <div class=\"h mono\">${hhmm(agora)}</div>\n      <button class=\"simbtn\" data-hora-real>${d2.state.horaReal ? 'usar cena' : 'usar hora real'}</button>\n      <button class=\"temabtn\" data-tema title=\"${d2.state.tema === 'light' ? 'Mudar para tema escuro' : 'Mudar para tema claro'}\" aria-label=\"${d2.state.tema === 'light' ? 'Mudar para tema escuro' : 'Mudar para tema claro'}\">${d2.state.tema === 'light' ? '☽' : '☀'}</button>\n    </div>\n  </div>`;\n}\n\n/* ---------------- tela 1 ---------------- */\nfunction viewPainel(d2, agora) {\n  const peds = lista(d2, 'pedido');\n  const abertos = peds.filter(aberto);\n  const grupos = { no_prazo: [], em_risco: [], vai_estourar: [], estourado: [] };\n  abertos.forEach(p => { const e = estado(p, agora); if (grupos[e]) grupos[e].push(p); });\n\n  const kpiHoje = lista(d2, 'kpidia').find(k => k.dia_offset === 0) || {};\n  const criticos = abertos\n    .map(p => ({ p: p, r: prazoMin(p) - agora, e: estado(p, agora) }))\n    .sort((a, b) => a.r - b.r).slice(0, 12);\n\n  const porAgente = {};\n  abertos.forEach(p => {\n    const e = estado(p, agora);\n    if (e === 'estourado' || e === 'vai_estourar' || e === 'em_risco') {\n      const k = p.agente_usuario || 'sem agente';\n      if (!porAgente[k]) porAgente[k] = { nome: p.agente_nome || 'Nao manifestado', equipe: p.equipe, estourado: 0, vai: 0, risco: 0 };\n      if (e === 'estourado') porAgente[k].estourado++;\n      else if (e === 'vai_estourar') porAgente[k].vai++;\n      else porAgente[k].risco++;\n    }\n  });\n  const ranking = Object.keys(porAgente).map(k => Object.assign({ usuario: k }, porAgente[k]))\n    .sort((a, b) => (b.estourado * 100 + b.vai * 10 + b.risco) - (a.estourado * 100 + a.vai * 10 + a.risco)).slice(0, 6);\n\n  return `\n  <div class=\"grid counters\">\n    ${counter('c-ok', grupos.no_prazo.length, 'No prazo', 'mais de 2h de folga')}\n    ${counter('c-warn', grupos.em_risco.length, 'Em risco', 'menos de 2h para o corte')}\n    ${counter('c-crit', grupos.vai_estourar.length, 'Vai estourar', 'menos de 30 min')}\n    ${counter('c-crit', grupos.estourado.length, 'Estourado', 'passou do prazo, sem baixa')}\n  </div>\n\n  <div class=\"grid\" style=\"grid-template-columns:1.55fr 1fr;margin-top:14px\">\n    <div class=\"panel\">\n      <h3>Vao estourar primeiro <em>${abertos.length} pedidos em rua</em></h3>\n      <table><thead><tr>\n        <th>Restante</th><th>Remessa</th><th>Cliente</th><th>Bairro</th><th>Agente</th><th>Corte</th>\n      </tr></thead><tbody>\n      ${criticos.map(({ p, r, e }) => `\n        <tr class=\"sel\" data-abre-pedido=\"${p.cod_remessa}\" data-key=\"${p._id}\">\n          <td><span class=\"chip ${e === 'estourado' || e === 'vai_estourar' ? 'ch-crit' : e === 'em_risco' ? 'ch-warn' : 'ch-ok'}\">${r < 0 ? '-' + dur(r) : dur(r)}</span></td>\n          <td class=\"mono\">${p.cod_remessa}</td>\n          <td>${esc(p.cliente_nome)}<div class=\"tiny\">${esc(p.marketplace)}</div></td>\n          <td>${esc(p.bairro)}<div class=\"tiny\">${esc(p.regiao)}</div></td>\n          <td>${esc(p.agente_nome)}<div class=\"tiny\">${esc(p.equipe)}</div></td>\n          <td class=\"mono\">${hhmm(p.prazo_hora * 60)}${p.prazo_dia < 0 ? ' <span class=\"tiny\">' + diaLabel(p.prazo_dia) + '</span>' : ''}</td>\n        </tr>`).join('')}\n      </tbody></table>\n    </div>\n\n    <div style=\"display:flex;flex-direction:column;gap:14px\">\n      <div class=\"panel\">\n        <h3>Puxando o SLA agora</h3>\n        <table><tbody>\n        ${ranking.map(a => `\n          <tr class=\"sel\" data-abre-agente=\"${a.usuario}\" data-key=\"${a.usuario}\">\n            <td><span class=\"strong\">${esc(a.nome)}</span><div class=\"tiny\">${esc(a.equipe)}</div></td>\n            <td class=\"num\" style=\"width:120px\">\n              ${a.estourado ? '<span class=\"chip ch-crit\">' + a.estourado + ' est.</span> ' : ''}\n              ${a.vai ? '<span class=\"chip ch-crit\">' + a.vai + '</span> ' : ''}\n              ${a.risco ? '<span class=\"chip ch-warn\">' + a.risco + '</span>' : ''}\n            </td>\n          </tr>`).join('')}\n        ${ranking.length ? '' : '<tr><td class=\"tiny\">Nenhum agente em risco no momento.</td></tr>'}\n        </tbody></table>\n      </div>\n\n      <div class=\"panel\">\n        <h3>O dia ate agora</h3>\n        <table><tbody>\n          <tr><td>Pedidos recebidos</td><td class=\"num strong\">${fmtInt(kpiHoje.recebidos)}</td></tr>\n          <tr><td>Baixados</td><td class=\"num strong\">${fmtInt(kpiHoje.entregues)}</td></tr>\n          <tr><td>Fora do prazo</td><td class=\"num strong\" style=\"color:var(--crit)\">${fmtInt(kpiHoje.fora_prazo)}</td></tr>\n          <tr><td>SLA do dia</td><td class=\"num strong\" style=\"color:var(--ok)\">${fmtPct(pct(kpiHoje.no_prazo, kpiHoje.entregues))}</td></tr>\n        </tbody></table>\n      </div>\n    </div>\n  </div>\n\n  <div class=\"origem\">Status: API TRACKen (simulada), leitura ${hhmm(agora - 5)} &middot; Agente: export da Torre de Operacoes &middot; Marketplace: coluna Historico Ecommerce</div>`;\n}\nfunction counter(cls, n, label, extra) {\n  return `<div class=\"counter ${cls}\"><div class=\"n mono\">${n}</div><div class=\"l\">${label}</div><div class=\"x\">${extra}</div></div>`;\n}\n\n/* ---------------- tela 2 ---------------- */\nfunction viewScorecard(d2) {\n  const periodo = d2.state.periodo || 'hoje';\n  const agrupar = d2.state.agrupar || 'agente';\n  const linhas = lista(d2, 'agenteperiodo').filter(r => r.periodo === periodo);\n  const agentes = lista(d2, 'agente');\n  const mapa = {};\n  agentes.forEach(a => { mapa[a.usuario] = a; });\n\n  let rows;\n  if (agrupar === 'equipe') {\n    const eq = {};\n    linhas.forEach(r => {\n      const k = r.equipe || '-';\n      if (!eq[k]) eq[k] = { chave: k, nome: k, sub: '', entregas: 0, no_prazo: 0, fora_prazo: 0, casos: 0, n: 0 };\n      eq[k].entregas += r.entregas || 0; eq[k].no_prazo += r.no_prazo || 0;\n      eq[k].fora_prazo += r.fora_prazo || 0; eq[k].casos += (r.casos_alta || 0) + (r.casos_media || 0); eq[k].n++;\n    });\n    rows = Object.values(eq).map(e => Object.assign(e, { sub: e.n + ' agentes' }));\n  } else {\n    rows = linhas.map(r => ({\n      chave: r.usuario, nome: r.nome, sub: r.equipe,\n      entregas: r.entregas || 0, no_prazo: r.no_prazo || 0, fora_prazo: r.fora_prazo || 0,\n      casos: (r.casos_alta || 0) + (r.casos_media || 0),\n      situacao: (mapa[r.usuario] || {}).situacao\n    }));\n  }\n  rows.forEach(r => {\n    r.pct = pct(r.no_prazo, r.entregas);\n    r.por1k = r.entregas > 0 ? (r.casos / r.entregas) * 1000 : 0;\n  });\n  rows.sort((a, b) => a.pct - b.pct);\n\n  return `\n  <h2 class=\"h2\">Scorecard</h2>\n  <p class=\"sub\">Ordenado do pior para o melhor. O par que importa e <b>% no prazo</b> ao lado de <b>casos por mil baixas</b> — um agente pode ter prazo impecavel justamente porque limpa a propria hora.</p>\n  <div class=\"toolbar\">\n    <div class=\"seg\">\n      ${['hoje', 'semana', 'mes'].map(p => `<button data-periodo=\"${p}\" class=\"${periodo === p ? 'on' : ''}\">${p === 'mes' ? 'mes' : p}</button>`).join('')}\n    </div>\n    <div class=\"seg\">\n      ${[['agente', 'por agente'], ['equipe', 'por equipe']].map(([k, t]) => `<button data-agrupar=\"${k}\" class=\"${agrupar === k ? 'on' : ''}\">${t}</button>`).join('')}\n    </div>\n    <div class=\"spacer\"></div>\n    <span class=\"tiny\">${rows.length} linhas &middot; periodo: ${periodo}</span>\n  </div>\n  <div class=\"panel\">\n    <table><thead><tr>\n      <th>${agrupar === 'equipe' ? 'Equipe' : 'Agente'}</th><th class=\"num\">Entregas</th><th class=\"num\">% no prazo</th>\n      <th class=\"num\">Fora</th><th class=\"num\">Casos</th><th class=\"num\">Casos / 1.000</th><th>Situacao</th><th></th>\n    </tr></thead><tbody>\n    ${rows.map(r => {\n    const bad = r.pct < 99.0, mid = r.pct < 99.5;\n    return `<tr class=\"sel\" ${agrupar === 'agente' ? 'data-abre-agente=\"' + r.chave + '\"' : ''} data-key=\"${r.chave}\">\n        <td><span class=\"strong\">${esc(r.nome)}</span><div class=\"tiny\">${esc(r.sub)}</div></td>\n        <td class=\"num\">${fmtInt(r.entregas)}</td>\n        <td class=\"num strong\" style=\"color:${bad ? 'var(--crit)' : mid ? 'var(--warn)' : 'var(--ok)'}\">${fmtPct(r.pct)}</td>\n        <td class=\"num\">${fmtInt(r.fora_prazo)}</td>\n        <td class=\"num\">${r.casos || '-'}</td>\n        <td class=\"num\" style=\"color:${r.por1k >= 1 ? 'var(--crit)' : r.por1k > 0 ? 'var(--warn)' : 'var(--ink3)'}\">${r.por1k > 0 ? r.por1k.toFixed(2).replace('.', ',') : '-'}</td>\n        <td>${r.situacao === 'bloqueado' ? '<span class=\"chip ch-crit\">bloqueado</span>' : agrupar === 'agente' ? '<span class=\"chip ch-mute\">ativo</span>' : ''}</td>\n        <td>${agrupar === 'agente' ? '<button class=\"btn ' + (r.situacao === 'bloqueado' ? 'btn-ok' : 'btn-crit') + '\" data-bloquear=\"' + r.chave + '\">' + (r.situacao === 'bloqueado' ? 'Desbloquear' : 'Bloquear') + '</button>' : ''}</td>\n      </tr>`;\n  }).join('')}\n    </tbody></table>\n  </div>\n  <div class=\"origem\">Volumes: rollup por agente e periodo &middot; Situacao e bloqueio: base propria (a ordem de bloqueio nao e escrita no TRACKen)</div>`;\n}\n\n/* ---------------- tela 3 ---------------- */\nfunction viewCasos(d2) {\n  const f = d2.state.filtroSev || 'todas';\n  let casos = lista(d2, 'caso').slice();\n  if (f !== 'todas') casos = casos.filter(c => f === 'abertos' ? c.situacao === 'aberto' : c.severidade === f);\n  const ordem = { alta: 0, media: 1, baixa: 2 };\n  casos.sort((a, b) => (ordem[a.severidade] - ordem[b.severidade]) || (b.detectado_dia - a.detectado_dia));\n  const todos = lista(d2, 'caso');\n  const nAlta = todos.filter(c => c.severidade === 'alta').length;\n\n  return `\n  <h2 class=\"h2\">Casos suspeitos</h2>\n  <p class=\"sub\">${todos.length} casos no mes, ${nAlta} de severidade alta. Cada caso ja vem com a evidencia montada — pronto para confrontar o agente ou defender o seller numa mediacao.</p>\n  <div class=\"toolbar\">\n    <div class=\"seg\">\n      ${[['todas', 'todos'], ['abertos', 'abertos'], ['alta', 'alta'], ['media', 'media'], ['baixa', 'baixa']]\n      .map(([k, t]) => `<button data-sev=\"${k}\" class=\"${f === k ? 'on' : ''}\">${t}</button>`).join('')}\n    </div>\n    <div class=\"spacer\"></div><span class=\"tiny\">${casos.length} casos listados</span>\n  </div>\n  <div class=\"panel\">\n    <table><thead><tr>\n      <th>Sev.</th><th>Regra</th><th>Remessa</th><th>Agente</th><th>Cliente</th><th>Quando</th><th>Situacao</th>\n    </tr></thead><tbody>\n    ${casos.map(c => `\n      <tr class=\"sel\" data-abre-caso=\"${c._id}\" data-key=\"${c._id}\">\n        <td><span class=\"chip ${c.severidade === 'alta' ? 'ch-crit' : c.severidade === 'media' ? 'ch-warn' : 'ch-mute'}\">${c.severidade}</span></td>\n        <td><span class=\"strong\">${c.regra}</span><div class=\"tiny\">${esc(REGRAS[c.regra] || c.regra_nome)}</div></td>\n        <td class=\"mono\">${c.cod_remessa}</td>\n        <td>${esc(c.agente_nome)}<div class=\"tiny\">${esc(c.equipe)}</div></td>\n        <td>${esc(c.cliente_nome)}</td>\n        <td>${diaLabel(c.detectado_dia)}<div class=\"tiny mono\">${hhmm(c.detectado_min)}</div></td>\n        <td>${c.situacao === 'aberto' ? '<span class=\"chip ch-info\">aberto</span>' : c.situacao === 'procedente' ? '<span class=\"chip ch-crit\">procedente</span>' : '<span class=\"chip ch-mute\">improcedente</span>'}</td>\n      </tr>`).join('')}\n    ${casos.length ? '' : '<tr><td class=\"tiny\">Nenhum caso com esse filtro.</td></tr>'}\n    </tbody></table>\n  </div>\n  <div class=\"origem\">Regras R1 a R8 aplicadas sobre o historico de status e a coluna Status Marketplace</div>`;\n}\n\n/* ---------------- tela 4 ---------------- */\nfunction viewFechamento(d2) {\n  const dias = lista(d2, 'kpidia').slice().sort((a, b) => a.dia_offset - b.dia_offset);\n  const tot = dias.reduce((s, d) => ({\n    entregues: s.entregues + (d.entregues || 0),\n    no_prazo: s.no_prazo + (d.no_prazo || 0),\n    fora: s.fora + (d.fora_prazo || 0)\n  }), { entregues: 0, no_prazo: 0, fora: 0 });\n  const slaMes = pct(tot.no_prazo, tot.entregues);\n  const tolerado = Math.round(tot.entregues * (100 - META) / 100);\n  const restante = tolerado - tot.fora;\n  const consumido = tolerado > 0 ? Math.min(100, (tot.fora / tolerado) * 100) : 0;\n\n  const peds = lista(d2, 'pedido').filter(p => !aberto(p));\n  const porRegiao = {};\n  peds.forEach(p => {\n    const k = p.regiao || '-';\n    if (!porRegiao[k]) porRegiao[k] = { n: 0, fora: 0 };\n    porRegiao[k].n++;\n    if (p.entregue_min > (p.prazo_hora || 21) * 60) porRegiao[k].fora++;\n  });\n\n  return `\n  <h2 class=\"h2\">Fechamento de SLA</h2>\n  <p class=\"sub\">Meta contratual com o Mercado Livre: <b>${fmtPct(META, 1)}</b> no mes. Abaixo, quanto da folga ja foi gasta.</p>\n\n  <div class=\"grid counters\">\n    ${counter(slaMes >= META ? 'c-ok' : 'c-crit', fmtPct(slaMes), 'SLA do mes', fmtInt(tot.entregues) + ' baixas apuradas')}\n    ${counter('c-info', fmtInt(tolerado), 'Folga do mes', 'pedidos que podem furar a meta')}\n    ${counter('c-warn', fmtInt(tot.fora), 'Folga gasta', fmtPct(consumido, 0) + ' do orcamento')}\n    ${counter(restante > 0 ? 'c-ok' : 'c-crit', fmtInt(restante), 'Folga restante', restante > 0 ? 'ainda cabe errar' : 'meta ja estourada')}\n  </div>\n\n  <div class=\"grid\" style=\"grid-template-columns:1.6fr 1fr;margin-top:14px\">\n    <div class=\"panel\">\n      <h3>SLA por dia <em>ultimos ${dias.length} dias &middot; barra vermelha = dia abaixo da meta</em></h3>\n      <div class=\"bars\">\n        ${dias.map(d => {\n    const p = pct(d.no_prazo, d.entregues);\n    const alt = Math.max(2, Math.min(100, ((p - 97.5) / (100 - 97.5)) * 100));\n    return `<div class=\"barwrap\" title=\"${diaLabel(d.dia_offset)}: ${fmtPct(p)}\"><div class=\"bar ${p < META ? 'miss' : ''}\" style=\"height:${alt}%\"></div></div>`;\n  }).join('')}\n      </div>\n      <div class=\"metaline\"><span>meta ${fmtPct(META, 1)}</span></div>\n      <div style=\"padding:14px 16px 16px\" class=\"tiny\">Escala de 97,5% a 100% — nessa faixa meio ponto percentual e a diferenca entre bater e furar o contrato.</div>\n    </div>\n\n    <div class=\"panel\">\n      <h3>O que consumiu a folga</h3>\n      <table><thead><tr><th>Regiao</th><th class=\"num\">Baixas</th><th class=\"num\">Fora</th></tr></thead><tbody>\n      ${Object.keys(porRegiao).sort((a, b) => porRegiao[b].fora - porRegiao[a].fora).map(k => `\n        <tr data-key=\"${k}\"><td>${esc(k)}</td><td class=\"num\">${porRegiao[k].n}</td>\n        <td class=\"num\" style=\"color:${porRegiao[k].fora ? 'var(--crit)' : 'var(--ink3)'}\">${porRegiao[k].fora || '-'}</td></tr>`).join('')}\n      </tbody></table>\n    </div>\n  </div>\n\n  <div class=\"note\" style=\"margin-top:14px\">\n    <b>Leitura:</b> a meta nao e um percentual abstrato — e um saldo. Neste mes cabem <b>${fmtInt(tolerado)}</b> pedidos fora do prazo; ${fmtInt(tot.fora)} ja foram gastos e sobram <b>${fmtInt(restante)}</b>. Os dois dias vermelhos do grafico sozinhos custaram mais de mil.\n  </div>\n  <div class=\"origem\">Denominador: pedidos cujo prazo cai no mes &middot; Meta a confirmar por marketplace (ver decisao D1)</div>`;\n}\n\n/* ---------------- tela 5 ---------------- */\nfunction viewComissao(d2) {\n  const rows = lista(d2, 'comissao').slice().sort((a, b) => (b.faturamento_mes || 0) - (a.faturamento_mes || 0));\n  const excecoes = rows.filter(r => r.alerta);\n  const validos = rows.filter(r => !r.alerta || r.alerta === 'duplicado');\n  const totalFat = validos.reduce((s, r) => s + (r.faturamento_mes || 0), 0);\n  const totalCom = validos.reduce((s, r) => s + (r.faturamento_mes || 0) * (r.percentual || 5) / 100, 0);\n\n  const porRep = {};\n  rows.forEach(r => {\n    if (!r.usuario_comercial) return;\n    if (!porRep[r.usuario_comercial]) porRep[r.usuario_comercial] = { fat: 0, com: 0, n: 0 };\n    porRep[r.usuario_comercial].fat += r.faturamento_mes || 0;\n    porRep[r.usuario_comercial].com += (r.faturamento_mes || 0) * (r.percentual || 5) / 100;\n    porRep[r.usuario_comercial].n++;\n  });\n\n  const ALERTA = {\n    duplicado: ['ch-warn', 'CNPJ com mais de um cadastro no TRACKen'],\n    sem_dono: ['ch-crit', 'Cliente sem responsavel comercial na carteira'],\n    sem_faturamento: ['ch-mute', 'Sem faturamento no mes']\n  };\n\n  return `\n  <h2 class=\"h2\">Previa de comissionamento</h2>\n  <p class=\"sub\">Faturamento do mes por cliente, cruzado com a carteira comercial. As excecoes vem antes do total — e isso que faz o financeiro confiar no numero em vez de conferir na mao.</p>\n\n  <div class=\"panel\" style=\"margin-bottom:14px\">\n    <h3>Excecoes a resolver antes de fechar <em>${excecoes.length} de ${rows.length} clientes</em></h3>\n    <table><tbody>\n    ${excecoes.map(r => `\n      <tr data-key=\"${r._id}\">\n        <td style=\"width:220px\"><span class=\"chip ${ALERTA[r.alerta][0]}\">${r.alerta.replace('_', ' ')}</span></td>\n        <td><span class=\"strong\">${esc(r.cliente_nome)}</span><div class=\"tiny mono\">${esc(r.cnpj)}</div></td>\n        <td class=\"tiny\">${ALERTA[r.alerta][1]}</td>\n        <td class=\"num\">${fmtBRL(r.faturamento_mes)}</td>\n      </tr>`).join('')}\n    ${excecoes.length ? '' : '<tr><td class=\"tiny\">Nenhuma excecao.</td></tr>'}\n    </tbody></table>\n  </div>\n\n  <div class=\"grid\" style=\"grid-template-columns:1.7fr 1fr\">\n    <div class=\"panel\">\n      <h3>Por cliente <em>total ${fmtBRL(totalCom)} sobre ${fmtBRL(totalFat)}</em></h3>\n      <table><thead><tr>\n        <th>Cliente</th><th>No TRACKen</th><th>Comercial</th><th>SDR</th><th class=\"num\">Pedidos</th><th class=\"num\">Faturamento</th><th class=\"num\">5%</th>\n      </tr></thead><tbody>\n      ${rows.map(r => `\n        <tr data-key=\"${r._id}\">\n          <td><span class=\"strong\">${esc(r.cliente_nome)}</span><div class=\"tiny mono\">${esc(r.cnpj)}</div></td>\n          <td class=\"tiny mono\">${r.nome_tracken ? esc(r.nome_tracken) : '<span style=\"color:var(--crit)\">nao mapeado</span>'}</td>\n          <td>${r.usuario_comercial ? esc(r.usuario_comercial) : '<span class=\"chip ch-crit\">sem dono</span>'}</td>\n          <td class=\"tiny\">${esc(r.sdr)}</td>\n          <td class=\"num\">${fmtInt(r.pedidos_mes)}</td>\n          <td class=\"num\">${fmtBRL(r.faturamento_mes)}</td>\n          <td class=\"num strong\">${fmtBRL((r.faturamento_mes || 0) * (r.percentual || 5) / 100)}</td>\n        </tr>`).join('')}\n      </tbody></table>\n    </div>\n\n    <div class=\"panel\">\n      <h3>Por representante</h3>\n      <table><thead><tr><th>Comercial</th><th class=\"num\">Clientes</th><th class=\"num\">Comissao</th></tr></thead><tbody>\n      ${Object.keys(porRep).sort((a, b) => porRep[b].com - porRep[a].com).map(k => `\n        <tr data-key=\"${k}\"><td>${esc(k)}</td><td class=\"num\">${porRep[k].n}</td>\n        <td class=\"num strong\">${fmtBRL(porRep[k].com)}</td></tr>`).join('')}\n      </tbody></table>\n    </div>\n  </div>\n  <div class=\"origem\">Faturamento: Financeiro &gt; Faturamento de Clientes do TRACKen &middot; Carteira comercial: base propria da TM &middot; Juncao por CNPJ</div>`;\n}\n\n/* ---------------- drawer ---------------- */\nfunction drawer(d2, agora) {\n  const dw = d2.state.drawer;\n  if (!dw) return '';\n  let corpo = '';\n  if (dw.tipo === 'caso') corpo = drawerCaso(d2, dw.id);\n  else if (dw.tipo === 'agente') corpo = drawerAgente(d2, dw.id);\n  else if (dw.tipo === 'pedido') corpo = drawerPedido(d2, dw.id, agora);\n  return `<div class=\"drawer\"><div class=\"backdrop\" data-fecha></div><div class=\"sheet\">\n    <button class=\"close\" data-fecha>&times;</button>${corpo}</div></div>`;\n}\n\nfunction drawerCaso(d2, id) {\n  const c = lista(d2, 'caso').find(x => x._id === id);\n  if (!c) return '<p>Caso nao encontrado.</p>';\n  const p = lista(d2, 'pedido').find(x => x.cod_remessa === c.cod_remessa) || {};\n  const evs = lista(d2, 'evento').filter(e => e.cod_remessa === c.cod_remessa).sort((a, b) => a.ordem - b.ordem);\n  const prazo = (p.prazo_hora || 21) * 60;\n\n  return `\n  <span class=\"chip ${c.severidade === 'alta' ? 'ch-crit' : c.severidade === 'media' ? 'ch-warn' : 'ch-mute'}\">${c.severidade}</span>\n  <span class=\"chip ch-mute\">${c.regra}</span>\n  <h4 style=\"margin-top:12px\">${esc(REGRAS[c.regra] || c.regra_nome)}</h4>\n  <p class=\"sub\" style=\"margin-bottom:0\">${esc(c.resumo)}</p>\n\n  <dl class=\"kv\">\n    <dt>Remessa</dt><dd class=\"mono\">${c.cod_remessa}</dd>\n    <dt>Pedido</dt><dd class=\"mono\">${esc(c.num_pedido)}</dd>\n    <dt>Agente</dt><dd>${esc(c.agente_nome)} <span class=\"tiny mono\">${esc(c.agente_usuario)}</span></dd>\n    <dt>Equipe</dt><dd>${esc(c.equipe)}</dd>\n    <dt>Cliente</dt><dd>${esc(c.cliente_nome)}</dd>\n    <dt>Detectado</dt><dd>${diaLabel(c.detectado_dia)} as ${hhmm(c.detectado_min)}</dd>\n    <dt>Prazo do pedido</dt><dd class=\"mono\">${hhmm(prazo)}</dd>\n  </dl>\n\n  <div class=\"note\"><b>Evidencia.</b><br>${esc(c.evidencia)}</div>\n\n  <h3 style=\"font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink2);margin:22px 0 0;font-family:'IBM Plex Mono',monospace\">Linha do tempo do pedido</h3>\n  <ul class=\"tl\">\n    ${evs.map(e => {\n    const lag = (e.coletado_min || 0) - (e.hora_min || 0);\n    const suspeito = lag > 20 || (e.status === 'ENTREGUE' && e.hora_min <= prazo && e.coletado_min > prazo);\n    return `<li class=\"${suspeito ? 'flag' : ''}\" data-key=\"${e.cod_remessa}-${e.ordem}\">\n        <div class=\"t\">${esc(e.status)} <span class=\"mono\" style=\"color:var(--ink2)\">${hhmm(e.hora_min)}</span></div>\n        <div class=\"d\">registro chegou ${hhmm(e.coletado_min)} <span class=\"${suspeito ? 'lag' : ''}\">(${lag >= 0 ? '+' : ''}${dur(lag)} de defasagem)</span> &middot; usuario <span class=\"mono\">${esc(e.usuario)}</span></div>\n        ${e.recebedor || e.observacao ? '<div class=\"d\">recebedor: <b>' + (esc(e.recebedor) || '<span style=\"color:var(--crit)\">vazio</span>') + '</b> &middot; documento: ' + (esc(e.documento) || '<span style=\"color:var(--crit)\">vazio</span>') + (e.observacao ? ' &middot; \"' + esc(e.observacao) + '\"' : '') + '</div>' : ''}\n      </li>`;\n  }).join('')}\n  </ul>\n\n  <div style=\"display:flex;gap:8px;margin-top:22px\">\n    <button class=\"btn btn-crit\" data-caso-id=\"${c._id}\" data-caso-situacao=\"procedente\">Marcar procedente</button>\n    <button class=\"btn\" data-caso-id=\"${c._id}\" data-caso-situacao=\"improcedente\">Improcedente</button>\n  </div>\n  <div class=\"origem\">Situacao atual: ${esc(c.situacao)}</div>`;\n}\n\nfunction drawerAgente(d2, usuario) {\n  const a = lista(d2, 'agente').find(x => x.usuario === usuario);\n  if (!a) return '<p>Agente nao encontrado.</p>';\n  const per = lista(d2, 'agenteperiodo').filter(r => r.usuario === usuario);\n  const casos = lista(d2, 'caso').filter(c => c.agente_usuario === usuario);\n  const abertos = lista(d2, 'pedido').filter(p => p.agente_usuario === usuario && aberto(p));\n\n  return `\n  <h4>${esc(a.nome)}</h4>\n  <p class=\"sub\">${esc(a.equipe)} &middot; coordenacao de ${esc(a.coordenador)}</p>\n  <dl class=\"kv\">\n    <dt>Usuario</dt><dd class=\"mono\">${esc(a.usuario)}</dd>\n    <dt>Telefone</dt><dd class=\"mono\">${esc(a.telefone)}</dd>\n    <dt>Veiculo</dt><dd>${esc(a.veiculo)}</dd>\n    <dt>Situacao</dt><dd>${a.situacao === 'bloqueado' ? '<span class=\"chip ch-crit\">bloqueado</span>' : '<span class=\"chip ch-ok\">ativo</span>'}</dd>\n    ${a.situacao === 'bloqueado' ? '<dt>Motivo</dt><dd>' + esc(a.motivo_bloqueio) + '</dd><dt>Bloqueado por</dt><dd class=\"mono\">' + esc(a.bloqueado_por) + '</dd>' : ''}\n    <dt>Em rua agora</dt><dd>${abertos.length} pedidos</dd>\n  </dl>\n\n  <div class=\"panel\" style=\"margin-top:16px\">\n    <h3>Desempenho</h3>\n    <table><thead><tr><th>Periodo</th><th class=\"num\">Entregas</th><th class=\"num\">% no prazo</th><th class=\"num\">Casos</th></tr></thead><tbody>\n    ${['hoje', 'semana', 'mes'].map(pd => {\n    const r = per.find(x => x.periodo === pd) || {};\n    const pp = pct(r.no_prazo, r.entregas);\n    return `<tr data-key=\"${pd}\"><td>${pd}</td><td class=\"num\">${fmtInt(r.entregas)}</td>\n      <td class=\"num strong\" style=\"color:${pp < 99 ? 'var(--crit)' : pp < 99.5 ? 'var(--warn)' : 'var(--ok)'}\">${r.entregas ? fmtPct(pp) : '-'}</td>\n      <td class=\"num\">${((r.casos_alta || 0) + (r.casos_media || 0)) || '-'}</td></tr>`;\n  }).join('')}\n    </tbody></table>\n  </div>\n\n  ${casos.length ? `<div class=\"panel\" style=\"margin-top:14px\"><h3>Casos do agente</h3><table><tbody>\n    ${casos.map(c => `<tr class=\"sel\" data-abre-caso=\"${c._id}\" data-key=\"${c._id}\">\n      <td><span class=\"chip ${c.severidade === 'alta' ? 'ch-crit' : c.severidade === 'media' ? 'ch-warn' : 'ch-mute'}\">${c.regra}</span></td>\n      <td class=\"tiny\">${esc(c.resumo)}</td><td class=\"tiny\">${diaLabel(c.detectado_dia)}</td></tr>`).join('')}\n  </tbody></table></div>` : ''}\n\n  <div style=\"margin-top:22px\">\n    <button class=\"btn ${a.situacao === 'bloqueado' ? 'btn-ok' : 'btn-crit'}\" data-bloquear=\"${a.usuario}\">\n      ${a.situacao === 'bloqueado' ? 'Desbloquear agente' : 'Bloquear agente'}\n    </button>\n  </div>\n  <div class=\"origem\">A decisao e registrada aqui com autor, hora e evidencia. A ordem de bloqueio e executada no TRACKen — este sistema nao escreve la.</div>`;\n}\n\nfunction drawerPedido(d2, cod, agora) {\n  const p = lista(d2, 'pedido').find(x => String(x.cod_remessa) === String(cod));\n  if (!p) return '<p>Pedido nao encontrado.</p>';\n  const e = estado(p, agora);\n  const r = prazoMin(p) - agora;\n  return `\n  <span class=\"chip ${e === 'estourado' || e === 'vai_estourar' ? 'ch-crit' : e === 'em_risco' ? 'ch-warn' : 'ch-ok'}\">${ESTADO_LABEL[e]}</span>\n  <h4 style=\"margin-top:12px\">Remessa ${p.cod_remessa}</h4>\n  <p class=\"sub\">${esc(p.cliente_nome)} &middot; ${esc(p.marketplace)}</p>\n  <dl class=\"kv\">\n    <dt>Restante</dt><dd class=\"strong mono\">${aberto(p) ? (r < 0 ? '-' + dur(r) : dur(r)) : 'entregue'}</dd>\n    <dt>Prazo</dt><dd class=\"mono\">${hhmm(p.prazo_hora * 60)} ${diaLabel(p.prazo_dia)}</dd>\n    <dt>Pedido</dt><dd class=\"mono\">${esc(p.num_pedido)}</dd>\n    <dt>Nota fiscal</dt><dd class=\"mono\">${esc(p.nota_fiscal)}</dd>\n    <dt>Destinatario</dt><dd>${esc(p.destinatario)}</dd>\n    <dt>Endereco</dt><dd>${esc(p.bairro)}, ${esc(p.cidade)} &middot; ${esc(p.cep)}<div class=\"tiny\">regiao ${esc(p.regiao)}</div></dd>\n    <dt>Valor NF</dt><dd>${fmtBRL(p.valor_nf)}</dd>\n    <dt>Agente</dt><dd>${esc(p.agente_nome)}<div class=\"tiny\">${esc(p.equipe)}</div></dd>\n    <dt>Manifesto</dt><dd class=\"mono\">${p.manifesto ? esc(p.manifesto) : '<span style=\"color:var(--warn)\">nao manifestado</span>'}</dd>\n    <dt>Tentativas</dt><dd>${p.tentativas}</dd>\n    <dt>Status TRACKen</dt><dd>${esc(p.status_atual)}</dd>\n    <dt>Status Marketplace</dt><dd>${esc(p.mkt_status)}<div class=\"tiny mono\">${hhmm(p.mkt_min)}</div></dd>\n  </dl>\n  <div class=\"origem\">Status: API TRACKen (simulada) &middot; Agente: export da Torre de Operacoes</div>`;\n}\n","at":"2026-08-26T21:02:35.932Z"}}}]}},{"reference":"ExternalComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f060d9b1ca96def42f3c40a","displayName":"Builder AuthStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"credentials":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"UsersDataSet"}},"sessionShared":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},"email":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"nR6Q9d7qdaPtZhJ28Q8Dy"},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"yPCJBTKo8q1Mw0B_3Kpwl"},"component":"data2-core-types@ArtboardReference"}}},"session":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"name"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"sessionMetadata":{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},{"params":{"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"active"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.status"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is active user"}]},"component":"data2-core-logical-operators@And","displayName":"is active and has _id"}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $user"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-primitives@String","params":{"content":"@data2.app"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.email"}}}}},"component":"data2-core-functions@Includes","displayName":"isData2User"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}},"component":"data2-core-flow@Step"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.d2_app"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"management"}}]},"component":"data2-core-functions@Includes","displayName":"isData2App Exception"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}},"component":"data2-core-flow@Step"},{"params":{"resultName":{"component":"data2-core-primitives@String","params":{"content":"has_access"}},"action":{"params":{"compare":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}]},"component":"data2-core-logical-operators@Or"},"else":{"params":{"actions":[{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $metadata.system"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":"filter","args":[{"_id":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records.length"}}}}},"component":"data2-core-logical-operators@Not","displayName":"systems not found"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check system found"},{"params":{"actions":[{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"organization":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"cursor.current.organization._id"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"}]},"component":"data2-core-flow@Parallel"}]},"component":"data2-core-flow@Series","displayName":"common setup"},{"params":{"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"else":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"compare":{"params":{"components":{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"mapper":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"system"}}],"body":{"params":{"expression":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.visibility"}}}},"defaultCase":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"public"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"billing-owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}},{"component":"data2-core-primitives@String","params":{"content":"member"}}]},"component":"data2-core-functions@Includes","displayName":"has role with access"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"collaborator"}}},"component":"data2-core-comparison-operators@Equal","displayName":"is collaborator"}]},"component":"data2-core-logical-operators@And","displayName":"is org member and collaborator"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is collaborator"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is collaborator and has system access"}]},"component":"data2-core-logical-operators@Or"}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"private"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}}]},"component":"data2-core-functions@Includes","displayName":"is owner/admin"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is owner/admin"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is member and has system access"}]},"component":"data2-core-logical-operators@Or","displayName":"is owner/admin or has system access"}}}]},"component":"data2-core-flow@Switch"}}}},"component":"data2-core-functions@ArrayMap"}},"component":"data2-core-logical-operators@And","displayName":"has org member for all systems in request"}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}},"component":"data2-core-flow@If"}},"component":"data2-core-flow@Step"},{"params":{"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"},"compare":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"has_access"}}}}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"sessionExpiresIn":{"component":"data2-core-primitives@Number","params":{"content":604800}},"sessionRenewal":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"identityProviders":[{"provider":{"component":"data2-core-primitives@String","params":{"content":"GOOGLE"}},"clientId":{"component":"data2-core-primitives@String","params":{"content":"55470861603-22pvfc1t49lp8cjnbfk71s5ct9hp1q1v.apps.googleusercontent.com"}}}]},"reference":"Data2BuilderAuthentication","updatedAt":"2026-08-06T19:31:23.557Z"},{"_id":"5f060ee51ca96def42f3fbd1","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"UsersTableDataSource"}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}}},"reference":"UsersDataSet","updatedAt":"2026-03-04T21:16:40.291Z"},{"_id":"68f938cf5fb002e33752a43d","displayName":"InternalApplicationsAuthenticationStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}}},"verifier":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{"reference":"InternalApplicationsVerifierDataSet"}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"secret"}},"credentials":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}],"session":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}]},"reference":"InternalApplicationsAuthenticationStrategy","updatedAt":"2025-10-22T20:08:54.442Z","createdAt":"2025-10-22T20:04:31.198Z"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"_id":"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":"6a8f510e2e83a7b3d435fbc3","component":"data2-core-primitives@Artboard","system":"6a8c48a1e9d7f931a6fd649e","displayName":"App","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"App"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0}}},"reference":"sXo6rMiqdL0iRToD8BjKj","deleteMetadata":{}},{"_id":"87e496620208834fdfe2dd19","parent":"6a8f510e2e83a7b3d435fbc3","component":"tm-logistica-poc@prazoeprova","system":"6a8c48a1e9d7f931a6fd649e","displayName":"Prazo e Prova (app)","params":{"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"top":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}}},"reference":"M8WjbUGVCmEAePdUReTM-","deleteMetadata":{}}]}},{"_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":"6a8f52668c33b1efb42c0d7c","displayName":"Prazo e Prova","reference":"AjDh__IDU3QDbnmv7E21X","params":{"domain":{"component":"data2-core-primitives@String","params":{"content":"app"}},"entryPoint":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"sXo6rMiqdL0iRToD8BjKj"}}},"system":"6a8c48a1e9d7f931a6fd649e","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}